aikido-zen 1.1.2 → 1.2.3
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/lib/aikido/zen/agent.rb +0 -3
- data/lib/aikido/zen/collector/event.rb +0 -27
- data/lib/aikido/zen/collector/stats.rb +1 -11
- data/lib/aikido/zen/collector.rb +2 -16
- data/lib/aikido/zen/config.rb +2 -10
- data/lib/aikido/zen/rails_engine.rb +0 -1
- data/lib/aikido/zen/runtime_settings.rb +4 -51
- data/lib/aikido/zen/version.rb +1 -1
- data/lib/aikido/zen.rb +1 -11
- metadata +1 -3
- data/lib/aikido/zen/middleware/ip_list_checker.rb +0 -47
- data/lib/aikido/zen/runtime_settings/ip_list.rb +0 -34
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3312144ec7337da035ccdafd8a804cd64ebd67c8e671eaa9114a3326d2dfef16
|
|
4
|
+
data.tar.gz: 9b4c37976859977fc634a9af783f5b08287d1e0b5232cdf1b276fb5720d6c981
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e2ccd10321a51f382a3bd6f308ddb9abb09bf2241d35ec55c0cf17fe4d5abf81e3626a53217af717141b7fc8d728398aeb42c705f552ff260042b5e136a5d067
|
|
7
|
+
data.tar.gz: 1a77ca857611ee1038862f24f2b98704c9d241f4d1c0c945ff51e9942eed3cbc767acaf8e0e5059c6655432a3967b6860e2d530a456b62cdf64cace02b8fac07
|
data/lib/aikido/zen/agent.rb
CHANGED
|
@@ -160,9 +160,6 @@ 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")
|
|
166
163
|
end
|
|
167
164
|
end
|
|
168
165
|
end
|
|
@@ -95,33 +95,6 @@ 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
|
-
|
|
125
98
|
class TrackAttackWave < Event
|
|
126
99
|
register "track_attack_wave"
|
|
127
100
|
|
|
@@ -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, :
|
|
11
|
+
attr_reader :started_at, :ended_at, :requests, :aborted_requests, :rate_limited_requests, :user_agents, :attack_waves, :blocked_attack_waves, :sinks
|
|
12
12
|
|
|
13
13
|
# @!visibility private
|
|
14
14
|
attr_writer :ended_at
|
|
@@ -22,7 +22,6 @@ 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 }
|
|
26
25
|
@attack_waves = 0
|
|
27
26
|
@blocked_attack_waves = 0
|
|
28
27
|
@sinks = Hash.new { |h, k| h[k] = Collector::SinkStats.new(k, @config) }
|
|
@@ -80,12 +79,6 @@ module Aikido::Zen
|
|
|
80
79
|
user_agent_keys&.each { |user_agent_key| @user_agents[user_agent_key] += 1 }
|
|
81
80
|
end
|
|
82
81
|
|
|
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
|
-
|
|
89
82
|
# @param being_blocked [Boolean] whether the Agent blocked the request
|
|
90
83
|
# @return [void]
|
|
91
84
|
def add_attack_wave(being_blocked:)
|
|
@@ -134,9 +127,6 @@ module Aikido::Zen
|
|
|
134
127
|
},
|
|
135
128
|
userAgents: {
|
|
136
129
|
breakdown: @user_agents
|
|
137
|
-
},
|
|
138
|
-
ipAddresses: {
|
|
139
|
-
breakdown: @ip_lists
|
|
140
130
|
}
|
|
141
131
|
}
|
|
142
132
|
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
|
|
104
|
+
# @param [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?
|
|
108
108
|
|
|
109
109
|
add_event(Events::TrackUserAgent.new(user_agent_keys))
|
|
110
110
|
end
|
|
@@ -113,20 +113,6 @@ 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
|
-
|
|
130
116
|
# Track stats about an attack detected by our scanners.
|
|
131
117
|
#
|
|
132
118
|
# @param attack [Aikido::Zen::Events::AttackWave]
|
data/lib/aikido/zen/config.rb
CHANGED
|
@@ -322,18 +322,10 @@ 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
|
|
325
|
+
DEFAULT_BLOCKED_RESPONDER = ->(request, blocking_type) do
|
|
326
326
|
message = case blocking_type
|
|
327
327
|
when :ip
|
|
328
|
-
"Your IP address is not allowed to access this resource. (Your 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
|
|
328
|
+
format("Your IP address is not allowed to access this resource. (Your IP: %s)", request.ip)
|
|
337
329
|
when :user_agent
|
|
338
330
|
"You are not allowed to access this resource because you have been identified as a bot."
|
|
339
331
|
else
|
|
@@ -17,7 +17,6 @@ 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,
|
|
21
20
|
Aikido::Zen::Middleware::UserAgentChecker,
|
|
22
21
|
Aikido::Zen::Middleware::AttackProtector,
|
|
23
22
|
Aikido::Zen::Middleware::AttackWaveProtector,
|
|
@@ -11,14 +11,11 @@ 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, :
|
|
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
|
|
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 ||= []
|
|
22
19
|
self.domains ||= RuntimeSettings::Domains.new
|
|
23
20
|
end
|
|
24
21
|
|
|
@@ -45,15 +42,6 @@ module Aikido::Zen
|
|
|
45
42
|
# @!attribute [rw] blocking_mode
|
|
46
43
|
# @return [Boolean]
|
|
47
44
|
|
|
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
|
-
|
|
57
45
|
# @!attribute [rw] blocked_user_agent_regexp
|
|
58
46
|
# @return [Regexp]
|
|
59
47
|
|
|
@@ -124,24 +112,6 @@ module Aikido::Zen
|
|
|
124
112
|
pattern: pattern
|
|
125
113
|
}
|
|
126
114
|
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
|
|
145
115
|
end
|
|
146
116
|
|
|
147
117
|
# Construct a regular expression from the non-nil and non-empty string,
|
|
@@ -195,25 +165,9 @@ module Aikido::Zen
|
|
|
195
165
|
def user_agent_keys(user_agent)
|
|
196
166
|
return [] if user_agent_details.nil?
|
|
197
167
|
|
|
198
|
-
user_agent_details
|
|
199
|
-
|
|
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) }
|
|
168
|
+
user_agent_details
|
|
169
|
+
.filter { |record| record[:pattern].match?(user_agent) }
|
|
170
|
+
.map { |record| record[:key] }
|
|
217
171
|
end
|
|
218
172
|
|
|
219
173
|
def block_outbound?(connection)
|
|
@@ -227,6 +181,5 @@ module Aikido::Zen
|
|
|
227
181
|
end
|
|
228
182
|
|
|
229
183
|
require_relative "runtime_settings/ip_set"
|
|
230
|
-
require_relative "runtime_settings/ip_list"
|
|
231
184
|
require_relative "runtime_settings/endpoints"
|
|
232
185
|
require_relative "runtime_settings/domains"
|
data/lib/aikido/zen/version.rb
CHANGED
data/lib/aikido/zen.rb
CHANGED
|
@@ -17,7 +17,6 @@ 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"
|
|
21
20
|
require_relative "zen/middleware/user_agent_checker"
|
|
22
21
|
require_relative "zen/middleware/attack_protector"
|
|
23
22
|
require_relative "zen/middleware/attack_wave_protector"
|
|
@@ -134,7 +133,7 @@ module Aikido
|
|
|
134
133
|
collector.track_rate_limited_request
|
|
135
134
|
end
|
|
136
135
|
|
|
137
|
-
# Track
|
|
136
|
+
# Track monitored and blocked user agents.
|
|
138
137
|
#
|
|
139
138
|
# @param user_agent_keys [Array<String>, nil] the user agent keys
|
|
140
139
|
# from matching runtime firewall list user agent details.
|
|
@@ -143,15 +142,6 @@ module Aikido
|
|
|
143
142
|
collector.track_user_agent(user_agent_keys)
|
|
144
143
|
end
|
|
145
144
|
|
|
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
|
-
|
|
155
145
|
# Track statistics about an attack wave the app is handling.
|
|
156
146
|
#
|
|
157
147
|
# @param attack_wave [Aikido::Zen::Events::AttackWave]
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: aikido-zen
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.2.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Aikido Security
|
|
@@ -126,7 +126,6 @@ files:
|
|
|
126
126
|
- lib/aikido/zen/middleware/attack_wave_protector.rb
|
|
127
127
|
- lib/aikido/zen/middleware/context_setter.rb
|
|
128
128
|
- lib/aikido/zen/middleware/fork_detector.rb
|
|
129
|
-
- lib/aikido/zen/middleware/ip_list_checker.rb
|
|
130
129
|
- lib/aikido/zen/middleware/middleware.rb
|
|
131
130
|
- lib/aikido/zen/middleware/rack_throttler.rb
|
|
132
131
|
- lib/aikido/zen/middleware/request_tracker.rb
|
|
@@ -153,7 +152,6 @@ files:
|
|
|
153
152
|
- lib/aikido/zen/runtime_settings/domain_settings.rb
|
|
154
153
|
- lib/aikido/zen/runtime_settings/domains.rb
|
|
155
154
|
- lib/aikido/zen/runtime_settings/endpoints.rb
|
|
156
|
-
- lib/aikido/zen/runtime_settings/ip_list.rb
|
|
157
155
|
- lib/aikido/zen/runtime_settings/ip_set.rb
|
|
158
156
|
- lib/aikido/zen/runtime_settings/protection_settings.rb
|
|
159
157
|
- lib/aikido/zen/runtime_settings/rate_limit_settings.rb
|
|
@@ -1,47 +0,0 @@
|
|
|
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
|
|
@@ -1,34 +0,0 @@
|
|
|
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
|
-
def self.from_json(data)
|
|
11
|
-
new(
|
|
12
|
-
key: data["key"],
|
|
13
|
-
source: data["source"],
|
|
14
|
-
description: data["description"],
|
|
15
|
-
ips: RuntimeSettings::IPSet.from_json(data["ips"])
|
|
16
|
-
)
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def initialize(key:, source:, description:, ips:)
|
|
20
|
-
@key = key
|
|
21
|
-
@source = source
|
|
22
|
-
@description = description
|
|
23
|
-
@ips = ips
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
def inspect
|
|
27
|
-
"#<#{self.class} #{@key}>"
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def include?(ip)
|
|
31
|
-
@ips.include?(ip)
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
end
|