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,50 @@
1
+ require_relative 'prepend'
2
+ require_relative 'chain'
3
+
4
+ require 'uri'
5
+
6
+ module NewRelic::Security
7
+ module Instrumentation
8
+ module Patron::Session
9
+
10
+ def request_on_enter(action, url, headers, options)
11
+ event = nil
12
+ NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
13
+ ob = {}
14
+ ob[:Method] = action
15
+ final_url = self.base_url.nil? ? url : "#{self.base_url}#{url}"
16
+ uri = NewRelic::Security::Instrumentation::InstrumentationUtils.parse_uri(final_url)
17
+ if uri
18
+ ob[:scheme] = uri.scheme
19
+ ob[:host] = uri.host
20
+ ob[:port] = uri.port
21
+ ob[:URI] = uri.to_s
22
+ ob[:path] = uri.path
23
+ ob[:query] = uri.query
24
+ ob[:Body] = options[:data]
25
+ ob[:Headers] = headers
26
+ ob.each { |_, value| value.dup.force_encoding(ISO_8859_1).encode(UTF_8) if value.is_a?(String) }
27
+ event = NewRelic::Security::Agent::Control::Collector.collect(HTTP_REQUEST, [ob])
28
+ end
29
+ NewRelic::Security::Instrumentation::InstrumentationUtils.add_tracing_data(headers, event) if event
30
+ event
31
+ rescue => exception
32
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
33
+ ensure
34
+ yield
35
+ return event
36
+ end
37
+
38
+ def request_on_exit(event)
39
+ NewRelic::Security::Agent.logger.debug "OnExit : #{self.class}.#{__method__}"
40
+ NewRelic::Security::Agent::Utils.create_exit_event(event)
41
+ rescue => exception
42
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
43
+ ensure
44
+ yield
45
+ end
46
+ end
47
+ end
48
+ end
49
+
50
+ NewRelic::Security::Instrumentation::InstrumentationLoader.install_instrumentation(:patron, ::Patron::Session, ::NewRelic::Security::Instrumentation::Patron::Session)
@@ -0,0 +1,18 @@
1
+ module NewRelic::Security
2
+ module Instrumentation
3
+ module Patron
4
+ module Session
5
+ module Prepend
6
+ include NewRelic::Security::Instrumentation::Patron::Session
7
+
8
+ def request(action, url, headers, options = {})
9
+ retval = nil
10
+ event = request_on_enter(action, url, headers, options) { retval = super }
11
+ request_on_exit(event) { return retval }
12
+ end
13
+
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,49 @@
1
+ module NewRelic::Security
2
+ module Instrumentation
3
+ module PG
4
+ module Connection
5
+ module Chain
6
+
7
+ def self.instrument!
8
+ ::PG::Connection.class_eval do
9
+ include NewRelic::Security::Instrumentation::PG::Connection
10
+
11
+ alias_method :exec_without_security, :exec
12
+
13
+ def exec(sql)
14
+ retval = nil
15
+ event = exec_on_enter(sql) { retval = exec_without_security(sql) }
16
+ exec_on_exit(event) { return retval }
17
+ end
18
+
19
+ alias_method :async_exec_without_security, :async_exec
20
+
21
+ def async_exec(*args)
22
+ retval = nil
23
+ event = async_exec_on_enter(*args) { retval = async_exec_without_security(*args) }
24
+ async_exec_on_exit(event) { return retval }
25
+ end
26
+
27
+ alias_method :prepare_without_security, :prepare
28
+
29
+ def prepare(*args)
30
+ retval = nil
31
+ event = prepare_on_enter(*args) { retval = prepare_without_security(*args) }
32
+ prepare_on_exit(event) { return retval }
33
+ end
34
+
35
+ alias_method :exec_prepared_without_security, :exec_prepared
36
+
37
+ def exec_prepared(*args)
38
+ retval = nil
39
+ event = exec_prepared_on_enter(*args) { retval = exec_prepared_without_security(*args) }
40
+ exec_prepared_on_exit(event) { return retval }
41
+ end
42
+
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,102 @@
1
+ require_relative 'prepend'
2
+ require_relative 'chain'
3
+
4
+ module NewRelic::Security
5
+ module Instrumentation
6
+ module PG::Connection
7
+
8
+ def exec_on_enter(sql)
9
+ event = nil
10
+ NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
11
+ hash = {}
12
+ hash[:sql] = sql
13
+ hash[:parameters] = []
14
+ event = NewRelic::Security::Agent::Control::Collector.collect(SQL_DB_COMMAND, [hash], POSTGRES) unless NewRelic::Security::Instrumentation::InstrumentationUtils.sql_filter_events?(hash[:sql])
15
+ rescue => exception
16
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
17
+ ensure
18
+ yield
19
+ return event
20
+ end
21
+
22
+ def exec_on_exit(event)
23
+ NewRelic::Security::Agent.logger.debug "OnExit : #{self.class}.#{__method__}"
24
+ NewRelic::Security::Agent::Utils.create_exit_event(event)
25
+ rescue => exception
26
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
27
+ ensure
28
+ yield
29
+ end
30
+
31
+ def async_exec_on_enter(*args)
32
+ event = nil
33
+ NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
34
+ hash = {}
35
+ hash[:sql] = args[0]
36
+ hash[:parameters] = []
37
+ event = NewRelic::Security::Agent::Control::Collector.collect(SQL_DB_COMMAND, [hash], POSTGRES) unless NewRelic::Security::Instrumentation::InstrumentationUtils.sql_filter_events?(hash[:sql])
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 async_exec_on_exit(event)
46
+ NewRelic::Security::Agent.logger.debug "OnExit : #{self.class}.#{__method__}"
47
+ NewRelic::Security::Agent::Utils.create_exit_event(event)
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 prepare_on_enter(*args)
55
+ event = nil
56
+ NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
57
+ NewRelic::Security::Agent::Control::HTTPContext.get_context.cache[args[0].to_s] = args[1].to_s if NewRelic::Security::Agent::Control::HTTPContext.get_context
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 prepare_on_exit(event)
66
+ NewRelic::Security::Agent.logger.debug "OnExit : #{self.class}.#{__method__}"
67
+ rescue => exception
68
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
69
+ ensure
70
+ yield
71
+ end
72
+
73
+ def exec_prepared_on_enter(*args)
74
+ event = nil
75
+ NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
76
+ hash = {}
77
+ hash[:sql] = NewRelic::Security::Agent::Control::HTTPContext.get_context.cache[args[0].to_s] if NewRelic::Security::Agent::Control::HTTPContext.get_context
78
+ hash[:sql] = self.exec("select statement from pg_prepared_statements where name = '#{args[0]}'").getvalue(0,0) unless hash[:sql]
79
+ hash[:parameters] = args[1].map(&:to_s)
80
+ event = NewRelic::Security::Agent::Control::Collector.collect(SQL_DB_COMMAND, [hash], POSTGRES) unless NewRelic::Security::Instrumentation::InstrumentationUtils.sql_filter_events?(hash[:sql])
81
+ NewRelic::Security::Agent::Control::HTTPContext.get_context.cache.delete(args[0].to_s) if NewRelic::Security::Agent::Control::HTTPContext.get_context
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 exec_prepared_on_exit(event)
90
+ NewRelic::Security::Agent.logger.debug "OnExit : #{self.class}.#{__method__}"
91
+ NewRelic::Security::Agent::Utils.create_exit_event(event)
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
+ end
99
+ end
100
+ end
101
+
102
+ NewRelic::Security::Instrumentation::InstrumentationLoader.install_instrumentation(:pg, ::PG::Connection, ::NewRelic::Security::Instrumentation::PG::Connection)
@@ -0,0 +1,36 @@
1
+ module NewRelic::Security
2
+ module Instrumentation
3
+ module PG
4
+ module Connection
5
+ module Prepend
6
+ include NewRelic::Security::Instrumentation::PG::Connection
7
+
8
+ def exec(sql)
9
+ retval = nil
10
+ event = exec_on_enter(sql) { retval = super }
11
+ exec_on_exit(event) { return retval }
12
+ end
13
+
14
+ def async_exec(*args)
15
+ retval = nil
16
+ event = async_exec_on_enter(*args) { retval = super }
17
+ async_exec_on_exit(event) { return retval }
18
+ end
19
+
20
+ def prepare(*args)
21
+ retval = nil
22
+ event = prepare_on_enter(*args) { retval = super }
23
+ prepare_on_exit(event) { return retval }
24
+ end
25
+
26
+ def exec_prepared(*args)
27
+ retval = nil
28
+ event = exec_prepared_on_enter(*args) { retval = super }
29
+ exec_prepared_on_exit(event) { return retval }
30
+ end
31
+
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,31 @@
1
+ module NewRelic::Security
2
+ module Instrumentation
3
+ module PTY
4
+ module Chain
5
+ def self.instrument!
6
+ ::PTY.class_eval do
7
+ class << self
8
+ include NewRelic::Security::Instrumentation::PTY
9
+
10
+ alias_method :spawn_without_security, :spawn
11
+
12
+ def spawn(*var)
13
+ retval = nil
14
+ event = spawn_on_enter(*var) { retval = spawn_without_security(*var) }
15
+ spawn_on_exit(event) { return retval }
16
+ end
17
+
18
+ alias_method :getpty_without_security, :getpty
19
+
20
+ def getpty(*var, &block)
21
+ retval = nil
22
+ event = getpty_on_enter(*var) { retval = getpty_without_security(*var, &block) }
23
+ getpty_on_exit(event) { return retval }
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,52 @@
1
+ require_relative 'prepend'
2
+ require_relative 'chain'
3
+
4
+ module NewRelic::Security
5
+ module Instrumentation
6
+ module PTY
7
+
8
+ def spawn_on_enter(*var)
9
+ event = nil
10
+ NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
11
+ event = NewRelic::Security::Agent::Control::Collector.collect(SYSTEM_COMMAND, var)
12
+ rescue => exception
13
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
14
+ ensure
15
+ yield
16
+ return event
17
+ end
18
+
19
+ def spawn_on_exit(event)
20
+ NewRelic::Security::Agent.logger.debug "OnExit : #{self.class}.#{__method__}"
21
+ NewRelic::Security::Agent::Utils.create_exit_event(event)
22
+ rescue => exception
23
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
24
+ ensure
25
+ yield
26
+ end
27
+
28
+ def getpty_on_enter(*var)
29
+ event = nil
30
+ NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
31
+ event = NewRelic::Security::Agent::Control::Collector.collect(SYSTEM_COMMAND, var)
32
+ rescue => exception
33
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
34
+ ensure
35
+ yield
36
+ return event
37
+ end
38
+
39
+ def getpty_on_exit(event)
40
+ NewRelic::Security::Agent.logger.debug "OnExit : #{self.class}.#{__method__}"
41
+ NewRelic::Security::Agent::Utils.create_exit_event(event)
42
+ rescue => exception
43
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
44
+ ensure
45
+ yield
46
+ end
47
+
48
+ end
49
+ end
50
+ end
51
+
52
+ NewRelic::Security::Instrumentation::InstrumentationLoader.install_instrumentation(:pty, ::PTY.singleton_class, ::NewRelic::Security::Instrumentation::PTY)
@@ -0,0 +1,22 @@
1
+ module NewRelic::Security
2
+ module Instrumentation
3
+ module PTY
4
+ module Prepend
5
+ include NewRelic::Security::Instrumentation::PTY
6
+
7
+ def spawn(*var)
8
+ retval = nil
9
+ event = spawn_on_enter(*var) { retval = super }
10
+ spawn_on_exit(event) { return retval }
11
+ end
12
+
13
+ def getpty(*var, &block)
14
+ retval = nil
15
+ event = getpty_on_enter(*var) { retval = super }
16
+ getpty_on_exit(event) { return retval }
17
+ end
18
+
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,46 @@
1
+ module NewRelic::Security
2
+ module Instrumentation
3
+ module Rails
4
+ module Engine
5
+ module Chain
6
+ def self.instrument!
7
+ ::Rails::Engine.class_eval do
8
+ include NewRelic::Security::Instrumentation::Rails::Engine
9
+
10
+ alias_method :call_without_security, :call
11
+
12
+ def call(env)
13
+ retval = nil
14
+ event = call_on_enter(env) { retval = call_without_security(env) }
15
+ call_on_exit(event, retval) { return retval }
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ module ActionDispatch
24
+ module Journey
25
+ module Router
26
+ module Chain
27
+ def self.instrument!
28
+ ::ActionDispatch::Journey::Router.class_eval do
29
+ include NewRelic::Security::Instrumentation::ActionDispatch::Journey::Router
30
+
31
+ alias_method :find_routes_without_security, :find_routes
32
+
33
+ def find_routes(req)
34
+ retval = nil
35
+ event = find_routes_on_enter(req) { retval = find_routes_without_security(req) }
36
+ find_routes_on_exit(event, retval) { return retval }
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+
45
+ end
46
+ end
@@ -0,0 +1,67 @@
1
+ require_relative 'prepend'
2
+ require_relative 'chain'
3
+
4
+ module NewRelic::Security
5
+ module Instrumentation
6
+ module Rails::Engine
7
+ # TODO: Revisit this hook for more base level hook which can support any framework by default.
8
+ def call_on_enter(env)
9
+ event = nil
10
+ NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
11
+ NewRelic::Security::Agent.config.update_port = NewRelic::Security::Agent::Utils.app_port(env) unless NewRelic::Security::Agent.config[:listen_port]
12
+ NewRelic::Security::Agent::Utils.get_app_routes(:rails) if NewRelic::Security::Agent.agent.route_map.empty?
13
+ NewRelic::Security::Agent::Control::HTTPContext.set_context(env)
14
+ NewRelic::Security::Agent::Utils.parse_fuzz_header(NewRelic::Security::Agent::Control::HTTPContext.get_context)
15
+ rescue => exception
16
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
17
+ ensure
18
+ yield
19
+ return event
20
+ end
21
+
22
+ def call_on_exit(event, retval)
23
+ NewRelic::Security::Agent.logger.debug "OnExit : #{self.class}.#{__method__}"
24
+ # NewRelic::Security::Agent.logger.debug "\n\nHTTP Context : #{::NewRelic::Agent::Tracer.current_transaction.instance_variable_get(:@security_context_data).inspect}\n\n"
25
+ NewRelic::Security::Agent::Control::ReflectedXSS.check_xss(NewRelic::Security::Agent::Control::HTTPContext.get_context, retval) if NewRelic::Security::Agent.config[:'security.detection.rxss.enabled']
26
+ NewRelic::Security::Agent::Utils.delete_created_files(NewRelic::Security::Agent::Control::HTTPContext.get_context)
27
+ NewRelic::Security::Agent::Control::HTTPContext.reset_context
28
+ NewRelic::Security::Agent.logger.debug "Exit event : #{event}"
29
+ rescue => exception
30
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
31
+ ensure
32
+ yield
33
+ end
34
+
35
+ end
36
+
37
+ module ActionDispatch::Journey::Router
38
+
39
+ def find_routes_on_enter(req)
40
+ event = nil
41
+ NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
42
+ rescue => exception
43
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
44
+ ensure
45
+ yield
46
+ return event
47
+ end
48
+
49
+ def find_routes_on_exit(event, retval)
50
+ NewRelic::Security::Agent.logger.debug "OnExit : #{self.class}.#{__method__}"
51
+
52
+ unless retval[0].nil?
53
+ route = retval[0][2].path.spec.to_s.gsub(/\(\.:format\)/, EMPTY_STRING)
54
+ ctxt = NewRelic::Security::Agent::Control::HTTPContext.get_context
55
+ ctxt.route = "#{ctxt.method}@#{route}" unless ctxt.nil?
56
+ end
57
+ rescue => exception
58
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
59
+ ensure
60
+ yield
61
+ end
62
+ end
63
+ end
64
+ end
65
+
66
+ NewRelic::Security::Instrumentation::InstrumentationLoader.install_instrumentation(:rails, ::Rails::Engine, ::NewRelic::Security::Instrumentation::Rails::Engine)
67
+ NewRelic::Security::Instrumentation::InstrumentationLoader.install_instrumentation(:rails, ::ActionDispatch::Journey::Router, ::NewRelic::Security::Instrumentation::ActionDispatch::Journey::Router)
@@ -0,0 +1,33 @@
1
+ module NewRelic::Security
2
+ module Instrumentation
3
+ module Rails
4
+ module Engine
5
+ module Prepend
6
+ include NewRelic::Security::Instrumentation::Rails::Engine
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
+ end
14
+ end
15
+ end
16
+
17
+ module ActionDispatch
18
+ module Journey
19
+ module Router
20
+ module Prepend
21
+ include NewRelic::Security::Instrumentation::ActionDispatch::Journey::Router
22
+
23
+ def find_routes(req)
24
+ retval = nil
25
+ event = find_routes_on_enter(req) { retval = super }
26
+ find_routes_on_exit(event, retval) { return retval }
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,22 @@
1
+ module NewRelic::Security
2
+ module Instrumentation
3
+ module Roda
4
+ module Chain
5
+ def self.instrument!
6
+ ::Roda.class_eval do
7
+ include NewRelic::Security::Instrumentation::Roda
8
+
9
+ alias_method :_roda_handle_main_route_without_security, :_roda_handle_main_route
10
+
11
+ def _roda_handle_main_route(*args)
12
+ retval = nil
13
+ event = _roda_handle_main_route_on_enter(self.env) { retval = _roda_handle_main_route_without_security(*args) }
14
+ _roda_handle_main_route_on_exit(event, retval) { return retval }
15
+ end
16
+
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,41 @@
1
+ require_relative 'prepend'
2
+ require_relative 'chain'
3
+
4
+ module NewRelic::Security
5
+ module Instrumentation
6
+ module Roda
7
+
8
+ def _roda_handle_main_route_on_enter(env)
9
+ event = nil
10
+ NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
11
+ NewRelic::Security::Agent.config.update_port = NewRelic::Security::Agent::Utils.app_port(env) unless NewRelic::Security::Agent.config[:listen_port]
12
+ NewRelic::Security::Agent::Utils.get_app_routes(:roda) if NewRelic::Security::Agent.agent.route_map.empty?
13
+ NewRelic::Security::Agent::Control::HTTPContext.set_context(env)
14
+ ctxt = NewRelic::Security::Agent::Control::HTTPContext.get_context
15
+ ctxt.route = "#{env[REQUEST_METHOD].to_s}@#{env[PATH_INFO].to_s}" if ctxt
16
+ NewRelic::Security::Agent::Utils.parse_fuzz_header(NewRelic::Security::Agent::Control::HTTPContext.get_context)
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 _roda_handle_main_route_on_exit(event, retval)
25
+ NewRelic::Security::Agent.logger.debug "OnExit : #{self.class}.#{__method__}"
26
+ # NewRelic::Security::Agent.logger.debug "\n\nHTTP Context : #{::NewRelic::Agent::Tracer.current_transaction.instance_variable_get(:@security_context_data).inspect}\n\n"
27
+ NewRelic::Security::Agent::Control::ReflectedXSS.check_xss(NewRelic::Security::Agent::Control::HTTPContext.get_context, retval) if NewRelic::Security::Agent.config[:'security.detection.rxss.enabled']
28
+ NewRelic::Security::Agent::Utils.delete_created_files(NewRelic::Security::Agent::Control::HTTPContext.get_context)
29
+ NewRelic::Security::Agent::Control::HTTPContext.reset_context
30
+ NewRelic::Security::Agent.logger.debug "Exit event : #{event}"
31
+ rescue => exception
32
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
33
+ ensure
34
+ yield
35
+ end
36
+
37
+ end
38
+ end
39
+ end
40
+
41
+ NewRelic::Security::Instrumentation::InstrumentationLoader.install_instrumentation(:roda, ::Roda, ::NewRelic::Security::Instrumentation::Roda)
@@ -0,0 +1,16 @@
1
+ module NewRelic::Security
2
+ module Instrumentation
3
+ module Roda
4
+ module Prepend
5
+ include NewRelic::Security::Instrumentation::Roda
6
+
7
+ def _roda_handle_main_route(*args)
8
+ retval = nil
9
+ event = _roda_handle_main_route_on_enter(self.env) { retval = super }
10
+ _roda_handle_main_route_on_exit(event, retval) { return retval }
11
+ end
12
+
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,29 @@
1
+ module NewRelic::Security
2
+ module Instrumentation
3
+ module Sinatra
4
+ module Base
5
+ module Chain
6
+ def self.instrument!
7
+ ::Sinatra::Base.class_eval do
8
+ include NewRelic::Security::Instrumentation::Sinatra::Base
9
+
10
+ alias_method :call_without_security, :call
11
+
12
+ def call(env)
13
+ retval = nil
14
+ event = call_on_enter(env) { retval = call_without_security(env) }
15
+ call_on_exit(event, retval) { return retval }
16
+ end
17
+
18
+ alias_method :route_eval_without_security, :route_eval
19
+
20
+ def route_eval(&block)
21
+ route_eval_on_enter { route_eval_without_security(&block) }
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,49 @@
1
+ require_relative 'prepend'
2
+ require_relative 'chain'
3
+
4
+ module NewRelic::Security
5
+ module Instrumentation
6
+ module Sinatra::Base
7
+
8
+ def call_on_enter(env)
9
+ event = nil
10
+ NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
11
+ NewRelic::Security::Agent.config.update_port = NewRelic::Security::Agent::Utils.app_port(env) unless NewRelic::Security::Agent.config[:listen_port]
12
+ NewRelic::Security::Agent::Utils.get_app_routes(:sinatra) if NewRelic::Security::Agent.agent.route_map.empty?
13
+ NewRelic::Security::Agent::Control::HTTPContext.set_context(env)
14
+ NewRelic::Security::Agent::Utils.parse_fuzz_header(NewRelic::Security::Agent::Control::HTTPContext.get_context)
15
+ rescue => exception
16
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
17
+ ensure
18
+ yield
19
+ return event
20
+ end
21
+
22
+ def call_on_exit(event, retval)
23
+ NewRelic::Security::Agent.logger.debug "OnExit : #{self.class}.#{__method__}"
24
+ # NewRelic::Security::Agent.logger.debug "\n\nHTTP Context : #{::NewRelic::Agent::Tracer.current_transaction.instance_variable_get(:@security_context_data).inspect}\n\n"
25
+ NewRelic::Security::Agent::Control::ReflectedXSS.check_xss(NewRelic::Security::Agent::Control::HTTPContext.get_context, retval) if NewRelic::Security::Agent.config[:'security.detection.rxss.enabled']
26
+ NewRelic::Security::Agent::Utils.delete_created_files(NewRelic::Security::Agent::Control::HTTPContext.get_context)
27
+ NewRelic::Security::Agent::Control::HTTPContext.reset_context
28
+ NewRelic::Security::Agent.logger.debug "Exit event : #{event}"
29
+ rescue => exception
30
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
31
+ ensure
32
+ yield
33
+ end
34
+
35
+ def route_eval_on_enter
36
+ NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
37
+ ctxt = NewRelic::Security::Agent::Control::HTTPContext.get_context
38
+ ctxt.route = self.env["sinatra.route"].split.join("@") unless ctxt.nil?
39
+ rescue => exception
40
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
41
+ ensure
42
+ yield
43
+ end
44
+
45
+ end
46
+ end
47
+ end
48
+
49
+ NewRelic::Security::Instrumentation::InstrumentationLoader.install_instrumentation(:sinatra, ::Sinatra::Base, ::NewRelic::Security::Instrumentation::Sinatra::Base)