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



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

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



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

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

#handle_track_outbound(connection) ⇒ Object



178
179
180
# File 'lib/aikido/zen/collector.rb', line 178

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



190
191
192
# File 'lib/aikido/zen/collector.rb', line 190

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

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



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

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



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

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.



217
218
219
220
# File 'lib/aikido/zen/collector.rb', line 217

def hosts
  handle
  @hosts.get
end

#middleware_installed!Object



194
195
196
# File 'lib/aikido/zen/collector.rb', line 194

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)


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

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.



225
226
227
228
# File 'lib/aikido/zen/collector.rb', line 225

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.



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

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:



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

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:



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

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

#track_outbound(connection) ⇒ void

This method returns an undefined value.

Track an HTTP connections to an external host.

Parameters:



174
175
176
# File 'lib/aikido/zen/collector.rb', line 174

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:



186
187
188
# File 'lib/aikido/zen/collector.rb', line 186

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:



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

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:



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

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:

  • the (Array<String>, nil)

    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?

  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.



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

def users
  handle
  @users.get
end