Class: Aikido::Zen::Collector

Inherits:
Object
  • Object
show all
Defined in:
lib/aikido/zen/collector.rb,
lib/aikido/zen/collector/event.rb

Overview

Handles collecting all the runtime statistics to report back to the Aikido servers.

Defined Under Namespace

Modules: Events Classes: Event, Hosts, Routes, SinkStats, Stats, Users

Instance Method Summary collapse

Constructor Details

#initialize(config: Aikido::Zen.config) ⇒ Collector

Returns a new instance of Collector.



9
10
11
12
13
14
15
16
17
18
19
20
# File 'lib/aikido/zen/collector.rb', line 9

def initialize(config: Aikido::Zen.config)
  @config = config

  @events = Queue.new

  @stats = Concurrent::AtomicReference.new(Stats.new(@config))
  @users = Concurrent::AtomicReference.new(Users.new(@config))
  @hosts = Concurrent::AtomicReference.new(Hosts.new(@config))
  @routes = Concurrent::AtomicReference.new(Routes.new(@config))

  @middleware_installed = Concurrent::AtomicBoolean.new
end

Instance Method Details

#add_event(event) ⇒ void

This method returns an undefined value.

Add an event, to be handled in the collector in current process or sent to a collector in another process.

Parameters:



27
28
29
# File 'lib/aikido/zen/collector.rb', line 27

def add_event(event)
  @events << event
end

#flush(at: Time.now.utc) ⇒ Aikido::Zen::Events::Heartbeat

Flush all the stats into a Heartbeat event that can be reported back to the Aikido servers.

Parameters:

  • at (Time) (defaults to: Time.now.utc)

    the time at which stats collection stopped and the start of the new stats collection period. Defaults to now.

Returns:



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/aikido/zen/collector.rb', line 56

def flush(at: Time.now.utc)
  handle

  stats = @stats.get_and_set(Stats.new(@config))
  users = @users.get_and_set(Users.new(@config))
  hosts = @hosts.get_and_set(Hosts.new(@config))
  routes = @routes.get_and_set(Routes.new(@config))

  start(at: at)
  stats = stats.flush(at: at)

  Aikido::Zen::Events::Heartbeat.new(
    stats: stats, users: users, hosts: hosts, routes: routes, middleware_installed: middleware_installed?
  )
end

#flush_eventsArray<Aikido::Zen::Collector::Event>

Flush all events.

Returns:



39
40
41
# File 'lib/aikido/zen/collector.rb', line 39

def flush_events
  Array.new(@events.size) { @events.pop }
end

#handlevoid

This method returns an undefined value.

Handle the events in the queue.



46
47
48
# File 'lib/aikido/zen/collector.rb', line 46

def handle
  flush_events.each { |event| event.handle(self) }
end

#handle_track_attack(sink_name, being_blocked:) ⇒ Object



166
167
168
169
170
# File 'lib/aikido/zen/collector.rb', line 166

def handle_track_attack(sink_name, being_blocked:)
  synchronize(@stats) do |stats|
    stats.add_attack(sink_name, being_blocked: being_blocked)
  end
end

#handle_track_attack_wave(being_blocked:) ⇒ Object



138
139
140
141
142
# File 'lib/aikido/zen/collector.rb', line 138

def handle_track_attack_wave(being_blocked:)
  synchronize(@stats) do |stats|
    stats.add_attack_wave(being_blocked: being_blocked)
  end
end

#handle_track_ip_list(ip_list_keys) ⇒ Object



126
127
128
# File 'lib/aikido/zen/collector.rb', line 126

def handle_track_ip_list(ip_list_keys)
  synchronize(@stats) { |stats| stats.add_ip_list(ip_list_keys) }
end

#handle_track_outbound(connection) ⇒ Object



192
193
194
# File 'lib/aikido/zen/collector.rb', line 192

def handle_track_outbound(connection)
  synchronize(@hosts) { |hosts| hosts.add(connection) }
end

#handle_track_rate_limited_requestObject



98
99
100
# File 'lib/aikido/zen/collector.rb', line 98

def handle_track_rate_limited_request
  synchronize(@stats) { |stats| stats.add_rate_limited_request }
end

#handle_track_requestObject



87
88
89
# File 'lib/aikido/zen/collector.rb', line 87

def handle_track_request
  synchronize(@stats) { |stats| stats.add_request }
end

#handle_track_route(route, schema) ⇒ Object



204
205
206
# File 'lib/aikido/zen/collector.rb', line 204

def handle_track_route(route, schema)
  synchronize(@routes) { |routes| routes.add(route, schema) }
end

#handle_track_scan(sink_name, duration, has_errors:) ⇒ Object



152
153
154
155
156
# File 'lib/aikido/zen/collector.rb', line 152

def handle_track_scan(sink_name, duration, has_errors:)
  synchronize(@stats) do |stats|
    stats.add_scan(sink_name, duration, has_errors: has_errors)
  end
end

#handle_track_user(actor) ⇒ Object



180
181
182
# File 'lib/aikido/zen/collector.rb', line 180

def handle_track_user(actor)
  synchronize(@users) { |users| users.add(actor) }
end

#handle_track_user_agent(user_agent_keys) ⇒ Object



112
113
114
# File 'lib/aikido/zen/collector.rb', line 112

def handle_track_user_agent(user_agent_keys)
  synchronize(@stats) { |stats| stats.add_user_agent(user_agent_keys) }
end

#has_events?Boolean

Returns whether the collector has any events.

Returns:

  • (Boolean)

    whether the collector has any events



32
33
34
# File 'lib/aikido/zen/collector.rb', line 32

def has_events?
  !@events.empty?
end

#hostsObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Note:

Visible for testing.



231
232
233
234
# File 'lib/aikido/zen/collector.rb', line 231

def hosts
  handle
  @hosts.get
end

#middleware_installed!Object



208
209
210
# File 'lib/aikido/zen/collector.rb', line 208

def middleware_installed!
  @middleware_installed.make_true
end

#middleware_installed?Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Note:

Visible for testing.

Returns:

  • (Boolean)


247
248
249
# File 'lib/aikido/zen/collector.rb', line 247

def middleware_installed?
  @middleware_installed.true?
end

#routesObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Note:

Visible for testing.



239
240
241
242
# File 'lib/aikido/zen/collector.rb', line 239

def routes
  handle
  @routes.get
end

#start(at: Time.now.utc) ⇒ void

This method returns an undefined value.

Sets the start time for this collection period.

Parameters:

  • at (Time) (defaults to: Time.now.utc)

    defaults to now.



76
77
78
# File 'lib/aikido/zen/collector.rb', line 76

def start(at: Time.now.utc)
  synchronize(@stats) { |stats| stats.start(at) }
end

#statsObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Note:

Visible for testing.



215
216
217
218
# File 'lib/aikido/zen/collector.rb', line 215

def stats
  handle
  @stats.get
end

#track_attack(attack) ⇒ void

This method returns an undefined value.

Track stats about an attack detected by our scanners.

Parameters:



162
163
164
# File 'lib/aikido/zen/collector.rb', line 162

def track_attack(attack)
  add_event(Events::TrackAttack.new(attack.sink.name, being_blocked: attack.blocked?))
end

#track_attack_wave(being_blocked:) ⇒ void

This method returns an undefined value.

Track stats about an attack detected by our scanners.

Parameters:



134
135
136
# File 'lib/aikido/zen/collector.rb', line 134

def track_attack_wave(being_blocked:)
  add_event(Events::TrackAttackWave.new(being_blocked: being_blocked))
end

#track_ip_list(ip_list_keys) ⇒ void

This method returns an undefined value.

Track stats about blocked and monitored IP lists

Parameters:

  • ip_list_keys (Array<String>, nil)


120
121
122
123
124
# File 'lib/aikido/zen/collector.rb', line 120

def track_ip_list(ip_list_keys)
  return if ip_list_keys.nil? || ip_list_keys.empty?

  add_event(Events::TrackIPList.new(ip_list_keys))
end

#track_outbound(connection) ⇒ void

This method returns an undefined value.

Track an HTTP connections to an external host.

Parameters:



188
189
190
# File 'lib/aikido/zen/collector.rb', line 188

def track_outbound(connection)
  add_event(Events::TrackOutbound.new(connection))
end

#track_rate_limited_requestvoid

This method returns an undefined value.

Track stats about the rate_limited_requests



94
95
96
# File 'lib/aikido/zen/collector.rb', line 94

def track_rate_limited_request
  add_event(Events::TrackRateLimitedRequest.new)
end

#track_requestvoid

This method returns an undefined value.

Track stats about the requests



83
84
85
# File 'lib/aikido/zen/collector.rb', line 83

def track_request
  add_event(Events::TrackRequest.new)
end

#track_route(request) ⇒ void

This method returns an undefined value.

Record the visited endpoint, and if enabled, the API schema for this endpoint.

Parameters:



200
201
202
# File 'lib/aikido/zen/collector.rb', line 200

def track_route(request)
  add_event(Events::TrackRoute.new(request.route, request.schema))
end

#track_scan(scan) ⇒ void

This method returns an undefined value.

Track stats about a scan performed by one of our sinks.

Parameters:



148
149
150
# File 'lib/aikido/zen/collector.rb', line 148

def track_scan(scan)
  add_event(Events::TrackScan.new(scan.sink.name, scan.duration, has_errors: scan.errors?))
end

#track_user(actor) ⇒ void

This method returns an undefined value.

Track the user reported by the developer to be behind this request.

Parameters:



176
177
178
# File 'lib/aikido/zen/collector.rb', line 176

def track_user(actor)
  add_event(Events::TrackUser.new(actor))
end

#track_user_agent(user_agent_keys) ⇒ void

This method returns an undefined value.

Track stats about monitored and blocked user agents

Parameters:

  • user_agent_keys (Array<String>, nil)

    the user agent keys



106
107
108
109
110
# File 'lib/aikido/zen/collector.rb', line 106

def track_user_agent(user_agent_keys)
  return if user_agent_keys.nil? || user_agent_keys.empty?

  add_event(Events::TrackUserAgent.new(user_agent_keys))
end

#usersObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Note:

Visible for testing.



223
224
225
226
# File 'lib/aikido/zen/collector.rb', line 223

def users
  handle
  @users.get
end