From be753e3bb14370a0dd288009f2ce50d7dcc2143a Mon Sep 17 00:00:00 2001 From: nrosandich Date: Fri, 18 Jul 2025 14:03:05 +1200 Subject: [PATCH 1/2] Update authentication audit event to use Auditor EE: true Changelog: changed --- app/controllers/sessions_controller.rb | 28 ++++++++- .../types/authenticated_with_password.yml | 10 +++ .../types/authenticated_with_two_factor.yml | 10 +++ .../types/authenticated_with_webauthn.yml | 10 +++ doc/user/compliance/audit_event_types.md | 3 + spec/controllers/sessions_controller_spec.rb | 63 ++++++++++++++++--- 6 files changed, 114 insertions(+), 10 deletions(-) create mode 100644 config/audit_events/types/authenticated_with_password.yml create mode 100644 config/audit_events/types/authenticated_with_two_factor.yml create mode 100644 config/audit_events/types/authenticated_with_webauthn.yml diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index 7f5e057758347a..b8ee5e8a4789d4 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -280,13 +280,37 @@ def valid_otp_attempt?(user) user.invalidate_otp_backup_code!(user_params[:otp_attempt]) end + def audit_event_name_for_authentication_method(method) + case method + when AuthenticationEvent::TWO_FACTOR + 'authenticated_with_two_factor' + when AuthenticationEvent::TWO_FACTOR_WEBAUTHN + 'authenticated_with_webauthn' + else + 'authenticated_with_password' + end + end + def log_audit_event(user, resource, options = {}) Gitlab::AppLogger.info( "Successful Login: username=#{resource.username} ip=#{request.remote_ip} " \ "method=#{options[:with]} admin=#{resource.admin?}" ) - AuditEventService.new(user, user, options) - .for_authentication.security_event + + event_name = audit_event_name_for_authentication_method(options[:with] || AuthenticationEvent::STANDARD) + audit_context = { + name: event_name, + author: user, + scope: user, + target: user, + message: "Signed in with #{options[:with]} authentication", + authentication_event: true, + authentication_provider: options[:with], + additional_details: { + with: options[:with] + } + } + ::Gitlab::Audit::Auditor.audit(audit_context) end def log_user_activity(user) diff --git a/config/audit_events/types/authenticated_with_password.yml b/config/audit_events/types/authenticated_with_password.yml new file mode 100644 index 00000000000000..0b450b5f772199 --- /dev/null +++ b/config/audit_events/types/authenticated_with_password.yml @@ -0,0 +1,10 @@ +--- +name: authenticated_with_password +description: User successfully signed in with password +introduced_by_issue: https://gitlab.com/gitlab-org/gitlab/-/issues/555101 +introduced_by_mr: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/198216 +milestone: '18.2' +feature_category: system_access +saved_to_database: true +streamed: true +scope: [User] diff --git a/config/audit_events/types/authenticated_with_two_factor.yml b/config/audit_events/types/authenticated_with_two_factor.yml new file mode 100644 index 00000000000000..2354481903163e --- /dev/null +++ b/config/audit_events/types/authenticated_with_two_factor.yml @@ -0,0 +1,10 @@ +--- +name: authenticated_with_two_factor +description: User successfully signed in with two-factor authentication +introduced_by_issue: https://gitlab.com/gitlab-org/gitlab/-/issues/555101 +introduced_by_mr: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/198216 +milestone: '18.2' +feature_category: system_access +saved_to_database: true +streamed: true +scope: [User] diff --git a/config/audit_events/types/authenticated_with_webauthn.yml b/config/audit_events/types/authenticated_with_webauthn.yml new file mode 100644 index 00000000000000..cc200da9244aa5 --- /dev/null +++ b/config/audit_events/types/authenticated_with_webauthn.yml @@ -0,0 +1,10 @@ +--- +name: authenticated_with_webauthn +description: User successfully signed in with WebAuthn device +introduced_by_issue: https://gitlab.com/gitlab-org/gitlab/-/issues/555101 +introduced_by_mr: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/198216 +milestone: '18.2' +feature_category: system_access +saved_to_database: true +streamed: true +scope: [User] diff --git a/doc/user/compliance/audit_event_types.md b/doc/user/compliance/audit_event_types.md index 713d043f7ac1c1..31cdf4725c694a 100644 --- a/doc/user/compliance/audit_event_types.md +++ b/doc/user/compliance/audit_event_types.md @@ -644,6 +644,9 @@ Audit event types belong to the following product categories. | [`user_enable_admin_mode`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/104754) | Admin Mode enabled | {{< icon name="check-circle" >}} Yes | GitLab [15.7](https://gitlab.com/gitlab-org/gitlab/-/issues/362101) | User | | [`authenticated_with_ldap`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/175763) | User successfully signed in with LDAP | {{< icon name="check-circle" >}} Yes | GitLab [17.11](https://gitlab.com/gitlab-org/gitlab/-/issues/509377) | User | | [`authenticated_with_oauth`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/175763) | User successfully signed in with OAuth | {{< icon name="check-circle" >}} Yes | GitLab [17.11](https://gitlab.com/gitlab-org/gitlab/-/issues/509377) | User | +| [`authenticated_with_password`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/198216) | User successfully signed in with password | {{< icon name="check-circle" >}} Yes | GitLab [18.2](https://gitlab.com/gitlab-org/gitlab/-/issues/555101) | User | +| [`authenticated_with_two_factor`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/198216) | User successfully signed in with two-factor authentication | {{< icon name="check-circle" >}} Yes | GitLab [18.2](https://gitlab.com/gitlab-org/gitlab/-/issues/555101) | User | +| [`authenticated_with_webauthn`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/198216) | User successfully signed in with WebAuthn device | {{< icon name="check-circle" >}} Yes | GitLab [18.2](https://gitlab.com/gitlab-org/gitlab/-/issues/555101) | User | ### Team planning diff --git a/spec/controllers/sessions_controller_spec.rb b/spec/controllers/sessions_controller_spec.rb index 6349db704feca0..11d170ff25217a 100644 --- a/spec/controllers/sessions_controller_spec.rb +++ b/spec/controllers/sessions_controller_spec.rb @@ -261,9 +261,17 @@ end end - it 'creates an audit log record' do + it 'creates audit event records' do expect { post(:create, params: { user: user_params }) }.to change { AuditEvent.count }.by(1) - expect(AuditEvent.last.details[:with]).to eq('standard') + .and change { AuditEvents::UserAuditEvent.count }.by(1) + + audit_event = AuditEvent.last + expect(audit_event.details[:with]).to eq('standard') + expect(audit_event.details[:event_name]).to eq('authenticated_with_password') + + user_audit_event = AuditEvents::UserAuditEvent.last + expect(user_audit_event.event_name).to eq('authenticated_with_password') + expect(user_audit_event.details[:with]).to eq('standard') end it 'creates an authentication event record' do @@ -605,9 +613,17 @@ def authenticate_2fa(otp_user_id: user.id, **user_params) end end - it "creates an audit log record" do + it 'creates audit event records' do expect { authenticate_2fa(login: user.username, otp_attempt: user.current_otp) }.to change { AuditEvent.count }.by(1) - expect(AuditEvent.last.details[:with]).to eq("two-factor") + .and change { AuditEvents::UserAuditEvent.count }.by(1) + + audit_event = AuditEvent.last + expect(audit_event.details[:with]).to eq('two-factor') + expect(audit_event.details[:event_name]).to eq('authenticated_with_two_factor') + + user_audit_event = AuditEvents::UserAuditEvent.last + expect(user_audit_event.event_name).to eq('authenticated_with_two_factor') + expect(user_audit_event.details[:with]).to eq('two-factor') end it "creates an authentication event record" do @@ -661,12 +677,19 @@ def authenticate_2fa(user_params) end end - it "creates an audit log record" do + it 'creates audit event records' do allow_any_instance_of(Webauthn::AuthenticateService).to receive(:execute).and_return(true) - expect { authenticate_2fa(login: user.username, device_response: "{}") }.to( - change { AuditEvent.count }.by(1)) - expect(AuditEvent.last.details[:with]).to eq("two-factor-via-webauthn-device") + expect { authenticate_2fa(login: user.username, device_response: "{}") }.to change { AuditEvent.count }.by(1) + .and change { AuditEvents::UserAuditEvent.count }.by(1) + + audit_event = AuditEvent.last + expect(audit_event.details[:with]).to eq('two-factor-via-webauthn-device') + expect(audit_event.details[:event_name]).to eq('authenticated_with_webauthn') + + user_audit_event = AuditEvents::UserAuditEvent.last + expect(user_audit_event.event_name).to eq('authenticated_with_webauthn') + expect(user_audit_event.details[:with]).to eq('two-factor-via-webauthn-device') end it "creates an authentication event record" do @@ -719,6 +742,30 @@ def authenticate_2fa(user_params) end end + describe '#audit_event_name_for_authentication_method' do + let(:controller) { described_class.new } + + it 'returns correct event name for standard authentication' do + expect(controller.send(:audit_event_name_for_authentication_method, AuthenticationEvent::STANDARD)) + .to eq('authenticated_with_password') + end + + it 'returns correct event name for two-factor authentication' do + expect(controller.send(:audit_event_name_for_authentication_method, AuthenticationEvent::TWO_FACTOR)) + .to eq('authenticated_with_two_factor') + end + + it 'returns correct event name for WebAuthn authentication' do + expect(controller.send(:audit_event_name_for_authentication_method, AuthenticationEvent::TWO_FACTOR_WEBAUTHN)) + .to eq('authenticated_with_webauthn') + end + + it 'returns correct event name for unknown authentication method' do + expect(controller.send(:audit_event_name_for_authentication_method, 'unknown')) + .to eq('authenticated_with_password') + end + end + context 'when login fails' do before do @request.env["warden.options"] = { action: 'unauthenticated' } -- GitLab From 096d620708868207e4cdef8037665c418b2ad13b Mon Sep 17 00:00:00 2001 From: nrosandich Date: Fri, 1 Aug 2025 10:39:13 +1200 Subject: [PATCH 2/2] Update release milestone --- config/audit_events/types/authenticated_with_password.yml | 2 +- config/audit_events/types/authenticated_with_two_factor.yml | 2 +- config/audit_events/types/authenticated_with_webauthn.yml | 2 +- doc/user/compliance/audit_event_types.md | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/config/audit_events/types/authenticated_with_password.yml b/config/audit_events/types/authenticated_with_password.yml index 0b450b5f772199..cacd71dedc792b 100644 --- a/config/audit_events/types/authenticated_with_password.yml +++ b/config/audit_events/types/authenticated_with_password.yml @@ -3,7 +3,7 @@ name: authenticated_with_password description: User successfully signed in with password introduced_by_issue: https://gitlab.com/gitlab-org/gitlab/-/issues/555101 introduced_by_mr: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/198216 -milestone: '18.2' +milestone: '18.3' feature_category: system_access saved_to_database: true streamed: true diff --git a/config/audit_events/types/authenticated_with_two_factor.yml b/config/audit_events/types/authenticated_with_two_factor.yml index 2354481903163e..bf31b6e3656c42 100644 --- a/config/audit_events/types/authenticated_with_two_factor.yml +++ b/config/audit_events/types/authenticated_with_two_factor.yml @@ -3,7 +3,7 @@ name: authenticated_with_two_factor description: User successfully signed in with two-factor authentication introduced_by_issue: https://gitlab.com/gitlab-org/gitlab/-/issues/555101 introduced_by_mr: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/198216 -milestone: '18.2' +milestone: '18.3' feature_category: system_access saved_to_database: true streamed: true diff --git a/config/audit_events/types/authenticated_with_webauthn.yml b/config/audit_events/types/authenticated_with_webauthn.yml index cc200da9244aa5..e20440637644bc 100644 --- a/config/audit_events/types/authenticated_with_webauthn.yml +++ b/config/audit_events/types/authenticated_with_webauthn.yml @@ -3,7 +3,7 @@ name: authenticated_with_webauthn description: User successfully signed in with WebAuthn device introduced_by_issue: https://gitlab.com/gitlab-org/gitlab/-/issues/555101 introduced_by_mr: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/198216 -milestone: '18.2' +milestone: '18.3' feature_category: system_access saved_to_database: true streamed: true diff --git a/doc/user/compliance/audit_event_types.md b/doc/user/compliance/audit_event_types.md index 31cdf4725c694a..9bbca195e4cc43 100644 --- a/doc/user/compliance/audit_event_types.md +++ b/doc/user/compliance/audit_event_types.md @@ -644,9 +644,9 @@ Audit event types belong to the following product categories. | [`user_enable_admin_mode`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/104754) | Admin Mode enabled | {{< icon name="check-circle" >}} Yes | GitLab [15.7](https://gitlab.com/gitlab-org/gitlab/-/issues/362101) | User | | [`authenticated_with_ldap`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/175763) | User successfully signed in with LDAP | {{< icon name="check-circle" >}} Yes | GitLab [17.11](https://gitlab.com/gitlab-org/gitlab/-/issues/509377) | User | | [`authenticated_with_oauth`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/175763) | User successfully signed in with OAuth | {{< icon name="check-circle" >}} Yes | GitLab [17.11](https://gitlab.com/gitlab-org/gitlab/-/issues/509377) | User | -| [`authenticated_with_password`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/198216) | User successfully signed in with password | {{< icon name="check-circle" >}} Yes | GitLab [18.2](https://gitlab.com/gitlab-org/gitlab/-/issues/555101) | User | -| [`authenticated_with_two_factor`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/198216) | User successfully signed in with two-factor authentication | {{< icon name="check-circle" >}} Yes | GitLab [18.2](https://gitlab.com/gitlab-org/gitlab/-/issues/555101) | User | -| [`authenticated_with_webauthn`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/198216) | User successfully signed in with WebAuthn device | {{< icon name="check-circle" >}} Yes | GitLab [18.2](https://gitlab.com/gitlab-org/gitlab/-/issues/555101) | User | +| [`authenticated_with_password`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/198216) | User successfully signed in with password | {{< icon name="check-circle" >}} Yes | GitLab [18.3](https://gitlab.com/gitlab-org/gitlab/-/issues/555101) | User | +| [`authenticated_with_two_factor`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/198216) | User successfully signed in with two-factor authentication | {{< icon name="check-circle" >}} Yes | GitLab [18.3](https://gitlab.com/gitlab-org/gitlab/-/issues/555101) | User | +| [`authenticated_with_webauthn`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/198216) | User successfully signed in with WebAuthn device | {{< icon name="check-circle" >}} Yes | GitLab [18.3](https://gitlab.com/gitlab-org/gitlab/-/issues/555101) | User | ### Team planning -- GitLab