Skip to content
Snippets Groups Projects
Unverified Commit a546012b authored by Drew Blessing's avatar Drew Blessing Committed by Drew Blessing
Browse files

Log authentication events alongside existing audit events

For authentication, add both an audit event and authentication
event for the short term. Eventually we will diverge and only
store authentication events when an authentication occours.
At that time, authentication events will be a subclass of audit
events. For now we store both and use authentication events for
usage ping exclusively.
parent 578b3889
Branches 301218-docs-aqualls-fix-core
No related tags found
No related merge requests found
Loading
Loading
@@ -25,6 +25,8 @@ class AuditEventService
#
# @return [AuditEventService]
def for_authentication
mark_as_authentication_event!
@details = {
with: @details[:with],
target_id: @author.id,
Loading
Loading
@@ -40,6 +42,7 @@ class AuditEventService
# @return [AuditEvent] persited if saves and non-persisted if fails
def security_event
log_security_event_to_file
log_authentication_event_to_database
log_security_event_to_database
end
 
Loading
Loading
@@ -50,6 +53,7 @@ class AuditEventService
 
private
 
attr_accessor :authentication_event
attr_reader :ip_address
 
def build_author(author)
Loading
Loading
@@ -70,6 +74,22 @@ class AuditEventService
}
end
 
def authentication_event_payload
{
# @author can be a User or various Gitlab::Audit authors.
# Only capture real users for successful authentication events.
user: author_if_user,
user_name: @author.name,
ip_address: ip_address,
result: AuthenticationEvent.results[:success],
provider: @details[:with]
}
end
def author_if_user
@author if @author.is_a?(User)
end
def file_logger
@file_logger ||= Gitlab::AuditJsonLogger.build
end
Loading
Loading
@@ -78,11 +98,25 @@ class AuditEventService
@details.merge(@details.slice(:from, :to).transform_values(&:to_s))
end
 
def mark_as_authentication_event!
self.authentication_event = true
end
def authentication_event?
authentication_event
end
def log_security_event_to_database
return if Gitlab::Database.read_only?
 
AuditEvent.create(base_payload.merge(details: @details))
end
def log_authentication_event_to_database
return unless Gitlab::Database.read_write? && authentication_event?
AuthenticationEvent.create(authentication_event_payload)
end
end
 
AuditEventService.prepend_if_ee('EE::AuditEventService')
---
title: Log authentication events alongside existing audit events
merge_request: 42033
author:
type: added
Loading
Loading
@@ -11,6 +11,11 @@ RSpec.describe Ldap::OmniauthCallbacksController do
expect(request.env['warden']).to be_authenticated
end
 
it 'creates an authentication event record' do
expect { post provider }.to change { AuthenticationEvent.count }.by(1)
expect(AuthenticationEvent.last.provider).to eq(provider.to_s)
end
context 'with sign in prevented' do
let(:ldap_settings) { ldap_setting_defaults.merge(prevent_ldap_sign_in: true) }
 
Loading
Loading
Loading
Loading
@@ -170,6 +170,11 @@ RSpec.describe OmniauthCallbacksController, type: :controller do
expect(request.env['warden']).to be_authenticated
end
 
it 'creates an authentication event record' do
expect { post provider }.to change { AuthenticationEvent.count }.by(1)
expect(AuthenticationEvent.last.provider).to eq(provider.to_s)
end
context 'when user has no linked provider' do
let(:user) { create(:user) }
 
Loading
Loading
Loading
Loading
@@ -140,6 +140,11 @@ RSpec.describe SessionsController do
expect(AuditEvent.last.details[:with]).to eq('standard')
end
 
it 'creates an authentication event record' do
expect { post(:create, params: { user: user_params }) }.to change { AuthenticationEvent.count }.by(1)
expect(AuthenticationEvent.last.provider).to eq('standard')
end
include_examples 'user login request with unique ip limit', 302 do
def request
post(:create, params: { user: user_params })
Loading
Loading
@@ -407,6 +412,11 @@ RSpec.describe SessionsController 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")
end
it "creates an authentication event record" do
expect { authenticate_2fa(login: user.username, otp_attempt: user.current_otp) }.to change { AuthenticationEvent.count }.by(1)
expect(AuthenticationEvent.last.provider).to eq("two-factor")
end
end
 
context 'when using two-factor authentication via U2F device' do
Loading
Loading
@@ -448,6 +458,13 @@ RSpec.describe SessionsController do
expect { authenticate_2fa_u2f(login: user.username, device_response: "{}") }.to change { AuditEvent.count }.by(1)
expect(AuditEvent.last.details[:with]).to eq("two-factor-via-u2f-device")
end
it "creates an authentication event record" do
allow(U2fRegistration).to receive(:authenticate).and_return(true)
expect { authenticate_2fa_u2f(login: user.username, device_response: "{}") }.to change { AuthenticationEvent.count }.by(1)
expect(AuthenticationEvent.last.provider).to eq("two-factor-via-u2f-device")
end
end
end
 
Loading
Loading
Loading
Loading
@@ -52,6 +52,22 @@ RSpec.describe AuditEventService do
expect(details[:action]).to eq(:create)
expect(details[:target_id]).to eq(1)
end
context 'authentication event' do
let(:audit_service) { described_class.new(user, user, with: 'standard') }
it 'creates an authentication event' do
expect(AuthenticationEvent).to receive(:create).with(
user: user,
user_name: user.name,
ip_address: user.current_sign_in_ip,
result: AuthenticationEvent.results[:success],
provider: 'standard'
)
audit_service.for_authentication.security_event
end
end
end
 
describe '#log_security_event_to_file' do
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment