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,65 @@
1
+ module NewRelic::Security
2
+ module Instrumentation
3
+ module Kernel
4
+ module Chain
5
+ def self.instrument!
6
+ ::Object.class_eval do
7
+ include NewRelic::Security::Instrumentation::Kernel
8
+
9
+ private
10
+
11
+ # TODO: This hook is useful for applying instrumentation on dynamically loaded modules, dynamic loading of module is unsupported for now.
12
+ # alias_method :require_without_security, :require
13
+
14
+ # def require(name)
15
+ # retval = nil
16
+ # event = require_on_enter(name) { retval = require_without_security(name) }
17
+ # require_on_exit(event, retval, name) { return retval }
18
+ # end
19
+
20
+ alias_method :system_without_security, :system
21
+
22
+ def system(*var)
23
+ retval = nil
24
+ event = system_on_enter(*var) { retval = system_without_security(*var) }
25
+ system_on_exit(event, retval) { return retval }
26
+ end
27
+
28
+ alias_method :backtick_without_security, :`
29
+
30
+ def `(cmd)
31
+ retval = nil
32
+ event = backtick_on_enter(cmd) { retval = backtick_without_security(cmd) }
33
+ backtick_on_exit(event) { return retval }
34
+ end
35
+
36
+ alias_method :spawn_without_security, :spawn
37
+
38
+ def spawn(*var)
39
+ retval = nil
40
+ event = spawn_on_enter(*var) { retval = spawn_without_security(*var) }
41
+ spawn_on_exit(event, retval) { return retval }
42
+ end
43
+
44
+ alias_method :exec_without_security, :exec
45
+
46
+ def exec(*var)
47
+ retval = nil
48
+ event = exec_on_enter(*var) { retval = exec_without_security(*var) }
49
+ exec_on_exit(event) { return retval }
50
+ end
51
+
52
+ alias_method :open_without_security, :open
53
+
54
+ def open(*args, **kwargs)
55
+ retval = nil
56
+ event = open_on_enter(*args, **kwargs) { retval = open_without_security(*args, **kwargs) }
57
+ open_on_exit(event, retval) { return retval }
58
+ end
59
+
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,167 @@
1
+ require_relative 'prepend'
2
+ require_relative 'chain'
3
+
4
+ module NewRelic::Security
5
+ module Instrumentation
6
+ module Kernel
7
+
8
+ def require_on_enter(name)
9
+ event = nil
10
+ NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
11
+ rescue => exception
12
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
13
+ ensure
14
+ yield
15
+ return event
16
+ end
17
+
18
+ def require_on_exit(event, retval, name)
19
+ NewRelic::Security::Agent.logger.debug "OnExit : #{self.class}.#{__method__}"
20
+ if retval
21
+ NewRelic::Security::Agent.logger.info "Dynamic loading of #{name} module observed, TODO: Call Instrumentation API"
22
+ # TODO: Call Instrumentation API here (Dynamic loading of module observed)
23
+ end
24
+ rescue => exception
25
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
26
+ ensure
27
+ yield
28
+ end
29
+
30
+ def system_on_enter(*var)
31
+ event = nil
32
+ NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
33
+ ic_args = []
34
+ var.each { |arg|
35
+ ic_args << arg if arg.is_a? String
36
+ }
37
+ event = NewRelic::Security::Agent::Control::Collector.collect(SYSTEM_COMMAND, ic_args)
38
+ rescue => exception
39
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
40
+ ensure
41
+ yield
42
+ return event
43
+ end
44
+
45
+ def system_on_exit(event, retval)
46
+ NewRelic::Security::Agent.logger.debug "OnExit : #{self.class}.#{__method__}"
47
+ NewRelic::Security::Agent::Utils.create_exit_event(event) if retval
48
+ rescue => exception
49
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
50
+ ensure
51
+ yield
52
+ end
53
+
54
+ def backtick_on_enter(cmd)
55
+ event = nil
56
+ NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
57
+ event = NewRelic::Security::Agent::Control::Collector.collect(SYSTEM_COMMAND, Array(cmd))
58
+ rescue => exception
59
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
60
+ ensure
61
+ yield
62
+ return event
63
+ end
64
+
65
+ def backtick_on_exit(event)
66
+ NewRelic::Security::Agent.logger.debug "OnExit : #{self.class}.#{__method__}"
67
+ NewRelic::Security::Agent::Utils.create_exit_event(event) if $? && $?.exitstatus == 0
68
+ rescue => exception
69
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
70
+ ensure
71
+ yield
72
+ end
73
+
74
+ def spawn_on_enter(*var)
75
+ event = nil
76
+ NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
77
+ ic_args = []
78
+ var.each { |arg|
79
+ ic_args << arg if arg.is_a? String
80
+ }
81
+ event = NewRelic::Security::Agent::Control::Collector.collect(SYSTEM_COMMAND, ic_args)
82
+ rescue => exception
83
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
84
+ ensure
85
+ yield
86
+ return event
87
+ end
88
+
89
+ def spawn_on_exit(event, retval)
90
+ NewRelic::Security::Agent.logger.debug "OnExit : #{self.class}.#{__method__}"
91
+ NewRelic::Security::Agent::Utils.create_exit_event(event) if retval.is_a?(Integer)
92
+ rescue => exception
93
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
94
+ ensure
95
+ yield
96
+ end
97
+
98
+ def exec_on_enter(*var)
99
+ event = nil
100
+ NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
101
+ event = NewRelic::Security::Agent::Control::Collector.collect(SYSTEM_COMMAND, var)
102
+ rescue => exception
103
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
104
+ ensure
105
+ yield
106
+ return event
107
+ end
108
+
109
+ def exec_on_exit(event)
110
+ NewRelic::Security::Agent.logger.debug "OnExit : #{self.class}.#{__method__}"
111
+ NewRelic::Security::Agent.logger.debug "Exit event : #{event}"
112
+ # TODO: Add exit event if required
113
+ rescue => exception
114
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
115
+ ensure
116
+ yield
117
+ end
118
+
119
+ def open_on_enter(*args, **kwargs)
120
+ event = nil
121
+ NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
122
+ fname = ::File.path(args[0]) #some times it is 'String' or 'Path' class
123
+ if fname.start_with?(PIPE)
124
+ event = NewRelic::Security::Agent::Control::Collector.collect(SYSTEM_COMMAND, args)
125
+ else
126
+ abs_path = ::File.expand_path(fname)
127
+ if args.length == 2
128
+ fmode = args[1]
129
+ event_category = NewRelic::Security::Instrumentation::InstrumentationUtils::OPEN_MODES.include?(fmode) ? READ : WRITE
130
+ if NewRelic::Security::Instrumentation::InstrumentationUtils.notify_app_integrity_open?(fname, abs_path, fmode)
131
+ event = NewRelic::Security::Agent::Control::Collector.collect(FILE_INTEGRITY, Array(fname), event_category)
132
+ else
133
+ if NewRelic::Security::Instrumentation::InstrumentationUtils.read_filter?(fname, abs_path)
134
+ NewRelic::Security::Agent.logger.debug "Filtered because File name exist in filtered list #{self.class}.#{__method__} Args:: #{fname} #{fmode}"
135
+ else
136
+ event = NewRelic::Security::Agent::Control::Collector.collect(FILE_OPERATION, Array(fname), event_category)
137
+ end
138
+ end
139
+ else
140
+ if NewRelic::Security::Instrumentation::InstrumentationUtils.read_filter?(fname, abs_path)
141
+ NewRelic::Security::Agent.logger.debug "Filtered because File name exist in filtered list #{self.class}.#{__method__} Args:: #{args}"
142
+ else
143
+ event = NewRelic::Security::Agent::Control::Collector.collect(FILE_OPERATION, Array(fname), READ)
144
+ end
145
+ end
146
+ end
147
+ rescue => exception
148
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
149
+ ensure
150
+ yield
151
+ return event
152
+ end
153
+
154
+ def open_on_exit(event, retval)
155
+ NewRelic::Security::Agent.logger.debug "OnExit : #{self.class}.#{__method__}"
156
+ NewRelic::Security::Agent::Utils.create_exit_event(event) if retval.is_a?(Integer)
157
+ rescue => exception
158
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
159
+ ensure
160
+ yield
161
+ end
162
+
163
+ end
164
+ end
165
+ end
166
+
167
+ NewRelic::Security::Instrumentation::InstrumentationLoader.install_instrumentation(:kernel, ::Object, ::NewRelic::Security::Instrumentation::Kernel)
@@ -0,0 +1,50 @@
1
+ module NewRelic::Security
2
+ module Instrumentation
3
+ module Kernel
4
+ module Prepend
5
+ include NewRelic::Security::Instrumentation::Kernel
6
+
7
+ private
8
+
9
+ # TODO: This hook is useful for applying instrumentation on dynamically loaded modules, dynamic loading of module is unsupported for now.
10
+ # def require(name)
11
+ # retval = nil
12
+ # event = require_on_enter(name) { retval = super }
13
+ # require_on_exit(event, retval, name) { return retval }
14
+ # end
15
+
16
+ def system(*var)
17
+ retval = nil
18
+ event = system_on_enter(*var) { retval = super }
19
+ system_on_exit(event, retval) { return retval }
20
+ end
21
+
22
+ def `(cmd)
23
+ retval = nil
24
+ event = backtick_on_enter(cmd) { retval = super }
25
+ backtick_on_exit(event) { return retval }
26
+ end
27
+
28
+ def spawn(*var)
29
+ retval = nil
30
+ event = spawn_on_enter(*var) { retval = super }
31
+ spawn_on_exit(event, retval) { return retval }
32
+ end
33
+
34
+ # TODO: Add fork hook if required
35
+ def exec(*var)
36
+ retval = nil
37
+ event = exec_on_enter(*var) { retval = super }
38
+ exec_on_exit(event) { return retval }
39
+ end
40
+
41
+ def open(*args, **kwargs)
42
+ retval = nil
43
+ event = open_on_enter(*args, **kwargs) { retval = super }
44
+ open_on_exit(event, retval) { return retval }
45
+ end
46
+
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,106 @@
1
+ module NewRelic::Security
2
+ module Instrumentation
3
+ module Mongo
4
+ module Collection
5
+ module Chain
6
+ def self.instrument!
7
+ ::Mongo::Collection.class_eval do
8
+ include NewRelic::Security::Instrumentation::Mongo::Collection
9
+
10
+ alias_method :find_without_security, :find
11
+
12
+ def find(filter = nil, options = {})
13
+ retval = nil
14
+ event = find_on_enter(filter, options) { retval = find_without_security(filter, options) }
15
+ find_on_exit(event) { return retval }
16
+ end
17
+
18
+ alias_method :insert_one_without_security, :insert_one
19
+
20
+ def insert_one(document, opts = {})
21
+ retval = nil
22
+ event = insert_one_on_enter(document, opts) { retval = insert_one_without_security(document, opts) }
23
+ insert_one_on_exit(event) { return retval }
24
+ end
25
+
26
+ alias_method :insert_many_without_security, :insert_many
27
+
28
+ def insert_many(documents, options = {})
29
+ retval = nil
30
+ event = insert_many_on_enter(documents, options) { retval = insert_many_without_security(documents, options) }
31
+ insert_many_on_exit(event) { return retval }
32
+ end
33
+ end
34
+ end
35
+ end
36
+
37
+ module View
38
+ module Chain
39
+ def self.instrument!
40
+ ::Mongo::Collection::View.class_eval do
41
+ include NewRelic::Security::Instrumentation::Mongo::Collection::View
42
+
43
+ alias_method :update_one_without_security, :update_one
44
+
45
+ def update_one(spec, opts = {})
46
+ retval = nil
47
+ event = update_one_on_enter(spec, opts) { retval = update_one_without_security(spec, opts) }
48
+ update_one_on_exit(event) { return retval }
49
+ end
50
+
51
+ alias_method :update_many_without_security, :update_many
52
+
53
+ def update_many(spec, opts = {})
54
+ retval = nil
55
+ event = update_many_on_enter(spec, opts) { retval = update_many_without_security(spec, opts) }
56
+ update_many_on_exit(event) { return retval }
57
+ end
58
+
59
+ alias_method :delete_one_without_security, :delete_one
60
+
61
+ def delete_one(opts = {})
62
+ retval = nil
63
+ event = delete_one_on_enter(opts) { retval = delete_one_without_security(opts) }
64
+ delete_one_on_exit(event) { return retval }
65
+ end
66
+
67
+ alias_method :find_one_and_delete_without_security, :find_one_and_delete
68
+
69
+ def find_one_and_delete(opts = {})
70
+ retval = nil
71
+ event = find_one_and_delete_on_enter(opts) { retval = find_one_and_delete_without_security(opts) }
72
+ find_one_and_delete_on_exit(event) { return retval }
73
+ end
74
+
75
+ alias_method :delete_many_without_security, :delete_many
76
+
77
+ def delete_many(opts = {})
78
+ retval = nil
79
+ event = delete_many_on_enter(opts) { retval = delete_many_without_security(opts) }
80
+ delete_many_on_exit(event) { return retval }
81
+ end
82
+
83
+ alias_method :replace_one_without_security, :replace_one
84
+
85
+ def replace_one(replacement, opts = {})
86
+ retval = nil
87
+ event = replace_one_on_enter(replacement, opts) { retval = replace_one_without_security(replacement, opts) }
88
+ replace_one_on_exit(event) { return retval }
89
+ end
90
+
91
+ alias_method :find_one_and_update_without_security, :find_one_and_update
92
+
93
+ def find_one_and_update(document, opts = {})
94
+ retval = nil
95
+ event = find_one_and_update_on_enter(document, opts) { retval = find_one_and_update_without_security(document, opts) }
96
+ find_one_and_update_on_exit(event) { return retval }
97
+ end
98
+
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,273 @@
1
+ require_relative 'prepend'
2
+ require_relative 'chain'
3
+
4
+ module NewRelic::Security
5
+ module Instrumentation
6
+ module Mongo::Collection
7
+
8
+ def find_on_enter(filter, options)
9
+ event = nil
10
+ NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
11
+ hash = {}
12
+ hash[:payload] = {}
13
+ hash[:payload][:filter] = filter
14
+ hash[:payload][:options] = options
15
+ hash[:payloadType] = :find #bind params
16
+ event = NewRelic::Security::Agent::Control::Collector.collect(NOSQL_DB_COMMAND, [hash], MONGO)
17
+ rescue => exception
18
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
19
+ ensure
20
+ yield
21
+ return event
22
+ end
23
+
24
+ def find_on_exit(event)
25
+ NewRelic::Security::Agent.logger.debug "OnExit : #{self.class}.#{__method__}"
26
+ NewRelic::Security::Agent::Utils.create_exit_event(event)
27
+ rescue => exception
28
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
29
+ ensure
30
+ yield
31
+ end
32
+
33
+ def insert_one_on_enter(document, opts)
34
+ event = nil
35
+ NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
36
+ if caller_locations[1].label.to_s == "insert_one_with_clear_cache"
37
+ NewRelic::Security::Agent.logger.debug "Filtered to break the loop calling #{self.class}.#{__method__} from 'insert_one_with_clear_cache'"
38
+ return
39
+ end
40
+ hash = {}
41
+ hash[:payload] = {}
42
+ hash[:payload][:document] = document
43
+ hash[:payload][:opts] = opts
44
+ hash[:payloadType] = :insert
45
+ event = NewRelic::Security::Agent::Control::Collector.collect(NOSQL_DB_COMMAND, [hash], MONGO)
46
+ rescue => exception
47
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
48
+ ensure
49
+ yield
50
+ return event
51
+ end
52
+
53
+ def insert_one_on_exit(event)
54
+ NewRelic::Security::Agent.logger.debug "OnExit : #{self.class}.#{__method__}"
55
+ NewRelic::Security::Agent::Utils.create_exit_event(event)
56
+ rescue => exception
57
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
58
+ ensure
59
+ yield
60
+ end
61
+
62
+ def insert_many_on_enter(documents, options)
63
+ event = nil
64
+ NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
65
+ hash = {}
66
+ hash[:payload] = {}
67
+ hash[:payload][:documents] = documents
68
+ hash[:payload][:options] = options
69
+ hash[:payloadType] = :insert
70
+ event = NewRelic::Security::Agent::Control::Collector.collect(NOSQL_DB_COMMAND, [hash], MONGO)
71
+ rescue => exception
72
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
73
+ ensure
74
+ yield
75
+ return event
76
+ end
77
+
78
+ def insert_many_on_exit(event)
79
+ NewRelic::Security::Agent.logger.debug "OnExit : #{self.class}.#{__method__}"
80
+ NewRelic::Security::Agent::Utils.create_exit_event(event)
81
+ rescue => exception
82
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
83
+ ensure
84
+ yield
85
+ end
86
+ end
87
+
88
+ module Mongo::Collection::View
89
+ def update_one_on_enter(spec, opts)
90
+ event = nil
91
+ NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
92
+ hash = {}
93
+ hash[:payload] = {}
94
+ hash[:payload][:filter] = instance_variable_get(:@filter)
95
+ hash[:payload][:spec] = spec
96
+ hash[:payload][:opts] = opts
97
+ hash[:payloadType] = :update
98
+ event = NewRelic::Security::Agent::Control::Collector.collect(NOSQL_DB_COMMAND, [hash], MONGO)
99
+ rescue => exception
100
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
101
+ ensure
102
+ yield
103
+ return event
104
+ end
105
+
106
+ def update_one_on_exit(event)
107
+ NewRelic::Security::Agent.logger.debug "OnExit : #{self.class}.#{__method__}"
108
+ NewRelic::Security::Agent::Utils.create_exit_event(event)
109
+ rescue => exception
110
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
111
+ ensure
112
+ yield
113
+ end
114
+
115
+ def update_many_on_enter(spec, opts)
116
+ event = nil
117
+ NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
118
+ hash = {}
119
+ hash[:payload] = {}
120
+ hash[:payload][:filter] = instance_variable_get(:@filter)
121
+ hash[:payload][:spec] = spec
122
+ hash[:payload][:opts] = opts
123
+ hash[:payloadType] = :update
124
+ event = NewRelic::Security::Agent::Control::Collector.collect(NOSQL_DB_COMMAND, [hash], MONGO)
125
+ rescue => exception
126
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
127
+ ensure
128
+ yield
129
+ return event
130
+ end
131
+
132
+ def update_many_on_exit(event)
133
+ NewRelic::Security::Agent.logger.debug "OnExit : #{self.class}.#{__method__}"
134
+ NewRelic::Security::Agent::Utils.create_exit_event(event)
135
+ rescue => exception
136
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
137
+ ensure
138
+ yield
139
+ end
140
+
141
+ def delete_one_on_enter(opts)
142
+ event = nil
143
+ NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
144
+ hash = {}
145
+ hash[:payload] = {}
146
+ hash[:payload][:filter] = instance_variable_get(:@filter)
147
+ hash[:payload][:opts] = opts
148
+ hash[:payloadType] = :delete
149
+ event = NewRelic::Security::Agent::Control::Collector.collect(NOSQL_DB_COMMAND, [hash], MONGO)
150
+ rescue => exception
151
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
152
+ ensure
153
+ yield
154
+ return event
155
+ end
156
+
157
+ def delete_one_on_exit(event)
158
+ NewRelic::Security::Agent.logger.debug "OnExit : #{self.class}.#{__method__}"
159
+ NewRelic::Security::Agent::Utils.create_exit_event(event)
160
+ rescue => exception
161
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
162
+ ensure
163
+ yield
164
+ end
165
+
166
+ def find_one_and_delete_on_enter(opts)
167
+ event = nil
168
+ NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
169
+ hash = {}
170
+ hash[:payload] = {}
171
+ hash[:payload][:filter] = instance_variable_get(:@filter)
172
+ hash[:payload][:opts] = opts
173
+ hash[:payloadType] = :delete
174
+ event = NewRelic::Security::Agent::Control::Collector.collect(NOSQL_DB_COMMAND, [hash], MONGO)
175
+ rescue => exception
176
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
177
+ ensure
178
+ yield
179
+ return event
180
+ end
181
+
182
+ def find_one_and_delete_on_exit(event)
183
+ NewRelic::Security::Agent.logger.debug "OnExit : #{self.class}.#{__method__}"
184
+ NewRelic::Security::Agent::Utils.create_exit_event(event)
185
+ rescue => exception
186
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
187
+ ensure
188
+ yield
189
+ end
190
+
191
+ def delete_many_on_enter(opts)
192
+ event = nil
193
+ NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
194
+ hash = {}
195
+ hash[:payload] = {}
196
+ hash[:payload][:filter] = instance_variable_get(:@filter)
197
+ hash[:payload][:opts] = opts
198
+ hash[:payloadType] = :delete
199
+ event = NewRelic::Security::Agent::Control::Collector.collect(NOSQL_DB_COMMAND, [hash], MONGO)
200
+ rescue => exception
201
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
202
+ ensure
203
+ yield
204
+ return event
205
+ end
206
+
207
+ def delete_many_on_exit(event)
208
+ NewRelic::Security::Agent.logger.debug "OnExit : #{self.class}.#{__method__}"
209
+ NewRelic::Security::Agent::Utils.create_exit_event(event)
210
+ rescue => exception
211
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
212
+ ensure
213
+ yield
214
+ end
215
+
216
+ def replace_one_on_enter(replacement, opts)
217
+ event = nil
218
+ NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
219
+ hash = {}
220
+ hash[:payload] = {}
221
+ hash[:payload][:filter] = instance_variable_get(:@filter)
222
+ hash[:payload][:replacement] = replacement
223
+ hash[:payload][:opts] = opts
224
+ hash[:payloadType] = :update
225
+ event = NewRelic::Security::Agent::Control::Collector.collect(NOSQL_DB_COMMAND, [hash], MONGO)
226
+ rescue => exception
227
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
228
+ ensure
229
+ yield
230
+ return event
231
+ end
232
+
233
+ def replace_one_on_exit(event)
234
+ NewRelic::Security::Agent.logger.debug "OnExit : #{self.class}.#{__method__}"
235
+ NewRelic::Security::Agent::Utils.create_exit_event(event)
236
+ rescue => exception
237
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
238
+ ensure
239
+ yield
240
+ end
241
+
242
+ def find_one_and_update_on_enter(document, opts)
243
+ event = nil
244
+ NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
245
+ hash = {}
246
+ hash[:payload] = {}
247
+ hash[:payload][:filter] = instance_variable_get(:@filter)
248
+ hash[:payload][:document] = document
249
+ hash[:payload][:opts] = opts
250
+ hash[:payloadType] = :update
251
+ event = NewRelic::Security::Agent::Control::Collector.collect(NOSQL_DB_COMMAND, [hash], MONGO)
252
+ rescue => exception
253
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
254
+ ensure
255
+ yield
256
+ return event
257
+ end
258
+
259
+ def find_one_and_update_on_exit(event)
260
+ NewRelic::Security::Agent.logger.debug "OnExit : #{self.class}.#{__method__}"
261
+ NewRelic::Security::Agent::Utils.create_exit_event(event)
262
+ rescue => exception
263
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
264
+ ensure
265
+ yield
266
+ end
267
+
268
+ end
269
+ end
270
+ end
271
+
272
+ NewRelic::Security::Instrumentation::InstrumentationLoader.install_instrumentation(:mongo, ::Mongo::Collection, ::NewRelic::Security::Instrumentation::Mongo::Collection)
273
+ NewRelic::Security::Instrumentation::InstrumentationLoader.install_instrumentation(:mongo, ::Mongo::Collection::View, ::NewRelic::Security::Instrumentation::Mongo::Collection::View)