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
-
#kind ⇒ String
readonly
Category of operation this sink represents.
-
#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, kind, 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'sreporterto track statistics and potentially handle theAttack, if anything.
Constructor Details
#initialize(name, kind, scanners:, operation: name, reporter: DEFAULT_REPORTER) ⇒ Sink
Returns a new instance of Sink.
60 61 62 63 64 65 66 67 68 |
# File 'lib/aikido/zen/sink.rb', line 60 def initialize(name, kind, scanners:, operation: name, reporter: DEFAULT_REPORTER) raise ArgumentError, "scanners cannot be empty" if scanners.empty? @name = name @kind = kind @operation = operation @scanners = scanners @reporter = reporter end |
Instance Attribute Details
#kind ⇒ String (readonly)
47 48 49 |
# File 'lib/aikido/zen/sink.rb', line 47 def kind @kind end |
#name ⇒ String (readonly)
44 45 46 |
# File 'lib/aikido/zen/sink.rb', line 44 def name @name end |
#operation ⇒ String (readonly)
56 57 58 |
# File 'lib/aikido/zen/sink.rb', line 56 def operation @operation end |
#scanners ⇒ Array<#call> (readonly)
50 51 52 |
# File 'lib/aikido/zen/sink.rb', line 50 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.
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
# File 'lib/aikido/zen/sink.rb', line 87 def scan(context: Aikido::Zen.current_context, **scan_params) return if context&.scanning context&.scanning = true return if context&.protection_disabled? scan = Scan.new(sink: self, context: context) scans_performed = 0 scan.perform do result = nil scanners.each do |scanner| next if scanner.skips_on_nil_context? && context.nil? result = scanner.call(scan: scan, sink: self, context: context, **scan_params) scans_performed += 1 break result if result rescue => error scan.track_error(error, scanner) end result end @reporter.call(scan) if scans_performed > 0 scan ensure context&.scanning = false end |