From bc299f54e841488b4ab37777761db1dfc7f3b60e Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Tue, 27 Apr 2021 08:57:43 +0000 Subject: Add latest changes from gitlab-org/security/gitlab@13-11-stable-ee --- .../graphql/mutations/notes/create/note_spec.rb | 2 + spec/requests/jwt_controller_spec.rb | 10 ++--- ...dependency_proxy_authentication_service_spec.rb | 25 ++++++------ spec/services/projects/download_service_spec.rb | 5 ++- spec/support/helpers/graphql_helpers.rb | 18 +++++---- .../requests/graphql_shared_examples.rb | 46 ++++++++++++++++++++++ 6 files changed, 79 insertions(+), 27 deletions(-) (limited to 'spec') diff --git a/spec/requests/api/graphql/mutations/notes/create/note_spec.rb b/spec/requests/api/graphql/mutations/notes/create/note_spec.rb index 1eed1c8e2ae..8dd8ed361ba 100644 --- a/spec/requests/api/graphql/mutations/notes/create/note_spec.rb +++ b/spec/requests/api/graphql/mutations/notes/create/note_spec.rb @@ -31,6 +31,8 @@ RSpec.describe 'Adding a Note' do project.add_developer(current_user) end + it_behaves_like 'a working GraphQL mutation' + it_behaves_like 'a Note mutation that creates a Note' it_behaves_like 'a Note mutation when there are active record validation errors' diff --git a/spec/requests/jwt_controller_spec.rb b/spec/requests/jwt_controller_spec.rb index 8be26784a3d..5b5658da97e 100644 --- a/spec/requests/jwt_controller_spec.rb +++ b/spec/requests/jwt_controller_spec.rb @@ -263,25 +263,21 @@ RSpec.describe JwtController do let(:credential_user) { group_deploy_token.username } let(:credential_password) { group_deploy_token.token } - it_behaves_like 'with valid credentials' + it_behaves_like 'returning response status', :forbidden end context 'with project deploy token' do let(:credential_user) { project_deploy_token.username } let(:credential_password) { project_deploy_token.token } - it_behaves_like 'with valid credentials' + it_behaves_like 'returning response status', :forbidden end context 'with invalid credentials' do let(:credential_user) { 'foo' } let(:credential_password) { 'bar' } - it 'returns unauthorized' do - subject - - expect(response).to have_gitlab_http_status(:unauthorized) - end + it_behaves_like 'returning response status', :unauthorized end end diff --git a/spec/services/auth/dependency_proxy_authentication_service_spec.rb b/spec/services/auth/dependency_proxy_authentication_service_spec.rb index ba50149f53a..1fd1677c7da 100644 --- a/spec/services/auth/dependency_proxy_authentication_service_spec.rb +++ b/spec/services/auth/dependency_proxy_authentication_service_spec.rb @@ -13,28 +13,31 @@ RSpec.describe Auth::DependencyProxyAuthenticationService do describe '#execute' do subject { service.execute(authentication_abilities: nil) } + shared_examples 'returning' do |status:, message:| + it "returns #{message}", :aggregate_failures do + expect(subject[:http_status]).to eq(status) + expect(subject[:message]).to eq(message) + end + end + context 'dependency proxy is not enabled' do before do stub_config(dependency_proxy: { enabled: false }) end - it 'returns not found' do - result = subject - - expect(result[:http_status]).to eq(404) - expect(result[:message]).to eq('dependency proxy not enabled') - end + it_behaves_like 'returning', status: 404, message: 'dependency proxy not enabled' end context 'without a user' do let(:user) { nil } - it 'returns forbidden' do - result = subject + it_behaves_like 'returning', status: 403, message: 'access forbidden' + end + + context 'with a deploy token as user' do + let_it_be(:user) { create(:deploy_token) } - expect(result[:http_status]).to eq(403) - expect(result[:message]).to eq('access forbidden') - end + it_behaves_like 'returning', status: 403, message: 'access forbidden' end context 'with a user' do diff --git a/spec/services/projects/download_service_spec.rb b/spec/services/projects/download_service_spec.rb index 0f743eaa7f5..7d4fce814f5 100644 --- a/spec/services/projects/download_service_spec.rb +++ b/spec/services/projects/download_service_spec.rb @@ -20,8 +20,9 @@ RSpec.describe Projects::DownloadService do context 'for URLs that are on the whitelist' do before do - stub_request(:get, 'http://mycompany.fogbugz.com/rails_sample.jpg').to_return(body: File.read(Rails.root + 'spec/fixtures/rails_sample.jpg')) - stub_request(:get, 'http://mycompany.fogbugz.com/doc_sample.txt').to_return(body: File.read(Rails.root + 'spec/fixtures/doc_sample.txt')) + # `ssrf_filter` resolves the hostname. See https://github.com/carrierwaveuploader/carrierwave/commit/91714adda998bc9e8decf5b1f5d260d808761304 + stub_request(:get, %r{http://[\d\.]+/rails_sample.jpg}).to_return(body: File.read(Rails.root + 'spec/fixtures/rails_sample.jpg')) + stub_request(:get, %r{http://[\d\.]+/doc_sample.txt}).to_return(body: File.read(Rails.root + 'spec/fixtures/doc_sample.txt')) end context 'an image file' do diff --git a/spec/support/helpers/graphql_helpers.rb b/spec/support/helpers/graphql_helpers.rb index d714f04fbba..9d6c6ab93e4 100644 --- a/spec/support/helpers/graphql_helpers.rb +++ b/spec/support/helpers/graphql_helpers.rb @@ -396,17 +396,21 @@ module GraphqlHelpers post api('/', current_user, version: 'graphql'), params: { _json: queries }, headers: headers end - def post_graphql(query, current_user: nil, variables: nil, headers: {}) + def post_graphql(query, current_user: nil, variables: nil, headers: {}, token: {}) params = { query: query, variables: serialize_variables(variables) } - post api('/', current_user, version: 'graphql'), params: params, headers: headers + post api('/', current_user, version: 'graphql', **token), params: params, headers: headers - if graphql_errors # Errors are acceptable, but not this one: - expect(graphql_errors).not_to include(a_hash_including('message' => 'Internal server error')) - end + return unless graphql_errors + + # Errors are acceptable, but not this one: + expect(graphql_errors).not_to include(a_hash_including('message' => 'Internal server error')) end - def post_graphql_mutation(mutation, current_user: nil) - post_graphql(mutation.query, current_user: current_user, variables: mutation.variables) + def post_graphql_mutation(mutation, current_user: nil, token: {}) + post_graphql(mutation.query, + current_user: current_user, + variables: mutation.variables, + token: token) end def post_graphql_mutation_with_uploads(mutation, current_user: nil) diff --git a/spec/support/shared_examples/requests/graphql_shared_examples.rb b/spec/support/shared_examples/requests/graphql_shared_examples.rb index a66bc7112fe..d133c5ea641 100644 --- a/spec/support/shared_examples/requests/graphql_shared_examples.rb +++ b/spec/support/shared_examples/requests/graphql_shared_examples.rb @@ -10,6 +10,52 @@ RSpec.shared_examples 'a working graphql query' do end end +RSpec.shared_examples 'a working GraphQL mutation' do + include GraphqlHelpers + + before do + post_graphql_mutation(mutation, current_user: current_user, token: token) + end + + shared_examples 'allows access to the mutation' do + let(:scopes) { ['api'] } + + it_behaves_like 'a working graphql query' do + it 'returns data' do + expect(graphql_data.compact).not_to be_empty + end + end + end + + shared_examples 'prevents access to the mutation' do + let(:scopes) { ['read_api'] } + + it 'does not resolve the mutation' do + expect(graphql_data.compact).to be_empty + expect(graphql_errors).to be_present + end + end + + context 'with a personal access token' do + let(:token) do + pat = create(:personal_access_token, user: current_user, scopes: scopes) + { personal_access_token: pat } + end + + it_behaves_like 'prevents access to the mutation' + it_behaves_like 'allows access to the mutation' + end + + context 'with an OAuth token' do + let(:token) do + { oauth_access_token: create(:oauth_access_token, resource_owner: current_user, scopes: scopes.join(' ')) } + end + + it_behaves_like 'prevents access to the mutation' + it_behaves_like 'allows access to the mutation' + end +end + RSpec.shared_examples 'a mutation on an unauthorized resource' do it_behaves_like 'a mutation that returns top-level errors', errors: [::Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR] -- cgit v1.2.3