diff --git a/app/services/groups/ssh_certificates/create_service.rb b/app/services/groups/ssh_certificates/create_service.rb index 6890901c306d0c25e59a43d2eeb4ad24812e40d8..e45700783959e2fc86c02521e5303c663a6fa49c 100644 --- a/app/services/groups/ssh_certificates/create_service.rb +++ b/app/services/groups/ssh_certificates/create_service.rb @@ -3,9 +3,10 @@ module Groups module SshCertificates class CreateService - def initialize(group, params) + def initialize(group, params, current_user) @group = group @params = params + @current_user = current_user end def execute @@ -41,7 +42,7 @@ def execute private - attr_reader :group, :params + attr_reader :group, :params, :current_user def generate_fingerprint(key) Gitlab::SSHPublicKey.new(key).fingerprint_sha256&.delete_prefix('SHA256:') @@ -49,3 +50,5 @@ def generate_fingerprint(key) end end end + +Groups::SshCertificates::CreateService.prepend_mod_with('Groups::SshCertificates::CreateService') diff --git a/app/services/groups/ssh_certificates/destroy_service.rb b/app/services/groups/ssh_certificates/destroy_service.rb index 7a450d5bee67f72d8d6d4aa59a6ecc603a2258b7..5f7bba12878b35e9b74117a50d31a87ffe36dc12 100644 --- a/app/services/groups/ssh_certificates/destroy_service.rb +++ b/app/services/groups/ssh_certificates/destroy_service.rb @@ -3,16 +3,17 @@ module Groups module SshCertificates class DestroyService - def initialize(group, params) + def initialize(group, params, current_user) @group = group @params = params + @current_user = current_user end def execute ssh_certificate = group.ssh_certificates.find(params[:ssh_certificates_id]) ssh_certificate.destroy! - ServiceResponse.success + ServiceResponse.success(payload: { ssh_certificate: ssh_certificate }) rescue ActiveRecord::RecordNotFound ServiceResponse.error( @@ -29,7 +30,9 @@ def execute private - attr_reader :group, :params + attr_reader :group, :params, :current_user end end end + +Groups::SshCertificates::DestroyService.prepend_mod_with('Groups::SshCertificates::DestroyService') diff --git a/doc/administration/audit_event_streaming/audit_event_types.md b/doc/administration/audit_event_streaming/audit_event_types.md index 2d1249e2b6c5e74e6a076ebbaf6c6d826fb3dec2..6e1436284d051e76b42bccc40d7db51cefd28b57 100644 --- a/doc/administration/audit_event_streaming/audit_event_types.md +++ b/doc/administration/audit_event_streaming/audit_event_types.md @@ -228,6 +228,8 @@ Audit event types belong to the following product categories. | Name | Description | Saved to database | Streamed | Introduced in | |:-----|:------------|:------------------|:---------|:--------------| +| [`create_ssh_certificate`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/134556) | Event triggered when an SSH certificate is created.| **{check-circle}** Yes | **{check-circle}** Yes | GitLab [16.6](https://gitlab.com/gitlab-org/gitlab/-/issues/427413) | +| [`delete_ssh_certificate`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/134556) | Event triggered when an SSH certificate is deleted.| **{check-circle}** Yes | **{check-circle}** Yes | GitLab [16.6](https://gitlab.com/gitlab-org/gitlab/-/issues/427413) | | [`group_created`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/121005) | Event triggered when a group is created.| **{check-circle}** Yes | **{check-circle}** Yes | GitLab [16.3](https://gitlab.com/gitlab-org/gitlab/-/issues/411595) | | [`group_lfs_enabled_updated`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/106079) | Event triggered when a groups lfs enabled is updated.| **{check-circle}** Yes | **{check-circle}** Yes | GitLab [15.7](https://gitlab.com/gitlab-org/gitlab/-/issues/369323) | | [`group_membership_lock_updated`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/106079) | Event triggered when a groups membership lock is updated.| **{check-circle}** Yes | **{check-circle}** Yes | GitLab [15.7](https://gitlab.com/gitlab-org/gitlab/-/issues/369323) | diff --git a/ee/app/services/ee/groups/ssh_certificates/create_service.rb b/ee/app/services/ee/groups/ssh_certificates/create_service.rb new file mode 100644 index 0000000000000000000000000000000000000000..7479708da4c86988eb1c38d36c678ddb8ecd7461 --- /dev/null +++ b/ee/app/services/ee/groups/ssh_certificates/create_service.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +module EE + module Groups + module SshCertificates + module CreateService + extend ::Gitlab::Utils::Override + + override :execute + def execute + response = super + log_audit_event(response.payload) if response.success? + response + end + + private + + def log_audit_event(ssh_certificate) + audit_context = { + name: "create_ssh_certificate", + author: current_user, + scope: group, + target: ssh_certificate, + target_details: ssh_certificate.title, + message: "Created SSH certificate with id #{ssh_certificate.id} and title #{ssh_certificate.title}" + } + + ::Gitlab::Audit::Auditor.audit(audit_context) + end + end + end + end +end diff --git a/ee/app/services/ee/groups/ssh_certificates/destroy_service.rb b/ee/app/services/ee/groups/ssh_certificates/destroy_service.rb new file mode 100644 index 0000000000000000000000000000000000000000..87ce3b9fd5a91f96ce61c9e8493b9ea2b0cb764e --- /dev/null +++ b/ee/app/services/ee/groups/ssh_certificates/destroy_service.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +module EE + module Groups + module SshCertificates + module DestroyService + extend ::Gitlab::Utils::Override + + override :execute + def execute + response = super + log_audit_event(response.payload[:ssh_certificate]) if response.success? + response + end + + private + + def log_audit_event(ssh_certificate) + audit_context = { + name: "delete_ssh_certificate", + author: current_user, + scope: group, + target: ssh_certificate, + target_details: ssh_certificate.title, + message: "Deleted SSH certificate with id #{ssh_certificate.id} and title #{ssh_certificate.title}" + } + + ::Gitlab::Audit::Auditor.audit(audit_context) + end + end + end + end +end diff --git a/ee/config/audit_events/types/create_ssh_certificate.yml b/ee/config/audit_events/types/create_ssh_certificate.yml new file mode 100644 index 0000000000000000000000000000000000000000..8dcc89dcda94d8ce0b329f73274e6d583847ec91 --- /dev/null +++ b/ee/config/audit_events/types/create_ssh_certificate.yml @@ -0,0 +1,9 @@ +--- +name: create_ssh_certificate +description: Event triggered when an SSH certificate is created. +introduced_by_issue: https://gitlab.com/gitlab-org/gitlab/-/issues/427413 +introduced_by_mr: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/134556 +feature_category: "groups_and_projects" +milestone: "16.6" +saved_to_database: true +streamed: true diff --git a/ee/config/audit_events/types/delete_ssh_certificate.yml b/ee/config/audit_events/types/delete_ssh_certificate.yml new file mode 100644 index 0000000000000000000000000000000000000000..8213d37cc80cde5b58be9ec036aeaf0a6a1ff00c --- /dev/null +++ b/ee/config/audit_events/types/delete_ssh_certificate.yml @@ -0,0 +1,9 @@ +--- +name: delete_ssh_certificate +description: Event triggered when an SSH certificate is deleted. +introduced_by_issue: https://gitlab.com/gitlab-org/gitlab/-/issues/427413 +introduced_by_mr: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/134556 +feature_category: "groups_and_projects" +milestone: "16.6" +saved_to_database: true +streamed: true diff --git a/ee/lib/ee/api/groups.rb b/ee/lib/ee/api/groups.rb index f754e3626a45e311c8f1e9b2a0de66cb23453c29..5957cbba083cdfd0b6a342b3b080b4a0a7ccd701 100644 --- a/ee/lib/ee/api/groups.rb +++ b/ee/lib/ee/api/groups.rb @@ -292,7 +292,7 @@ def delete_group(group) check_ssh_certificate_available_to_group(group) - response = ::Groups::SshCertificates::CreateService.new(group, params).execute + response = ::Groups::SshCertificates::CreateService.new(group, params, current_user).execute if response.success? present response.payload, with: EE::API::Entities::SshCertificate else @@ -316,7 +316,7 @@ def delete_group(group) check_ssh_certificate_available_to_group(group) - response = ::Groups::SshCertificates::DestroyService.new(group, params).execute + response = ::Groups::SshCertificates::DestroyService.new(group, params, current_user).execute if response.success? no_content! diff --git a/ee/spec/services/groups/ssh_certificates/create_service_spec.rb b/ee/spec/services/groups/ssh_certificates/create_service_spec.rb index d8fb4272204cdb314b9c5605e2fc547b77f7ef14..0f90a351811a5a692d12e8863ef85c8e929c3662 100644 --- a/ee/spec/services/groups/ssh_certificates/create_service_spec.rb +++ b/ee/spec/services/groups/ssh_certificates/create_service_spec.rb @@ -4,10 +4,11 @@ RSpec.describe Groups::SshCertificates::CreateService, '#execute', feature_category: :groups_and_projects do let_it_be(:group, reload: true) { create(:group) } + let_it_be(:current_user) { create(:user) } let(:title) { 'Title 1' } let(:key) { generate_key } let(:ssh_certificate_params) { { title: title, key: key } } - let(:service) { described_class.new(group, ssh_certificate_params) } + let(:service) { described_class.new(group, ssh_certificate_params, current_user) } context 'when group and params are provided' do it 'succeeds' do @@ -49,6 +50,31 @@ end end + context 'when creating an SSH certificate' do + it_behaves_like 'audit event logging' do + let(:operation) { service.execute } + let(:attributes) do + { + author_id: current_user.id, + entity_id: group.id, + entity_type: 'Group', + details: { + author_class: 'User', + author_name: current_user.name, + custom_message: "Created SSH certificate with id #{group.ssh_certificates.first.id} and title #{title}", + target_details: group.ssh_certificates.first.title, + target_id: group.ssh_certificates.first.id, + target_type: 'Groups::SshCertificate' + } + } + end + + def fail_condition! + allow(group.ssh_certificates).to receive(:create!).and_raise(ActiveRecord::RecordInvalid) + end + end + end + def generate_key SSHData::PrivateKey::RSA.generate( ::Gitlab::SSHPublicKey.supported_sizes(:rsa).min, unsafe_allow_small_key: true diff --git a/ee/spec/services/groups/ssh_certificates/destroy_service_spec.rb b/ee/spec/services/groups/ssh_certificates/destroy_service_spec.rb index af06b135ce70bb5377cdaba1d6ede581d661714b..5fefc2c4862403f2248df3c29162af636425f84e 100644 --- a/ee/spec/services/groups/ssh_certificates/destroy_service_spec.rb +++ b/ee/spec/services/groups/ssh_certificates/destroy_service_spec.rb @@ -5,9 +5,9 @@ RSpec.describe Groups::SshCertificates::DestroyService, '#execute', feature_category: :groups_and_projects do let_it_be(:ssh_certificate) { create(:group_ssh_certificate) } let_it_be(:group, reload: true) { create(:group, ssh_certificates: [ssh_certificate]) } - + let_it_be(:current_user) { create(:user) } let(:ssh_certificate_params) { { ssh_certificates_id: ssh_certificate.id } } - let(:service) { described_class.new(group, ssh_certificate_params) } + let(:service) { described_class.new(group, ssh_certificate_params, current_user) } context 'when group and params are provided' do it 'succeeds' do @@ -36,4 +36,29 @@ expect(response.errors.first).to eq("SSH Certificate not found") end end + + context 'when deleting an SSH certificate' do + it_behaves_like 'audit event logging' do + let(:operation) { service.execute } + let(:attributes) do + { + author_id: current_user.id, + entity_id: group.id, + entity_type: 'Group', + details: { + author_class: 'User', + author_name: current_user.name, + custom_message: "Deleted SSH certificate with id #{ssh_certificate.id} and title #{ssh_certificate.title}", + target_details: ssh_certificate.title, + target_id: ssh_certificate.id, + target_type: 'Groups::SshCertificate' + } + } + end + + def fail_condition! + allow(group.ssh_certificates).to receive(:find).and_raise(ActiveRecord::RecordNotFound) + end + end + end end