Class: Gitlab::Audit::Auditor
- Inherits:
-
Object
- Object
- Gitlab::Audit::Auditor
- Defined in:
- lib/gitlab/audit/auditor.rb
Constant Summary collapse
- PERMITTED_TARGET_CLASSES =
[ ::Operations::FeatureFlag ].freeze
Instance Attribute Summary collapse
-
#name ⇒ Object
readonly
Returns the value of attribute name.
-
#scope ⇒ Object
readonly
Returns the value of attribute scope.
Class Method Summary collapse
-
.audit(context, &block) ⇒ Object
Record audit events.
Instance Method Summary collapse
- #audit_enabled? ⇒ Boolean
- #authentication_event? ⇒ Boolean
- #authentication_event_payload ⇒ Object
- #author_if_user ⇒ Object
- #build_event(message) ⇒ Object
-
#initialize(context = {}) ⇒ Auditor
constructor
A new instance of Auditor.
- #log_authentication_event ⇒ Object
- #log_events_and_stream(events) ⇒ Object
- #log_to_database(events) ⇒ Object
- #log_to_file(events) ⇒ Object
- #log_to_file_and_stream(events) ⇒ Object
- #multiple_audit ⇒ Object
- #permitted_target? ⇒ Boolean
- #record(events) ⇒ Object
- #send_to_stream(events) ⇒ Object
- #single_audit ⇒ Object
- #stream_only? ⇒ Boolean
Constructor Details
#initialize(context = {}) ⇒ Auditor
Returns a new instance of Auditor.
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/gitlab/audit/auditor.rb', line 62 def initialize(context = {}) @context = context @name = @context.fetch(:name, 'audit_operation') @is_audit_event_yaml_defined = Gitlab::Audit::Type::Definition.defined?(@name) @stream_only = stream_only? @author = @context.fetch(:author) @scope = @context.fetch(:scope) @target = @context.fetch(:target) @created_at = @context.fetch(:created_at, DateTime.current) @message = @context.fetch(:message, '') @additional_details = @context.fetch(:additional_details, {}) @ip_address = @context[:ip_address] @target_details = @context[:target_details] @authentication_event = @context.fetch(:authentication_event, false) @authentication_provider = @context[:authentication_provider] return if @is_audit_event_yaml_defined raise StandardError, "Audit event type YML file is not defined for #{@name}. Please read " \ "https://docs.gitlab.com/ee/development/audit_event_guide/" \ "#how-to-instrument-new-audit-events for adding a new audit event" end |
Instance Attribute Details
#name ⇒ Object (readonly)
Returns the value of attribute name.
6 7 8 |
# File 'lib/gitlab/audit/auditor.rb', line 6 def name @name end |
#scope ⇒ Object (readonly)
Returns the value of attribute scope.
6 7 8 |
# File 'lib/gitlab/audit/auditor.rb', line 6 def scope @scope end |
Class Method Details
.audit(context, &block) ⇒ Object
Record audit events
50 51 52 53 54 55 56 57 58 59 60 |
# File 'lib/gitlab/audit/auditor.rb', line 50 def self.audit(context, &block) auditor = new(context) return unless auditor.audit_enabled? if block auditor.multiple_audit(&block) else auditor.single_audit end end |
Instance Method Details
#audit_enabled? ⇒ Boolean
117 118 119 |
# File 'lib/gitlab/audit/auditor.rb', line 117 def audit_enabled? authentication_event? || permitted_target? end |
#authentication_event? ⇒ Boolean
125 126 127 |
# File 'lib/gitlab/audit/auditor.rb', line 125 def authentication_event? @authentication_event end |
#authentication_event_payload ⇒ Object
146 147 148 149 150 151 152 153 154 155 156 |
# File 'lib/gitlab/audit/auditor.rb', line 146 def authentication_event_payload { # @author can be a User or various Gitlab::Audit authors. # Only capture real users for successful authentication events. user: , user_name: @author.name, ip_address: Gitlab::RequestContext.instance.client_ip || @author.current_sign_in_ip, result: AuthenticationEvent.results[:success], provider: @authentication_provider } end |
#author_if_user ⇒ Object
158 159 160 |
# File 'lib/gitlab/audit/auditor.rb', line 158 def @author if @author.is_a?(User) end |
#build_event(message) ⇒ Object
166 167 168 169 170 171 172 173 174 175 176 177 |
# File 'lib/gitlab/audit/auditor.rb', line 166 def build_event() AuditEvents::BuildService.new( author: @author, scope: @scope, target: @target, created_at: @created_at, message: , additional_details: @additional_details, ip_address: @ip_address, target_details: @target_details ).execute end |
#log_authentication_event ⇒ Object
137 138 139 140 141 142 143 144 |
# File 'lib/gitlab/audit/auditor.rb', line 137 def log_authentication_event return unless Gitlab::Database.read_write? && authentication_event? event = AuthenticationEvent.new(authentication_event_payload) event.save! rescue ActiveRecord::RecordInvalid => e ::Gitlab::ErrorTracking.track_exception(e, audit_operation: @name) end |
#log_events_and_stream(events) ⇒ Object
101 102 103 104 105 106 107 108 109 110 |
# File 'lib/gitlab/audit/auditor.rb', line 101 def log_events_and_stream(events) log_authentication_event saved_events = log_to_database(events) # we only want to override events with saved_events when it successfully saves into database. # we are doing so to ensure events in memory reflects events saved in database and have id column. events = saved_events if saved_events.present? log_to_file_and_stream(events) end |
#log_to_database(events) ⇒ Object
179 180 181 182 183 184 185 186 187 188 189 |
# File 'lib/gitlab/audit/auditor.rb', line 179 def log_to_database(events) if events.one? events.first.save! events else event_ids = AuditEvent.bulk_insert!(events, returns: :ids) AuditEvent.id_in(event_ids) end rescue ActiveRecord::RecordInvalid => e ::Gitlab::ErrorTracking.track_exception(e, audit_operation: @name) end |
#log_to_file(events) ⇒ Object
191 192 193 194 195 |
# File 'lib/gitlab/audit/auditor.rb', line 191 def log_to_file(events) file_logger = ::Gitlab::AuditJsonLogger.build events.each { |event| file_logger.info(log_payload(event)) } end |
#log_to_file_and_stream(events) ⇒ Object
112 113 114 115 |
# File 'lib/gitlab/audit/auditor.rb', line 112 def log_to_file_and_stream(events) log_to_file(events) send_to_stream(events) end |
#multiple_audit ⇒ Object
92 93 94 95 |
# File 'lib/gitlab/audit/auditor.rb', line 92 def multiple_audit # For now we dont have any need to implement multiple audit event functionality in CE # Defined in EE end |
#permitted_target? ⇒ Boolean
121 122 123 |
# File 'lib/gitlab/audit/auditor.rb', line 121 def permitted_target? @target.class.in? PERMITTED_TARGET_CLASSES end |
#record(events) ⇒ Object
97 98 99 |
# File 'lib/gitlab/audit/auditor.rb', line 97 def record(events) @stream_only ? send_to_stream(events) : log_events_and_stream(events) end |
#send_to_stream(events) ⇒ Object
162 163 164 |
# File 'lib/gitlab/audit/auditor.rb', line 162 def send_to_stream(events) # Defined in EE end |
#single_audit ⇒ Object
86 87 88 89 90 |
# File 'lib/gitlab/audit/auditor.rb', line 86 def single_audit events = [build_event(@message)] record(events) end |
#stream_only? ⇒ Boolean
129 130 131 132 133 134 135 |
# File 'lib/gitlab/audit/auditor.rb', line 129 def stream_only? if @is_audit_event_yaml_defined Gitlab::Audit::Type::Definition.stream_only?(@name) else @context.fetch(:stream_only, false) end end |