From f4c7cc7de7a87be216a97872f1b3647abdbdfac2 Mon Sep 17 00:00:00 2001 From: "Alan (Maciej) Paruszewski" <mparuszewski@gitlab.com> Date: Wed, 8 Dec 2021 00:15:30 +0100 Subject: [PATCH 1/2] Add request specs for security policies mutations --- .../assign_security_policy_project_spec.rb | 75 ++++++++++++++++ .../create_security_policy_project_spec.rb | 76 +++++++++++++++++ .../unassign_security_policy_project_spec.rb | 85 +++++++++++++++++++ 3 files changed, 236 insertions(+) create mode 100644 ee/spec/requests/api/graphql/mutations/security_policy/assign_security_policy_project_spec.rb create mode 100644 ee/spec/requests/api/graphql/mutations/security_policy/create_security_policy_project_spec.rb create mode 100644 ee/spec/requests/api/graphql/mutations/security_policy/unassign_security_policy_project_spec.rb diff --git a/ee/spec/requests/api/graphql/mutations/security_policy/assign_security_policy_project_spec.rb b/ee/spec/requests/api/graphql/mutations/security_policy/assign_security_policy_project_spec.rb new file mode 100644 index 00000000000000..6361c3f2760644 --- /dev/null +++ b/ee/spec/requests/api/graphql/mutations/security_policy/assign_security_policy_project_spec.rb @@ -0,0 +1,75 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'Assigns scan execution policy project to a project' do + include GraphqlHelpers + + let_it_be_with_refind(:owner) { create(:user) } + let_it_be_with_refind(:user) { create(:user) } + let_it_be_with_refind(:project) { create(:project, namespace: owner.namespace) } + let_it_be_with_refind(:policy_project) { create(:project) } + let_it_be_with_refind(:policy_project_id) { GitlabSchema.id_from_object(policy_project) } + + let(:current_user) { owner } + + subject { post_graphql_mutation(mutation, current_user: current_user) } + + def mutation + variables = { project_path: project.full_path, security_policy_project_id: GitlabSchema.id_from_object(policy_project).to_s } + + graphql_mutation(:security_policy_project_assign, variables) do + <<-QL.strip_heredoc + errors + QL + end + end + + def mutation_response + graphql_mutation_response(:security_policy_project_assign) + end + + context 'when permission is set for user' do + before do + stub_licensed_features(security_orchestration_policies: true) + end + + context 'when user is an owner of the project' do + it 'assigns the security policy project', :aggregate_failures do + subject + + orchestration_policy_configuration = project.security_orchestration_policy_configuration + + expect(graphql_data_at[:errors]).to be_nil + expect(orchestration_policy_configuration.security_policy_management_project).to eq(policy_project) + end + end + + context 'when user is not an owner' do + let(:current_user) { user } + + before do + project.add_maintainer(user) + end + + it_behaves_like 'a mutation that returns top-level errors', + errors: [Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR] + end + end + + context 'when policy_project_id is invalid' do + let_it_be_with_refind(:policy_project_id) { 'invalid' } + + it_behaves_like 'a mutation that returns top-level errors', + errors: [Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR] + end + + context 'when feature is not licensed' do + before do + stub_licensed_features(security_orchestration_policies: false) + end + + it_behaves_like 'a mutation that returns top-level errors', + errors: [Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR] + end +end diff --git a/ee/spec/requests/api/graphql/mutations/security_policy/create_security_policy_project_spec.rb b/ee/spec/requests/api/graphql/mutations/security_policy/create_security_policy_project_spec.rb new file mode 100644 index 00000000000000..bb2a011f6783d4 --- /dev/null +++ b/ee/spec/requests/api/graphql/mutations/security_policy/create_security_policy_project_spec.rb @@ -0,0 +1,76 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'Creates and assigns scan execution policy project to a project' do + include GraphqlHelpers + + let_it_be_with_refind(:owner) { create(:user) } + let_it_be_with_refind(:user) { create(:user) } + let_it_be_with_refind(:project) { create(:project, namespace: owner.namespace) } + + let(:current_user) { owner } + + subject { post_graphql_mutation(mutation, current_user: current_user) } + + def mutation + variables = { project_path: project.full_path } + + graphql_mutation(:security_policy_project_create, variables) do + <<-QL.strip_heredoc + errors + QL + end + end + + def mutation_response + graphql_mutation_response(:security_policy_project_create) + end + + context 'when permission is set for user' do + before do + # todo: investigate too many qeuries issue as part of Project Management Database and Query Performance + # epic: https://gitlab.com/groups/gitlab-org/-/epics/5804 + stub_const('Gitlab::QueryLimiting::Transaction::THRESHOLD', 130) + stub_licensed_features(security_orchestration_policies: true) + end + + context 'when user is an owner of the project' do + it 'creates and assigns the security policy project', :aggregate_failures do + expect { subject }.to change { ::Project.count }.by(1) + + orchestration_policy_configuration = project.security_orchestration_policy_configuration + + expect(graphql_data_at[:errors]).to be_nil + expect(orchestration_policy_configuration.security_policy_management_project.name).to eq("#{project.name} - Security policy project") + end + end + + context 'when user is not an owner' do + let(:current_user) { user } + + before do + project.add_maintainer(user) + end + + it_behaves_like 'a mutation that returns top-level errors', + errors: [Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR] + end + end + + context 'when policy_project_id is invalid' do + let_it_be_with_refind(:policy_project_id) { 'invalid' } + + it_behaves_like 'a mutation that returns top-level errors', + errors: [Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR] + end + + context 'when feature is not licensed' do + before do + stub_licensed_features(security_orchestration_policies: false) + end + + it_behaves_like 'a mutation that returns top-level errors', + errors: [Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR] + end +end diff --git a/ee/spec/requests/api/graphql/mutations/security_policy/unassign_security_policy_project_spec.rb b/ee/spec/requests/api/graphql/mutations/security_policy/unassign_security_policy_project_spec.rb new file mode 100644 index 00000000000000..ab12aebd5c9406 --- /dev/null +++ b/ee/spec/requests/api/graphql/mutations/security_policy/unassign_security_policy_project_spec.rb @@ -0,0 +1,85 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'Unassigns scan execution policy project from a project' do + include GraphqlHelpers + + let_it_be_with_refind(:owner) { create(:user) } + let_it_be_with_refind(:user) { create(:user) } + let_it_be_with_refind(:project) { create(:project, namespace: owner.namespace) } + let_it_be_with_refind(:policy_project) { create(:project) } + let_it_be_with_refind(:policy_project_id) { GitlabSchema.id_from_object(policy_project) } + + let(:current_user) { owner } + + subject { post_graphql_mutation(mutation, current_user: current_user) } + + def mutation + variables = { project_path: project.full_path } + + graphql_mutation(:security_policy_project_unassign, variables) do + <<-QL.strip_heredoc + errors + QL + end + end + + def mutation_response + graphql_mutation_response(:security_policy_project_unassign) + end + + context 'when permission is set for user' do + before do + stub_licensed_features(security_orchestration_policies: true) + end + + context 'when user is an owner of the project' do + context 'when there is no security policy project assigned to the project' do + it 'assigns the security policy project', :aggregate_failures do + subject + + expect(graphql_data_at[:errors]).to be_nil + end + end + + context 'when security policy project is assigned to the project' do + let!(:security_policy_management_project) { create(:project, :repository, namespace: current_user.namespace) } + let!(:policy_configuration) { create(:security_orchestration_policy_configuration, project: project, security_policy_management_project: security_policy_management_project) } + + it 'unassigns the security policy project', :aggregate_failures do + expect { subject }.to change { ::Security::OrchestrationPolicyConfiguration.count }.by(-1) + + expect(graphql_data_at[:errors]).to be_nil + end + end + end + + context 'when user is not an owner' do + let(:current_user) { user } + + before do + project.add_maintainer(user) + end + + it_behaves_like 'a mutation that returns top-level errors', + errors: [Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR] + end + end + + context 'when policy_project_id is invalid' do + let_it_be_with_refind(:policy_project_id) { 'invalid' } + + it_behaves_like 'a mutation that returns top-level errors', + errors: [Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR] + end + + context 'when feature is not licensed' do + before do + stub_licensed_features(security_orchestration_policies: false) + end + + it_behaves_like 'a mutation that returns top-level errors', + errors: [Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR] + end +end -- GitLab From f1d62e163a971c9866e7317bbcdadb2cf580ddb3 Mon Sep 17 00:00:00 2001 From: "Alan (Maciej) Paruszewski" <mparuszewski@gitlab.com> Date: Mon, 13 Dec 2021 22:01:04 +0100 Subject: [PATCH 2/2] Address MR comments --- .../create_security_policy_project.rb | 1 - .../assign_security_policy_project_spec.rb | 17 ++++++------- .../create_security_policy_project_spec.rb | 24 +++++++++---------- .../unassign_security_policy_project_spec.rb | 21 ++++++---------- 4 files changed, 28 insertions(+), 35 deletions(-) diff --git a/ee/app/graphql/mutations/security_policy/create_security_policy_project.rb b/ee/app/graphql/mutations/security_policy/create_security_policy_project.rb index 22c4d5141ef3df..7fa7e4ee5ca47c 100644 --- a/ee/app/graphql/mutations/security_policy/create_security_policy_project.rb +++ b/ee/app/graphql/mutations/security_policy/create_security_policy_project.rb @@ -23,7 +23,6 @@ def resolve(args) project = authorized_find!(args[:project_path]) result = create_project(project) - return { project: nil, errors: [result[:message]] } if result[:status] == :error { diff --git a/ee/spec/requests/api/graphql/mutations/security_policy/assign_security_policy_project_spec.rb b/ee/spec/requests/api/graphql/mutations/security_policy/assign_security_policy_project_spec.rb index 6361c3f2760644..d3dbbcec5349d7 100644 --- a/ee/spec/requests/api/graphql/mutations/security_policy/assign_security_policy_project_spec.rb +++ b/ee/spec/requests/api/graphql/mutations/security_policy/assign_security_policy_project_spec.rb @@ -16,7 +16,7 @@ subject { post_graphql_mutation(mutation, current_user: current_user) } def mutation - variables = { project_path: project.full_path, security_policy_project_id: GitlabSchema.id_from_object(policy_project).to_s } + variables = { project_path: project.full_path, security_policy_project_id: policy_project_id.to_s } graphql_mutation(:security_policy_project_assign, variables) do <<-QL.strip_heredoc @@ -29,7 +29,7 @@ def mutation_response graphql_mutation_response(:security_policy_project_assign) end - context 'when permission is set for user' do + context 'when licensed feature is available' do before do stub_licensed_features(security_orchestration_policies: true) end @@ -40,7 +40,8 @@ def mutation_response orchestration_policy_configuration = project.security_orchestration_policy_configuration - expect(graphql_data_at[:errors]).to be_nil + expect(response).to have_gitlab_http_status(:success) + expect(mutation_response['errors']).to be_empty expect(orchestration_policy_configuration.security_policy_management_project).to eq(policy_project) end end @@ -55,13 +56,13 @@ def mutation_response it_behaves_like 'a mutation that returns top-level errors', errors: [Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR] end - end - context 'when policy_project_id is invalid' do - let_it_be_with_refind(:policy_project_id) { 'invalid' } + context 'when policy_project_id is invalid' do + let_it_be_with_refind(:policy_project_id) { "gid://gitlab/Project/#{non_existing_record_id}" } - it_behaves_like 'a mutation that returns top-level errors', - errors: [Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR] + it_behaves_like 'a mutation that returns top-level errors', + errors: [Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR] + end end context 'when feature is not licensed' do diff --git a/ee/spec/requests/api/graphql/mutations/security_policy/create_security_policy_project_spec.rb b/ee/spec/requests/api/graphql/mutations/security_policy/create_security_policy_project_spec.rb index bb2a011f6783d4..f5308d26b01e22 100644 --- a/ee/spec/requests/api/graphql/mutations/security_policy/create_security_policy_project_spec.rb +++ b/ee/spec/requests/api/graphql/mutations/security_policy/create_security_policy_project_spec.rb @@ -18,6 +18,10 @@ def mutation graphql_mutation(:security_policy_project_create, variables) do <<-QL.strip_heredoc + project { + id + name + } errors QL end @@ -27,10 +31,11 @@ def mutation_response graphql_mutation_response(:security_policy_project_create) end - context 'when permission is set for user' do + context 'when licensed feature is available' do before do - # todo: investigate too many qeuries issue as part of Project Management Database and Query Performance - # epic: https://gitlab.com/groups/gitlab-org/-/epics/5804 + # TODO: investigate too many qeuries issue as part of Project Management Database and Query Performance + # Epic: https://gitlab.com/groups/gitlab-org/-/epics/5804 + # Issue: https://gitlab.com/gitlab-org/gitlab/-/issues/348344 stub_const('Gitlab::QueryLimiting::Transaction::THRESHOLD', 130) stub_licensed_features(security_orchestration_policies: true) end @@ -41,8 +46,10 @@ def mutation_response orchestration_policy_configuration = project.security_orchestration_policy_configuration - expect(graphql_data_at[:errors]).to be_nil - expect(orchestration_policy_configuration.security_policy_management_project.name).to eq("#{project.name} - Security policy project") + expect(response).to have_gitlab_http_status(:success) + expect(mutation_response['errors']).to be_empty + expect(mutation_response.dig('project', 'id')).to eq(orchestration_policy_configuration.security_policy_management_project.to_gid.to_s) + expect(mutation_response.dig('project', 'name')).to eq("#{project.name} - Security policy project") end end @@ -58,13 +65,6 @@ def mutation_response end end - context 'when policy_project_id is invalid' do - let_it_be_with_refind(:policy_project_id) { 'invalid' } - - it_behaves_like 'a mutation that returns top-level errors', - errors: [Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR] - end - context 'when feature is not licensed' do before do stub_licensed_features(security_orchestration_policies: false) diff --git a/ee/spec/requests/api/graphql/mutations/security_policy/unassign_security_policy_project_spec.rb b/ee/spec/requests/api/graphql/mutations/security_policy/unassign_security_policy_project_spec.rb index ab12aebd5c9406..30bb548e88f4ff 100644 --- a/ee/spec/requests/api/graphql/mutations/security_policy/unassign_security_policy_project_spec.rb +++ b/ee/spec/requests/api/graphql/mutations/security_policy/unassign_security_policy_project_spec.rb @@ -8,8 +8,6 @@ let_it_be_with_refind(:owner) { create(:user) } let_it_be_with_refind(:user) { create(:user) } let_it_be_with_refind(:project) { create(:project, namespace: owner.namespace) } - let_it_be_with_refind(:policy_project) { create(:project) } - let_it_be_with_refind(:policy_project_id) { GitlabSchema.id_from_object(policy_project) } let(:current_user) { owner } @@ -29,17 +27,18 @@ def mutation_response graphql_mutation_response(:security_policy_project_unassign) end - context 'when permission is set for user' do + context 'when licensed feature is available' do before do stub_licensed_features(security_orchestration_policies: true) end context 'when user is an owner of the project' do context 'when there is no security policy project assigned to the project' do - it 'assigns the security policy project', :aggregate_failures do - subject + it 'unassigns the security policy project', :aggregate_failures do + expect { subject }.not_to change { ::Security::OrchestrationPolicyConfiguration.count } - expect(graphql_data_at[:errors]).to be_nil + expect(response).to have_gitlab_http_status(:success) + expect(mutation_response['errors']).to eq(["Policy project doesn't exist"]) end end @@ -50,7 +49,8 @@ def mutation_response it 'unassigns the security policy project', :aggregate_failures do expect { subject }.to change { ::Security::OrchestrationPolicyConfiguration.count }.by(-1) - expect(graphql_data_at[:errors]).to be_nil + expect(response).to have_gitlab_http_status(:success) + expect(mutation_response['errors']).to be_empty end end end @@ -67,13 +67,6 @@ def mutation_response end end - context 'when policy_project_id is invalid' do - let_it_be_with_refind(:policy_project_id) { 'invalid' } - - it_behaves_like 'a mutation that returns top-level errors', - errors: [Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR] - end - context 'when feature is not licensed' do before do stub_licensed_features(security_orchestration_policies: false) -- GitLab