From 3149ebdef7cc95786189f9440c39c9b7136e5066 Mon Sep 17 00:00:00 2001 From: Imam Hossain Date: Fri, 4 Jul 2025 18:04:47 +0200 Subject: [PATCH 1/3] Audit invalid policy YAML in security policy project Adds audit event for invalid policy YAML in security policy project. This helps track when policies are invalidated. --- .../types/policy_yaml_invalidated.yml | 10 +++ doc/user/compliance/audit_event_types.md | 1 + ...cy_yaml_invalidated_audit_event_service.rb | 47 +++++++++++ ...date_orchestration_policy_configuration.rb | 13 +++ ...ct_policy_yaml_invalidated_audit_event.yml | 10 +++ ...ml_invalidated_audit_event_service_spec.rb | 81 +++++++++++++++++++ ...orchestration_policy_configuration_spec.rb | 50 ++++++++++++ 7 files changed, 212 insertions(+) create mode 100644 config/audit_events/types/policy_yaml_invalidated.yml create mode 100644 ee/app/services/security/security_orchestration_policies/collect_policy_yaml_invalidated_audit_event_service.rb create mode 100644 ee/config/feature_flags/gitlab_com_derisk/collect_policy_yaml_invalidated_audit_event.yml create mode 100644 ee/spec/services/security/security_orchestration_policies/collect_policy_yaml_invalidated_audit_event_service_spec.rb diff --git a/config/audit_events/types/policy_yaml_invalidated.yml b/config/audit_events/types/policy_yaml_invalidated.yml new file mode 100644 index 00000000000000..33f98b2541911e --- /dev/null +++ b/config/audit_events/types/policy_yaml_invalidated.yml @@ -0,0 +1,10 @@ +--- +name: policy_yaml_invalidated +description: The policy YAML is invalidated in security policy project +introduced_by_issue: https://gitlab.com/gitlab-org/gitlab/-/work_items/550892 +introduced_by_mr: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/196713 +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 9bec0fcd36d6a0..d6be6fe7653e4c 100644 --- a/doc/user/compliance/audit_event_types.md +++ b/doc/user/compliance/audit_event_types.md @@ -542,6 +542,7 @@ Audit event types belong to the following product categories. | [`merge_request_merged_with_policy_violations`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/195775) | A merge request merged with security policy violations | {{< icon name="check-circle" >}} Yes | GitLab [18.2](https://gitlab.com/gitlab-org/gitlab/-/work_items/549813) | 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 | +| [`policy_yaml_invalidated`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/196713) | The policy YAML is invalidated in security policy project | {{< icon name="check-circle" >}} Yes | GitLab [18.2](https://gitlab.com/gitlab-org/gitlab/-/work_items/550892) | Project | ### Security testing configuration diff --git a/ee/app/services/security/security_orchestration_policies/collect_policy_yaml_invalidated_audit_event_service.rb b/ee/app/services/security/security_orchestration_policies/collect_policy_yaml_invalidated_audit_event_service.rb new file mode 100644 index 00000000000000..4ca48f2d1e2adb --- /dev/null +++ b/ee/app/services/security/security_orchestration_policies/collect_policy_yaml_invalidated_audit_event_service.rb @@ -0,0 +1,47 @@ +# frozen_string_literal: true + +module Security + module SecurityOrchestrationPolicies + class CollectPolicyYamlInvalidatedAuditEventService + include Gitlab::Utils::StrongMemoize + + def initialize(policy_configuration) + @policy_configuration = policy_configuration + end + + def execute + return if policy_configuration.policy_configuration_valid? + + ::Gitlab::Audit::Auditor.audit(audit_context) + end + + private + + attr_reader :policy_configuration + + def audit_context + { + name: 'policy_yaml_invalidated', + author: commit&.author || Gitlab::Audit::DeletedAuthor.new(id: -4, name: 'Unknown User'), + scope: policy_management_project, + target: policy_management_project, + message: 'The policy YAML has been invalidated in the security policy project. ' \ + 'Security policies will no longer be enforced.', + additional_details: { + security_policy_project_commit_sha: commit&.sha, + security_orchestration_policy_configuration_id: policy_configuration.id + } + } + end + + def commit + policy_configuration.latest_commit_before_configured_at + end + + def policy_management_project + policy_configuration.security_policy_management_project + end + strong_memoize_attr :policy_management_project + end + end +end diff --git a/ee/app/workers/concerns/update_orchestration_policy_configuration.rb b/ee/app/workers/concerns/update_orchestration_policy_configuration.rb index a5ede2c8d1c07a..7042ee12528962 100644 --- a/ee/app/workers/concerns/update_orchestration_policy_configuration.rb +++ b/ee/app/workers/concerns/update_orchestration_policy_configuration.rb @@ -9,6 +9,7 @@ def update_policy_configuration(configuration, force_resync = false) Security::ScanResultPolicies::DeleteScanResultPolicyReadsWorker.perform_async(configuration.id) update_configuration_timestamp!(configuration) + audit_invalid_policy_yaml(configuration) return end @@ -39,6 +40,18 @@ def update_experiments_configuration!(configuration) ).execute end + def audit_invalid_policy_yaml(configuration) + return if Feature.disabled?(:collect_policy_yaml_invalidated_audit_event, + configuration.security_policy_management_project) + + Security::SecurityOrchestrationPolicies::CollectPolicyYamlInvalidatedAuditEventService.new(configuration).execute + rescue StandardError => e + Gitlab::ErrorTracking.track_exception(e, + security_policy_management_project_id: configuration.security_policy_management_project.id, + configuration_id: configuration.id + ) + end + def update_configuration_timestamp!(configuration) configuration.update!(configured_at: Time.current) end diff --git a/ee/config/feature_flags/gitlab_com_derisk/collect_policy_yaml_invalidated_audit_event.yml b/ee/config/feature_flags/gitlab_com_derisk/collect_policy_yaml_invalidated_audit_event.yml new file mode 100644 index 00000000000000..e6dd681efef68e --- /dev/null +++ b/ee/config/feature_flags/gitlab_com_derisk/collect_policy_yaml_invalidated_audit_event.yml @@ -0,0 +1,10 @@ +--- +name: collect_policy_yaml_invalidated_audit_event +description: +feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/work_items/550892 +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/196713 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/553626 +milestone: '18.2' +group: group::security policies +type: gitlab_com_derisk +default_enabled: false diff --git a/ee/spec/services/security/security_orchestration_policies/collect_policy_yaml_invalidated_audit_event_service_spec.rb b/ee/spec/services/security/security_orchestration_policies/collect_policy_yaml_invalidated_audit_event_service_spec.rb new file mode 100644 index 00000000000000..e277c6111bc85a --- /dev/null +++ b/ee/spec/services/security/security_orchestration_policies/collect_policy_yaml_invalidated_audit_event_service_spec.rb @@ -0,0 +1,81 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Security::SecurityOrchestrationPolicies::CollectPolicyYamlInvalidatedAuditEventService, feature_category: :security_policy_management do + let_it_be(:project) { create(:project) } + let_it_be(:user) { create(:user) } + let_it_be(:policy_configuration) do + create(:security_orchestration_policy_configuration, security_policy_management_project: project) + end + + subject(:service) { described_class.new(policy_configuration) } + + describe '#execute' do + before do + allow(Gitlab::Audit::Auditor).to receive(:audit).and_call_original + end + + context 'when policy configuration is valid' do + before do + allow(policy_configuration).to receive(:policy_configuration_valid?).and_return(true) + end + + it 'does not create an audit event' do + expect(::Gitlab::Audit::Auditor).not_to receive(:audit) + + service.execute + end + end + + context 'when policy configuration is invalid' do + before do + allow(policy_configuration).to receive_messages( + policy_configuration_valid?: false, + latest_commit_before_configured_at: commit + ) + end + + context 'when commit is present' do + let(:commit) { build(:commit, project: project, author: user) } + + let(:audit_context) do + { + name: 'policy_yaml_invalidated', + author: user, + scope: project, + target: project, + message: 'The policy YAML has been invalidated in the security policy project. ' \ + 'Security policies will no longer be enforced.', + additional_details: { + security_policy_project_commit_sha: commit&.sha, + security_orchestration_policy_configuration_id: policy_configuration.id + } + } + end + + it 'creates an audit event with the correct attributes' do + expect(::Gitlab::Audit::Auditor).to receive(:audit).with(audit_context) + + service.execute + end + end + + context 'when commit is not present' do + let(:commit) { nil } + + it 'creates an audit event with an unknown author' do + expect(::Gitlab::Audit::Auditor).to receive(:audit).with( + hash_including( + name: 'policy_yaml_invalidated', + author: a_kind_of(::Gitlab::Audit::DeletedAuthor), + additional_details: hash_including(security_policy_project_commit_sha: be_nil) + ) + ) + + service.execute + end + end + end + end +end diff --git a/ee/spec/workers/concerns/update_orchestration_policy_configuration_spec.rb b/ee/spec/workers/concerns/update_orchestration_policy_configuration_spec.rb index b1445dfd5d464f..8f0dfb6bfb9730 100644 --- a/ee/spec/workers/concerns/update_orchestration_policy_configuration_spec.rb +++ b/ee/spec/workers/concerns/update_orchestration_policy_configuration_spec.rb @@ -251,6 +251,56 @@ def self.name expect(configuration.reload.configured_at).to be_like_time(Time.current) end + describe 'auditing invalid policy yaml' do + let(:audit_service) do + Security::SecurityOrchestrationPolicies::CollectPolicyYamlInvalidatedAuditEventService.new( + configuration + ) + end + + before do + allow(Security::SecurityOrchestrationPolicies::CollectPolicyYamlInvalidatedAuditEventService) + .to receive(:new).with(configuration).and_return(audit_service) + end + + it 'audits the invalid policy yaml' do + expect(audit_service).to receive(:execute) + + execute + end + + context 'when there is an error' do + before do + allow(audit_service).to receive(:execute).and_raise(StandardError) + allow(Gitlab::ErrorTracking).to receive(:track_exception).and_call_original + end + + it 'logs an error and proceeds' do + expect(Gitlab::ErrorTracking).to receive(:track_exception).with( + an_instance_of(StandardError), + security_policy_management_project_id: configuration.security_policy_management_project.id, + configuration_id: configuration.id + ) + + execute + end + end + + context 'when the collect policy yaml invalidated audit event feature is disabled' do + before do + stub_feature_flags(collect_policy_yaml_invalidated_audit_event: false) + end + + it 'does not audit the invalid policy yaml' do + expect( + Security::SecurityOrchestrationPolicies::CollectPolicyYamlInvalidatedAuditEventService + ).not_to receive(:new) + + execute + end + end + end + context 'with existing policy reads' do let_it_be(:policy_read) do create(:scan_result_policy_read, security_orchestration_policy_configuration: configuration) -- GitLab From f2c4393e3188ebecb2f6cbefc51ee7d790d4fb85 Mon Sep 17 00:00:00 2001 From: Imam Hossain Date: Fri, 4 Jul 2025 18:08:57 +0200 Subject: [PATCH 2/3] Update rspec example --- .../update_orchestration_policy_configuration_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ee/spec/workers/concerns/update_orchestration_policy_configuration_spec.rb b/ee/spec/workers/concerns/update_orchestration_policy_configuration_spec.rb index 8f0dfb6bfb9730..f4f329abbb0682 100644 --- a/ee/spec/workers/concerns/update_orchestration_policy_configuration_spec.rb +++ b/ee/spec/workers/concerns/update_orchestration_policy_configuration_spec.rb @@ -275,14 +275,14 @@ def self.name allow(Gitlab::ErrorTracking).to receive(:track_exception).and_call_original end - it 'logs an error and proceeds' do + it 'tracks the error error and proceeds' do expect(Gitlab::ErrorTracking).to receive(:track_exception).with( an_instance_of(StandardError), security_policy_management_project_id: configuration.security_policy_management_project.id, configuration_id: configuration.id ) - execute + expect { execute }.not_to raise_error end end -- GitLab From 1cd659bf40a4006dccfd6eb6438a6c88166ccd45 Mon Sep 17 00:00:00 2001 From: Imam Hossain Date: Mon, 7 Jul 2025 15:08:08 +0200 Subject: [PATCH 3/3] Address review comments --- config/audit_events/types/policy_yaml_invalidated.yml | 2 +- doc/user/compliance/audit_event_types.md | 2 +- .../collect_policy_yaml_invalidated_audit_event.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/config/audit_events/types/policy_yaml_invalidated.yml b/config/audit_events/types/policy_yaml_invalidated.yml index 33f98b2541911e..f24485549cd2f1 100644 --- a/config/audit_events/types/policy_yaml_invalidated.yml +++ b/config/audit_events/types/policy_yaml_invalidated.yml @@ -2,7 +2,7 @@ name: policy_yaml_invalidated description: The policy YAML is invalidated in security policy project introduced_by_issue: https://gitlab.com/gitlab-org/gitlab/-/work_items/550892 -introduced_by_mr: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/196713 +introduced_by_mr: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/196721 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 d6be6fe7653e4c..78db3be8cffe18 100644 --- a/doc/user/compliance/audit_event_types.md +++ b/doc/user/compliance/audit_event_types.md @@ -542,7 +542,7 @@ Audit event types belong to the following product categories. | [`merge_request_merged_with_policy_violations`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/195775) | A merge request merged with security policy violations | {{< icon name="check-circle" >}} Yes | GitLab [18.2](https://gitlab.com/gitlab-org/gitlab/-/work_items/549813) | 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 | -| [`policy_yaml_invalidated`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/196713) | The policy YAML is invalidated in security policy project | {{< icon name="check-circle" >}} Yes | GitLab [18.2](https://gitlab.com/gitlab-org/gitlab/-/work_items/550892) | Project | +| [`policy_yaml_invalidated`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/196721) | The policy YAML is invalidated in security policy project | {{< icon name="check-circle" >}} Yes | GitLab [18.2](https://gitlab.com/gitlab-org/gitlab/-/work_items/550892) | Project | ### Security testing configuration diff --git a/ee/config/feature_flags/gitlab_com_derisk/collect_policy_yaml_invalidated_audit_event.yml b/ee/config/feature_flags/gitlab_com_derisk/collect_policy_yaml_invalidated_audit_event.yml index e6dd681efef68e..67d4d6502ad6d5 100644 --- a/ee/config/feature_flags/gitlab_com_derisk/collect_policy_yaml_invalidated_audit_event.yml +++ b/ee/config/feature_flags/gitlab_com_derisk/collect_policy_yaml_invalidated_audit_event.yml @@ -2,7 +2,7 @@ name: collect_policy_yaml_invalidated_audit_event description: feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/work_items/550892 -introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/196713 +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/196721 rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/553626 milestone: '18.2' group: group::security policies -- GitLab