Class: Aikido::Zen::Sink
- Inherits:
-
Object
- Object
- Aikido::Zen::Sink
- Defined in:
- lib/aikido/zen/sink.rb
Overview
Sinks serve as the proxies between a given library that we protect (such as a database adapter that we patch to prevent SQL injections) and the reporting agent.
When a library is patched to track and potentially block attacks, we rely on a sink to run any scans required, and report any attacks to our agent.
Constant Summary collapse
- DEFAULT_REPORTER =
->(scan) { Aikido::Zen.track_scan(scan) }
Instance Attribute Summary collapse
-
#name ⇒ String
readonly
Name of the patched library (e.g. “mysql2”).
-
#operation ⇒ String
readonly
Descriptor of the module / method being scanned for attacks.
-
#scanners ⇒ Array<#call>
readonly
List of registered scanners for this sink.
Instance Method Summary collapse
-
#initialize(name, scanners:, operation: name, reporter: DEFAULT_REPORTER) ⇒ Sink
constructor
A new instance of Sink.
-
#scan(context: Aikido::Zen.current_context, **scan_params) ⇒ Aikido::Zen::Scan?
Run the given arguments through all the registered scanners, until one of them returns an Attack or all return
nil
, and report the findings back to the Sink’sreporter
to track statistics and potentially handle theAttack
, if anything.
Constructor Details
#initialize(name, scanners:, operation: name, reporter: DEFAULT_REPORTER) ⇒ Sink
Returns a new instance of Sink.
56 57 58 59 60 61 62 63 |
# File 'lib/aikido/zen/sink.rb', line 56 def initialize(name, scanners:, operation: name, reporter: DEFAULT_REPORTER) raise ArgumentError, "scanners cannot be empty" if scanners.empty? @name = name @operation = operation @scanners = scanners @reporter = reporter end |
Instance Attribute Details
#name ⇒ String (readonly)
Returns name of the patched library (e.g. “mysql2”).
43 44 45 |
# File 'lib/aikido/zen/sink.rb', line 43 def name @name end |
#operation ⇒ String (readonly)
Returns descriptor of the module / method being scanned for attacks. This is fed into Attacks when instantiated. In certain cases, some scanners allow you to specialize this by using an operation
param of their own.
52 53 54 |
# File 'lib/aikido/zen/sink.rb', line 52 def operation @operation end |
#scanners ⇒ Array<#call> (readonly)
Returns list of registered scanners for this sink.
46 47 48 |
# File 'lib/aikido/zen/sink.rb', line 46 def scanners @scanners end |
Instance Method Details
#scan(context: Aikido::Zen.current_context, **scan_params) ⇒ Aikido::Zen::Scan?
Run the given arguments through all the registered scanners, until one of them returns an Attack or all return nil
, and report the findings back to the Sink’s reporter
to track statistics and potentially handle the Attack
, if anything.
This checks if runtime protection has been turned off for the current route first, and if so skips the scanning altogether, returning nil.
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/aikido/zen/sink.rb', line 82 def scan(context: Aikido::Zen.current_context, **scan_params) return if context&.protection_disabled? scan = Scan.new(sink: self, context: context) scan.perform do result = nil scanners.each do |scanner| result = scanner.call(sink: self, context: context, **scan_params) break result if result rescue Aikido::Zen::InternalsError => error Aikido::Zen.config.logger.warn(error.) scan.track_error(error, scanner) rescue => error scan.track_error(error, scanner) end result end @reporter.call(scan) scan end |