From c9bcd7d7916dcff4ba36f80ee771bdaaef8f608a Mon Sep 17 00:00:00 2001 From: Sashi Kumar Kumaresan Date: Fri, 27 Jun 2025 12:53:38 +0200 Subject: [PATCH 1/8] Create audit logs when an MR is bypassed by security policy This MR create audit logs when an MR is bypassed by source branch exceptions in security policy bypass settings. EE: true Changelog: added --- ...equest_branch_bypassed_by_security_policy.yml | 11 +++++++++++ doc/user/compliance/audit_event_types.md | 1 + ee/app/models/ee/merge_request.rb | 9 +++++++++ .../ee/merge_requests/after_create_service.rb | 1 + .../services/ee/merge_requests/base_service.rb | 16 ++++++++++++++++ .../services/ee/merge_requests/reopen_service.rb | 1 + .../services/ee/merge_requests/update_service.rb | 1 + 7 files changed, 40 insertions(+) create mode 100644 config/audit_events/types/merge_request_branch_bypassed_by_security_policy.yml diff --git a/config/audit_events/types/merge_request_branch_bypassed_by_security_policy.yml b/config/audit_events/types/merge_request_branch_bypassed_by_security_policy.yml new file mode 100644 index 00000000000000..957c34cdc5eeec --- /dev/null +++ b/config/audit_events/types/merge_request_branch_bypassed_by_security_policy.yml @@ -0,0 +1,11 @@ +--- +name: merge_request_branch_bypassed_by_security_policy +description: The merge request's approval is bypassed by the branches configured in + the security policy +introduced_by_issue: https://gitlab.com/gitlab-org/gitlab/-/issues/549646 +introduced_by_mr: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/194709 +feature_category: security_policy_management +milestone: '18.2' +saved_to_database: true +streamed: true +scope: [Project] diff --git a/doc/user/compliance/audit_event_types.md b/doc/user/compliance/audit_event_types.md index 78d9af2078d320..6826b706d2760e 100644 --- a/doc/user/compliance/audit_event_types.md +++ b/doc/user/compliance/audit_event_types.md @@ -539,6 +539,7 @@ Audit event types belong to the following product categories. | [`security_policy_update`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/192797) | A security policy is updated | {{< icon name="check-circle" >}} Yes | GitLab [18.1](https://gitlab.com/gitlab-org/gitlab/-/issues/539230) | Project | | [`policy_violations_detected`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/193482) | Security policy violation is detected in the merge request | {{< icon name="dotted-circle" >}} No | GitLab [18.2](https://gitlab.com/gitlab-org/gitlab/-/work_items/549811) | Project | | [`policy_violations_resolved`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/193482) | Security policy violations are resolved in the merge request | {{< icon name="dotted-circle" >}} No | GitLab [18.2](https://gitlab.com/gitlab-org/gitlab/-/issues/549812) | Project | +| [`merge_request_branch_bypassed_by_security_policy`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/194709) | The merge request's approval is bypassed by the branches configured in the security policy | {{< icon name="check-circle" >}} Yes | GitLab [18.2](https://gitlab.com/gitlab-org/gitlab/-/issues/549646) | Project | ### Security testing configuration diff --git a/ee/app/models/ee/merge_request.rb b/ee/app/models/ee/merge_request.rb index dbdee243d58394..28dcd26e89ebd6 100644 --- a/ee/app/models/ee/merge_request.rb +++ b/ee/app/models/ee/merge_request.rb @@ -485,6 +485,15 @@ def schedule_policy_synchronization end end + def security_policies_exempting_branch_bypass_settings + approval_rules + .includes(approval_policy_rule: :security_policy) + .select(&:branches_exempted_by_policy?) + .map(&:approval_policy_rule) + .map(&:security_policy) + .uniq + end + # TODO: Will be removed with https://gitlab.com/gitlab-org/gitlab/-/issues/504296 def sync_project_approval_rules_for_policy_configuration(configuration_id) return if merged? diff --git a/ee/app/services/ee/merge_requests/after_create_service.rb b/ee/app/services/ee/merge_requests/after_create_service.rb index e3d9e1edf095d4..efdd2a926fd89c 100644 --- a/ee/app/services/ee/merge_requests/after_create_service.rb +++ b/ee/app/services/ee/merge_requests/after_create_service.rb @@ -22,6 +22,7 @@ def prepare_merge_request(merge_request) schedule_approval_notifications(merge_request) schedule_duo_code_review(merge_request) track_usage_event if merge_request.project.scan_result_policy_reads.any? + audit_security_policy_branch_bypass(merge_request) publish_event(merge_request) end diff --git a/ee/app/services/ee/merge_requests/base_service.rb b/ee/app/services/ee/merge_requests/base_service.rb index 850c040de37e2d..1b4f1e46c247a0 100644 --- a/ee/app/services/ee/merge_requests/base_service.rb +++ b/ee/app/services/ee/merge_requests/base_service.rb @@ -139,6 +139,22 @@ def capture_suggested_reviewers_accepted(merge_request) .perform_async(merge_request.id, suggested_reviewer_ids) end + def audit_security_policy_branch_bypass(merge_request) + matching_policies = merge_request.security_policies_exempting_branch_bypass_settings + + return if matching_policies.empty? + + matching_policies.each do |policy| + next unless Feature.enabled?(:approval_policy_branch_exceptions, policy.security_policy_management_project) + + log_audit_event( + merge_request, + 'merge_request_branch_bypassed_by_security_policy', + "Approvals bypassed by security policy #{policy.name}" + ) + end + end + def log_audit_event(merge_request, event_name, message) audit_context = { name: event_name, diff --git a/ee/app/services/ee/merge_requests/reopen_service.rb b/ee/app/services/ee/merge_requests/reopen_service.rb index 1ac7c561a6d600..5f68e88b3551e1 100644 --- a/ee/app/services/ee/merge_requests/reopen_service.rb +++ b/ee/app/services/ee/merge_requests/reopen_service.rb @@ -10,6 +10,7 @@ def execute(merge_request) super.tap do delete_approvals(merge_request) resync_policies(merge_request) + audit_security_policy_branch_bypass(merge_request) if current_user.project_bot? log_audit_event(merge_request, 'merge_request_reopened_by_project_bot', diff --git a/ee/app/services/ee/merge_requests/update_service.rb b/ee/app/services/ee/merge_requests/update_service.rb index 117eccac64b43f..4233b6d0248ab4 100644 --- a/ee/app/services/ee/merge_requests/update_service.rb +++ b/ee/app/services/ee/merge_requests/update_service.rb @@ -63,6 +63,7 @@ def delete_approvals_on_target_branch_change(merge_request) delete_approvals(merge_request) if reset_approvals?(merge_request, nil) sync_any_merge_request_approval_rules(merge_request) notify_for_policy_violations(merge_request) + audit_security_policy_branch_bypass(merge_request) end def reset_approval_rules(merge_request) -- GitLab From 622f470f2106fb051a0ef6b5e3cb1a921d128961 Mon Sep 17 00:00:00 2001 From: Sashi Kumar Kumaresan Date: Fri, 27 Jun 2025 13:19:41 +0200 Subject: [PATCH 2/8] Update audit event docs --- doc/user/compliance/audit_event_types.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/user/compliance/audit_event_types.md b/doc/user/compliance/audit_event_types.md index 6826b706d2760e..95b18ff8f2ddae 100644 --- a/doc/user/compliance/audit_event_types.md +++ b/doc/user/compliance/audit_event_types.md @@ -537,9 +537,9 @@ Audit event types belong to the following product categories. | [`security_policy_create`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/192797) | A security policy is created | {{< icon name="check-circle" >}} Yes | GitLab [18.1](https://gitlab.com/gitlab-org/gitlab/-/issues/539230) | Project | | [`security_policy_delete`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/192797) | A security policy is deleted | {{< icon name="check-circle" >}} Yes | GitLab [18.1](https://gitlab.com/gitlab-org/gitlab/-/issues/539230) | Project | | [`security_policy_update`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/192797) | A security policy is updated | {{< icon name="check-circle" >}} Yes | GitLab [18.1](https://gitlab.com/gitlab-org/gitlab/-/issues/539230) | Project | +| [`merge_request_branch_bypassed_by_security_policy`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/194709) | The merge request's approval is bypassed by the branches configured in the security policy | {{< icon name="check-circle" >}} Yes | GitLab [18.2](https://gitlab.com/gitlab-org/gitlab/-/issues/549646) | Project | | [`policy_violations_detected`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/193482) | Security policy violation is detected in the merge request | {{< icon name="dotted-circle" >}} No | GitLab [18.2](https://gitlab.com/gitlab-org/gitlab/-/work_items/549811) | Project | | [`policy_violations_resolved`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/193482) | Security policy violations are resolved in the merge request | {{< icon name="dotted-circle" >}} No | GitLab [18.2](https://gitlab.com/gitlab-org/gitlab/-/issues/549812) | Project | -| [`merge_request_branch_bypassed_by_security_policy`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/194709) | The merge request's approval is bypassed by the branches configured in the security policy | {{< icon name="check-circle" >}} Yes | GitLab [18.2](https://gitlab.com/gitlab-org/gitlab/-/issues/549646) | Project | ### Security testing configuration -- GitLab From 962a85ef0dfa59bcb47ccc6fd3c37f0c9cefcfaa Mon Sep 17 00:00:00 2001 From: Sashi Kumar Kumaresan Date: Fri, 27 Jun 2025 22:32:02 +0200 Subject: [PATCH 3/8] Fix and add more spec --- ee/app/models/approval_merge_request_rule.rb | 10 ++-- ee/app/models/security/policy.rb | 1 + .../ee/merge_requests/base_service.rb | 2 +- ee/spec/models/merge_request_spec.rb | 39 ++++++++++++++ .../after_create_service_spec.rb | 2 + .../ee/merge_requests/reopen_service_spec.rb | 4 ++ .../ee/merge_requests/update_service_spec.rb | 8 +++ ...ty_policy_branch_bypass_shared_examples.rb | 54 +++++++++++++++++++ 8 files changed, 114 insertions(+), 6 deletions(-) create mode 100644 ee/spec/support/shared_examples/services/merge_requests/audit_security_policy_branch_bypass_shared_examples.rb diff --git a/ee/app/models/approval_merge_request_rule.rb b/ee/app/models/approval_merge_request_rule.rb index b3d699a0c7d30f..f23ce6be4d392a 100644 --- a/ee/app/models/approval_merge_request_rule.rb +++ b/ee/app/models/approval_merge_request_rule.rb @@ -139,6 +139,11 @@ def applicable_to_branch?(branch) self.approval_project_rule.applies_to_branch?(branch) end + def branches_exempted_by_policy? + approval_policy_rule.present? && + approval_policy_rule.branches_exempted_by_policy?(merge_request.source_branch, merge_request.target_branch) + end + def sync_approved_approvers # Before being merged, approved_approvers are dynamically calculated in # ApprovalWrappedRule instead of being persisted. @@ -237,9 +242,4 @@ def policy_applies_to_target_branch?(branch) approval_policy_rule.policy_applies_to_target_branch?(branch, project.default_branch) end - - def branches_exempted_by_policy? - approval_policy_rule.present? && - approval_policy_rule.branches_exempted_by_policy?(merge_request.source_branch, merge_request.target_branch) - end end diff --git a/ee/app/models/security/policy.rb b/ee/app/models/security/policy.rb index c5b804eaabd56e..fc61c728f94b94 100644 --- a/ee/app/models/security/policy.rb +++ b/ee/app/models/security/policy.rb @@ -19,6 +19,7 @@ class Policy < ApplicationRecord APPROVAL_MERGE_REQUEST_RULES_BATCH_SIZE = 5000 belongs_to :security_orchestration_policy_configuration, class_name: 'Security::OrchestrationPolicyConfiguration' + belongs_to :security_policy_management_project, class_name: 'Project' has_many :approval_policy_rules, class_name: 'Security::ApprovalPolicyRule', foreign_key: 'security_policy_id', inverse_of: :security_policy has_many :scan_execution_policy_rules, class_name: 'Security::ScanExecutionPolicyRule', diff --git a/ee/app/services/ee/merge_requests/base_service.rb b/ee/app/services/ee/merge_requests/base_service.rb index 1b4f1e46c247a0..6147b075d0615b 100644 --- a/ee/app/services/ee/merge_requests/base_service.rb +++ b/ee/app/services/ee/merge_requests/base_service.rb @@ -145,7 +145,7 @@ def audit_security_policy_branch_bypass(merge_request) return if matching_policies.empty? matching_policies.each do |policy| - next unless Feature.enabled?(:approval_policy_branch_exceptions, policy.security_policy_management_project) + next unless ::Feature.enabled?(:approval_policy_branch_exceptions, policy.security_policy_management_project) log_audit_event( merge_request, diff --git a/ee/spec/models/merge_request_spec.rb b/ee/spec/models/merge_request_spec.rb index 596d68a8f7c3eb..47d02b4b6df785 100644 --- a/ee/spec/models/merge_request_spec.rb +++ b/ee/spec/models/merge_request_spec.rb @@ -3468,4 +3468,43 @@ def stub_foss_conditions_met it_behaves_like 'synchronizes policies for a merge request' end + + describe '#security_policies_exempting_branch_bypass_settings' do + let_it_be(:security_policy) do + create(:security_policy, content: { + bypass_settings: { + branches: [ + { source: { name: 'feature' }, target: { name: 'main' } } + ] + } + }) + end + + let_it_be(:approval_policy_rule) do + create(:approval_policy_rule, security_policy: security_policy) + end + + let_it_be(:merge_request) { create(:merge_request, source_branch: 'feature', target_branch: 'main') } + + context 'when merge_request has approval rule with security policy' do + let_it_be(:approval_rule) do + create(:approval_merge_request_rule, merge_request: merge_request, approval_policy_rule: approval_policy_rule) + end + + it 'returns the security policy that exempts the branch' do + expect(merge_request.security_policies_exempting_branch_bypass_settings).to contain_exactly(security_policy) + end + + it 'returns empty if no rules exempt the branch' do + merge_request.update!(source_branch: 'other', target_branch: 'main') + expect(merge_request.security_policies_exempting_branch_bypass_settings).to be_empty + end + end + + context 'when merge_request does not have approval rule with security policy' do + it 'returns empty' do + expect(merge_request.security_policies_exempting_branch_bypass_settings).to be_empty + end + end + end end diff --git a/ee/spec/services/ee/merge_requests/after_create_service_spec.rb b/ee/spec/services/ee/merge_requests/after_create_service_spec.rb index c25ce4c9a2aa89..8afa93b8960a5f 100644 --- a/ee/spec/services/ee/merge_requests/after_create_service_spec.rb +++ b/ee/spec/services/ee/merge_requests/after_create_service_spec.rb @@ -36,6 +36,8 @@ it_behaves_like 'synchronizes policies for a merge request' end + it_behaves_like 'audits security policy branch bypass' + describe 'suggested reviewers' do before do allow(MergeRequests::FetchSuggestedReviewersWorker).to receive(:perform_async) diff --git a/ee/spec/services/ee/merge_requests/reopen_service_spec.rb b/ee/spec/services/ee/merge_requests/reopen_service_spec.rb index 5f48ea38365d33..0e18986d6f5c5e 100644 --- a/ee/spec/services/ee/merge_requests/reopen_service_spec.rb +++ b/ee/spec/services/ee/merge_requests/reopen_service_spec.rb @@ -65,6 +65,10 @@ end end + it_behaves_like 'audits security policy branch bypass' do + let(:execute) { merge_request_reopen_service } + end + describe '#resync_policies' do let(:feature_licensed) { true } let_it_be(:scan_result_policy_read) { create(:scan_result_policy_read, project: project) } diff --git a/ee/spec/services/ee/merge_requests/update_service_spec.rb b/ee/spec/services/ee/merge_requests/update_service_spec.rb index d90970e5c537d2..ac99363b0b5995 100644 --- a/ee/spec/services/ee/merge_requests/update_service_spec.rb +++ b/ee/spec/services/ee/merge_requests/update_service_spec.rb @@ -286,6 +286,14 @@ def update_merge_request(opts) it_behaves_like 'reset all approvals' end + + it_behaves_like 'audits security policy branch bypass' do + before do + merge_request.update!(target_branch: 'master') + end + + let(:execute) { update_merge_request(target_branch: 'main') } + end end context 'updating blocking merge requests' do diff --git a/ee/spec/support/shared_examples/services/merge_requests/audit_security_policy_branch_bypass_shared_examples.rb b/ee/spec/support/shared_examples/services/merge_requests/audit_security_policy_branch_bypass_shared_examples.rb new file mode 100644 index 00000000000000..249f7e2f68f768 --- /dev/null +++ b/ee/spec/support/shared_examples/services/merge_requests/audit_security_policy_branch_bypass_shared_examples.rb @@ -0,0 +1,54 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.shared_examples 'audits security policy branch bypass' do + let_it_be(:security_policy) do + create(:security_policy, content: { + bypass_settings: { + branches: [ + { source: { name: 'feature' }, target: { name: 'main' } } + ] + } + }) + end + + let_it_be(:approval_policy_rule) do + create(:approval_policy_rule, security_policy: security_policy) + end + + let_it_be(:merge_request) { create(:merge_request, source_branch: 'feature', target_branch: 'main') } + + context 'when security policy with branch bypass is present' do + let_it_be(:approval_rule) do + create(:approval_merge_request_rule, merge_request: merge_request, approval_policy_rule: approval_policy_rule) + end + + it 'creates an audit event' do + expect { execute } + .to change { AuditEvent.count }.by(1) + + event = AuditEvent.last + expect(event.details[:custom_message]).to include('Approvals bypassed by security policy') + expect(event.entity).to eq(merge_request.target_project) + end + + context 'when approval_policy_branch_exceptions is disabled' do + before do + stub_feature_flags(approval_policy_branch_exceptions: false) + end + + it 'does not create an audit event' do + expect { execute } + .not_to change { AuditEvent.count } + end + end + end + + context 'when security policy does not exist with branch bypass' do + it 'does not create an audit event' do + expect { execute } + .not_to change { AuditEvent.count } + end + end +end -- GitLab From 0fda2eeda8630a4c330c079ff4dd7882543400cf Mon Sep 17 00:00:00 2001 From: Sashi Kumar Kumaresan Date: Fri, 27 Jun 2025 22:39:55 +0200 Subject: [PATCH 4/8] Address AI bot review comments --- ee/app/models/ee/merge_request.rb | 3 ++- ee/app/services/ee/merge_requests/base_service.rb | 2 +- ee/spec/models/merge_request_spec.rb | 8 ++++---- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/ee/app/models/ee/merge_request.rb b/ee/app/models/ee/merge_request.rb index 28dcd26e89ebd6..1c92e8b9c17b71 100644 --- a/ee/app/models/ee/merge_request.rb +++ b/ee/app/models/ee/merge_request.rb @@ -485,7 +485,7 @@ def schedule_policy_synchronization end end - def security_policies_exempting_branch_bypass_settings + def security_policies_with_branch_exceptions approval_rules .includes(approval_policy_rule: :security_policy) .select(&:branches_exempted_by_policy?) @@ -493,6 +493,7 @@ def security_policies_exempting_branch_bypass_settings .map(&:security_policy) .uniq end + strong_memoize_attr :security_policies_with_branch_exceptions # TODO: Will be removed with https://gitlab.com/gitlab-org/gitlab/-/issues/504296 def sync_project_approval_rules_for_policy_configuration(configuration_id) diff --git a/ee/app/services/ee/merge_requests/base_service.rb b/ee/app/services/ee/merge_requests/base_service.rb index 6147b075d0615b..a26607257c8042 100644 --- a/ee/app/services/ee/merge_requests/base_service.rb +++ b/ee/app/services/ee/merge_requests/base_service.rb @@ -140,7 +140,7 @@ def capture_suggested_reviewers_accepted(merge_request) end def audit_security_policy_branch_bypass(merge_request) - matching_policies = merge_request.security_policies_exempting_branch_bypass_settings + matching_policies = merge_request.security_policies_with_branch_exceptions return if matching_policies.empty? diff --git a/ee/spec/models/merge_request_spec.rb b/ee/spec/models/merge_request_spec.rb index 47d02b4b6df785..afa41d8fe2ad44 100644 --- a/ee/spec/models/merge_request_spec.rb +++ b/ee/spec/models/merge_request_spec.rb @@ -3469,7 +3469,7 @@ def stub_foss_conditions_met it_behaves_like 'synchronizes policies for a merge request' end - describe '#security_policies_exempting_branch_bypass_settings' do + describe '#security_policies_with_branch_exceptions' do let_it_be(:security_policy) do create(:security_policy, content: { bypass_settings: { @@ -3492,18 +3492,18 @@ def stub_foss_conditions_met end it 'returns the security policy that exempts the branch' do - expect(merge_request.security_policies_exempting_branch_bypass_settings).to contain_exactly(security_policy) + expect(merge_request.security_policies_with_branch_exceptions).to contain_exactly(security_policy) end it 'returns empty if no rules exempt the branch' do merge_request.update!(source_branch: 'other', target_branch: 'main') - expect(merge_request.security_policies_exempting_branch_bypass_settings).to be_empty + expect(merge_request.security_policies_with_branch_exceptions).to be_empty end end context 'when merge_request does not have approval rule with security policy' do it 'returns empty' do - expect(merge_request.security_policies_exempting_branch_bypass_settings).to be_empty + expect(merge_request.security_policies_with_branch_exceptions).to be_empty end end end -- GitLab From fecae835f2aeafd0b712f1a83037697e662db42a Mon Sep 17 00:00:00 2001 From: Sashi Kumar Kumaresan Date: Fri, 27 Jun 2025 23:07:58 +0200 Subject: [PATCH 5/8] Update introduced_by_mr in audit event definition --- .../audit_events/types/merge_request_merged_by_project_bot.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ee/config/audit_events/types/merge_request_merged_by_project_bot.yml b/ee/config/audit_events/types/merge_request_merged_by_project_bot.yml index 5fc5146ba352c5..cdfcfd975adf6a 100644 --- a/ee/config/audit_events/types/merge_request_merged_by_project_bot.yml +++ b/ee/config/audit_events/types/merge_request_merged_by_project_bot.yml @@ -2,7 +2,7 @@ name: merge_request_merged_by_project_bot description: A merge request is merged using a project access token introduced_by_issue: https://gitlab.com/gitlab-org/gitlab/-/issues/323299 -introduced_by_mr: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/120927 +introduced_by_mr: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/195942 feature_category: code_review_workflow milestone: '16.1' saved_to_database: true -- GitLab From 71a6925604f02ad3c2266df8a7792ba70384b3e4 Mon Sep 17 00:00:00 2001 From: Sashi Kumar Kumaresan Date: Fri, 27 Jun 2025 23:10:40 +0200 Subject: [PATCH 6/8] Update audit event docs --- doc/user/compliance/audit_event_types.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/user/compliance/audit_event_types.md b/doc/user/compliance/audit_event_types.md index 95b18ff8f2ddae..3e9404e9c8442b 100644 --- a/doc/user/compliance/audit_event_types.md +++ b/doc/user/compliance/audit_event_types.md @@ -128,7 +128,7 @@ Audit event types belong to the following product categories. | [`merge_request_closed_by_project_bot`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/120927) | A merge request is closed using a project access token | {{< icon name="check-circle" >}} Yes | GitLab [16.1](https://gitlab.com/gitlab-org/gitlab/-/issues/323299) | Project | | [`merge_request_created_by_project_bot`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/120927) | A merge request is created using a project access token | {{< icon name="check-circle" >}} Yes | GitLab [16.1](https://gitlab.com/gitlab-org/gitlab/-/issues/323299) | Project | | [`merge_request_invalid_approver_rules`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/100496) | An invalid rule when merge request is approved | {{< icon name="check-circle" >}} Yes | GitLab [15.5](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/100496) | Project | -| [`merge_request_merged_by_project_bot`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/120927) | A merge request is merged using a project access token | {{< icon name="check-circle" >}} Yes | GitLab [16.1](https://gitlab.com/gitlab-org/gitlab/-/issues/323299) | Project | +| [`merge_request_merged_by_project_bot`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/195942) | A merge request is merged using a project access token | {{< icon name="check-circle" >}} Yes | GitLab [16.1](https://gitlab.com/gitlab-org/gitlab/-/issues/323299) | Project | | [`merge_request_reopened_by_project_bot`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/120927) | A merge request is reopened using a project access token | {{< icon name="check-circle" >}} Yes | GitLab [16.1](https://gitlab.com/gitlab-org/gitlab/-/issues/323299) | Project | | [`project_merge_method_updated`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/83922) | A project's merge request method is updated | {{< icon name="check-circle" >}} Yes | GitLab [14.10](https://gitlab.com/gitlab-org/gitlab/-/issues/301124) | Project | | [`project_merge_requests_author_approval_updated`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/106652) | A project's MR author approval setting is updated | {{< icon name="check-circle" >}} Yes | GitLab [15.7](https://gitlab.com/gitlab-org/gitlab/-/issues/369288) | Project | -- GitLab From 05f2eb9e910108b82413247065a87024239f6415 Mon Sep 17 00:00:00 2001 From: Sashi Kumar Kumaresan Date: Mon, 30 Jun 2025 11:04:09 +0200 Subject: [PATCH 7/8] Fix failing spec and update definition --- .../merge_request_branch_bypassed_by_security_policy.yml | 2 +- doc/user/compliance/audit_event_types.md | 4 ++-- .../types/merge_request_merged_by_project_bot.yml | 2 +- ee/spec/models/merge_request_spec.rb | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/config/audit_events/types/merge_request_branch_bypassed_by_security_policy.yml b/config/audit_events/types/merge_request_branch_bypassed_by_security_policy.yml index 957c34cdc5eeec..df611a29d8395c 100644 --- a/config/audit_events/types/merge_request_branch_bypassed_by_security_policy.yml +++ b/config/audit_events/types/merge_request_branch_bypassed_by_security_policy.yml @@ -3,7 +3,7 @@ name: merge_request_branch_bypassed_by_security_policy description: The merge request's approval is bypassed by the branches configured in the security policy introduced_by_issue: https://gitlab.com/gitlab-org/gitlab/-/issues/549646 -introduced_by_mr: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/194709 +introduced_by_mr: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/195942 feature_category: security_policy_management milestone: '18.2' saved_to_database: true diff --git a/doc/user/compliance/audit_event_types.md b/doc/user/compliance/audit_event_types.md index 3e9404e9c8442b..97e1271bda2778 100644 --- a/doc/user/compliance/audit_event_types.md +++ b/doc/user/compliance/audit_event_types.md @@ -128,7 +128,7 @@ Audit event types belong to the following product categories. | [`merge_request_closed_by_project_bot`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/120927) | A merge request is closed using a project access token | {{< icon name="check-circle" >}} Yes | GitLab [16.1](https://gitlab.com/gitlab-org/gitlab/-/issues/323299) | Project | | [`merge_request_created_by_project_bot`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/120927) | A merge request is created using a project access token | {{< icon name="check-circle" >}} Yes | GitLab [16.1](https://gitlab.com/gitlab-org/gitlab/-/issues/323299) | Project | | [`merge_request_invalid_approver_rules`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/100496) | An invalid rule when merge request is approved | {{< icon name="check-circle" >}} Yes | GitLab [15.5](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/100496) | Project | -| [`merge_request_merged_by_project_bot`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/195942) | A merge request is merged using a project access token | {{< icon name="check-circle" >}} Yes | GitLab [16.1](https://gitlab.com/gitlab-org/gitlab/-/issues/323299) | Project | +| [`merge_request_merged_by_project_bot`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/120927) | A merge request is merged using a project access token | {{< icon name="check-circle" >}} Yes | GitLab [16.1](https://gitlab.com/gitlab-org/gitlab/-/issues/323299) | Project | | [`merge_request_reopened_by_project_bot`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/120927) | A merge request is reopened using a project access token | {{< icon name="check-circle" >}} Yes | GitLab [16.1](https://gitlab.com/gitlab-org/gitlab/-/issues/323299) | Project | | [`project_merge_method_updated`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/83922) | A project's merge request method is updated | {{< icon name="check-circle" >}} Yes | GitLab [14.10](https://gitlab.com/gitlab-org/gitlab/-/issues/301124) | Project | | [`project_merge_requests_author_approval_updated`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/106652) | A project's MR author approval setting is updated | {{< icon name="check-circle" >}} Yes | GitLab [15.7](https://gitlab.com/gitlab-org/gitlab/-/issues/369288) | Project | @@ -537,7 +537,7 @@ Audit event types belong to the following product categories. | [`security_policy_create`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/192797) | A security policy is created | {{< icon name="check-circle" >}} Yes | GitLab [18.1](https://gitlab.com/gitlab-org/gitlab/-/issues/539230) | Project | | [`security_policy_delete`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/192797) | A security policy is deleted | {{< icon name="check-circle" >}} Yes | GitLab [18.1](https://gitlab.com/gitlab-org/gitlab/-/issues/539230) | Project | | [`security_policy_update`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/192797) | A security policy is updated | {{< icon name="check-circle" >}} Yes | GitLab [18.1](https://gitlab.com/gitlab-org/gitlab/-/issues/539230) | Project | -| [`merge_request_branch_bypassed_by_security_policy`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/194709) | The merge request's approval is bypassed by the branches configured in the security policy | {{< icon name="check-circle" >}} Yes | GitLab [18.2](https://gitlab.com/gitlab-org/gitlab/-/issues/549646) | Project | +| [`merge_request_branch_bypassed_by_security_policy`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/195942) | The merge request's approval is bypassed by the branches configured in the security policy | {{< icon name="check-circle" >}} Yes | GitLab [18.2](https://gitlab.com/gitlab-org/gitlab/-/issues/549646) | Project | | [`policy_violations_detected`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/193482) | Security policy violation is detected in the merge request | {{< icon name="dotted-circle" >}} No | GitLab [18.2](https://gitlab.com/gitlab-org/gitlab/-/work_items/549811) | Project | | [`policy_violations_resolved`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/193482) | Security policy violations are resolved in the merge request | {{< icon name="dotted-circle" >}} No | GitLab [18.2](https://gitlab.com/gitlab-org/gitlab/-/issues/549812) | Project | diff --git a/ee/config/audit_events/types/merge_request_merged_by_project_bot.yml b/ee/config/audit_events/types/merge_request_merged_by_project_bot.yml index cdfcfd975adf6a..5fc5146ba352c5 100644 --- a/ee/config/audit_events/types/merge_request_merged_by_project_bot.yml +++ b/ee/config/audit_events/types/merge_request_merged_by_project_bot.yml @@ -2,7 +2,7 @@ name: merge_request_merged_by_project_bot description: A merge request is merged using a project access token introduced_by_issue: https://gitlab.com/gitlab-org/gitlab/-/issues/323299 -introduced_by_mr: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/195942 +introduced_by_mr: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/120927 feature_category: code_review_workflow milestone: '16.1' saved_to_database: true diff --git a/ee/spec/models/merge_request_spec.rb b/ee/spec/models/merge_request_spec.rb index afa41d8fe2ad44..193d0ede28e039 100644 --- a/ee/spec/models/merge_request_spec.rb +++ b/ee/spec/models/merge_request_spec.rb @@ -3484,7 +3484,7 @@ def stub_foss_conditions_met create(:approval_policy_rule, security_policy: security_policy) end - let_it_be(:merge_request) { create(:merge_request, source_branch: 'feature', target_branch: 'main') } + let_it_be_with_refind(:merge_request) { create(:merge_request, source_branch: 'feature', target_branch: 'main') } context 'when merge_request has approval rule with security policy' do let_it_be(:approval_rule) do -- GitLab From ae3150b9ca4c2a4a0eada438778862c7015b23a9 Mon Sep 17 00:00:00 2001 From: Sashi Kumar Kumaresan Date: Mon, 30 Jun 2025 13:07:30 +0200 Subject: [PATCH 8/8] Fix failing spec --- ...ty_policy_branch_bypass_shared_examples.rb | 37 +++++++++---------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/ee/spec/support/shared_examples/services/merge_requests/audit_security_policy_branch_bypass_shared_examples.rb b/ee/spec/support/shared_examples/services/merge_requests/audit_security_policy_branch_bypass_shared_examples.rb index 249f7e2f68f768..abd89fcf75d0ea 100644 --- a/ee/spec/support/shared_examples/services/merge_requests/audit_security_policy_branch_bypass_shared_examples.rb +++ b/ee/spec/support/shared_examples/services/merge_requests/audit_security_policy_branch_bypass_shared_examples.rb @@ -3,30 +3,31 @@ require 'spec_helper' RSpec.shared_examples 'audits security policy branch bypass' do - let_it_be(:security_policy) do - create(:security_policy, content: { - bypass_settings: { - branches: [ - { source: { name: 'feature' }, target: { name: 'main' } } - ] - } - }) + let_it_be_with_refind(:merge_request) do + create(:merge_request, source_branch: 'feature', target_branch: 'main') end - let_it_be(:approval_policy_rule) do - create(:approval_policy_rule, security_policy: security_policy) - end + context 'when security policy with branch bypass is present' do + let_it_be(:security_policy) do + create(:security_policy, content: { + bypass_settings: { + branches: [ + { source: { name: 'feature' }, target: { name: 'main' } } + ] + } + }) + end - let_it_be(:merge_request) { create(:merge_request, source_branch: 'feature', target_branch: 'main') } + let_it_be(:approval_policy_rule) do + create(:approval_policy_rule, security_policy: security_policy) + end - context 'when security policy with branch bypass is present' do let_it_be(:approval_rule) do create(:approval_merge_request_rule, merge_request: merge_request, approval_policy_rule: approval_policy_rule) end it 'creates an audit event' do - expect { execute } - .to change { AuditEvent.count }.by(1) + expect { execute }.to change { AuditEvent.count }.by(1) event = AuditEvent.last expect(event.details[:custom_message]).to include('Approvals bypassed by security policy') @@ -39,16 +40,14 @@ end it 'does not create an audit event' do - expect { execute } - .not_to change { AuditEvent.count } + expect { execute }.not_to change { AuditEvent.count } end end end context 'when security policy does not exist with branch bypass' do it 'does not create an audit event' do - expect { execute } - .not_to change { AuditEvent.count } + expect { execute }.not_to change { AuditEvent.count } end end end -- GitLab