aikido-zen 1.6.0 → 1.7.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bbe496756f6406545bc23d9e0e485d819c71557b70ef240e41467d2c6078433e
4
- data.tar.gz: f4518f842c1d8c6a510d978ff792dfbf1e8ef355abf6158f8287bd15499888bc
3
+ metadata.gz: 651c1ff033d7689d75fa83bc27e64249463e74ad5ecac534df46e2cae96fcda2
4
+ data.tar.gz: 8232034fd237b6b4be9cde3cbea8d35c9a796d05b6f72bb90ff4cfc63888d037
5
5
  SHA512:
6
- metadata.gz: f30781c3f9fe4f0e990003b3ad037c7f3f3ced3872420b3530d3361f852b8a908ae88184045133003e6c6cb4e97e38fbe0f74568109cc0f8243baac06a142d4c
7
- data.tar.gz: 0fe5077d3613a69fb44ff0dbb01914df3f3b7ea72515c221d380568e8340b0eaa0fa3737d65d454e19a4b0076591333c130f686598ce9ff77b8062573c112bde
6
+ metadata.gz: bf4940ca74224b195ddbe9447b5d14d61b6f677c152f484a5ed71b6fe100482e5bd71d917f57807b632b24e93e4b9f6d9dbb53f6cc5cdc280dcf3e3315fdbcfd
7
+ data.tar.gz: f7746da3d5a9bb8e4c54be18c689fc3338ba7598fe59a683921ff47a8455b6800572016a4ad1103bc42aa0f01e09f34d9e38aecf957474c8dbd18847632ac937
@@ -18,12 +18,14 @@ module Aikido::Zen
18
18
 
19
19
  def initialize(
20
20
  config: Aikido::Zen.config,
21
+ settings: Aikido::Zen.runtime_settings,
21
22
  collector: Aikido::Zen.collector,
22
23
  worker: Aikido::Zen::Worker.new(config: config),
23
24
  api_client: Aikido::Zen::APIClient.new(config: config),
24
25
  api_stream: Aikido::Zen::APIStream.new(config: config)
25
26
  )
26
27
  @config = config
28
+ @settings = settings
27
29
  @collector = collector
28
30
  @worker = worker
29
31
  @api_client = api_client
@@ -68,6 +70,15 @@ module Aikido::Zen
68
70
  report(Events::Started.new(time: @started_at)) do |response|
69
71
  if update_settings_from_runtime_config!(response, reason: "after start")
70
72
  updated_settings!
73
+
74
+ if @config.realtime_settings_updates_enabled? || @settings.realtime_settings_updates_enabled?
75
+ @api_stream.handle("config-updated") do |event|
76
+ @config.logger.debug("Received server-sent event: config-updated")
77
+ settings_updated(event)
78
+ end
79
+
80
+ @api_stream.start!
81
+ end
71
82
  # :nocov:
72
83
  else
73
84
  # empty
@@ -83,15 +94,6 @@ module Aikido::Zen
83
94
  @config.logger.error(err.message)
84
95
  end
85
96
 
86
- if @config.realtime_settings_updates_enabled?
87
- @api_stream.handle("config-updated") do |event|
88
- @config.logger.debug("Received server-sent event: config-updated")
89
- settings_updated(event)
90
- end
91
-
92
- @api_stream.start!
93
- end
94
-
95
97
  poll_for_setting_updates
96
98
 
97
99
  @config.initial_heartbeat_delays.each do |heartbeat_delay|
@@ -197,7 +199,7 @@ module Aikido::Zen
197
199
  # @return [void]
198
200
  # @see Aikido::Zen::RuntimeSettings
199
201
  def poll_for_setting_updates
200
- @worker.every(@config.polling_interval) do
202
+ @worker.every(@config.polling_interval, run_now: true) do
201
203
  if @api_client.should_fetch_settings?
202
204
  if update_settings_from_runtime_config!(@api_client.fetch_runtime_config, reason: "after polling")
203
205
  updated_settings!
@@ -29,10 +29,13 @@ module Aikido::Zen
29
29
  @ipv6_ranges = []
30
30
 
31
31
  ips.each do |ip|
32
+ range = ip.to_range
33
+ ip_int_range = (range.begin.to_i..range.end.to_i)
34
+
32
35
  if ip.ipv4?
33
- @ipv4_ranges << ip.to_range
36
+ @ipv4_ranges << ip_int_range
34
37
  elsif ip.ipv6?
35
- @ipv6_ranges << ip.to_range
38
+ @ipv6_ranges << ip_int_range
36
39
  else
37
40
  raise ArgumentError, "Unsupported IP address family: #{ip.inspect}"
38
41
  end
@@ -50,10 +53,12 @@ module Aikido::Zen
50
53
  native_ip = nativize_ip(ip)
51
54
  return false if native_ip.nil?
52
55
 
56
+ ip_int = native_ip.to_i
57
+
53
58
  if native_ip.ipv4?
54
- ranges_cover?(@ipv4_ranges, native_ip)
59
+ ranges_cover?(@ipv4_ranges, ip_int)
55
60
  elsif native_ip.ipv6?
56
- ranges_cover?(@ipv6_ranges, native_ip)
61
+ ranges_cover?(@ipv6_ranges, ip_int)
57
62
  else
58
63
  raise ArgumentError, "Unsupported IP address family: #{ip.inspect}"
59
64
  end
@@ -78,12 +83,12 @@ module Aikido::Zen
78
83
  end
79
84
  end
80
85
 
81
- def ranges_cover?(ranges, ip)
82
- index = ranges.bsearch_index { |range| range.begin > ip }
86
+ def ranges_cover?(ranges, ip_int)
87
+ index = ranges.bsearch_index { |range| range.begin > ip_int }
83
88
  index = index ? index - 1 : ranges.size - 1
84
89
  return false if index < 0
85
90
 
86
- ranges[index].cover?(ip)
91
+ ranges[index].cover?(ip_int)
87
92
  end
88
93
  end
89
94
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "set"
4
+
3
5
  module Aikido::Zen
4
6
  # Stores the firewall configuration sourced from the Aikido dashboard. This
5
7
  # object is updated by the Agent regularly.
@@ -11,7 +13,25 @@ module Aikido::Zen
11
13
  #
12
14
  # You can subscribe to changes with +#add_observer(object, func_name)+, which
13
15
  # 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, :blocked_ip_lists, :allowed_ip_lists, :monitored_ip_lists, :block_new_outbound, :domains, :excluded_user_ids_from_rate_limiting) do
16
+ RuntimeSettings = Struct.new(
17
+ :updated_at,
18
+ :heartbeat_interval,
19
+ :endpoints,
20
+ :blocked_user_ids,
21
+ :bypassed_ips,
22
+ :received_any_stats,
23
+ :blocking_mode,
24
+ :blocked_user_agent_regexp,
25
+ :monitored_user_agent_regexp,
26
+ :user_agent_details,
27
+ :blocked_ip_lists,
28
+ :allowed_ip_lists,
29
+ :monitored_ip_lists,
30
+ :block_new_outbound,
31
+ :domains,
32
+ :excluded_user_ids_from_rate_limiting,
33
+ :enabled_features
34
+ ) do
15
35
  def initialize(*)
16
36
  super
17
37
  self.endpoints ||= RuntimeSettings::Endpoints.new
@@ -20,6 +40,7 @@ module Aikido::Zen
20
40
  self.allowed_ip_lists ||= []
21
41
  self.monitored_ip_lists ||= []
22
42
  self.domains ||= RuntimeSettings::Domains.new
43
+ self.enabled_features ||= Set.new
23
44
  end
24
45
 
25
46
  # @!attribute [rw] updated_at
@@ -73,6 +94,9 @@ module Aikido::Zen
73
94
  # @return [Array<String>, nil] the user IDs that should be skipped from
74
95
  # rate limiting entirely.
75
96
 
97
+ # @!attribute [rw] enabled_features
98
+ # @return [Set<String>]
99
+
76
100
  # Parse and interpret the JSON response from the core API with updated
77
101
  # runtime settings, and apply the changes.
78
102
  #
@@ -97,6 +121,8 @@ module Aikido::Zen
97
121
 
98
122
  self.excluded_user_ids_from_rate_limiting = data["excludedUserIdsFromRateLimiting"]
99
123
 
124
+ self.enabled_features = Set.new(data["enabledFeatures"])
125
+
100
126
  updated_at != last_updated_at
101
127
  end
102
128
 
@@ -223,6 +249,14 @@ module Aikido::Zen
223
249
 
224
250
  (!domain.nil? && domain.block?) || (domain.nil? && block_new_outbound)
225
251
  end
252
+
253
+ private def enabled_feature?(feature)
254
+ enabled_features.include?(feature)
255
+ end
256
+
257
+ def realtime_settings_updates_enabled?
258
+ enabled_feature?("realtime_updates")
259
+ end
226
260
  end
227
261
  end
228
262
 
@@ -70,6 +70,10 @@ module Aikido::Zen
70
70
  Helpers.scan(wrapped_request, connection, "request")
71
71
 
72
72
  request.on(:response) do |response|
73
+ # HTTPX emits an ErrorResponse (no status/headers) through this
74
+ # same callback when the request fails at the transport level.
75
+ next if response.is_a?(::HTTPX::ErrorResponse)
76
+
73
77
  Scanners::SSRFScanner.track_redirects(
74
78
  request: wrapped_request,
75
79
  response: Helpers.wrap_response(response)
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Aikido
4
4
  module Zen
5
- VERSION = "1.6.0"
5
+ VERSION = "1.7.0"
6
6
 
7
7
  # The version of libzen_internals that we build against.
8
8
  LIBZEN_VERSION = "0.1.61"
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.6.0
4
+ version: 1.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aikido Security
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-07-23 00:00:00.000000000 Z
11
+ date: 2026-08-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby