aikido-zen 0.1.0.alpha4-arm64-darwin

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.
Files changed (85) hide show
  1. checksums.yaml +7 -0
  2. data/.ruby-version +1 -0
  3. data/.standard.yml +3 -0
  4. data/CHANGELOG.md +5 -0
  5. data/CODE_OF_CONDUCT.md +132 -0
  6. data/LICENSE +674 -0
  7. data/README.md +40 -0
  8. data/Rakefile +63 -0
  9. data/lib/aikido/zen/actor.rb +116 -0
  10. data/lib/aikido/zen/agent.rb +187 -0
  11. data/lib/aikido/zen/api_client.rb +132 -0
  12. data/lib/aikido/zen/attack.rb +138 -0
  13. data/lib/aikido/zen/capped_collections.rb +68 -0
  14. data/lib/aikido/zen/config.rb +229 -0
  15. data/lib/aikido/zen/context/rack_request.rb +24 -0
  16. data/lib/aikido/zen/context/rails_request.rb +42 -0
  17. data/lib/aikido/zen/context.rb +101 -0
  18. data/lib/aikido/zen/errors.rb +88 -0
  19. data/lib/aikido/zen/event.rb +66 -0
  20. data/lib/aikido/zen/internals.rb +64 -0
  21. data/lib/aikido/zen/libzen-v0.1.26.aarch64.dylib +0 -0
  22. data/lib/aikido/zen/middleware/check_allowed_addresses.rb +38 -0
  23. data/lib/aikido/zen/middleware/set_context.rb +26 -0
  24. data/lib/aikido/zen/middleware/throttler.rb +50 -0
  25. data/lib/aikido/zen/outbound_connection.rb +45 -0
  26. data/lib/aikido/zen/outbound_connection_monitor.rb +19 -0
  27. data/lib/aikido/zen/package.rb +22 -0
  28. data/lib/aikido/zen/payload.rb +48 -0
  29. data/lib/aikido/zen/rails_engine.rb +53 -0
  30. data/lib/aikido/zen/rate_limiter/breaker.rb +61 -0
  31. data/lib/aikido/zen/rate_limiter/bucket.rb +76 -0
  32. data/lib/aikido/zen/rate_limiter/result.rb +31 -0
  33. data/lib/aikido/zen/rate_limiter.rb +55 -0
  34. data/lib/aikido/zen/request/heuristic_router.rb +109 -0
  35. data/lib/aikido/zen/request/rails_router.rb +84 -0
  36. data/lib/aikido/zen/request/schema/auth_discovery.rb +86 -0
  37. data/lib/aikido/zen/request/schema/auth_schemas.rb +40 -0
  38. data/lib/aikido/zen/request/schema/builder.rb +125 -0
  39. data/lib/aikido/zen/request/schema/definition.rb +112 -0
  40. data/lib/aikido/zen/request/schema/empty_schema.rb +28 -0
  41. data/lib/aikido/zen/request/schema.rb +72 -0
  42. data/lib/aikido/zen/request.rb +97 -0
  43. data/lib/aikido/zen/route.rb +39 -0
  44. data/lib/aikido/zen/runtime_settings/endpoints.rb +49 -0
  45. data/lib/aikido/zen/runtime_settings/ip_set.rb +36 -0
  46. data/lib/aikido/zen/runtime_settings/protection_settings.rb +62 -0
  47. data/lib/aikido/zen/runtime_settings/rate_limit_settings.rb +47 -0
  48. data/lib/aikido/zen/runtime_settings.rb +70 -0
  49. data/lib/aikido/zen/scan.rb +75 -0
  50. data/lib/aikido/zen/scanners/sql_injection_scanner.rb +95 -0
  51. data/lib/aikido/zen/scanners/ssrf/dns_lookups.rb +27 -0
  52. data/lib/aikido/zen/scanners/ssrf/private_ip_checker.rb +85 -0
  53. data/lib/aikido/zen/scanners/ssrf_scanner.rb +251 -0
  54. data/lib/aikido/zen/scanners/stored_ssrf_scanner.rb +43 -0
  55. data/lib/aikido/zen/scanners.rb +5 -0
  56. data/lib/aikido/zen/sink.rb +108 -0
  57. data/lib/aikido/zen/sinks/async_http.rb +63 -0
  58. data/lib/aikido/zen/sinks/curb.rb +89 -0
  59. data/lib/aikido/zen/sinks/em_http.rb +71 -0
  60. data/lib/aikido/zen/sinks/excon.rb +103 -0
  61. data/lib/aikido/zen/sinks/http.rb +76 -0
  62. data/lib/aikido/zen/sinks/httpclient.rb +68 -0
  63. data/lib/aikido/zen/sinks/httpx.rb +61 -0
  64. data/lib/aikido/zen/sinks/mysql2.rb +21 -0
  65. data/lib/aikido/zen/sinks/net_http.rb +85 -0
  66. data/lib/aikido/zen/sinks/patron.rb +88 -0
  67. data/lib/aikido/zen/sinks/pg.rb +50 -0
  68. data/lib/aikido/zen/sinks/resolv.rb +41 -0
  69. data/lib/aikido/zen/sinks/socket.rb +51 -0
  70. data/lib/aikido/zen/sinks/sqlite3.rb +30 -0
  71. data/lib/aikido/zen/sinks/trilogy.rb +21 -0
  72. data/lib/aikido/zen/sinks/typhoeus.rb +78 -0
  73. data/lib/aikido/zen/sinks.rb +21 -0
  74. data/lib/aikido/zen/stats/routes.rb +53 -0
  75. data/lib/aikido/zen/stats/sink_stats.rb +95 -0
  76. data/lib/aikido/zen/stats/users.rb +26 -0
  77. data/lib/aikido/zen/stats.rb +171 -0
  78. data/lib/aikido/zen/synchronizable.rb +24 -0
  79. data/lib/aikido/zen/system_info.rb +84 -0
  80. data/lib/aikido/zen/version.rb +10 -0
  81. data/lib/aikido/zen.rb +138 -0
  82. data/lib/aikido-zen.rb +3 -0
  83. data/lib/aikido.rb +3 -0
  84. data/tasklib/libzen.rake +128 -0
  85. metadata +175 -0
data/lib/aikido/zen.rb ADDED
@@ -0,0 +1,138 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "zen/version"
4
+ require_relative "zen/errors"
5
+ require_relative "zen/actor"
6
+ require_relative "zen/config"
7
+ require_relative "zen/system_info"
8
+ require_relative "zen/agent"
9
+ require_relative "zen/api_client"
10
+ require_relative "zen/context"
11
+ require_relative "zen/middleware/set_context"
12
+ require_relative "zen/outbound_connection"
13
+ require_relative "zen/outbound_connection_monitor"
14
+ require_relative "zen/runtime_settings"
15
+ require_relative "zen/rate_limiter"
16
+ require_relative "zen/scanners"
17
+ require_relative "zen/middleware/check_allowed_addresses"
18
+ require_relative "zen/rails_engine" if defined?(::Rails)
19
+
20
+ module Aikido
21
+ module Zen
22
+ # @return [Aikido::Zen::Config] the agent configuration.
23
+ def self.config
24
+ @config ||= Config.new
25
+ end
26
+
27
+ # Gets information about the current system configuration, which is sent to
28
+ # the server along with any events.
29
+ def self.system_info
30
+ @system_info ||= SystemInfo.new
31
+ end
32
+
33
+ # Gets the current context object that holds all information about the
34
+ # current request.
35
+ #
36
+ # @return [Aikido::Zen::Context, nil]
37
+ def self.current_context
38
+ Thread.current[:_aikido_current_context_]
39
+ end
40
+
41
+ # Sets the current context object that holds all information about the
42
+ # current request, or +nil+ to clear the current context.
43
+ #
44
+ # @param context [Aikido::Zen::Context, nil]
45
+ # @return [Aikido::Zen::Context, nil]
46
+ def self.current_context=(context)
47
+ Thread.current[:_aikido_current_context_] = context
48
+ end
49
+
50
+ # Track statistics about the result of a Sink's scan, and report it as an
51
+ # Attack if one is detected.
52
+ #
53
+ # @param scan [Aikido::Zen::Scan]
54
+ # @return [void]
55
+ # @raise [Aikido::Zen::UnderAttackError] if the scan detected an Attack
56
+ # and blocking_mode is enabled.
57
+ def self.track_scan(scan)
58
+ agent.stats.add_scan(scan)
59
+ agent.handle_attack(scan.attack) if scan.attack?
60
+ end
61
+
62
+ # Track statistics about an HTTP request the app is handling.
63
+ #
64
+ # @param context [Aikido::Zen::Request]
65
+ # @return [void]
66
+ def self.track_request(request)
67
+ agent.stats.add_request(request)
68
+ end
69
+
70
+ # Tracks a network connection made to an external service.
71
+ #
72
+ # @param connection [Aikido::Zen::OutboundConnection]
73
+ # @return [void]
74
+ def self.track_outbound(connection)
75
+ agent.stats.add_outbound(connection)
76
+ end
77
+
78
+ # Track the user making the current request.
79
+ #
80
+ # @param (see Aikido::Zen.Actor)
81
+ # @return [void]
82
+ def self.track_user(user)
83
+ actor = Aikido::Zen::Actor(user)
84
+
85
+ if actor
86
+ agent.stats.add_user(actor)
87
+ else
88
+ id_attr, name_attr = config.user_attribute_mappings.values_at(:id, :name)
89
+ config.logger.warn(format(<<~LOG, obj: user, id: id_attr, name: name_attr))
90
+ Incompatible object sent to Aikido::Zen.track_user: %<obj>p
91
+
92
+ The object must satisfy one of the following:
93
+
94
+ * Implement #to_aikido_actor
95
+ * Implement #to_model and have %<id>p and %<name>p attributes
96
+ * Be a Hash with :id (or "id") and, optionally, :name (or "name") keys
97
+ LOG
98
+ end
99
+ end
100
+
101
+ # Starts the background threads that keep the agent running.
102
+ #
103
+ # @return [void]
104
+ def self.initialize!
105
+ @agent ||= Agent.new
106
+ @agent.start!
107
+ end
108
+
109
+ # Stop any background threads.
110
+ def self.stop!
111
+ @agent&.stop!
112
+ end
113
+
114
+ # @return [Aikido::Zen::RuntimeSettings] the firewall configuration sourced
115
+ # from your Aikido dashboard. This is periodically polled for updates.
116
+ def self.runtime_settings
117
+ @runtime_settings ||= RuntimeSettings.new
118
+ end
119
+
120
+ # Load all sinks matching libraries loaded into memory. This method should
121
+ # be called after all other dependencies have been loaded into memory (i.e.
122
+ # at the end of the initialization process).
123
+ #
124
+ # If a new gem is required, this method can be called again safely.
125
+ #
126
+ # @return [void]
127
+ def self.load_sinks!
128
+ require_relative "zen/sinks"
129
+ end
130
+
131
+ private_class_method def self.agent
132
+ # We shouldn't start collecting data before we even initialize the agent,
133
+ # but might as well make sure we have a @agent going to report to.
134
+ @agent or initialize!
135
+ @agent
136
+ end
137
+ end
138
+ end
data/lib/aikido-zen.rb ADDED
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "aikido/zen"
data/lib/aikido.rb ADDED
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "aikido/zen"
@@ -0,0 +1,128 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "open-uri"
4
+ require "rubygems/package_task"
5
+
6
+ require_relative "../lib/aikido/zen/version"
7
+
8
+ LibZenDL = Struct.new(:os, :arch, :artifact) do
9
+ def download
10
+ puts "Downloading #{path}"
11
+ File.open(path, "wb") { |file| FileUtils.copy_stream(URI(url).open("rb"), file) }
12
+ end
13
+
14
+ def verify
15
+ expected = URI(url + ".sha256sum").read.split(/\s+/).first
16
+ actual = Digest::SHA256.file(path).to_s
17
+
18
+ if expected != actual
19
+ abort "Checksum mismatch on #{path}: Expected #{expected}, got #{actual}."
20
+ end
21
+ end
22
+
23
+ def version
24
+ "v#{Aikido::Zen::LIBZEN_VERSION}"
25
+ end
26
+
27
+ def path
28
+ [prefix, arch, ext].join(".")
29
+ end
30
+
31
+ def gem_path
32
+ platform = "-#{gemspec.platform}" unless gemspec.platform.to_s == "ruby"
33
+ "pkg/#{gemspec.name}-#{gemspec.version}#{platform}.gem"
34
+ end
35
+
36
+ def pkg_dir
37
+ File.dirname(gem_path)
38
+ end
39
+
40
+ def prefix
41
+ "lib/aikido/zen/libzen-#{version}"
42
+ end
43
+
44
+ def ext
45
+ case os
46
+ when :darwin then "dylib"
47
+ when :linux then "so"
48
+ when :windows then "dll"
49
+ end
50
+ end
51
+
52
+ def url
53
+ File.join("https://github.com/AikidoSec/zen-internals/releases/download", version, artifact)
54
+ end
55
+
56
+ def gem_platform
57
+ gem_os = (os == :windows) ? "mingw64" : os
58
+ platform = (arch == "aarch64") ? "arm64" : arch
59
+ Gem::Platform.new("#{platform}-#{gem_os}")
60
+ end
61
+
62
+ def gemspec(source = Bundler.load_gemspec("aikido-zen.gemspec"))
63
+ return @spec if defined?(@spec)
64
+
65
+ @spec = source.dup
66
+ @spec.platform = gem_platform
67
+ @spec.files << path
68
+ @spec
69
+ end
70
+
71
+ def namespace
72
+ "#{os}:#{arch}"
73
+ end
74
+ end
75
+
76
+ LIBZEN = [
77
+ LibZenDL.new(:darwin, "aarch64", "libzen_internals_aarch64-apple-darwin.dylib"),
78
+ LibZenDL.new(:darwin, "x86_64", "libzen_internals_x86_64-apple-darwin.dylib"),
79
+ LibZenDL.new(:linux, "aarch64", "libzen_internals_aarch64-unknown-linux-gnu.so"),
80
+ LibZenDL.new(:linux, "x86_64", "libzen_internals_x86_64-unknown-linux-gnu.so"),
81
+ LibZenDL.new(:windows, "x86_64", "libzen_internals_x86_64-pc-windows-gnu.dll")
82
+ ]
83
+ namespace :libzen do
84
+ LIBZEN.each do |lib|
85
+ desc "Download libzen for #{lib.os}-#{lib.arch} if necessary"
86
+ task(lib.namespace => lib.path)
87
+
88
+ file(lib.path) {
89
+ lib.download
90
+ lib.verify
91
+ }
92
+ CLEAN.include(lib.path)
93
+
94
+ directory lib.pkg_dir
95
+ CLOBBER.include(lib.pkg_dir)
96
+
97
+ file(lib.gem_path => [lib.path, lib.pkg_dir]) {
98
+ path = Gem::Package.build(lib.gemspec)
99
+ mv path, lib.pkg_dir
100
+ }
101
+ CLOBBER.include(lib.pkg_dir)
102
+
103
+ task "#{lib.namespace}:release" => [lib.gem_path, "release:guard_clean"] do
104
+ sh "gem", "push", lib.gem_path
105
+ end
106
+ end
107
+
108
+ desc "Build all the native gems for the different libzen versions"
109
+ task gems: LIBZEN.map(&:gem_path)
110
+
111
+ desc "Push all the native gems to RubyGems"
112
+ task release: LIBZEN.map { |lib| "#{lib.namespace}:release" }
113
+
114
+ desc "Download the libzen pre-built library for all platforms"
115
+ task "download:all" => LIBZEN.map(&:path)
116
+
117
+ desc "Downloads the libzen library for the current platform"
118
+ task "download:current" do
119
+ require "rbconfig"
120
+ os = case RbConfig::CONFIG["host_os"]
121
+ when /darwin/ then :darwin
122
+ when /mingw|cygwin|mswin/ then :windows
123
+ else :linux
124
+ end
125
+
126
+ Rake::Task["libzen:#{os}:#{RbConfig::CONFIG["build_cpu"]}"].invoke
127
+ end
128
+ end
metadata ADDED
@@ -0,0 +1,175 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: aikido-zen
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0.alpha4
5
+ platform: arm64-darwin
6
+ authors:
7
+ - Nicolas Sanguinetti
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2024-10-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: concurrent-ruby
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.0'
27
+ force_ruby_platform: false
28
+ - !ruby/object:Gem::Dependency
29
+ name: rack
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ force_ruby_platform: false
43
+ - !ruby/object:Gem::Dependency
44
+ name: ffi
45
+ requirement: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: '0'
50
+ type: :runtime
51
+ prerelease: false
52
+ version_requirements: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ force_ruby_platform: false
58
+ description:
59
+ email:
60
+ - foca@foca.io
61
+ executables: []
62
+ extensions: []
63
+ extra_rdoc_files: []
64
+ files:
65
+ - ".ruby-version"
66
+ - ".standard.yml"
67
+ - CHANGELOG.md
68
+ - CODE_OF_CONDUCT.md
69
+ - LICENSE
70
+ - README.md
71
+ - Rakefile
72
+ - lib/aikido-zen.rb
73
+ - lib/aikido.rb
74
+ - lib/aikido/zen.rb
75
+ - lib/aikido/zen/actor.rb
76
+ - lib/aikido/zen/agent.rb
77
+ - lib/aikido/zen/api_client.rb
78
+ - lib/aikido/zen/attack.rb
79
+ - lib/aikido/zen/capped_collections.rb
80
+ - lib/aikido/zen/config.rb
81
+ - lib/aikido/zen/context.rb
82
+ - lib/aikido/zen/context/rack_request.rb
83
+ - lib/aikido/zen/context/rails_request.rb
84
+ - lib/aikido/zen/errors.rb
85
+ - lib/aikido/zen/event.rb
86
+ - lib/aikido/zen/internals.rb
87
+ - lib/aikido/zen/libzen-v0.1.26.aarch64.dylib
88
+ - lib/aikido/zen/middleware/check_allowed_addresses.rb
89
+ - lib/aikido/zen/middleware/set_context.rb
90
+ - lib/aikido/zen/middleware/throttler.rb
91
+ - lib/aikido/zen/outbound_connection.rb
92
+ - lib/aikido/zen/outbound_connection_monitor.rb
93
+ - lib/aikido/zen/package.rb
94
+ - lib/aikido/zen/payload.rb
95
+ - lib/aikido/zen/rails_engine.rb
96
+ - lib/aikido/zen/rate_limiter.rb
97
+ - lib/aikido/zen/rate_limiter/breaker.rb
98
+ - lib/aikido/zen/rate_limiter/bucket.rb
99
+ - lib/aikido/zen/rate_limiter/result.rb
100
+ - lib/aikido/zen/request.rb
101
+ - lib/aikido/zen/request/heuristic_router.rb
102
+ - lib/aikido/zen/request/rails_router.rb
103
+ - lib/aikido/zen/request/schema.rb
104
+ - lib/aikido/zen/request/schema/auth_discovery.rb
105
+ - lib/aikido/zen/request/schema/auth_schemas.rb
106
+ - lib/aikido/zen/request/schema/builder.rb
107
+ - lib/aikido/zen/request/schema/definition.rb
108
+ - lib/aikido/zen/request/schema/empty_schema.rb
109
+ - lib/aikido/zen/route.rb
110
+ - lib/aikido/zen/runtime_settings.rb
111
+ - lib/aikido/zen/runtime_settings/endpoints.rb
112
+ - lib/aikido/zen/runtime_settings/ip_set.rb
113
+ - lib/aikido/zen/runtime_settings/protection_settings.rb
114
+ - lib/aikido/zen/runtime_settings/rate_limit_settings.rb
115
+ - lib/aikido/zen/scan.rb
116
+ - lib/aikido/zen/scanners.rb
117
+ - lib/aikido/zen/scanners/sql_injection_scanner.rb
118
+ - lib/aikido/zen/scanners/ssrf/dns_lookups.rb
119
+ - lib/aikido/zen/scanners/ssrf/private_ip_checker.rb
120
+ - lib/aikido/zen/scanners/ssrf_scanner.rb
121
+ - lib/aikido/zen/scanners/stored_ssrf_scanner.rb
122
+ - lib/aikido/zen/sink.rb
123
+ - lib/aikido/zen/sinks.rb
124
+ - lib/aikido/zen/sinks/async_http.rb
125
+ - lib/aikido/zen/sinks/curb.rb
126
+ - lib/aikido/zen/sinks/em_http.rb
127
+ - lib/aikido/zen/sinks/excon.rb
128
+ - lib/aikido/zen/sinks/http.rb
129
+ - lib/aikido/zen/sinks/httpclient.rb
130
+ - lib/aikido/zen/sinks/httpx.rb
131
+ - lib/aikido/zen/sinks/mysql2.rb
132
+ - lib/aikido/zen/sinks/net_http.rb
133
+ - lib/aikido/zen/sinks/patron.rb
134
+ - lib/aikido/zen/sinks/pg.rb
135
+ - lib/aikido/zen/sinks/resolv.rb
136
+ - lib/aikido/zen/sinks/socket.rb
137
+ - lib/aikido/zen/sinks/sqlite3.rb
138
+ - lib/aikido/zen/sinks/trilogy.rb
139
+ - lib/aikido/zen/sinks/typhoeus.rb
140
+ - lib/aikido/zen/stats.rb
141
+ - lib/aikido/zen/stats/routes.rb
142
+ - lib/aikido/zen/stats/sink_stats.rb
143
+ - lib/aikido/zen/stats/users.rb
144
+ - lib/aikido/zen/synchronizable.rb
145
+ - lib/aikido/zen/system_info.rb
146
+ - lib/aikido/zen/version.rb
147
+ - tasklib/libzen.rake
148
+ homepage: https://aikido.dev
149
+ licenses:
150
+ - AGPL-3.0-or-later
151
+ metadata:
152
+ homepage_uri: https://aikido.dev
153
+ source_code_uri: https://github.com/aikidosec/firewall-ruby
154
+ changelog_uri: https://github.com/aikidosec/firewall-ruby/blob/main/CHANGELOG.md
155
+ post_install_message:
156
+ rdoc_options: []
157
+ require_paths:
158
+ - lib
159
+ required_ruby_version: !ruby/object:Gem::Requirement
160
+ requirements:
161
+ - - ">="
162
+ - !ruby/object:Gem::Version
163
+ version: '2.7'
164
+ required_rubygems_version: !ruby/object:Gem::Requirement
165
+ requirements:
166
+ - - ">="
167
+ - !ruby/object:Gem::Version
168
+ version: '0'
169
+ requirements: []
170
+ rubygems_version: 3.5.16
171
+ signing_key:
172
+ specification_version: 4
173
+ summary: Embedded Web Application Firewall that autonomously protects Ruby apps against
174
+ common and critical attacks.
175
+ test_files: []