newrelic_security 0.1.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.
Files changed (205) hide show
  1. checksums.yaml +7 -0
  2. data/.github/ISSUE_TEMPLATE/bug_report.md +38 -0
  3. data/.github/ISSUE_TEMPLATE/enhancement.md +27 -0
  4. data/.github/actions/simplecov-report/LICENSE +22 -0
  5. data/.github/actions/simplecov-report/README.md +36 -0
  6. data/.github/actions/simplecov-report/__tests__/.keep +0 -0
  7. data/.github/actions/simplecov-report/__tests__/main.test.ts +3 -0
  8. data/.github/actions/simplecov-report/action.yml +25 -0
  9. data/.github/actions/simplecov-report/dist/index.js +10238 -0
  10. data/.github/actions/simplecov-report/dummy_coverage/.last_run.json +5 -0
  11. data/.github/actions/simplecov-report/jest.config.js +11 -0
  12. data/.github/actions/simplecov-report/package.json +51 -0
  13. data/.github/actions/simplecov-report/src/main.ts +54 -0
  14. data/.github/actions/simplecov-report/src/report.ts +28 -0
  15. data/.github/actions/simplecov-report/tsconfig.json +12 -0
  16. data/.github/workflows/pr_ci.yml +77 -0
  17. data/.github/workflows/release.yml +51 -0
  18. data/.github/workflows/repolinter.yml +31 -0
  19. data/.github/workflows/rubocop.yml +17 -0
  20. data/.github/workflows/scripts/rubygems-authenticate.py +13 -0
  21. data/.github/workflows/scripts/rubygems-publish.rb +33 -0
  22. data/.gitignore +72 -0
  23. data/.rubocop.yml +9 -0
  24. data/.rubocop_todo.yml +1414 -0
  25. data/.simplecov +16 -0
  26. data/CHANGELOG.md +69 -0
  27. data/CONTRIBUTING.md +22 -0
  28. data/Gemfile +6 -0
  29. data/Gemfile_test +58 -0
  30. data/LICENSE +43 -0
  31. data/README.md +133 -0
  32. data/README_agent.md +44 -0
  33. data/Rakefile +28 -0
  34. data/THIRD_PARTY_NOTICES.md +36 -0
  35. data/lib/newrelic_security/agent/agent.rb +109 -0
  36. data/lib/newrelic_security/agent/configuration/default_source.rb +8 -0
  37. data/lib/newrelic_security/agent/configuration/environment_source.rb +8 -0
  38. data/lib/newrelic_security/agent/configuration/manager.rb +178 -0
  39. data/lib/newrelic_security/agent/configuration/manual_source.rb +8 -0
  40. data/lib/newrelic_security/agent/configuration/server_source.rb +8 -0
  41. data/lib/newrelic_security/agent/configuration/yaml_source.rb +8 -0
  42. data/lib/newrelic_security/agent/control/app_info.rb +132 -0
  43. data/lib/newrelic_security/agent/control/application_url_mappings.rb +66 -0
  44. data/lib/newrelic_security/agent/control/collector.rb +117 -0
  45. data/lib/newrelic_security/agent/control/control_command.rb +117 -0
  46. data/lib/newrelic_security/agent/control/critical_message.rb +58 -0
  47. data/lib/newrelic_security/agent/control/event.rb +149 -0
  48. data/lib/newrelic_security/agent/control/event_counter.rb +28 -0
  49. data/lib/newrelic_security/agent/control/event_processor.rb +134 -0
  50. data/lib/newrelic_security/agent/control/event_stats.rb +26 -0
  51. data/lib/newrelic_security/agent/control/event_subscriber.rb +28 -0
  52. data/lib/newrelic_security/agent/control/exit_event.rb +38 -0
  53. data/lib/newrelic_security/agent/control/fuzz_request.rb +18 -0
  54. data/lib/newrelic_security/agent/control/grpc_context.rb +57 -0
  55. data/lib/newrelic_security/agent/control/health_check.rb +136 -0
  56. data/lib/newrelic_security/agent/control/http_context.rb +73 -0
  57. data/lib/newrelic_security/agent/control/iast_client.rb +151 -0
  58. data/lib/newrelic_security/agent/control/iast_data_transfer_request.rb +32 -0
  59. data/lib/newrelic_security/agent/control/reflected_xss.rb +258 -0
  60. data/lib/newrelic_security/agent/control/websocket_client.rb +131 -0
  61. data/lib/newrelic_security/agent/logging/init_logger.rb +91 -0
  62. data/lib/newrelic_security/agent/logging/logger.rb +92 -0
  63. data/lib/newrelic_security/agent/logging/null_logger.rb +21 -0
  64. data/lib/newrelic_security/agent/resources/cert.pem +50 -0
  65. data/lib/newrelic_security/agent/utils/agent_utils.rb +219 -0
  66. data/lib/newrelic_security/agent.rb +57 -0
  67. data/lib/newrelic_security/constants.rb +67 -0
  68. data/lib/newrelic_security/instrumentation-security/active_record/mysql2_adapter/chain.rb +70 -0
  69. data/lib/newrelic_security/instrumentation-security/active_record/mysql2_adapter/instrumentation.rb +187 -0
  70. data/lib/newrelic_security/instrumentation-security/active_record/mysql2_adapter/prepend.rb +54 -0
  71. data/lib/newrelic_security/instrumentation-security/active_record/postgresql_adapter/chain.rb +60 -0
  72. data/lib/newrelic_security/instrumentation-security/active_record/postgresql_adapter/instrumentation.rb +143 -0
  73. data/lib/newrelic_security/instrumentation-security/active_record/postgresql_adapter/prepend.rb +48 -0
  74. data/lib/newrelic_security/instrumentation-security/active_record/sqlite3_adapter/chain.rb +72 -0
  75. data/lib/newrelic_security/instrumentation-security/active_record/sqlite3_adapter/instrumentation.rb +187 -0
  76. data/lib/newrelic_security/instrumentation-security/active_record/sqlite3_adapter/prepend.rb +54 -0
  77. data/lib/newrelic_security/instrumentation-security/async-http/chain.rb +21 -0
  78. data/lib/newrelic_security/instrumentation-security/async-http/instrumentation.rb +46 -0
  79. data/lib/newrelic_security/instrumentation-security/async-http/prepend.rb +16 -0
  80. data/lib/newrelic_security/instrumentation-security/curb/chain.rb +26 -0
  81. data/lib/newrelic_security/instrumentation-security/curb/instrumentation.rb +52 -0
  82. data/lib/newrelic_security/instrumentation-security/curb/prepend.rb +18 -0
  83. data/lib/newrelic_security/instrumentation-security/dir/chain.rb +42 -0
  84. data/lib/newrelic_security/instrumentation-security/dir/instrumentation.rb +102 -0
  85. data/lib/newrelic_security/instrumentation-security/dir/prepend.rb +28 -0
  86. data/lib/newrelic_security/instrumentation-security/ethon/chain.rb +53 -0
  87. data/lib/newrelic_security/instrumentation-security/ethon/instrumentation.rb +122 -0
  88. data/lib/newrelic_security/instrumentation-security/ethon/prepend.rb +39 -0
  89. data/lib/newrelic_security/instrumentation-security/excon/chain.rb +23 -0
  90. data/lib/newrelic_security/instrumentation-security/excon/instrumentation.rb +44 -0
  91. data/lib/newrelic_security/instrumentation-security/excon/prepend.rb +17 -0
  92. data/lib/newrelic_security/instrumentation-security/file/chain.rb +34 -0
  93. data/lib/newrelic_security/instrumentation-security/file/instrumentation.rb +62 -0
  94. data/lib/newrelic_security/instrumentation-security/file/prepend.rb +22 -0
  95. data/lib/newrelic_security/instrumentation-security/grape/chain.rb +42 -0
  96. data/lib/newrelic_security/instrumentation-security/grape/instrumentation.rb +56 -0
  97. data/lib/newrelic_security/instrumentation-security/grape/prepend.rb +30 -0
  98. data/lib/newrelic_security/instrumentation-security/grpc/client/chain.rb +47 -0
  99. data/lib/newrelic_security/instrumentation-security/grpc/client/instrumentation.rb +37 -0
  100. data/lib/newrelic_security/instrumentation-security/grpc/client/prepend.rb +36 -0
  101. data/lib/newrelic_security/instrumentation-security/grpc/server/chain.rb +62 -0
  102. data/lib/newrelic_security/instrumentation-security/grpc/server/instrumentation.rb +65 -0
  103. data/lib/newrelic_security/instrumentation-security/grpc/server/prepend.rb +46 -0
  104. data/lib/newrelic_security/instrumentation-security/httpclient/chain.rb +30 -0
  105. data/lib/newrelic_security/instrumentation-security/httpclient/instrumentation.rb +82 -0
  106. data/lib/newrelic_security/instrumentation-security/httpclient/prepend.rb +22 -0
  107. data/lib/newrelic_security/instrumentation-security/httprb/chain.rb +21 -0
  108. data/lib/newrelic_security/instrumentation-security/httprb/instrumentation.rb +44 -0
  109. data/lib/newrelic_security/instrumentation-security/httprb/prepend.rb +16 -0
  110. data/lib/newrelic_security/instrumentation-security/httpx/chain.rb +23 -0
  111. data/lib/newrelic_security/instrumentation-security/httpx/instrumentation.rb +51 -0
  112. data/lib/newrelic_security/instrumentation-security/httpx/prepend.rb +18 -0
  113. data/lib/newrelic_security/instrumentation-security/instrumentation_loader.rb +50 -0
  114. data/lib/newrelic_security/instrumentation-security/instrumentation_utils.rb +165 -0
  115. data/lib/newrelic_security/instrumentation-security/io/chain.rb +113 -0
  116. data/lib/newrelic_security/instrumentation-security/io/instrumentation.rb +300 -0
  117. data/lib/newrelic_security/instrumentation-security/io/prepend.rb +86 -0
  118. data/lib/newrelic_security/instrumentation-security/kernel/chain.rb +65 -0
  119. data/lib/newrelic_security/instrumentation-security/kernel/instrumentation.rb +167 -0
  120. data/lib/newrelic_security/instrumentation-security/kernel/prepend.rb +50 -0
  121. data/lib/newrelic_security/instrumentation-security/mongo/chain.rb +106 -0
  122. data/lib/newrelic_security/instrumentation-security/mongo/instrumentation.rb +273 -0
  123. data/lib/newrelic_security/instrumentation-security/mongo/prepend.rb +77 -0
  124. data/lib/newrelic_security/instrumentation-security/mysql2/chain.rb +53 -0
  125. data/lib/newrelic_security/instrumentation-security/mysql2/instrumentation.rb +84 -0
  126. data/lib/newrelic_security/instrumentation-security/mysql2/prepend.rb +37 -0
  127. data/lib/newrelic_security/instrumentation-security/net_http/chain.rb +21 -0
  128. data/lib/newrelic_security/instrumentation-security/net_http/instrumentation.rb +60 -0
  129. data/lib/newrelic_security/instrumentation-security/net_http/prepend.rb +16 -0
  130. data/lib/newrelic_security/instrumentation-security/net_ldap/chain.rb +21 -0
  131. data/lib/newrelic_security/instrumentation-security/net_ldap/instrumentation.rb +42 -0
  132. data/lib/newrelic_security/instrumentation-security/net_ldap/prepend.rb +16 -0
  133. data/lib/newrelic_security/instrumentation-security/nokogiri/chain.rb +46 -0
  134. data/lib/newrelic_security/instrumentation-security/nokogiri/instrumentation.rb +36 -0
  135. data/lib/newrelic_security/instrumentation-security/nokogiri/prepend.rb +31 -0
  136. data/lib/newrelic_security/instrumentation-security/padrino/chain.rb +26 -0
  137. data/lib/newrelic_security/instrumentation-security/padrino/instrumentation.rb +42 -0
  138. data/lib/newrelic_security/instrumentation-security/padrino/prepend.rb +20 -0
  139. data/lib/newrelic_security/instrumentation-security/patron/chain.rb +23 -0
  140. data/lib/newrelic_security/instrumentation-security/patron/instrumentation.rb +50 -0
  141. data/lib/newrelic_security/instrumentation-security/patron/prepend.rb +18 -0
  142. data/lib/newrelic_security/instrumentation-security/pg/chain.rb +49 -0
  143. data/lib/newrelic_security/instrumentation-security/pg/instrumentation.rb +102 -0
  144. data/lib/newrelic_security/instrumentation-security/pg/prepend.rb +36 -0
  145. data/lib/newrelic_security/instrumentation-security/pty/chain.rb +31 -0
  146. data/lib/newrelic_security/instrumentation-security/pty/instrumentation.rb +52 -0
  147. data/lib/newrelic_security/instrumentation-security/pty/prepend.rb +22 -0
  148. data/lib/newrelic_security/instrumentation-security/rails/chain.rb +46 -0
  149. data/lib/newrelic_security/instrumentation-security/rails/instrumentation.rb +67 -0
  150. data/lib/newrelic_security/instrumentation-security/rails/prepend.rb +33 -0
  151. data/lib/newrelic_security/instrumentation-security/roda/chain.rb +22 -0
  152. data/lib/newrelic_security/instrumentation-security/roda/instrumentation.rb +41 -0
  153. data/lib/newrelic_security/instrumentation-security/roda/prepend.rb +16 -0
  154. data/lib/newrelic_security/instrumentation-security/sinatra/chain.rb +29 -0
  155. data/lib/newrelic_security/instrumentation-security/sinatra/instrumentation.rb +49 -0
  156. data/lib/newrelic_security/instrumentation-security/sinatra/prepend.rb +21 -0
  157. data/lib/newrelic_security/instrumentation-security/sqlite3/chain.rb +79 -0
  158. data/lib/newrelic_security/instrumentation-security/sqlite3/instrumentation.rb +164 -0
  159. data/lib/newrelic_security/instrumentation-security/sqlite3/prepend.rb +56 -0
  160. data/lib/newrelic_security/newrelic-security-api/api.rb +72 -0
  161. data/lib/newrelic_security/version.rb +5 -0
  162. data/lib/newrelic_security/websocket-client-simple/client.rb +128 -0
  163. data/lib/newrelic_security/websocket-client-simple/event_emitter.rb +72 -0
  164. data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/error.rb +129 -0
  165. data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/exception_handler.rb +32 -0
  166. data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/frame/base.rb +62 -0
  167. data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/frame/data.rb +49 -0
  168. data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/frame/handler/base.rb +41 -0
  169. data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/frame/handler/handler03.rb +224 -0
  170. data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/frame/handler/handler04.rb +18 -0
  171. data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/frame/handler/handler05.rb +15 -0
  172. data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/frame/handler/handler07.rb +78 -0
  173. data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/frame/handler/handler75.rb +78 -0
  174. data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/frame/handler.rb +15 -0
  175. data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/frame/incoming/client.rb +17 -0
  176. data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/frame/incoming/server.rb +17 -0
  177. data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/frame/incoming.rb +52 -0
  178. data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/frame/outgoing/client.rb +17 -0
  179. data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/frame/outgoing/server.rb +17 -0
  180. data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/frame/outgoing.rb +35 -0
  181. data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/frame.rb +11 -0
  182. data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/handshake/base.rb +142 -0
  183. data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/handshake/client.rb +130 -0
  184. data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/handshake/handler/base.rb +49 -0
  185. data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/handshake/handler/client.rb +32 -0
  186. data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/handshake/handler/client01.rb +20 -0
  187. data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/handshake/handler/client04.rb +63 -0
  188. data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/handshake/handler/client11.rb +22 -0
  189. data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/handshake/handler/client75.rb +39 -0
  190. data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/handshake/handler/client76.rb +105 -0
  191. data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/handshake/handler/server.rb +10 -0
  192. data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/handshake/handler/server04.rb +56 -0
  193. data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/handshake/handler/server75.rb +40 -0
  194. data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/handshake/handler/server76.rb +75 -0
  195. data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/handshake/handler.rb +21 -0
  196. data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/handshake/server.rb +179 -0
  197. data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/handshake.rb +10 -0
  198. data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/nice_inspect.rb +12 -0
  199. data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/version.rb +5 -0
  200. data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket.rb +50 -0
  201. data/lib/newrelic_security.rb +6 -0
  202. data/lib/tasks/all.rb +8 -0
  203. data/lib/tasks/coverage_report.rake +27 -0
  204. data/newrelic_security.gemspec +51 -0
  205. metadata +342 -0
@@ -0,0 +1,21 @@
1
+ module NewRelic::Security
2
+ module Instrumentation
3
+ module Sinatra
4
+ module Base
5
+ module Prepend
6
+ include NewRelic::Security::Instrumentation::Sinatra::Base
7
+
8
+ def call(env)
9
+ retval = nil
10
+ event = call_on_enter(env) { retval = super }
11
+ call_on_exit(event, retval) { return retval }
12
+ end
13
+
14
+ def route_eval
15
+ route_eval_on_enter { super }
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,79 @@
1
+ module NewRelic::Security
2
+ module Instrumentation
3
+ module SQLite3
4
+ module Database
5
+ module Chain
6
+
7
+ def self.instrument!
8
+ ::SQLite3::Database.class_eval do
9
+ include NewRelic::Security::Instrumentation::SQLite3::Database
10
+
11
+ alias_method :execute_without_security, :execute
12
+
13
+ def execute(sql, bind_vars = [], *args, &block)
14
+ retval = nil
15
+ event = execute_on_enter(sql, bind_vars, *args) { retval = execute_without_security(sql, bind_vars, *args, &block) }
16
+ execute_on_exit(event) { return retval }
17
+ end
18
+
19
+ alias_method :execute_batch_without_security, :execute_batch
20
+
21
+ def execute_batch(sql, bind_vars = [], *args)
22
+ retval = nil
23
+ event = execute_batch_on_enter(sql, bind_vars, *args) { retval = execute_batch_without_security(sql, bind_vars, *args) }
24
+ execute_batch_on_exit(event) { return retval }
25
+ end
26
+
27
+ if ::SQLite3::VERSION >= '1.4'
28
+ alias_method :execute_batch2_without_security, :execute_batch2
29
+
30
+ def execute_batch2(sql, &block)
31
+ retval = nil
32
+ event = execute_batch2_on_enter(sql) { retval = execute_batch2_without_security(sql, &block) }
33
+ execute_batch2_on_exit(event) { return retval }
34
+ end
35
+ end
36
+
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ module Statement
43
+ module Chain
44
+
45
+ def self.instrument!
46
+ ::SQLite3::Statement.class_eval do
47
+ include NewRelic::Security::Instrumentation::SQLite3::Statement
48
+
49
+ alias_method :initialize_without_security, :initialize
50
+
51
+ def initialize(db, sql)
52
+ retval = nil
53
+ event = initialize_on_enter(db, sql) { retval = initialize_without_security(db, sql) }
54
+ initialize_on_exit(event, retval, sql) { return retval }
55
+ end
56
+
57
+ alias_method :bind_params_without_security, :bind_params
58
+
59
+ def bind_params(*bind_vars)
60
+ retval = nil
61
+ event = bind_params_on_enter(*bind_vars) { retval = bind_params_without_security(*bind_vars) }
62
+ bind_params_on_exit(event) { return retval }
63
+ end
64
+
65
+ alias_method :execute_without_security, :execute
66
+
67
+ def execute(*bind_vars)
68
+ retval = nil
69
+ event = execute_on_enter(*bind_vars) { retval = execute_without_security(*bind_vars) }
70
+ execute_on_exit(event) { return retval }
71
+ end
72
+
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,164 @@
1
+ require_relative 'prepend'
2
+ require_relative 'chain'
3
+
4
+ module NewRelic::Security
5
+ module Instrumentation
6
+ module SQLite3::Database
7
+ # TODO: When bind_param(index, value) is called and then execute is called directly in such case bind_params found are nil because bind_param method is in ext c file.
8
+ def execute_on_enter(sql, bind_vars, *args)
9
+ event = nil
10
+ NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
11
+ hash = {}
12
+ hash[:sql] = sql
13
+ hash[:parameters] = bind_vars.is_a?(String) ? [bind_vars] : bind_vars.map(&:to_s)
14
+ hash[:parameters] = hash[:parameters] + args.map(&:to_s) unless args.empty?
15
+ event = NewRelic::Security::Agent::Control::Collector.collect(SQL_DB_COMMAND, [hash], SQLITE) unless NewRelic::Security::Instrumentation::InstrumentationUtils.sql_filter_events?(hash[:sql])
16
+ rescue => exception
17
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
18
+ ensure
19
+ yield
20
+ return event
21
+ end
22
+
23
+ def execute_on_exit(event)
24
+ NewRelic::Security::Agent.logger.debug "OnExit : #{self.class}.#{__method__}"
25
+ NewRelic::Security::Agent::Utils.create_exit_event(event)
26
+ rescue => exception
27
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
28
+ ensure
29
+ yield
30
+ end
31
+
32
+ def execute_batch_on_enter(sql, bind_vars, *args)
33
+ event = nil
34
+ NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
35
+ hash = {}
36
+ hash[:sql] = sql
37
+ hash[:parameters] = bind_vars.is_a?(String) ? [bind_vars] : bind_vars.map(&:to_s)
38
+ hash[:parameters] = hash[:parameters] + args unless args.empty?
39
+ event = NewRelic::Security::Agent::Control::Collector.collect(SQL_DB_COMMAND, [hash], SQLITE) unless NewRelic::Security::Instrumentation::InstrumentationUtils.sql_filter_events?(hash[:sql])
40
+ rescue => exception
41
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
42
+ ensure
43
+ yield
44
+ return event
45
+ end
46
+
47
+ def execute_batch_on_exit(event)
48
+ NewRelic::Security::Agent.logger.debug "OnExit : #{self.class}.#{__method__}"
49
+ NewRelic::Security::Agent::Utils.create_exit_event(event)
50
+ rescue => exception
51
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
52
+ ensure
53
+ yield
54
+ end
55
+
56
+ def execute_batch2_on_enter(sql)
57
+ event = nil
58
+ NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
59
+ hash = {}
60
+ hash[:sql] = sql
61
+ hash[:parameters] = []
62
+ event = NewRelic::Security::Agent::Control::Collector.collect(SQL_DB_COMMAND, [hash], SQLITE) unless NewRelic::Security::Instrumentation::InstrumentationUtils.sql_filter_events?(hash[:sql])
63
+ rescue => exception
64
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
65
+ ensure
66
+ yield
67
+ return event
68
+ end
69
+
70
+ def execute_batch2_on_exit(event)
71
+ NewRelic::Security::Agent.logger.debug "OnExit : #{self.class}.#{__method__}"
72
+ NewRelic::Security::Agent::Utils.create_exit_event(event)
73
+ rescue => exception
74
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
75
+ ensure
76
+ yield
77
+ end
78
+
79
+ end
80
+
81
+ module SQLite3::Statement
82
+
83
+ def initialize_on_enter(db, sql)
84
+ event = nil
85
+ NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
86
+ rescue => exception
87
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
88
+ ensure
89
+ yield
90
+ return event
91
+ end
92
+
93
+ def initialize_on_exit(event, retval, sql)
94
+ NewRelic::Security::Agent.logger.debug "OnExit : #{self.class}.#{__method__}"
95
+ NewRelic::Security::Agent::Control::HTTPContext.get_context.cache[retval.object_id] = { :sql => sql } if NewRelic::Security::Agent::Control::HTTPContext.get_context
96
+ rescue => exception
97
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
98
+ ensure
99
+ yield
100
+ end
101
+
102
+ def bind_params_on_enter(*bind_vars)
103
+ event = nil
104
+ NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
105
+ NewRelic::Security::Agent::Control::HTTPContext.get_context.cache[self.object_id][:parameters] = bind_vars.map(&:to_s) if NewRelic::Security::Agent::Control::HTTPContext.get_context && NewRelic::Security::Agent::Control::HTTPContext.get_context.cache.key?(self.object_id)
106
+ rescue => exception
107
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
108
+ ensure
109
+ yield
110
+ return event
111
+ end
112
+
113
+ def bind_params_on_exit(event)
114
+ NewRelic::Security::Agent.logger.debug "OnExit : #{self.class}.#{__method__}"
115
+ rescue => exception
116
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
117
+ ensure
118
+ yield
119
+ end
120
+
121
+ def execute_on_enter(*bind_vars)
122
+ event = nil
123
+ NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
124
+ ic_args = []
125
+ key = self.object_id
126
+ if NewRelic::Security::Agent::Control::HTTPContext.get_context && NewRelic::Security::Agent::Control::HTTPContext.get_context.cache.key?(self.object_id)
127
+ if bind_vars.length == 0
128
+ ic_args.push(NewRelic::Security::Agent::Control::HTTPContext.get_context.cache[key])
129
+ else
130
+ hash = {}
131
+ hash[:sql] = NewRelic::Security::Agent::Control::HTTPContext.get_context.cache[key][:sql]
132
+ hash[:parameters] = bind_vars.map(&:to_s)
133
+ ic_args.push(hash)
134
+ end
135
+ end
136
+ if ic_args[0].has_key?(:sql)
137
+ event = NewRelic::Security::Agent::Control::Collector.collect(SQL_DB_COMMAND, ic_args, SQLITE) unless NewRelic::Security::Instrumentation::InstrumentationUtils.sql_filter_events?(ic_args[0][:sql])
138
+ else
139
+ event = NewRelic::Security::Agent::Control::Collector.collect(SQL_DB_COMMAND, ic_args, SQLITE)
140
+ end
141
+ NewRelic::Security::Agent::Control::HTTPContext.get_context.cache.delete(key) if NewRelic::Security::Agent::Control::HTTPContext.get_context
142
+ rescue => exception
143
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
144
+ ensure
145
+ yield
146
+ return event
147
+ end
148
+
149
+ def execute_on_exit(event)
150
+ NewRelic::Security::Agent.logger.debug "OnExit : #{self.class}.#{__method__}"
151
+ NewRelic::Security::Agent::Utils.create_exit_event(event)
152
+ rescue => exception
153
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
154
+ ensure
155
+ yield
156
+ end
157
+
158
+ end
159
+
160
+ end
161
+ end
162
+
163
+ NewRelic::Security::Instrumentation::InstrumentationLoader.install_instrumentation(:sqlite3, ::SQLite3::Database, ::NewRelic::Security::Instrumentation::SQLite3::Database)
164
+ NewRelic::Security::Instrumentation::InstrumentationLoader.install_instrumentation(:sqlite3, ::SQLite3::Statement, ::NewRelic::Security::Instrumentation::SQLite3::Statement)
@@ -0,0 +1,56 @@
1
+ module NewRelic::Security
2
+ module Instrumentation
3
+ module SQLite3
4
+ module Database
5
+ module Prepend
6
+ include NewRelic::Security::Instrumentation::SQLite3::Database
7
+
8
+ def execute(sql, bind_vars = [], *args, &block)
9
+ retval = nil
10
+ event = execute_on_enter(sql, bind_vars, *args) { retval = super }
11
+ execute_on_exit(event) { return retval }
12
+ end
13
+
14
+ def execute_batch(sql, bind_vars = [], *args)
15
+ retval = nil
16
+ event = execute_batch_on_enter(sql, bind_vars, *args) { retval = super }
17
+ execute_batch_on_exit(event) { return retval }
18
+ end
19
+
20
+ if ::SQLite3::VERSION >= '1.4'
21
+ def execute_batch2(sql, &block)
22
+ retval = nil
23
+ event = execute_batch2_on_enter(sql) { retval = super }
24
+ execute_batch2_on_exit(event) { return retval }
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+ module Statement
31
+ module Prepend
32
+ include NewRelic::Security::Instrumentation::SQLite3::Statement
33
+
34
+ def initialize(db, sql)
35
+ retval = nil
36
+ event = initialize_on_enter(db, sql) { retval = super }
37
+ initialize_on_exit(event, retval, sql) { return retval }
38
+ end
39
+
40
+ def bind_params(*bind_vars)
41
+ retval = nil
42
+ event = bind_params_on_enter(*bind_vars) { retval = super }
43
+ bind_params_on_exit(event) { return retval }
44
+ end
45
+
46
+ def execute(*bind_vars)
47
+ retval = nil
48
+ event = execute_on_enter(*bind_vars) { retval = super }
49
+ execute_on_exit(event) { return retval }
50
+ end
51
+
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,72 @@
1
+ module NewRelic::Security
2
+ #
3
+ # This module contains most of the public API methods for the Ruby Security Agent.
4
+ #
5
+ # @api public
6
+ #
7
+ module API
8
+
9
+ #
10
+ # Check whether security is enabled
11
+ #
12
+ # @return [Boolean] true if security is enabled else false
13
+ #
14
+ # @api public
15
+ #
16
+ def is_security_active?
17
+ NewRelic::Security::Agent.config[:'agent.enabled'] && NewRelic::Security::Agent.config[:enabled]
18
+ end
19
+
20
+ #
21
+ # Manually initializes the security agent
22
+ #
23
+ # @param [Hash] Unused options Hash
24
+ #
25
+ # @return [nil]
26
+ #
27
+ # @api public
28
+ #
29
+ def manual_start(options = {})
30
+ raise "Options must be a hash" unless Hash === options
31
+ NewRelic::Security::Agent.config.enable_security
32
+ NewRelic::Security::Agent.agent.init
33
+ end
34
+
35
+ #
36
+ # Deactivates security and stops sending events to security engine
37
+ #
38
+ # @return [nil]
39
+ #
40
+ # @api public
41
+ #
42
+ def deactivate_security
43
+ NewRelic::Security::Agent.config.disable_security
44
+ end
45
+
46
+ #
47
+ # Send and event to security engine
48
+ #
49
+ # @param [NewRelic::Security::Agent::Control::Event] event IAST event to be sent to validator
50
+ #
51
+ # @return [nil]
52
+ #
53
+ # @api public
54
+ #
55
+ def send_event(event)
56
+ NewRelic::Security::Agent.agent.event_processor.send_event(event)
57
+ end
58
+
59
+ #
60
+ # Send and exit event to security engine
61
+ #
62
+ # @param [NewRelic::Security::Agent::Control::ExitEvent] exit_event IAST exit event for api call to be sent to validator
63
+ #
64
+ # @return [nil]
65
+ #
66
+ # @api public
67
+ #
68
+ def send_exit_event(exit_event)
69
+ NewRelic::Security::Agent.agent.event_processor.send_exit_event(exit_event)
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,5 @@
1
+ module NewRelic
2
+ module Security
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
@@ -0,0 +1,128 @@
1
+ require_relative 'websocket-ruby/lib/websocket.rb'
2
+ require 'socket'
3
+ require 'openssl'
4
+ require 'uri'
5
+ require 'newrelic_security/websocket-client-simple/event_emitter'
6
+
7
+ module NewRelic::Security
8
+ module WebSocket
9
+ module Client
10
+ module Simple
11
+
12
+ def self.connect(url, options={})
13
+ client = NewRelic::Security::WebSocket::Client::Simple::Client.new
14
+ yield client if block_given?
15
+ client.connect url, options
16
+ return client
17
+ end
18
+
19
+ class Client
20
+ include NewRelic::Security::EventEmitter
21
+ attr_reader :url, :handshake
22
+
23
+ def initialize
24
+ @socket = nil
25
+ end
26
+
27
+ def connect(url, options={})
28
+ return if @socket
29
+ @url = url
30
+ uri = URI.parse url
31
+ @socket = TCPSocket.new(uri.host,
32
+ uri.port || (uri.scheme == 'wss' ? 443 : 80))
33
+ if ['https', 'wss'].include? uri.scheme
34
+ ctx = OpenSSL::SSL::SSLContext.new
35
+ ctx.ssl_version = options[:ssl_version] if options[:ssl_version]
36
+ ctx.verify_mode = options[:verify_mode] if options[:verify_mode]
37
+ cert_store = options[:cert_store] || OpenSSL::X509::Store.new
38
+ cert_store.set_default_paths
39
+ ctx.cert_store = cert_store
40
+ @socket = ::OpenSSL::SSL::SSLSocket.new(@socket, ctx)
41
+ @socket.sync_close = true
42
+ @socket.hostname = uri.host
43
+ @socket.connect
44
+ end
45
+ @handshake = NewRelic::Security::WebSocket::Handshake::Client.new :url => url, :headers => options[:headers]
46
+ @handshaked = false
47
+ @pipe_broken = false
48
+ frame = NewRelic::Security::WebSocket::Frame::Incoming::Client.new
49
+ @closed = false
50
+ once :__close do |err|
51
+ close
52
+ emit :close, err
53
+ end
54
+
55
+ @thread = Thread.new do
56
+ while !@closed do
57
+ begin
58
+ unless recv_data = @socket.getc
59
+ sleep 1
60
+ next
61
+ end
62
+ unless @handshaked
63
+ @handshake << recv_data
64
+ if @handshake.finished?
65
+ @handshaked = true
66
+ emit :open
67
+ end
68
+ else
69
+ frame << recv_data
70
+ while msg = frame.next
71
+ emit :message, msg
72
+ end
73
+ end
74
+ rescue IOError => e
75
+ close false
76
+ rescue => e
77
+ emit :error, e
78
+ end
79
+ end
80
+ end
81
+
82
+ @socket.write @handshake.to_s
83
+ end
84
+
85
+ def send(data, opt={:type => :text})
86
+ return if !@handshaked or @closed
87
+ type = opt[:type]
88
+ frame = NewRelic::Security::WebSocket::Frame::Outgoing::Client.new(:data => data, :type => type, :version => @handshake.version)
89
+ begin
90
+ @socket.write frame.to_s
91
+ rescue IOError => e
92
+ @pipe_broken = true
93
+ emit :__close, e
94
+ rescue Errno::EPIPE => e
95
+ @pipe_broken = true
96
+ emit :__close, e
97
+ rescue OpenSSL::SSL::SSLError => e
98
+ @pipe_broken = true
99
+ emit :__close, e
100
+ end
101
+ end
102
+
103
+ def close(reconnect = true)
104
+ return if @closed
105
+ if !@pipe_broken
106
+ send nil, :type => :close
107
+ end
108
+ @closed = true
109
+ @socket.close if @socket
110
+ @socket = nil
111
+ emit :__close, reconnect
112
+ Thread.kill @thread if @thread
113
+ end
114
+
115
+ def open?
116
+ @handshake&.finished? and !@closed
117
+ end
118
+
119
+ def closed?
120
+ @closed
121
+ end
122
+
123
+ end
124
+
125
+ end
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,72 @@
1
+ module NewRelic::Security
2
+ module EventEmitter
3
+ def self.included(klass)
4
+ # klass.extend ClassMethods
5
+ klass.__send__ :include, InstanceMethods
6
+ end
7
+
8
+ def self.apply(object)
9
+ object.extend InstanceMethods
10
+ end
11
+
12
+ module ClassMethods
13
+ end
14
+
15
+ module InstanceMethods
16
+ def __events
17
+ @__events ||= []
18
+ end
19
+
20
+ def add_listener(type, params={}, &block)
21
+ raise ArgumentError, 'listener block not given' unless block_given?
22
+ id = __events.empty? ? 0 : __events.last[:id]+1
23
+ __events << {
24
+ :type => type.to_sym,
25
+ :listener => block,
26
+ :params => params,
27
+ :id => id
28
+ }
29
+ id
30
+ end
31
+
32
+ alias :on :add_listener
33
+
34
+ def remove_listener(id_or_type)
35
+ if id_or_type.is_a? Integer
36
+ __events.delete_if do |e|
37
+ e[:id] == id_or_type
38
+ end
39
+ elsif [String, Symbol].include? id_or_type.class
40
+ __events.delete_if do |e|
41
+ e[:type] == id_or_type.to_sym
42
+ end
43
+ end
44
+ end
45
+
46
+ def emit(type, *data)
47
+ type = type.to_sym
48
+ __events.each do |e|
49
+ case e[:type]
50
+ when type
51
+ listener = e[:listener]
52
+ e[:type] = nil if e[:params][:once]
53
+ instance_exec(*data, &listener)
54
+ when :*
55
+ listener = e[:listener]
56
+ e[:type] = nil if e[:params][:once]
57
+ instance_exec(type, *data, &listener)
58
+ end
59
+ end
60
+ __events.each do |e|
61
+ remove_listener e[:id] unless e[:type]
62
+ end
63
+ end
64
+
65
+ def once(type, &block)
66
+ add_listener type, {:once => true}, &block
67
+ end
68
+
69
+ end
70
+
71
+ end
72
+ end