diff --git a/app/models/user.rb b/app/models/user.rb index 96cdbb192bcd7ce970c52a04f3bae9ea52b9db25..2c24972004933e4347d5d5e6bca37867af6a6f43 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -2063,6 +2063,7 @@ def read_only_attribute?(attribute) # override, from Devise def lock_access!(opts = {}) Gitlab::AppLogger.info("Account Locked: username=#{username}") + audit_lock_access super end @@ -2608,6 +2609,9 @@ def ci_namespace_mirrors_for_group_members(level) def prefix_for_feed_token FEED_TOKEN_PREFIX end + + # method overriden in EE + def audit_lock_access; end end User.prepend_mod_with('User') diff --git a/doc/administration/audit_events.md b/doc/administration/audit_events.md index e924da39145d2526801fb741e374f3f9e8df803d..a80d3421d348fb61556832e3bc33f040f2d6fbb0 100644 --- a/doc/administration/audit_events.md +++ b/doc/administration/audit_events.md @@ -362,6 +362,9 @@ GitLab generates audit events when a cluster agent token is created or revoked. > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/276250) in GitLab 13.6, audit events for when a user is approved using the Admin Area. > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/276921) in GitLab 13.6, audit events for when a user's personal access token is successfully or unsuccessfully created or revoked. > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/298783) in GitLab 13.9, audit events for when a user requests access to an instance or is rejected using the Admin Area. +> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/238177) in + GitLab 15.1, audit events when a user's two-factor authentication is disabled. +> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/124169) in GitLab 16.2, audit events when a user's access is locked. The following user actions on a GitLab instance generate instance audit events: @@ -373,8 +376,8 @@ The following user actions on a GitLab instance generate instance audit events: - Grant OAuth access. - Failed second-factor authentication attempt. - A user's personal access token was successfully or unsuccessfully created or revoked. -- A user's two-factor authentication was disabled. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/238177) in - GitLab 15.1. +- A user's two-factor authentication was disabled. +- A user's access is locked. #### User management diff --git a/ee/app/models/ee/user.rb b/ee/app/models/ee/user.rb index 8c31e51348fcff9bb45f59a78e0f90b034168926..eb12df91d3bbc0e7222aeb087e289c8309d6c3ab 100644 --- a/ee/app/models/ee/user.rb +++ b/ee/app/models/ee/user.rb @@ -686,5 +686,21 @@ def perform_user_cap_check def should_delay_delete?(*args) super && !has_paid_namespace?(exclude_trials: true) end + + override :audit_lock_access + def audit_lock_access + unless access_locked? + reason = nil + reason = 'excessive failed login attempts' if attempts_exceeded? + + ::Gitlab::Audit::Auditor.audit( + name: 'user_access_locked', + author: ::User.admin_bot, + scope: self, + target: self, + message: ['User access locked', reason].compact.join(' - ') + ) + end + end end end diff --git a/ee/config/audit_events/types/user_access_locked.yml b/ee/config/audit_events/types/user_access_locked.yml new file mode 100644 index 0000000000000000000000000000000000000000..33d1dbda20c09041fa76e5454f750f3cae515c09 --- /dev/null +++ b/ee/config/audit_events/types/user_access_locked.yml @@ -0,0 +1,8 @@ +name: user_access_locked +description: Event triggered when user access to the instance is locked +introduced_by_issue: https://gitlab.com/gitlab-org/modelops/anti-abuse/team-tasks/-/issues/244 +introduced_by_mr: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/124169 +feature_category: 'system_access' +milestone: '16.2' +saved_to_database: true +streamed: true diff --git a/ee/spec/models/ee/user_spec.rb b/ee/spec/models/ee/user_spec.rb index 6b0767000490ce7354a5198d2dee23ee5a2c20eb..19500ee57daf0d8adc0e51c34aec8e9b36cf8ccd 100644 --- a/ee/spec/models/ee/user_spec.rb +++ b/ee/spec/models/ee/user_spec.rb @@ -2761,4 +2761,52 @@ end end end + + describe '#lock_access!' do + let_it_be(:gitlab_admin_bot) { described_class.admin_bot } + let_it_be_with_reload(:user) { create(:user) } + + subject { user.lock_access! } + + before do + stub_licensed_features(admin_audit_log: true) + end + + it 'logs a user_access_locked audit event' do + expect(::Gitlab::Audit::Auditor).to receive(:audit).with( + hash_including( + name: 'user_access_locked', + author: gitlab_admin_bot, + scope: user, + target: user, + message: 'User access locked' + ) + ).and_call_original + expect { subject }.to change { AuditEvent.count }.by(1) + end + + context 'when reason for access lock is excessive failed login attempts' do + before do + allow(user).to receive(:attempts_exceeded?).and_return(true) + end + + it 'logs a user_access_locked audit event with the correct message' do + expect(::Gitlab::Audit::Auditor).to receive(:audit).with( + hash_including(message: 'User access locked - excessive failed login attempts') + ) + + subject + end + end + + context 'when user access is already locked' do + before do + user.lock_access! + end + + it 'does not log an audit event' do + expect { subject }.not_to change { AuditEvent.count } + end + end + end end