aikido-zen 1.2.3-arm64-linux → 1.3.0-arm64-linux
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/benchmarks/ip_list/benchmark.rb +39 -0
- data/lib/aikido/zen/agent.rb +3 -0
- data/lib/aikido/zen/collector/event.rb +27 -0
- data/lib/aikido/zen/collector/stats.rb +11 -1
- data/lib/aikido/zen/collector.rb +16 -2
- data/lib/aikido/zen/config.rb +10 -2
- data/lib/aikido/zen/middleware/ip_list_checker.rb +47 -0
- data/lib/aikido/zen/rails_engine.rb +1 -0
- data/lib/aikido/zen/runtime_settings/ip_list.rb +89 -0
- data/lib/aikido/zen/runtime_settings/ip_set.rb +2 -0
- data/lib/aikido/zen/runtime_settings.rb +51 -4
- data/lib/aikido/zen/version.rb +1 -1
- data/lib/aikido/zen.rb +11 -1
- metadata +5 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 29ba9f159c292e608cbe95092d79ebe8b1deaead1e4520fecebf5c12cd98d5b2
|
|
4
|
+
data.tar.gz: 74089a226d69444bb22941cef2af77b16eea38f57a6f292fe1ba69fa281e6256
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d901c1021e6e37969296ada67fa49bb3a6c22c345cf0534d46927fc4cf4eae0560b385965cc998d0edfb8b4aa9e4f3cc426f1473e9e5e92f8472ce25142af773
|
|
7
|
+
data.tar.gz: 041476ab0a053ed6d13730976e8fdbd4abbb4f64fa96d8f1143e224a1d7edfc82db1777ddd064599c1976f343a5059987c16a78cb17d847e5b0f9a6b0ac55fb9
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require "benchmark"
|
|
4
|
+
require "aikido-zen"
|
|
5
|
+
|
|
6
|
+
random_ipv4_ranges = (0..).lazy.map do
|
|
7
|
+
ip_int = rand(2**32)
|
|
8
|
+
prefix = rand(8..32)
|
|
9
|
+
network = IPAddr.new(ip_int, Socket::AF_INET).mask(prefix)
|
|
10
|
+
"#{network}/#{prefix}"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
random_ipv6_ranges = (0..).lazy.map do
|
|
14
|
+
ip_int = rand(2**128)
|
|
15
|
+
prefix = rand(1..128)
|
|
16
|
+
network = IPAddr.new(ip_int, Socket::AF_INET6).mask(prefix)
|
|
17
|
+
"#{network}/#{prefix}"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
random_ip_ranges = (0..).lazy.map do
|
|
21
|
+
(rand < 0.5) ? random_ipv4_ranges.next : random_ipv6_ranges.next
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
if __FILE__ == $0
|
|
25
|
+
ip_ranges = random_ip_ranges.take(1000)
|
|
26
|
+
|
|
27
|
+
ip_list = Aikido::Zen::RuntimeSettings::IPList.from_json({
|
|
28
|
+
"key" => "key",
|
|
29
|
+
"source" => "source",
|
|
30
|
+
"description" => "description",
|
|
31
|
+
"ips" => ip_ranges
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
result = Benchmark.measure do
|
|
35
|
+
ip_ranges.all? { |ip_range| ip_list.include?(ip_range) }
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
puts result
|
|
39
|
+
end
|
data/lib/aikido/zen/agent.rb
CHANGED
|
@@ -160,6 +160,9 @@ module Aikido::Zen
|
|
|
160
160
|
if Aikido::Zen.runtime_settings.update_from_runtime_config_json(response)
|
|
161
161
|
updated_settings!
|
|
162
162
|
@config.logger.info("Updated runtime settings after heartbeat")
|
|
163
|
+
|
|
164
|
+
Aikido::Zen.runtime_settings.update_from_runtime_firewall_lists_json(@api_client.fetch_runtime_firewall_lists)
|
|
165
|
+
@config.logger.info("Updated runtime firewall list after heartbeat")
|
|
163
166
|
end
|
|
164
167
|
end
|
|
165
168
|
end
|
|
@@ -95,6 +95,33 @@ module Aikido::Zen
|
|
|
95
95
|
end
|
|
96
96
|
end
|
|
97
97
|
|
|
98
|
+
class TrackIPList < Event
|
|
99
|
+
register "track_ip_list"
|
|
100
|
+
|
|
101
|
+
def self.from_json(data)
|
|
102
|
+
new(data[:ip_list_keys])
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def initialize(ip_list_keys)
|
|
106
|
+
super()
|
|
107
|
+
@ip_list_keys = ip_list_keys
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def as_json
|
|
111
|
+
super.update({
|
|
112
|
+
ip_list_keys: @ip_list_keys
|
|
113
|
+
})
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def handle(collector)
|
|
117
|
+
collector.handle_track_ip_list(@ip_list_keys)
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def inspect
|
|
121
|
+
"#<#{self.class.name} #{@ip_list_keys.inspect}>"
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
98
125
|
class TrackAttackWave < Event
|
|
99
126
|
register "track_attack_wave"
|
|
100
127
|
|
|
@@ -8,7 +8,7 @@ module Aikido::Zen
|
|
|
8
8
|
# Tracks information about how the Aikido Agent is used in the app.
|
|
9
9
|
class Collector::Stats
|
|
10
10
|
# @!visibility private
|
|
11
|
-
attr_reader :started_at, :ended_at, :requests, :aborted_requests, :rate_limited_requests, :user_agents, :attack_waves, :blocked_attack_waves, :sinks
|
|
11
|
+
attr_reader :started_at, :ended_at, :requests, :aborted_requests, :rate_limited_requests, :user_agents, :ip_lists, :attack_waves, :blocked_attack_waves, :sinks
|
|
12
12
|
|
|
13
13
|
# @!visibility private
|
|
14
14
|
attr_writer :ended_at
|
|
@@ -22,6 +22,7 @@ module Aikido::Zen
|
|
|
22
22
|
@aborted_requests = 0
|
|
23
23
|
@rate_limited_requests = 0
|
|
24
24
|
@user_agents = Hash.new { |h, k| h[k] = 0 }
|
|
25
|
+
@ip_lists = Hash.new { |h, k| h[k] = 0 }
|
|
25
26
|
@attack_waves = 0
|
|
26
27
|
@blocked_attack_waves = 0
|
|
27
28
|
@sinks = Hash.new { |h, k| h[k] = Collector::SinkStats.new(k, @config) }
|
|
@@ -79,6 +80,12 @@ module Aikido::Zen
|
|
|
79
80
|
user_agent_keys&.each { |user_agent_key| @user_agents[user_agent_key] += 1 }
|
|
80
81
|
end
|
|
81
82
|
|
|
83
|
+
# @param user_agent_keys [Array<String>] the user agent keys
|
|
84
|
+
# @return [void]
|
|
85
|
+
def add_ip_list(ip_list_keys)
|
|
86
|
+
ip_list_keys&.each { |ip_list_key| @ip_lists[ip_list_key] += 1 }
|
|
87
|
+
end
|
|
88
|
+
|
|
82
89
|
# @param being_blocked [Boolean] whether the Agent blocked the request
|
|
83
90
|
# @return [void]
|
|
84
91
|
def add_attack_wave(being_blocked:)
|
|
@@ -127,6 +134,9 @@ module Aikido::Zen
|
|
|
127
134
|
},
|
|
128
135
|
userAgents: {
|
|
129
136
|
breakdown: @user_agents
|
|
137
|
+
},
|
|
138
|
+
ipAddresses: {
|
|
139
|
+
breakdown: @ip_lists
|
|
130
140
|
}
|
|
131
141
|
}
|
|
132
142
|
end
|
data/lib/aikido/zen/collector.rb
CHANGED
|
@@ -101,10 +101,10 @@ module Aikido::Zen
|
|
|
101
101
|
|
|
102
102
|
# Track stats about monitored and blocked user agents
|
|
103
103
|
#
|
|
104
|
-
# @param [Array<String>, nil] the user agent keys
|
|
104
|
+
# @param user_agent_keys [Array<String>, nil] the user agent keys
|
|
105
105
|
# @return [void]
|
|
106
106
|
def track_user_agent(user_agent_keys)
|
|
107
|
-
return if user_agent_keys.nil?
|
|
107
|
+
return if user_agent_keys.nil? || user_agent_keys.empty?
|
|
108
108
|
|
|
109
109
|
add_event(Events::TrackUserAgent.new(user_agent_keys))
|
|
110
110
|
end
|
|
@@ -113,6 +113,20 @@ module Aikido::Zen
|
|
|
113
113
|
synchronize(@stats) { |stats| stats.add_user_agent(user_agent_keys) }
|
|
114
114
|
end
|
|
115
115
|
|
|
116
|
+
# Track stats about blocked and monitored IP lists
|
|
117
|
+
#
|
|
118
|
+
# @param ip_list_keys [Array<String>, nil]
|
|
119
|
+
# @return [void]
|
|
120
|
+
def track_ip_list(ip_list_keys)
|
|
121
|
+
return if ip_list_keys.nil? || ip_list_keys.empty?
|
|
122
|
+
|
|
123
|
+
add_event(Events::TrackIPList.new(ip_list_keys))
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def handle_track_ip_list(ip_list_keys)
|
|
127
|
+
synchronize(@stats) { |stats| stats.add_ip_list(ip_list_keys) }
|
|
128
|
+
end
|
|
129
|
+
|
|
116
130
|
# Track stats about an attack detected by our scanners.
|
|
117
131
|
#
|
|
118
132
|
# @param attack [Aikido::Zen::Events::AttackWave]
|
data/lib/aikido/zen/config.rb
CHANGED
|
@@ -322,10 +322,18 @@ module Aikido::Zen
|
|
|
322
322
|
DEFAULT_DETACHED_AGENT_SOCKET_PATH = "aikido-detached-agent.%h.sock"
|
|
323
323
|
|
|
324
324
|
# @!visibility private
|
|
325
|
-
DEFAULT_BLOCKED_RESPONDER = ->(request, blocking_type) do
|
|
325
|
+
DEFAULT_BLOCKED_RESPONDER = ->(request, blocking_type, reason = nil) do
|
|
326
326
|
message = case blocking_type
|
|
327
327
|
when :ip
|
|
328
|
-
|
|
328
|
+
"Your IP address is not allowed to access this resource. (Your IP: #{request.ip})"
|
|
329
|
+
when :ip_allowed_list
|
|
330
|
+
"Your IP address is not allowed to access this resource. (Your IP: #{request.client_ip})"
|
|
331
|
+
when :ip_blocked_list
|
|
332
|
+
if reason.nil?
|
|
333
|
+
"Your IP is blocked."
|
|
334
|
+
else
|
|
335
|
+
"Your IP is blocked due to #{reason}."
|
|
336
|
+
end
|
|
329
337
|
when :user_agent
|
|
330
338
|
"You are not allowed to access this resource because you have been identified as a bot."
|
|
331
339
|
else
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Aikido::Zen
|
|
4
|
+
module Middleware
|
|
5
|
+
class IPListChecker
|
|
6
|
+
def initialize(app, zen: Aikido::Zen, config: zen.config, settings: zen.runtime_settings)
|
|
7
|
+
@app = app
|
|
8
|
+
@zen = zen
|
|
9
|
+
@config = config
|
|
10
|
+
@settings = settings
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def call(env)
|
|
14
|
+
request = Aikido::Zen::Middleware.request_from(env)
|
|
15
|
+
|
|
16
|
+
client_ip = request.client_ip
|
|
17
|
+
|
|
18
|
+
return @app.call(env) if bypassed_ip?(client_ip)
|
|
19
|
+
|
|
20
|
+
if !@settings.allowed_ip?(client_ip)
|
|
21
|
+
return @config.blocked_responder.call(request, :ip_allowed_list)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
monitored_ip_list_keys = @settings.monitored_ip_list_keys(client_ip)
|
|
25
|
+
@zen.track_ip_list(monitored_ip_list_keys)
|
|
26
|
+
|
|
27
|
+
blocked_ip_lists = @settings.blocked_ip_lists.filter { |ip_list| ip_list.include?(client_ip) }
|
|
28
|
+
|
|
29
|
+
if !blocked_ip_lists.empty?
|
|
30
|
+
@zen.track_ip_list(blocked_ip_lists.map(&:key))
|
|
31
|
+
|
|
32
|
+
return @config.blocked_responder.call(
|
|
33
|
+
request,
|
|
34
|
+
:ip_blocked_list,
|
|
35
|
+
blocked_ip_lists.first.description
|
|
36
|
+
)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
@app.call(env)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def bypassed_ip?(client_ip)
|
|
43
|
+
@settings.bypassed_ips.include?(client_ip)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -17,6 +17,7 @@ module Aikido::Zen
|
|
|
17
17
|
Aikido::Zen::Middleware::ForkDetector,
|
|
18
18
|
Aikido::Zen::Middleware::ContextSetter,
|
|
19
19
|
Aikido::Zen::Middleware::AllowedAddressChecker,
|
|
20
|
+
Aikido::Zen::Middleware::IPListChecker,
|
|
20
21
|
Aikido::Zen::Middleware::UserAgentChecker,
|
|
21
22
|
Aikido::Zen::Middleware::AttackProtector,
|
|
22
23
|
Aikido::Zen::Middleware::AttackWaveProtector,
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Aikido::Zen
|
|
4
|
+
class RuntimeSettings::IPList
|
|
5
|
+
attr_reader :key
|
|
6
|
+
attr_reader :source
|
|
7
|
+
attr_reader :description
|
|
8
|
+
attr_reader :ips
|
|
9
|
+
|
|
10
|
+
attr_reader :ipv4_ranges
|
|
11
|
+
attr_reader :ipv6_ranges
|
|
12
|
+
|
|
13
|
+
def self.from_json(data)
|
|
14
|
+
new(
|
|
15
|
+
key: data["key"],
|
|
16
|
+
source: data["source"],
|
|
17
|
+
description: data["description"],
|
|
18
|
+
ips: Array(data["ips"]).map { |ip| IPAddr.new(ip) }
|
|
19
|
+
)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def initialize(key:, source:, description:, ips:)
|
|
23
|
+
@key = key
|
|
24
|
+
@source = source
|
|
25
|
+
@description = description
|
|
26
|
+
@ips = ips
|
|
27
|
+
|
|
28
|
+
@ipv4_ranges = []
|
|
29
|
+
@ipv6_ranges = []
|
|
30
|
+
|
|
31
|
+
ips.each do |ip|
|
|
32
|
+
if ip.ipv4?
|
|
33
|
+
@ipv4_ranges << ip.to_range
|
|
34
|
+
elsif ip.ipv6?
|
|
35
|
+
@ipv6_ranges << ip.to_range
|
|
36
|
+
else
|
|
37
|
+
raise ArgumentError, "Unsupported IP address family: #{ip.inspect}"
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
@ipv4_ranges.sort_by!(&:begin)
|
|
42
|
+
@ipv6_ranges.sort_by!(&:begin)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def inspect
|
|
46
|
+
"#<#{self.class} #{@key}>"
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def include?(ip)
|
|
50
|
+
native_ip = nativize_ip(ip)
|
|
51
|
+
return false if native_ip.nil?
|
|
52
|
+
|
|
53
|
+
if native_ip.ipv4?
|
|
54
|
+
ranges_cover?(@ipv4_ranges, native_ip)
|
|
55
|
+
elsif native_ip.ipv6?
|
|
56
|
+
ranges_cover?(@ipv6_ranges, native_ip)
|
|
57
|
+
else
|
|
58
|
+
raise ArgumentError, "Unsupported IP address family: #{ip.inspect}"
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
private
|
|
63
|
+
|
|
64
|
+
def nativize_ip(ip)
|
|
65
|
+
case ip
|
|
66
|
+
when IPAddr
|
|
67
|
+
ip.native
|
|
68
|
+
when String
|
|
69
|
+
begin
|
|
70
|
+
IPAddr.new(ip).native
|
|
71
|
+
rescue IPAddr::InvalidAddressError
|
|
72
|
+
nil
|
|
73
|
+
end
|
|
74
|
+
when nil
|
|
75
|
+
nil
|
|
76
|
+
else
|
|
77
|
+
raise ArgumentError, "no explicit conversion of #{ip.class} to IPAddr"
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def ranges_cover?(ranges, ip)
|
|
82
|
+
index = ranges.bsearch_index { |range| range.begin > ip }
|
|
83
|
+
index = index ? index - 1 : ranges.size - 1
|
|
84
|
+
return false if index < 0
|
|
85
|
+
|
|
86
|
+
ranges[index].cover?(ip)
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
@@ -11,11 +11,14 @@ module Aikido::Zen
|
|
|
11
11
|
#
|
|
12
12
|
# You can subscribe to changes with +#add_observer(object, func_name)+, which
|
|
13
13
|
# will call the function passing the settings as an argument
|
|
14
|
-
RuntimeSettings = Struct.new(:updated_at, :heartbeat_interval, :endpoints, :blocked_user_ids, :bypassed_ips, :received_any_stats, :blocking_mode, :blocked_user_agent_regexp, :monitored_user_agent_regexp, :user_agent_details, :block_new_outbound, :domains, :excluded_user_ids_from_rate_limiting) do
|
|
14
|
+
RuntimeSettings = Struct.new(:updated_at, :heartbeat_interval, :endpoints, :blocked_user_ids, :bypassed_ips, :received_any_stats, :blocking_mode, :blocked_user_agent_regexp, :monitored_user_agent_regexp, :user_agent_details, :blocked_ip_lists, :allowed_ip_lists, :monitored_ip_lists, :block_new_outbound, :domains, :excluded_user_ids_from_rate_limiting) do
|
|
15
15
|
def initialize(*)
|
|
16
16
|
super
|
|
17
17
|
self.endpoints ||= RuntimeSettings::Endpoints.new
|
|
18
18
|
self.bypassed_ips ||= RuntimeSettings::IPSet.new
|
|
19
|
+
self.blocked_ip_lists ||= []
|
|
20
|
+
self.allowed_ip_lists ||= []
|
|
21
|
+
self.monitored_ip_lists ||= []
|
|
19
22
|
self.domains ||= RuntimeSettings::Domains.new
|
|
20
23
|
end
|
|
21
24
|
|
|
@@ -42,6 +45,15 @@ module Aikido::Zen
|
|
|
42
45
|
# @!attribute [rw] blocking_mode
|
|
43
46
|
# @return [Boolean]
|
|
44
47
|
|
|
48
|
+
# @!attribute [rw] blocked_ip_lists
|
|
49
|
+
# @return [Array<Aikido::Zen::RuntimeSettings::IPList>]
|
|
50
|
+
|
|
51
|
+
# @!attribute [rw] allowed_ip_lists
|
|
52
|
+
# @return [Array<Aikido::Zen::RuntimeSettings::IPList>]
|
|
53
|
+
|
|
54
|
+
# @!attribute [rw] monitored_ip_lists
|
|
55
|
+
# @return [Array<Aikido::Zen::RuntimeSettings::IPList>]
|
|
56
|
+
|
|
45
57
|
# @!attribute [rw] blocked_user_agent_regexp
|
|
46
58
|
# @return [Regexp]
|
|
47
59
|
|
|
@@ -112,6 +124,24 @@ module Aikido::Zen
|
|
|
112
124
|
pattern: pattern
|
|
113
125
|
}
|
|
114
126
|
end
|
|
127
|
+
|
|
128
|
+
self.blocked_ip_lists = []
|
|
129
|
+
|
|
130
|
+
data["blockedIPAddresses"]&.each do |ip_list|
|
|
131
|
+
blocked_ip_lists << RuntimeSettings::IPList.from_json(ip_list)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
self.allowed_ip_lists = []
|
|
135
|
+
|
|
136
|
+
data["allowedIPAddresses"]&.each do |ip_list|
|
|
137
|
+
allowed_ip_lists << RuntimeSettings::IPList.from_json(ip_list)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
self.monitored_ip_lists = []
|
|
141
|
+
|
|
142
|
+
data["monitoredIPAddresses"]&.each do |ip_list|
|
|
143
|
+
monitored_ip_lists << RuntimeSettings::IPList.from_json(ip_list)
|
|
144
|
+
end
|
|
115
145
|
end
|
|
116
146
|
|
|
117
147
|
# Construct a regular expression from the non-nil and non-empty string,
|
|
@@ -165,9 +195,25 @@ module Aikido::Zen
|
|
|
165
195
|
def user_agent_keys(user_agent)
|
|
166
196
|
return [] if user_agent_details.nil?
|
|
167
197
|
|
|
168
|
-
user_agent_details
|
|
169
|
-
|
|
170
|
-
|
|
198
|
+
user_agent_details.filter_map { |record| record[:key] if record[:pattern].match?(user_agent) }
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def allowed_ip?(ip)
|
|
202
|
+
allowed_ip_lists.empty? || allowed_ip_lists.any? { |ip_list| ip_list.include?(ip) }
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
def blocked_ip?(ip)
|
|
206
|
+
blocked_ip_lists.any? { |ip_list| ip_list.include?(ip) }
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def monitored_ip?(ip)
|
|
210
|
+
monitored_ip_lists.any? { |ip_list| ip_list.include?(ip) }
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
def monitored_ip_list_keys(ip)
|
|
214
|
+
return [] if ip.nil?
|
|
215
|
+
|
|
216
|
+
monitored_ip_lists.filter_map { |ip_list| ip_list.key if ip_list.include?(ip) }
|
|
171
217
|
end
|
|
172
218
|
|
|
173
219
|
def block_outbound?(connection)
|
|
@@ -181,5 +227,6 @@ module Aikido::Zen
|
|
|
181
227
|
end
|
|
182
228
|
|
|
183
229
|
require_relative "runtime_settings/ip_set"
|
|
230
|
+
require_relative "runtime_settings/ip_list"
|
|
184
231
|
require_relative "runtime_settings/endpoints"
|
|
185
232
|
require_relative "runtime_settings/domains"
|
data/lib/aikido/zen/version.rb
CHANGED
data/lib/aikido/zen.rb
CHANGED
|
@@ -17,6 +17,7 @@ require_relative "zen/middleware/middleware"
|
|
|
17
17
|
require_relative "zen/middleware/fork_detector"
|
|
18
18
|
require_relative "zen/middleware/context_setter"
|
|
19
19
|
require_relative "zen/middleware/allowed_address_checker"
|
|
20
|
+
require_relative "zen/middleware/ip_list_checker"
|
|
20
21
|
require_relative "zen/middleware/user_agent_checker"
|
|
21
22
|
require_relative "zen/middleware/attack_protector"
|
|
22
23
|
require_relative "zen/middleware/attack_wave_protector"
|
|
@@ -133,7 +134,7 @@ module Aikido
|
|
|
133
134
|
collector.track_rate_limited_request
|
|
134
135
|
end
|
|
135
136
|
|
|
136
|
-
# Track
|
|
137
|
+
# Track blocked and monitored user agents.
|
|
137
138
|
#
|
|
138
139
|
# @param user_agent_keys [Array<String>, nil] the user agent keys
|
|
139
140
|
# from matching runtime firewall list user agent details.
|
|
@@ -142,6 +143,15 @@ module Aikido
|
|
|
142
143
|
collector.track_user_agent(user_agent_keys)
|
|
143
144
|
end
|
|
144
145
|
|
|
146
|
+
# Track blocked and monitored IP lists.
|
|
147
|
+
#
|
|
148
|
+
# @param ip_list_keys [Array<String>, nil] the IP list keys
|
|
149
|
+
# from matching runtime firewall list IP lists.
|
|
150
|
+
# @return [void]
|
|
151
|
+
def self.track_ip_list(ip_list_keys)
|
|
152
|
+
collector.track_ip_list(ip_list_keys)
|
|
153
|
+
end
|
|
154
|
+
|
|
145
155
|
# Track statistics about an attack wave the app is handling.
|
|
146
156
|
#
|
|
147
157
|
# @param attack_wave [Aikido::Zen::Events::AttackWave]
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: aikido-zen
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.3.0
|
|
5
5
|
platform: arm64-linux
|
|
6
6
|
authors:
|
|
7
7
|
- Aikido Security
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-04-
|
|
11
|
+
date: 2026-04-28 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: concurrent-ruby
|
|
@@ -86,6 +86,7 @@ files:
|
|
|
86
86
|
- README.md
|
|
87
87
|
- Rakefile
|
|
88
88
|
- benchmarks/README.md
|
|
89
|
+
- benchmarks/ip_list/benchmark.rb
|
|
89
90
|
- benchmarks/rails7.1_benchmark.js
|
|
90
91
|
- benchmarks/rails7.1_sql_injection.js
|
|
91
92
|
- docs/banner.svg
|
|
@@ -131,6 +132,7 @@ files:
|
|
|
131
132
|
- lib/aikido/zen/middleware/attack_wave_protector.rb
|
|
132
133
|
- lib/aikido/zen/middleware/context_setter.rb
|
|
133
134
|
- lib/aikido/zen/middleware/fork_detector.rb
|
|
135
|
+
- lib/aikido/zen/middleware/ip_list_checker.rb
|
|
134
136
|
- lib/aikido/zen/middleware/middleware.rb
|
|
135
137
|
- lib/aikido/zen/middleware/rack_throttler.rb
|
|
136
138
|
- lib/aikido/zen/middleware/request_tracker.rb
|
|
@@ -157,6 +159,7 @@ files:
|
|
|
157
159
|
- lib/aikido/zen/runtime_settings/domain_settings.rb
|
|
158
160
|
- lib/aikido/zen/runtime_settings/domains.rb
|
|
159
161
|
- lib/aikido/zen/runtime_settings/endpoints.rb
|
|
162
|
+
- lib/aikido/zen/runtime_settings/ip_list.rb
|
|
160
163
|
- lib/aikido/zen/runtime_settings/ip_set.rb
|
|
161
164
|
- lib/aikido/zen/runtime_settings/protection_settings.rb
|
|
162
165
|
- lib/aikido/zen/runtime_settings/rate_limit_settings.rb
|