From 143d0e26664e85be9382d1b1f8e99ead96e5d642 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Thu, 18 Oct 2018 12:50:21 -0700 Subject: [PATCH] Add support for JSON logging for audit events This will add audit_json.log that writes one line per audit event. For example: { "severity":"INFO", "time":"2018-10-17T17:38:22.523Z", "author_id":3, "entity_id":2, "entity_type":"Project", "change":"visibility", "from":"Private", "to":"Public", "author_name":"John Doe4", "target_id":2, "target_type":"Project", "target_details":"namespace2/project2" } --- app/services/audit_event_service.rb | 26 ++++++++++++++++--- .../sh-add-audit-logging-json-ce.yml | 5 ++++ doc/administration/logs.md | 14 ++++++++++ lib/gitlab/audit_json_logger.rb | 9 +++++++ spec/services/audit_event_service_spec.rb | 26 +++++++++++++++++++ 5 files changed, 76 insertions(+), 4 deletions(-) create mode 100644 changelogs/unreleased/sh-add-audit-logging-json-ce.yml create mode 100644 lib/gitlab/audit_json_logger.rb create mode 100644 spec/services/audit_event_service_spec.rb diff --git a/app/services/audit_event_service.rb b/app/services/audit_event_service.rb index 4c5e22bdd7e..201048aaba5 100644 --- a/app/services/audit_event_service.rb +++ b/app/services/audit_event_service.rb @@ -17,11 +17,29 @@ class AuditEventService end def security_event - SecurityEvent.create( + log_security_event_to_file + log_security_event_to_database + end + + private + + def base_payload + { author_id: @author.id, entity_id: @entity.id, - entity_type: @entity.class.name, - details: @details - ) + entity_type: @entity.class.name + } + end + + def file_logger + @file_logger ||= Gitlab::AuditJsonLogger.build + end + + def log_security_event_to_file + file_logger.info(base_payload.merge(@details)) + end + + def log_security_event_to_database + SecurityEvent.create(base_payload.merge(details: @details)) end end diff --git a/changelogs/unreleased/sh-add-audit-logging-json-ce.yml b/changelogs/unreleased/sh-add-audit-logging-json-ce.yml new file mode 100644 index 00000000000..3c0a27da269 --- /dev/null +++ b/changelogs/unreleased/sh-add-audit-logging-json-ce.yml @@ -0,0 +1,5 @@ +--- +title: Add support for JSON logging for audit events +merge_request: 22471 +author: +type: added diff --git a/doc/administration/logs.md b/doc/administration/logs.md index a8cdd20581d..0e41a38b7e2 100644 --- a/doc/administration/logs.md +++ b/doc/administration/logs.md @@ -144,6 +144,20 @@ December 03, 2014 13:20 -> ERROR -> Command failed [1]: /usr/bin/git --git-dir=/ error: failed to push some refs to '/Users/vsizov/gitlab-development-kit/repositories/gitlabhq/gitlab_git.git' ``` +## `audit_json.log` + +This file lives in `/var/log/gitlab/gitlab-rails/audit_json.log` for +Omnibus GitLab packages or in `/home/git/gitlab/log/audit_json.log` for +installations from source. + +Changes to group or project settings are logged to this file. For example: + +```json +{"severity":"INFO","time":"2018-10-17T17:38:22.523Z","author_id":3,"entity_id":2,"entity_type":"Project","change":"visibility","from":"Private","to":"Public","author_name":"John Doe4","target_id":2,"target_type":"Project","target_details":"namespace2/project2"} +{"severity":"INFO","time":"2018-10-17T17:38:22.830Z","author_id":5,"entity_id":3,"entity_type":"Project","change":"name","from":"John Doe7 / project3","to":"John Doe7 / new name","author_name":"John Doe6","target_id":3,"target_type":"Project","target_details":"namespace3/project3"} +{"severity":"INFO","time":"2018-10-17T17:38:23.175Z","author_id":7,"entity_id":4,"entity_type":"Project","change":"path","from":"","to":"namespace4/newpath","author_name":"John Doe8","target_id":4,"target_type":"Project","target_details":"namespace4/newpath"} +``` + ## `sidekiq.log` This file lives in `/var/log/gitlab/gitlab-rails/sidekiq.log` for diff --git a/lib/gitlab/audit_json_logger.rb b/lib/gitlab/audit_json_logger.rb new file mode 100644 index 00000000000..12e0645f3e4 --- /dev/null +++ b/lib/gitlab/audit_json_logger.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +module Gitlab + class AuditJsonLogger < Gitlab::JsonLogger + def self.file_name_noext + 'audit_json' + end + end +end diff --git a/spec/services/audit_event_service_spec.rb b/spec/services/audit_event_service_spec.rb new file mode 100644 index 00000000000..32fd98e6ef9 --- /dev/null +++ b/spec/services/audit_event_service_spec.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe AuditEventService do + let(:project) { create(:project) } + let(:user) { create(:user) } + let(:project_member) { create(:project_member, user: user) } + let(:service) { described_class.new(user, project, { action: :destroy }) } + let(:logger) { instance_double(Gitlab::AuditJsonLogger) } + + describe '#security_event' do + before do + expect(service).to receive(:file_logger).and_return(logger) + end + + it 'creates an event and logs to a file' do + expect(logger).to receive(:info).with(author_id: user.id, + entity_id: project.id, + entity_type: "Project", + action: :destroy) + + expect { service.security_event }.to change(SecurityEvent, :count).by(1) + end + end +end