diff --git a/ee/lib/gitlab/auth/group_saml/identity_linker.rb b/ee/lib/gitlab/auth/group_saml/identity_linker.rb index fc608a71743e388e244d61adf3943a3b8e236d4a..c5d6bd293a66185ef7349e6d0dfe29790d250ebb 100644 --- a/ee/lib/gitlab/auth/group_saml/identity_linker.rb +++ b/ee/lib/gitlab/auth/group_saml/identity_linker.rb @@ -33,7 +33,7 @@ def error_message s_('GroupSAML|SAML Name ID and email address do not match your user account. Contact an administrator.') end - protected + private # rubocop: disable CodeReuse/ActiveRecord override :identity @@ -52,10 +52,16 @@ def update_group_membership end def update_extern_uid - return unless update_extern_uid_allowed? + existing_extern_uid = identity.extern_uid - identity.extern_uid = uid.to_s - save + success = if update_extern_uid_allowed? + identity.extern_uid = uid.to_s + save + else + false + end + + audit(success, existing_extern_uid, uid.to_s) end # When the current extern_uid doesn't match the @@ -76,6 +82,20 @@ def update_extern_uid_allowed? def update_extern_uid_failed? extern_uid_update_required? && !update_extern_uid_allowed? end + + def audit(success, old_uid, new_uid) + action = success ? "Updated" : "Failed to update" + + audit_context = { + name: 'update_mismatched_group_saml_extern_uid', + author: current_user, + scope: current_user, + target: current_user, + message: "#{action} extern_uid from #{old_uid} to #{new_uid}" + } + + ::Gitlab::Audit::Auditor.audit(audit_context) + end end end end diff --git a/ee/spec/lib/gitlab/auth/group_saml/identity_linker_spec.rb b/ee/spec/lib/gitlab/auth/group_saml/identity_linker_spec.rb index 7a4d1c36f607fd61208130d01d84b42c0c3f5002..c24090f719c9c84909a2535f4f5c00bbb38183ea 100644 --- a/ee/spec/lib/gitlab/auth/group_saml/identity_linker_spec.rb +++ b/ee/spec/lib/gitlab/auth/group_saml/identity_linker_spec.rb @@ -43,7 +43,12 @@ end context 'when the extern_uid does not match' do - let(:extern_uid) { 'ioKaiph5' } + let(:audit_event) { AuditEvent.last.details[:custom_message] } + let_it_be(:extern_uid) { 'ioKaiph5' } + + before do + stub_licensed_features(admin_audit_log: true) + end it 'updates the identity when the email address matches' do expect(identity.extern_uid).to eq(extern_uid) @@ -53,6 +58,7 @@ expect(identity.reload.extern_uid).to eq(uid) expect(identity_linker.failed?).to eq(false) expect(identity_linker.error_message).to be_empty + expect(audit_event).to eq("Updated extern_uid from #{extern_uid} to #{uid}") end it 'does not update the identity when the email address does not match', :aggregate_failures do @@ -66,6 +72,7 @@ .to eq( s_('GroupSAML|SAML Name ID and email address do not match your user account. Contact an administrator.') ) + expect(audit_event).to eq("Failed to update extern_uid from #{extern_uid} to #{uid}") end context 'when the extern_uid is already taken' do @@ -79,6 +86,7 @@ expect(identity.reload.extern_uid).to eq(extern_uid) expect(identity_linker.failed?).to eq(true) expect(identity_linker.error_message).to eq('Extern uid has already been taken') + expect(audit_event).to eq("Failed to update extern_uid from #{extern_uid} to #{uid}") end end end