diff options
Diffstat (limited to 'spec/requests/api/internal')
-rw-r--r-- | spec/requests/api/internal/base_spec.rb | 75 | ||||
-rw-r--r-- | spec/requests/api/internal/kubernetes_spec.rb | 6 | ||||
-rw-r--r-- | spec/requests/api/internal/mail_room_spec.rb | 194 |
3 files changed, 272 insertions, 3 deletions
diff --git a/spec/requests/api/internal/base_spec.rb b/spec/requests/api/internal/base_spec.rb index 0a71eb43f81..9aa8aaafc68 100644 --- a/spec/requests/api/internal/base_spec.rb +++ b/spec/requests/api/internal/base_spec.rb @@ -372,7 +372,38 @@ RSpec.describe API::Internal::Base do end end - describe "POST /internal/allowed", :clean_gitlab_redis_shared_state do + describe "POST /internal/allowed", :clean_gitlab_redis_shared_state, :clean_gitlab_redis_rate_limiting do + shared_examples 'rate limited request' do + let(:action) { 'git-upload-pack' } + let(:actor) { key } + + it 'is throttled by rate limiter' do + allow(::Gitlab::ApplicationRateLimiter).to receive(:threshold).and_return(1) + expect(::Gitlab::ApplicationRateLimiter).to receive(:throttled?).with(:gitlab_shell_operation, scope: [action, project.full_path, actor]).twice.and_call_original + + request + + expect(response).to have_gitlab_http_status(:ok) + + request + + expect(response).to have_gitlab_http_status(:too_many_requests) + expect(json_response['message']['error']).to eq('This endpoint has been requested too many times. Try again later.') + end + + context 'when rate_limit_gitlab_shell feature flag is disabled' do + before do + stub_feature_flags(rate_limit_gitlab_shell: false) + end + + it 'is not throttled by rate limiter' do + expect(::Gitlab::ApplicationRateLimiter).not_to receive(:throttled?) + + subject + end + end + end + context "access granted" do let(:env) { {} } @@ -530,6 +561,32 @@ RSpec.describe API::Internal::Base do expect(json_response["gitaly"]["features"]).to eq('gitaly-feature-mep-mep' => 'true') expect(user.reload.last_activity_on).to eql(Date.today) end + + it_behaves_like 'rate limited request' do + def request + pull(key, project) + end + end + + context 'when user_id is passed' do + it_behaves_like 'rate limited request' do + let(:actor) { user } + + def request + post( + api("/internal/allowed"), + params: { + user_id: user.id, + project: full_path_for(project), + gl_repository: gl_repository_for(project), + action: 'git-upload-pack', + secret_token: secret_token, + protocol: 'ssh' + } + ) + end + end + end end context "with a feature flag enabled for a project" do @@ -576,6 +633,14 @@ RSpec.describe API::Internal::Base do expect(json_response["gitaly"]["token"]).to eq(Gitlab::GitalyClient.token(project.repository_storage)) expect(user.reload.last_activity_on).to be_nil end + + it_behaves_like 'rate limited request' do + let(:action) { 'git-receive-pack' } + + def request + push(key, project) + end + end end context 'when receive_max_input_size has been updated' do @@ -838,6 +903,14 @@ RSpec.describe API::Internal::Base do expect(json_response["gitaly"]["address"]).to eq(Gitlab::GitalyClient.address(project.repository_storage)) expect(json_response["gitaly"]["token"]).to eq(Gitlab::GitalyClient.token(project.repository_storage)) end + + it_behaves_like 'rate limited request' do + let(:action) { 'git-upload-archive' } + + def request + archive(key, project) + end + end end context "not added to project" do diff --git a/spec/requests/api/internal/kubernetes_spec.rb b/spec/requests/api/internal/kubernetes_spec.rb index 245e4e6ba15..59d185fe6c8 100644 --- a/spec/requests/api/internal/kubernetes_spec.rb +++ b/spec/requests/api/internal/kubernetes_spec.rb @@ -53,7 +53,9 @@ RSpec.describe API::Internal::Kubernetes do shared_examples 'agent token tracking' do it 'tracks token usage' do - expect { response }.to change { agent_token.reload.read_attribute(:last_used_at) } + expect do + send_request(headers: { 'Authorization' => "Bearer #{agent_token.token}" }) + end.to change { agent_token.reload.read_attribute(:last_used_at) } end end @@ -149,7 +151,7 @@ RSpec.describe API::Internal::Kubernetes do let(:agent) { agent_token.agent } let(:project) { agent.project } - shared_examples 'agent token tracking' + include_examples 'agent token tracking' it 'returns expected data', :aggregate_failures do send_request(headers: { 'Authorization' => "Bearer #{agent_token.token}" }) diff --git a/spec/requests/api/internal/mail_room_spec.rb b/spec/requests/api/internal/mail_room_spec.rb new file mode 100644 index 00000000000..f3ca3708c0c --- /dev/null +++ b/spec/requests/api/internal/mail_room_spec.rb @@ -0,0 +1,194 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe API::Internal::MailRoom do + let(:base_configs) do + { + enabled: true, + address: 'address@example.com', + port: 143, + ssl: false, + start_tls: false, + mailbox: 'inbox', + idle_timeout: 60, + log_path: Rails.root.join('log', 'mail_room_json.log').to_s, + expunge_deleted: false + } + end + + let(:enabled_configs) do + { + incoming_email: base_configs.merge( + secure_file: Rails.root.join('tmp', 'tests', '.incoming_email_secret').to_s + ), + service_desk_email: base_configs.merge( + secure_file: Rails.root.join('tmp', 'tests', '.service_desk_email').to_s + ) + } + end + + let(:auth_payload) { { 'iss' => Gitlab::MailRoom::Authenticator::INTERNAL_API_REQUEST_JWT_ISSUER, 'iat' => (Time.now - 10.seconds).to_i } } + + let(:incoming_email_secret) { 'incoming_email_secret' } + let(:service_desk_email_secret) { 'service_desk_email_secret' } + + let(:email_content) { fixture_file("emails/commands_in_reply.eml") } + + before do + allow(Gitlab::MailRoom::Authenticator).to receive(:secret).with(:incoming_email).and_return(incoming_email_secret) + allow(Gitlab::MailRoom::Authenticator).to receive(:secret).with(:service_desk_email).and_return(service_desk_email_secret) + allow(Gitlab::MailRoom).to receive(:enabled_configs).and_return(enabled_configs) + end + + around do |example| + freeze_time do + example.run + end + end + + describe "POST /internal/mail_room/*mailbox_type" do + context 'handle incoming_email successfully' do + let(:auth_headers) do + jwt_token = JWT.encode(auth_payload, incoming_email_secret, 'HS256') + { Gitlab::MailRoom::Authenticator::INTERNAL_API_REQUEST_HEADER => jwt_token } + end + + it 'schedules a EmailReceiverWorker job with raw email content' do + Sidekiq::Testing.fake! do + expect do + post api("/internal/mail_room/incoming_email"), headers: auth_headers, params: email_content + end.to change { EmailReceiverWorker.jobs.size }.by(1) + end + + expect(response).to have_gitlab_http_status(:ok) + + job = EmailReceiverWorker.jobs.last + expect(job).to match a_hash_including('args' => [email_content]) + end + end + + context 'handle service_desk_email successfully' do + let(:auth_headers) do + jwt_token = JWT.encode(auth_payload, service_desk_email_secret, 'HS256') + { Gitlab::MailRoom::Authenticator::INTERNAL_API_REQUEST_HEADER => jwt_token } + end + + it 'schedules a ServiceDeskEmailReceiverWorker job with raw email content' do + Sidekiq::Testing.fake! do + expect do + post api("/internal/mail_room/service_desk_email"), headers: auth_headers, params: email_content + end.to change { ServiceDeskEmailReceiverWorker.jobs.size }.by(1) + end + + expect(response).to have_gitlab_http_status(:ok) + + job = ServiceDeskEmailReceiverWorker.jobs.last + expect(job).to match a_hash_including('args' => [email_content]) + end + end + + context 'email content exceeds limit' do + let(:auth_headers) do + jwt_token = JWT.encode(auth_payload, incoming_email_secret, 'HS256') + { Gitlab::MailRoom::Authenticator::INTERNAL_API_REQUEST_HEADER => jwt_token } + end + + before do + allow(EmailReceiverWorker).to receive(:perform_async).and_raise( + Gitlab::SidekiqMiddleware::SizeLimiter::ExceedLimitError.new(EmailReceiverWorker, email_content.bytesize, email_content.bytesize - 1) + ) + end + + it 'responds with 400 bad request and replies with a failure message' do + perform_enqueued_jobs do + Sidekiq::Testing.fake! do + expect do + post api("/internal/mail_room/incoming_email"), headers: auth_headers, params: email_content + end.not_to change { EmailReceiverWorker.jobs.size } + end + end + + expect(response).to have_gitlab_http_status(:bad_request) + expect(Gitlab::Json.parse(response.body)).to match a_hash_including( + "success" => false, + "message" => "We couldn't process your email because it is too large. Please create your issue or comment through the web interface." + ) + + email = ActionMailer::Base.deliveries.last + expect(email).not_to be_nil + expect(email.to).to match_array(["jake@adventuretime.ooo"]) + expect(email.subject).to include("Rejected") + expect(email.body.parts.last.to_s).to include("We couldn't process your email") + end + end + + context 'not authenticated' do + it 'responds with 401 Unauthorized' do + post api("/internal/mail_room/incoming_email") + + expect(response).to have_gitlab_http_status(:unauthorized) + end + end + + context 'wrong token authentication' do + let(:auth_headers) do + jwt_token = JWT.encode(auth_payload, 'wrongsecret', 'HS256') + { Gitlab::MailRoom::Authenticator::INTERNAL_API_REQUEST_HEADER => jwt_token } + end + + it 'responds with 401 Unauthorized' do + post api("/internal/mail_room/incoming_email"), headers: auth_headers + + expect(response).to have_gitlab_http_status(:unauthorized) + end + end + + context 'wrong mailbox type authentication' do + let(:auth_headers) do + jwt_token = JWT.encode(auth_payload, service_desk_email_secret, 'HS256') + { Gitlab::MailRoom::Authenticator::INTERNAL_API_REQUEST_HEADER => jwt_token } + end + + it 'responds with 401 Unauthorized' do + post api("/internal/mail_room/incoming_email"), headers: auth_headers + + expect(response).to have_gitlab_http_status(:unauthorized) + end + end + + context 'not supported mailbox type' do + let(:auth_headers) do + jwt_token = JWT.encode(auth_payload, incoming_email_secret, 'HS256') + { Gitlab::MailRoom::Authenticator::INTERNAL_API_REQUEST_HEADER => jwt_token } + end + + it 'responds with 401 Unauthorized' do + post api("/internal/mail_room/invalid_mailbox_type"), headers: auth_headers + + expect(response).to have_gitlab_http_status(:unauthorized) + end + end + + context 'not enabled mailbox type' do + let(:enabled_configs) do + { + incoming_email: base_configs.merge( + secure_file: Rails.root.join('tmp', 'tests', '.incoming_email_secret').to_s + ) + } + end + + let(:auth_headers) do + jwt_token = JWT.encode(auth_payload, service_desk_email_secret, 'HS256') + { Gitlab::MailRoom::Authenticator::INTERNAL_API_REQUEST_HEADER => jwt_token } + end + + it 'responds with 401 Unauthorized' do + post api("/internal/mail_room/service_desk_email"), headers: auth_headers + + expect(response).to have_gitlab_http_status(:unauthorized) + end + end + end +end |