Skip to content
Snippets Groups Projects
Commit a7229916 authored by Harsimar Sandhu's avatar Harsimar Sandhu :three: Committed by James Fargher
Browse files

Event type information for ci variable audit event

EE: true
Changelog: added
parent b8202f92
No related branches found
No related tags found
1 merge request!91983Event type information in ci variable audit event
......@@ -19,5 +19,9 @@ class GroupVariable < Ci::ApplicationRecord
scope :unprotected, -> { where(protected: false) }
scope :by_environment_scope, -> (environment_scope) { where(environment_scope: environment_scope) }
scope :for_groups, ->(group_ids) { where(group_id: group_ids) }
def audit_details
key
end
end
end
......@@ -18,5 +18,9 @@ class Variable < Ci::ApplicationRecord
scope :unprotected, -> { where(protected: false) }
scope :by_environment_scope, -> (environment_scope) { where(environment_scope: environment_scope) }
def audit_details
key
end
end
end
......@@ -4,8 +4,11 @@ module Ci
class AuditVariableChangeService < ::BaseContainerService
include ::Audit::Changes
AUDITABLE_VARIABLE_CLASSES = [::Ci::Variable, ::Ci::GroupVariable].freeze
def execute
return unless container.feature_available?(:audit_events)
return unless AUDITABLE_VARIABLE_CLASSES.include? params[:variable].class
case params[:action]
when :create, :destroy
......@@ -14,7 +17,8 @@ def execute
audit_changes(
:protected,
as: 'variable protection', entity: container,
model: params[:variable], target_details: params[:variable].key
model: params[:variable], target_details: params[:variable].key,
event_type: event_type_name(params[:variable], params[:action])
)
end
end
......@@ -22,20 +26,52 @@ def execute
private
def log_audit_event(action, variable)
case variable.class.to_s
when ::Ci::Variable.to_s
::AuditEventService.new(
current_user,
container,
action: action
).for_project_variable(variable.key).security_event
when ::Ci::GroupVariable.to_s
::AuditEventService.new(
current_user,
container,
action: action
).for_group_variable(variable.key).security_event
audit_context = {
name: event_type_name(variable, action),
author: current_user || ::Gitlab::Audit::UnauthenticatedAuthor.new,
scope: container,
target: variable,
message: message(variable, action),
additional_details: build_additional_details(variable, action)
}
::Gitlab::Audit::Auditor.audit(audit_context)
end
def event_type_name(variable, action)
name = ci_variable_name(variable)
case action
when :create
"#{name}_created"
when :destroy
"#{name}_deleted"
when :update
"#{name}_updated"
end
end
def message(variable, action)
name = ci_variable_name(variable).humanize(capitalize: false)
case action
when :create
"Added #{name}"
when :destroy
"Removed #{name}"
end
end
def build_additional_details(variable, action)
name = ci_variable_name(variable)
case action
when :create
{ add: name }
when :destroy
{ remove: name }
end
end
def ci_variable_name(variable)
variable.class.to_s.parameterize(preserve_case: true).underscore
end
end
end
......@@ -89,8 +89,8 @@ def additional_details(options)
def build_message(details)
message = ["Changed #{details[:change]}"]
message << "from #{details[:from]}" unless details[:from].blank?
message << "to #{details[:to]}" unless details[:to].blank?
message << "from #{details[:from]}" if details[:from].to_s.present?
message << "to #{details[:to]}" if details[:to].to_s.present?
message.join(' ')
end
......
......@@ -42,7 +42,7 @@
from: false,
to: true,
ip_address: ip_address,
custom_message: "Changed #{change_text} to true" })
custom_message: "Changed #{change_text} from false to true" })
expect(event.author_id).to eq(author.id)
expect(event.entity_id).to eq(entity.id)
......
......@@ -8,7 +8,10 @@
let_it_be(:user) { create(:user) }
let(:group) { create(:group) }
let(:variable) { create(:ci_group_variable) }
let(:group_variable) { create(:ci_group_variable, group: group) }
let(:destination) { create(:external_audit_event_destination, group: group) }
let(:project) { create(:project, group: group) }
let(:project_variable) { create(:ci_variable, project: project) }
let(:service) do
described_class.new(
......@@ -17,29 +20,58 @@
)
end
before do
group.variables << variable
shared_examples 'audit creation' do
let(:action) { :create }
it 'logs audit event' do
expect { execute }.to change(AuditEvent, :count).from(0).to(1)
end
it 'logs variable group creation' do
execute
audit_event = AuditEvent.last.present
expect(audit_event.action).to eq(message)
expect(audit_event.target).to eq(variable.key)
end
it_behaves_like 'sends correct event type in audit event stream' do
let_it_be(:event_type) { event_type }
end
end
context 'when audits are available' do
shared_examples 'audit when updating variable protection' do
let(:action) { :update }
before do
stub_licensed_features(audit_events: true)
variable.update!(protected: true)
end
context 'when creating variable' do
let(:action) { :create }
it 'logs audit event' do
expect { execute }.to change(AuditEvent, :count).from(0).to(1)
end
it 'logs audit event' do
expect { execute }.to change(AuditEvent, :count).from(0).to(1)
end
it 'logs variable protection update' do
execute
it 'logs variable creation' do
execute
audit_event = AuditEvent.last.present
expect(audit_event.action).to eq('Changed variable protection from false to true')
expect(audit_event.target).to eq(variable.key)
end
it_behaves_like 'sends correct event type in audit event stream' do
let_it_be(:event_type) { event_type }
end
end
audit_event = AuditEvent.last.present
shared_examples 'no audit events are created' do
context 'when creating variable' do
let(:action) { :create }
expect(audit_event.action).to eq('Added ci group variable')
expect(audit_event.target).to eq(variable.key)
it 'does not log an audit event' do
expect { execute }.not_to change(AuditEvent, :count).from(0)
end
end
......@@ -50,68 +82,115 @@
variable.update!(protected: true)
end
it 'logs audit event' do
expect { execute }.to change(AuditEvent, :count).from(0).to(1)
end
it 'logs variable protection update' do
execute
audit_event = AuditEvent.last.present
expect(audit_event.action).to eq('Changed variable protection from false to true')
expect(audit_event.target).to eq(variable.key)
it 'does not log an audit event' do
expect { execute }.not_to change(AuditEvent, :count).from(0)
end
end
context 'when destroying variable' do
let(:action) { :destroy }
it 'logs audit event' do
expect { execute }.to change(AuditEvent, :count).from(0).to(1)
it 'does not log an audit event' do
expect { execute }.not_to change(AuditEvent, :count).from(0)
end
end
end
shared_examples 'when destroying variable' do
let(:action) { :destroy }
it 'logs variable destruction' do
execute
it 'logs audit event' do
expect { execute }.to change(AuditEvent, :count).from(0).to(1)
end
audit_event = AuditEvent.last.present
it 'logs variable destruction' do
execute
expect(audit_event.action).to eq('Removed ci group variable')
expect(audit_event.target).to eq(variable.key)
end
audit_event = AuditEvent.last.present
expect(audit_event.action).to eq(message)
expect(audit_event.target).to eq(variable.key)
end
it_behaves_like 'sends correct event type in audit event stream' do
let_it_be(:event_type) { "ci_group_variable_deleted" }
end
end
context 'when audits are not available' do
context 'when audits are available' do
before do
stub_licensed_features(audit_events: false)
stub_licensed_features(audit_events: true)
stub_licensed_features(external_audit_events: true)
group.external_audit_event_destinations.create!(destination_url: 'http://example.com')
end
context 'when creating variable' do
let(:action) { :create }
context 'when creating group variable' do
it_behaves_like 'audit creation' do
let(:variable) { group_variable }
it 'does not log an audit event' do
expect { execute }.not_to change(AuditEvent, :count).from(0)
let_it_be(:message) { 'Added ci group variable' }
let_it_be(:event_type) { "ci_group_variable_created" }
end
end
context 'when updating variable protection' do
let(:action) { :update }
context 'when updating group variable protection' do
it_behaves_like 'audit when updating variable protection' do
let(:variable) { group_variable }
before do
variable.update!(protected: true)
let_it_be(:event_type) { "ci_group_variable_updated" }
end
end
it 'does not log an audit event' do
expect { execute }.not_to change(AuditEvent, :count).from(0)
context 'when deleting group variable' do
it_behaves_like 'audit when updating variable protection' do
let(:variable) { group_variable }
let_it_be(:message) { 'Removed ci group variable' }
let_it_be(:event_type) { "ci_group_variable_updated" }
end
end
context 'when destroying variable' do
let(:action) { :destroy }
context 'when creating project variable' do
it_behaves_like 'audit creation' do
let(:variable) { project_variable }
it 'does not log an audit event' do
expect { execute }.not_to change(AuditEvent, :count).from(0)
let_it_be(:message) { 'Added ci variable' }
let_it_be(:event_type) { "ci_variable_created" }
end
end
context 'when updating project variable protection' do
it_behaves_like 'audit when updating variable protection' do
let(:variable) { project_variable }
let_it_be(:event_type) { "ci_variable_updated" }
end
end
context 'when deleting project variable' do
it_behaves_like 'audit when updating variable protection' do
let(:variable) { project_variable }
let_it_be(:message) { 'Removed ci variable' }
let_it_be(:event_type) { "ci_variable_updated" }
end
end
end
context 'when audits are not available' do
before do
stub_licensed_features(audit_events: false)
end
context 'for group variable' do
it_behaves_like 'no audit events are created' do
let(:variable) { group_variable }
end
end
context 'for project variable' do
it_behaves_like 'no audit events are created' do
let(:variable) { project_variable }
end
end
end
......
......@@ -56,4 +56,10 @@
let!(:parent) { model.group }
end
describe '#audit_details' do
it "equals to the group variable's key" do
expect(subject.audit_details).to eq(subject.key)
end
end
end
......@@ -51,4 +51,10 @@
let!(:model) { create(:ci_variable, project: parent) }
end
end
describe '#audit_details' do
it "equals to the variable's key" do
expect(subject.audit_details).to eq(subject.key)
end
end
end
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