Commit 17b3cb6c authored by manojmj's avatar manojmj

Log impersonation actions in audit log

This change adds audit logs for user impersonation
when an admin starts/stops impersonating
another user.
parent b52d9c6c
......@@ -39,7 +39,7 @@ class Admin::UsersController < Admin::ApplicationController
warden.set_user(user, scope: :user)
Gitlab::AppLogger.info(_("User %{current_user_username} has started impersonating %{username}") % { current_user_username: current_user.username, username: user.username })
log_impersonation_event
flash[:alert] = _("You are now impersonating %{username}") % { username: user.username }
......@@ -236,6 +236,10 @@ class Admin::UsersController < Admin::ApplicationController
def check_impersonation_availability
access_denied! unless Gitlab.config.gitlab.impersonation_enabled
end
def log_impersonation_event
Gitlab::AppLogger.info(_("User %{current_user_username} has started impersonating %{username}") % { current_user_username: current_user.username, username: user.username })
end
end
Admin::UsersController.prepend(EE::Admin::UsersController)
......@@ -499,9 +499,7 @@ class ApplicationController < ActionController::Base
end
def stop_impersonation
impersonated_user = current_user
Gitlab::AppLogger.info("User #{impersonator.username} has stopped impersonating #{impersonated_user.username}")
log_impersonation_event
warden.set_user(impersonator, scope: :user)
session[:impersonator_id] = nil
......@@ -509,6 +507,14 @@ class ApplicationController < ActionController::Base
impersonated_user
end
def impersonated_user
current_user
end
def log_impersonation_event
Gitlab::AppLogger.info("User #{impersonator.username} has stopped impersonating #{impersonated_user.username}")
end
def impersonator
@impersonator ||= User.find(session[:impersonator_id]) if session[:impersonator_id]
end
......
......@@ -94,6 +94,7 @@ recorded:
- Changed password
- Ask for password reset
- Grant OAuth access
- Started/stopped user impersonation
It is possible to filter particular actions by choosing an audit data type from
the filter drop-down. You can further filter by specific group, project or user
......
......@@ -4,6 +4,8 @@
module EE
module Admin
module UsersController
extend ::Gitlab::Utils::Override
def reset_runners_minutes
user
......@@ -17,6 +19,17 @@ module EE
private
override :log_impersonation_event
def log_impersonation_event
super
log_audit_event
end
def log_audit_event
AuditEvents::ImpersonationAuditEventService.new(current_user, request.remote_ip, 'Started Impersonation').for_user(user.username).security_event
end
def allowed_user_params
super + [
:note,
......
......@@ -24,6 +24,17 @@ module EE
private
override :log_impersonation_event
def log_impersonation_event
super
log_audit_event
end
def log_audit_event
AuditEvents::ImpersonationAuditEventService.new(impersonator, request.remote_ip, 'Stopped Impersonation').for_user(impersonated_user.username).security_event
end
def set_current_ip_address(&block)
::Gitlab::IpAddressState.with(request.ip, &block) # rubocop: disable CodeReuse/ActiveRecord
end
......
# frozen_string_literal: true
module EE
module AuditEvents
class ImpersonationAuditEventService < ::AuditEventService
def initialize(author, ip_address, message)
super(author, author, {
action: :custom,
custom_message: message,
ip_address: ip_address
})
end
end
end
end
---
title: Log impersonation actions in audit log
merge_request: 14740
author:
type: added
# frozen_string_literal: true
require 'spec_helper'
describe Admin::ImpersonationsController do
let(:impersonator) { create(:admin) }
let(:user) { create(:user) }
describe "DELETE destroy" do
context "when signed in" do
before do
sign_in(user)
end
context "when impersonating" do
before do
session[:impersonator_id] = impersonator.id
stub_licensed_features(extended_audit_events: true)
end
it 'creates an audit log record' do
expect { delete :destroy }.to change { SecurityEvent.count }.by(1)
end
end
end
end
end
......@@ -38,4 +38,14 @@ describe Admin::UsersController do
end
end
end
describe "POST #impersonate" do
before do
stub_licensed_features(extended_audit_events: true)
end
it 'creates an audit log record' do
expect { post :impersonate, params: { id: user.username } }.to change { SecurityEvent.count }.by(1)
end
end
end
# frozen_string_literal: true
require 'spec_helper'
describe EE::AuditEvents::ImpersonationAuditEventService do
let(:impersonator) { create(:user) }
let(:ip_address) { '127.0.0.1' }
let(:message) { 'Impersonation Started' }
let(:logger) { instance_double(Gitlab::AuditJsonLogger) }
let(:service) { described_class.new(impersonator, ip_address, message) }
describe '#security_event' do
before do
stub_licensed_features(extended_audit_events: true)
end
it 'creates an event and logs to a file with the provided details' do
expect(service).to receive(:file_logger).and_return(logger)
expect(logger).to receive(:info).with(author_id: impersonator.id,
entity_id: impersonator.id,
entity_type: "User",
action: :custom,
ip_address: ip_address,
custom_message: message)
expect { service.security_event }.to change(SecurityEvent, :count).by(1)
security_event = SecurityEvent.last
expect(security_event.details).to eq(custom_message: message,
ip_address: ip_address,
action: :custom)
expect(security_event.author_id).to eq(impersonator.id)
expect(security_event.entity_id).to eq(impersonator.id)
expect(security_event.entity_type).to eq('User')
end
end
end
......@@ -279,6 +279,12 @@ describe Admin::UsersController do
expect(warden.user).to eq(user)
end
it 'logs the beginning of the impersonation event' do
expect(Gitlab::AppLogger).to receive(:info).with("User #{admin.username} has started impersonating #{user.username}").and_call_original
post :impersonate, params: { id: user.username }
end
it "redirects to root" do
post :impersonate, params: { id: user.username }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment