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,122 @@
1
+ require_relative 'prepend'
2
+ require_relative 'chain'
3
+ require 'uri'
4
+
5
+ module NewRelic::Security
6
+ module Instrumentation
7
+ module Ethon
8
+ module Easy
9
+
10
+ def fabricate_on_enter(url, action_name, options)
11
+ NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
12
+ NewRelic::Security::Agent::Control::HTTPContext.get_context.cache[self.object_id] = { :method => action_name } if NewRelic::Security::Agent::Control::HTTPContext.get_context
13
+ NewRelic::Security::Agent::Control::HTTPContext.get_context.cache[self.object_id][:body] = options[:body] if NewRelic::Security::Agent::Control::HTTPContext.get_context
14
+ rescue => exception
15
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
16
+ ensure
17
+ yield
18
+ end
19
+
20
+ def headers_equals_on_enter(headers)
21
+ NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
22
+ NewRelic::Security::Agent::Control::HTTPContext.get_context.cache[self.object_id][:headers] = headers if NewRelic::Security::Agent::Control::HTTPContext.get_context && NewRelic::Security::Agent::Control::HTTPContext.get_context.cache[self.object_id]
23
+ rescue => exception
24
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
25
+ ensure
26
+ yield
27
+ end
28
+
29
+ def perform_on_enter(*args)
30
+ event = nil
31
+ NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
32
+ context = NewRelic::Security::Agent::Control::HTTPContext.get_context.cache[self.object_id] if NewRelic::Security::Agent::Control::HTTPContext.get_context
33
+ uri = ::URI.parse(url)
34
+ ob = {}
35
+ ob[:Method] = context[:method] if context
36
+ ob[:scheme] = uri.scheme
37
+ ob[:host] = uri.host
38
+ ob[:port] = uri.port
39
+ ob[:URI] = uri.to_s
40
+ ob[:path] = uri.path
41
+ ob[:query] = uri.query
42
+ ob[:Body] = context[:body] if context
43
+ ob[:Headers] = context[:headers] if context
44
+ ob.each { |_, value| value.dup.force_encoding(ISO_8859_1).encode(UTF_8) if value.is_a?(String) }
45
+ event = NewRelic::Security::Agent::Control::Collector.collect(HTTP_REQUEST, [ob])
46
+ headers_copy = {}
47
+ headers_copy.merge!(context[:headers]) if context&.key?(:headers)
48
+ NewRelic::Security::Instrumentation::InstrumentationUtils.add_tracing_data(headers_copy, event) if event
49
+ self.headers = headers_copy if self.headers
50
+ event
51
+ rescue => exception
52
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
53
+ ensure
54
+ yield
55
+ return event
56
+ end
57
+
58
+ def perform_on_exit(event)
59
+ NewRelic::Security::Agent.logger.debug "OnExit : #{self.class}.#{__method__}"
60
+ NewRelic::Security::Agent::Utils.create_exit_event(event)
61
+ rescue => exception
62
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
63
+ ensure
64
+ yield
65
+ end
66
+ end
67
+
68
+ module Multi
69
+
70
+ def perform_on_enter(*args)
71
+ event = nil
72
+ NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
73
+ ic_args = []
74
+ easy_handles.each do |easy|
75
+ context = NewRelic::Security::Agent::Control::HTTPContext.get_context.cache[easy.object_id] if NewRelic::Security::Agent::Control::HTTPContext.get_context
76
+ uri = NewRelic::Security::Instrumentation::InstrumentationUtils.parse_uri(easy.url)
77
+ if uri
78
+ ob = {}
79
+ ob[:Method] = context[:method] if context
80
+ ob[:scheme] = uri.scheme
81
+ ob[:host] = uri.host
82
+ ob[:port] = uri.port
83
+ ob[:URI] = easy.url.to_s
84
+ ob[:path] = uri.path
85
+ ob[:query] = uri.query
86
+ ob[:Body] = context[:body] if context
87
+ ob[:Headers] = context[:headers] if context
88
+ ob.each { |_, value| value.dup.force_encoding(ISO_8859_1).encode(UTF_8) if value.is_a?(String) }
89
+ ic_args << ob
90
+ end
91
+ end
92
+ event = NewRelic::Security::Agent::Control::Collector.collect(HTTP_REQUEST, ic_args) unless ic_args.empty?
93
+ easy_handles.each do |easy|
94
+ context = NewRelic::Security::Agent::Control::HTTPContext.get_context.cache[easy.object_id] if NewRelic::Security::Agent::Control::HTTPContext.get_context
95
+ headers_copy = {}
96
+ headers_copy.merge!(context[:headers]) if context&.key?(:headers)
97
+ NewRelic::Security::Instrumentation::InstrumentationUtils.add_tracing_data(headers_copy, event) if event
98
+ easy.headers = headers_copy
99
+ end
100
+ event
101
+ rescue => exception
102
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
103
+ ensure
104
+ yield
105
+ return event
106
+ end
107
+
108
+ def perform_on_exit(event)
109
+ NewRelic::Security::Agent.logger.debug "OnExit : #{self.class}.#{__method__}"
110
+ NewRelic::Security::Agent::Utils.create_exit_event(event)
111
+ rescue => exception
112
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
113
+ ensure
114
+ yield
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
120
+
121
+ NewRelic::Security::Instrumentation::InstrumentationLoader.install_instrumentation(:ethon, ::Ethon::Easy, ::NewRelic::Security::Instrumentation::Ethon::Easy)
122
+ NewRelic::Security::Instrumentation::InstrumentationLoader.install_instrumentation(:ethon, ::Ethon::Multi, ::NewRelic::Security::Instrumentation::Ethon::Multi)
@@ -0,0 +1,39 @@
1
+ module NewRelic::Security
2
+ module Instrumentation
3
+ module Ethon
4
+ module Easy
5
+ module Prepend
6
+ include NewRelic::Security::Instrumentation::Ethon::Easy
7
+
8
+ def fabricate(url, action_name, options)
9
+ fabricate_on_enter(url, action_name, options) { return super }
10
+ end
11
+
12
+ def headers=(headers)
13
+ headers_equals_on_enter(headers) { return super }
14
+ end
15
+
16
+ def perform(*args)
17
+ retval = nil
18
+ event = perform_on_enter(*args) { retval = super }
19
+ perform_on_exit(event) { return retval }
20
+ end
21
+
22
+ end
23
+ end
24
+
25
+ module Multi
26
+ module Prepend
27
+ include NewRelic::Security::Instrumentation::Ethon::Multi
28
+
29
+ def perform(*args)
30
+ retval = nil
31
+ event = perform_on_enter(*args) { retval = super }
32
+ perform_on_exit(event) { return retval }
33
+ end
34
+
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,23 @@
1
+ module NewRelic::Security
2
+ module Instrumentation
3
+ module Excon
4
+ module Connection
5
+ module Chain
6
+ def self.instrument!
7
+ ::Excon::Connection.class_eval do
8
+ include NewRelic::Security::Instrumentation::Excon::Connection
9
+
10
+ alias_method :request_without_security, :request
11
+
12
+ def request(params={}, &block)
13
+ retval = nil
14
+ event = request_on_enter(params) { retval = request_without_security(params, &block) }
15
+ request_on_exit(event) { return retval }
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,44 @@
1
+ require_relative 'prepend'
2
+ require_relative 'chain'
3
+
4
+ module NewRelic::Security
5
+ module Instrumentation
6
+ module Excon::Connection
7
+
8
+ def request_on_enter(params)
9
+ event = nil
10
+ NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
11
+ ob = {}
12
+ ob[:Method] = params[:method]
13
+ ob[:scheme] = self.data[:scheme]
14
+ ob[:host] = self.data[:host]
15
+ ob[:port] = self.data[:port]
16
+ ob[:URI] = self.data[:query].nil? ? "#{self.data[:host]}#{self.data[:path]}" : "#{self.data[:host]}#{self.data[:path]}?#{self.data[:query]}"
17
+ ob[:path] = self.data[:path]
18
+ ob[:query] = self.data[:query]
19
+ ob[:Body] = self.data[:body]
20
+ ob[:Headers] = self.data[:headers]
21
+ ob.each { |_, value| value.dup.force_encoding(ISO_8859_1).encode(UTF_8) if value.is_a?(String) }
22
+ event = NewRelic::Security::Agent::Control::Collector.collect(HTTP_REQUEST, [ob])
23
+ NewRelic::Security::Instrumentation::InstrumentationUtils.add_tracing_data(self.data[:headers], event) if event
24
+ 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
+ return event
30
+ end
31
+
32
+ def request_on_exit(event)
33
+ NewRelic::Security::Agent.logger.debug "OnExit : #{self.class}.#{__method__}"
34
+ NewRelic::Security::Agent::Utils.create_exit_event(event)
35
+ rescue => exception
36
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
37
+ ensure
38
+ yield
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+ NewRelic::Security::Instrumentation::InstrumentationLoader.install_instrumentation(:excon, ::Excon::Connection, ::NewRelic::Security::Instrumentation::Excon::Connection)
@@ -0,0 +1,17 @@
1
+ module NewRelic::Security
2
+ module Instrumentation
3
+ module Excon
4
+ module Connection
5
+ module Prepend
6
+ include NewRelic::Security::Instrumentation::Excon::Connection
7
+
8
+ def request(params={}, &block)
9
+ retval = nil
10
+ event = request_on_enter(params) { retval = super }
11
+ request_on_exit(event) { return retval }
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,34 @@
1
+ module NewRelic::Security
2
+ module Instrumentation
3
+ module File
4
+ module Chain
5
+
6
+ def self.instrument!
7
+ ::File.class_eval do
8
+ class << self
9
+ include ::NewRelic::Security::Instrumentation::File
10
+
11
+ alias_method :delete_without_security, :delete
12
+
13
+ def delete(*var)
14
+ retval = nil
15
+ event = delete_on_enter(*var) { retval = delete_without_security(*var) }
16
+ delete_on_exit(event, retval) { return retval }
17
+ end
18
+
19
+ alias_method :unlink_without_security, :unlink
20
+
21
+ def unlink(*var)
22
+ retval = nil
23
+ event = unlink_on_enter(*var) { retval = unlink_without_security(*var) }
24
+ unlink_on_exit(event, retval) { return retval }
25
+ end
26
+
27
+ end
28
+ end
29
+ end
30
+
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,62 @@
1
+ require_relative 'prepend'
2
+ require_relative 'chain'
3
+
4
+ module NewRelic::Security
5
+ module Instrumentation
6
+ module File
7
+
8
+ def delete_on_enter(*var)
9
+ event = nil
10
+ NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
11
+ if NewRelic::Security::Instrumentation::InstrumentationUtils.notify_app_integrity_delete?(var)
12
+ event = NewRelic::Security::Agent::Control::Collector.collect(FILE_INTEGRITY, var, DELETE)
13
+ else
14
+ # TODO: Add handling read_filter for outside app root directory files, example ../abc.txt
15
+ NewRelic::Security::Agent.logger.debug "Filtered because File name exist in filtered list #{self.class}.#{__method__} Args:: #{var}"
16
+ end
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 delete_on_exit(event, retval)
25
+ NewRelic::Security::Agent.logger.debug "OnExit : #{self.class}.#{__method__}"
26
+ NewRelic::Security::Agent::Utils.create_exit_event(event) if retval.is_a?(Integer)
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 unlink_on_enter(*var)
34
+ event = nil
35
+ NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
36
+ if NewRelic::Security::Instrumentation::InstrumentationUtils.notify_app_integrity_delete?(var)
37
+ event = NewRelic::Security::Agent::Control::Collector.collect(FILE_INTEGRITY, var, DELETE)
38
+ else
39
+ # TODO: Add handling read_filter for outside app root directory files, example ../abc.txt
40
+ NewRelic::Security::Agent.logger.debug "Filtered because File name exist in filtered list #{self.class}.#{__method__} Args:: #{var}"
41
+ end
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 unlink_on_exit(event, retval)
50
+ NewRelic::Security::Agent.logger.debug "OnExit : #{self.class}.#{__method__}"
51
+ NewRelic::Security::Agent::Utils.create_exit_event(event) if retval.is_a?(Integer)
52
+ rescue => exception
53
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
54
+ ensure
55
+ yield
56
+ end
57
+
58
+ end
59
+ end
60
+ end
61
+
62
+ NewRelic::Security::Instrumentation::InstrumentationLoader.install_instrumentation(:file, ::File.singleton_class, ::NewRelic::Security::Instrumentation::File)
@@ -0,0 +1,22 @@
1
+ module NewRelic::Security
2
+ module Instrumentation
3
+ module File
4
+ module Prepend
5
+ include ::NewRelic::Security::Instrumentation::File
6
+
7
+ def delete(*var)
8
+ retval = nil
9
+ event = delete_on_enter(*var) { retval = super }
10
+ delete_on_exit(event, retval) { return retval }
11
+ end
12
+
13
+ def unlink(*var)
14
+ retval = nil
15
+ event = unlink_on_enter(*var) { retval = super }
16
+ unlink_on_exit(event, retval) { return retval }
17
+ end
18
+
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,42 @@
1
+ module NewRelic::Security
2
+ module Instrumentation
3
+ module Grape
4
+ module API
5
+ module Instance
6
+ module Chain
7
+ def self.instrument!
8
+ ::Grape::API::Instance.class_eval do
9
+ include NewRelic::Security::Instrumentation::Grape::API::Instance
10
+
11
+ alias_method :call_without_security, :call
12
+
13
+ def call(env)
14
+ retval = nil
15
+ event = call_on_enter(env) { retval = call_without_security(env) }
16
+ call_on_exit(event, retval) { return retval }
17
+ end
18
+
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ module Router
26
+ module Chain
27
+ def self.instrument!
28
+ ::Grape::Router.class_eval do
29
+ include NewRelic::Security::Instrumentation::Grape::Router
30
+
31
+ alias_method :prepare_env_from_route_without_security, :prepare_env_from_route
32
+
33
+ def prepare_env_from_route(env, route)
34
+ prepare_env_from_route_on_enter(route) { prepare_env_from_route_without_security(env, route) }
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,56 @@
1
+ require_relative 'prepend'
2
+ require_relative 'chain'
3
+
4
+ module NewRelic::Security
5
+ module Instrumentation
6
+ module Grape::API::Instance
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(:grape) 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 Grape
38
+ module Router
39
+
40
+ def prepare_env_from_route_on_enter(route)
41
+ NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
42
+ ctxt = NewRelic::Security::Agent::Control::HTTPContext.get_context
43
+ http_method = route.instance_variable_get(:@request_method) ? route.instance_variable_get(:@request_method) : route.instance_variable_get(:@options)[:method]
44
+ ctxt.route = "#{http_method}@#{route.options[:namespace]}" unless ctxt.nil?
45
+ rescue => exception
46
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
47
+ ensure
48
+ yield
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+
55
+ NewRelic::Security::Instrumentation::InstrumentationLoader.install_instrumentation(:grape, ::Grape::API::Instance, ::NewRelic::Security::Instrumentation::Grape::API::Instance)
56
+ NewRelic::Security::Instrumentation::InstrumentationLoader.install_instrumentation(:grape, ::Grape::Router, ::NewRelic::Security::Instrumentation::Grape::Router)
@@ -0,0 +1,30 @@
1
+ module NewRelic::Security
2
+ module Instrumentation
3
+ module Grape
4
+ module API
5
+ module Instance
6
+ module Prepend
7
+ include NewRelic::Security::Instrumentation::Grape::API::Instance
8
+
9
+ def call(env)
10
+ retval = nil
11
+ event = call_on_enter(env) { retval = super(env) }
12
+ call_on_exit(event, retval) { return retval }
13
+ end
14
+
15
+ end
16
+ end
17
+ end
18
+
19
+ module Router
20
+ module Prepend
21
+ include NewRelic::Security::Instrumentation::Grape::Router
22
+
23
+ def prepare_env_from_route(env, route)
24
+ prepare_env_from_route_on_enter(route) { super }
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,47 @@
1
+ module NewRelic::Security
2
+ module Instrumentation
3
+ module GRPC
4
+ module ClientStub
5
+ module Chain
6
+ def self.instrument!
7
+ ::GRPC::ClientStub.class_eval do
8
+ include NewRelic::Security::Instrumentation::GRPC::ClientStub
9
+
10
+ alias_method :request_response_without_security, :request_response
11
+
12
+ def request_response(method, req, marshal, unmarshal, deadline: nil, return_op: false, parent: nil, credentials: nil, metadata: {}) # rubocop:disable Metrics/ParameterLists
13
+ retval = nil
14
+ event = grpc_client_on_enter(method, metadata) { retval = request_response_without_security(method, req, marshal, unmarshal, deadline, return_op, parent, credentials, metadata) }
15
+ grpc_client_on_exit(event) { return retval }
16
+ end
17
+
18
+ alias_method :server_streamer_without_security, :server_streamer
19
+
20
+ def server_streamer(method, req, marshal, unmarshal, deadline: nil, return_op: false, parent: nil, credentials: nil, metadata: {}, &blk) # rubocop:disable Metrics/ParameterLists
21
+ retval = nil
22
+ event = grpc_client_on_enter(method, metadata) { retval = server_streamer_without_security(method, req, marshal, unmarshal, deadline, return_op, parent, credentials, metadata, &blk) }
23
+ grpc_client_on_exit(event) { return retval }
24
+ end
25
+
26
+ alias_method :client_streamer_without_security, :client_streamer
27
+
28
+ def client_streamer(method, requests, marshal, unmarshal, deadline: nil, return_op: false, parent: nil, credentials: nil, metadata: {}) # rubocop:disable Metrics/ParameterLists
29
+ retval = nil
30
+ event = grpc_client_on_enter(method, metadata) { retval = client_streamer_without_security(method, requests, marshal, unmarshal, deadline, return_op, parent, credentials, metadata) }
31
+ grpc_client_on_exit(event) { return retval }
32
+ end
33
+
34
+ alias_method :bidi_streamer_without_security, :bidi_streamer
35
+
36
+ def bidi_streamer(method, requests, marshal, unmarshal, deadline: nil, return_op: false, parent: nil, credentials: nil, metadata: {}, &blk) # rubocop:disable Metrics/ParameterLists
37
+ retval = nil
38
+ event = grpc_client_on_enter(method, metadata) { retval = bidi_streamer_without_security(method, requests, marshal, unmarshal, deadline, return_op, parent, credentials, metadata, &blk) }
39
+ grpc_client_on_exit(event) { return retval }
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,37 @@
1
+ require_relative 'prepend'
2
+ require_relative 'chain'
3
+
4
+ module NewRelic::Security
5
+ module Instrumentation
6
+ module GRPC
7
+ module ClientStub
8
+ def grpc_client_on_enter(method, metadata)
9
+ event = nil
10
+ NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
11
+ host = "grpc://#{instance_variable_get(:@host)}#{method}"
12
+ # TODO: Recheck this parameters, this is diff for other LCs
13
+ event = NewRelic::Security::Agent::Control::Collector.collect(HTTP_REQUEST, [{:host => host, :path => SLASH}])
14
+ # TODO: tracing data is required only in microservices, currently add_tracing_data data causing issues in gRPC.
15
+ # NewRelic::Security::Instrumentation::InstrumentationUtils.add_tracing_data(metadata, event) if event
16
+ event
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 grpc_client_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
+ end
33
+ end
34
+ end
35
+ end
36
+
37
+ NewRelic::Security::Instrumentation::InstrumentationLoader.install_instrumentation(:gRPC_Client, ::GRPC::ClientStub, ::NewRelic::Security::Instrumentation::GRPC::ClientStub)
@@ -0,0 +1,36 @@
1
+ module NewRelic::Security
2
+ module Instrumentation
3
+ module GRPC
4
+ module ClientStub
5
+ module Prepend
6
+ include NewRelic::Security::Instrumentation::GRPC::ClientStub
7
+
8
+ def request_response(method, req, marshal, unmarshal, deadline: nil, return_op: false, parent: nil, credentials: nil, metadata: {}) # rubocop:disable Metrics/ParameterLists
9
+ retval = nil
10
+ event = grpc_client_on_enter(method, metadata) { retval = super }
11
+ grpc_client_on_exit(event) { return retval }
12
+ end
13
+
14
+ def server_streamer(method, req, marshal, unmarshal, deadline: nil, return_op: false, parent: nil, credentials: nil, metadata: {}, &blk) # rubocop:disable Metrics/ParameterLists
15
+ retval = nil
16
+ event = grpc_client_on_enter(method, metadata) { retval = super }
17
+ grpc_client_on_exit(event) { return retval }
18
+ end
19
+
20
+ def client_streamer(method, requests, marshal, unmarshal, deadline: nil, return_op: false, parent: nil, credentials: nil, metadata: {}) # rubocop:disable Metrics/ParameterLists
21
+ retval = nil
22
+ event = grpc_client_on_enter(method, metadata) { retval = super }
23
+ grpc_client_on_exit(event) { return retval }
24
+ end
25
+
26
+ def bidi_streamer(method, requests, marshal, unmarshal, deadline: nil, return_op: false, parent: nil, credentials: nil, metadata: {}, &blk) # rubocop:disable Metrics/ParameterLists
27
+ retval = nil
28
+ event = grpc_client_on_enter(method, metadata) { retval = super }
29
+ grpc_client_on_exit(event) { return retval }
30
+ end
31
+
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end