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,62 @@
1
+ module NewRelic::Security
2
+ module Instrumentation
3
+ module GRPC
4
+ module RpcDesc
5
+ module Chain
6
+ def self.instrument!
7
+ ::GRPC::RpcDesc.class_eval do
8
+ include NewRelic::Security::Instrumentation::GRPC::RpcDesc
9
+
10
+ alias_method :handle_request_response_without_security, :handle_request_response
11
+
12
+ def handle_request_response(active_call, mth, inter_ctx)
13
+ grpc_server_on_enter(active_call, mth, inter_ctx, false, false) { return handle_request_response_without_security(active_call, mth, inter_ctx) }
14
+ end
15
+
16
+ alias_method :handle_client_streamer_without_security, :handle_client_streamer
17
+
18
+ def handle_client_streamer(active_call, mth, inter_ctx)
19
+ grpc_server_on_enter(active_call, mth, inter_ctx, true, false) { return handle_request_response_without_security(active_call, mth, inter_ctx) }
20
+ end
21
+
22
+ alias_method :handle_server_streamer_without_security, :handle_server_streamer
23
+
24
+ def handle_server_streamer(active_call, mth, inter_ctx)
25
+ grpc_server_on_enter(active_call, mth, inter_ctx, false, true) { return handle_request_response_without_security(active_call, mth, inter_ctx) }
26
+ end
27
+
28
+ alias_method :handle_bidi_streamer_without_security, :handle_bidi_streamer
29
+
30
+ def handle_bidi_streamer(active_call, mth, inter_ctx)
31
+ grpc_server_on_enter(active_call, mth, inter_ctx, true, true) { return handle_request_response_without_security(active_call, mth, inter_ctx) }
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+
38
+ module ActiveCall
39
+ module Chain
40
+ def self.instrument!
41
+ ::GRPC::ActiveCall.class_eval do
42
+ include NewRelic::Security::Instrumentation::GRPC::ActiveCall
43
+
44
+ alias_method :remote_read_without_security, :remote_read
45
+
46
+ def remote_read
47
+ retval = remote_read_without_security
48
+ remote_read_on_exit(retval) { return retval }
49
+ end
50
+
51
+ alias_method :output_metadata_without_security, :output_metadata
52
+
53
+ def output_metadata
54
+ output_metadata_on_enter { return output_metadata_without_security }
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,65 @@
1
+ require_relative 'prepend'
2
+ require_relative 'chain'
3
+ require 'json'
4
+
5
+ module NewRelic::Security
6
+ module Instrumentation
7
+ module GRPC
8
+ module RpcDesc
9
+ def grpc_server_on_enter(active_call, mth, inter_ctx, is_grpc_client_stream, is_grpc_server_stream)
10
+ event = nil
11
+ NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
12
+ grpc_request = {}
13
+ grpc_request[:headers] = active_call.metadata
14
+ grpc_request[:peer] = active_call.peer
15
+ # puts "mth : #{mth.class} #{mth.methods}"
16
+ # puts "mth :#{mth.original_name}, #{mth.to_s}, #{mth.name}, #{mth.receiver}, #{mth.parameters}, #{mth.owner}, #{mth.unbind}, #{mth.super_method},, #{mth.instance_variables}"
17
+ grpc_request[:method] = "#{mth.owner}/#{mth.original_name}"
18
+ grpc_request[:is_grpc_client_stream] = is_grpc_client_stream
19
+ grpc_request[:is_grpc_server_stream] = is_grpc_server_stream
20
+ is_grpc_client_stream ? grpc_request[:body] = [] : grpc_request[:body] = ::String.new
21
+ NewRelic::Security::Agent::Control::GRPCContext.set_context(grpc_request)
22
+ NewRelic::Security::Agent::Utils.parse_fuzz_header(NewRelic::Security::Agent::Control::GRPCContext.get_context)
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
+ return event
28
+ end
29
+ end
30
+
31
+ module ActiveCall
32
+
33
+ def remote_read_on_exit(retval)
34
+ NewRelic::Security::Agent.logger.debug "OnExit : #{self.class}.#{__method__}"
35
+ ctxt = NewRelic::Security::Agent::Control::GRPCContext.get_context
36
+ if ctxt
37
+ if ctxt.metadata[:reflectedMetaData][:isGrpcClientStream]
38
+ ctxt.body << retval.to_json
39
+ else
40
+ ctxt.body += retval.to_json
41
+ end
42
+ ctxt.metadata[:reflectedMetaData][:inputClass] = retval.class.name
43
+ end
44
+ rescue => exception
45
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
46
+ ensure
47
+ yield
48
+ end
49
+
50
+ def output_metadata_on_enter
51
+ NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
52
+ NewRelic::Security::Agent::Utils.delete_created_files(NewRelic::Security::Agent::Control::GRPCContext.get_context)
53
+ NewRelic::Security::Agent::Control::GRPCContext.reset_context
54
+ rescue => exception
55
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
56
+ ensure
57
+ yield
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+
64
+ NewRelic::Security::Instrumentation::InstrumentationLoader.install_instrumentation(:gRPC_Server, ::GRPC::RpcDesc, ::NewRelic::Security::Instrumentation::GRPC::RpcDesc)
65
+ NewRelic::Security::Instrumentation::InstrumentationLoader.install_instrumentation(:gRPC_Server, ::GRPC::ActiveCall, ::NewRelic::Security::Instrumentation::GRPC::ActiveCall)
@@ -0,0 +1,46 @@
1
+ module NewRelic::Security
2
+ module Instrumentation
3
+ module GRPC
4
+ module RpcDesc
5
+ module Prepend
6
+ include NewRelic::Security::Instrumentation::GRPC::RpcDesc
7
+
8
+ def handle_request_response(active_call, mth, inter_ctx)
9
+ grpc_server_on_enter(active_call, mth, inter_ctx, false, false) { super }
10
+ end
11
+
12
+ def handle_client_streamer(active_call, mth, inter_ctx)
13
+ grpc_server_on_enter(active_call, mth, inter_ctx, true, false) { super }
14
+ end
15
+
16
+ def handle_server_streamer(active_call, mth, inter_ctx)
17
+ grpc_server_on_enter(active_call, mth, inter_ctx, false, true) { super }
18
+ end
19
+
20
+ def handle_bidi_streamer(active_call, mth, inter_ctx)
21
+ grpc_server_on_enter(active_call, mth, inter_ctx, true, true) { super }
22
+ end
23
+
24
+ end
25
+ end
26
+
27
+ module ActiveCall
28
+ module Prepend
29
+ include NewRelic::Security::Instrumentation::GRPC::ActiveCall
30
+
31
+ def remote_read
32
+ retval = super
33
+ remote_read_on_exit(retval) { return retval }
34
+ end
35
+
36
+ def output_metadata
37
+ output_metadata_on_enter { super }
38
+ end
39
+
40
+ end
41
+ end
42
+
43
+ end
44
+
45
+ end
46
+ end
@@ -0,0 +1,30 @@
1
+ module NewRelic::Security
2
+ module Instrumentation
3
+ module HTTPClient
4
+ module Chain
5
+ def self.instrument!
6
+ ::HTTPClient.class_eval do
7
+ include NewRelic::Security::Instrumentation::HTTPClient
8
+
9
+ alias_method :do_request_without_security, :do_request
10
+
11
+ def do_request(method, uri, query, body, header, &block)
12
+ retval = nil
13
+ event = do_request_on_enter(method, uri, query, body, header) { retval = do_request_without_security(method, uri, query, body, header, &block) }
14
+ do_request_on_exit(event) { return retval }
15
+ end
16
+
17
+ alias_method :do_request_async_without_security, :do_request_async
18
+
19
+ def do_request_async(method, uri, query, body, header, &block)
20
+ retval = nil
21
+ event = do_request_async_on_enter(method, uri, query, body, header) { retval = do_request_async_without_security(method, uri, query, body, header, &block) }
22
+ do_request_async_on_exit(event) { return retval }
23
+ end
24
+
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,82 @@
1
+ require_relative 'prepend'
2
+ require_relative 'chain'
3
+
4
+ module NewRelic::Security
5
+ module Instrumentation
6
+ module HTTPClient
7
+
8
+ def do_request_on_enter(method, uri, query, body, header)
9
+ event = nil
10
+ NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
11
+ ob = {}
12
+ ob[:Method] = method
13
+ unless uri.nil?
14
+ ob[:scheme] = uri.scheme
15
+ ob[:host] = uri.host
16
+ ob[:port] = uri.port
17
+ ob[:URI] = uri.to_s
18
+ ob[:path] = uri.path
19
+ ob[:query] = uri.query
20
+ end
21
+ ob[:Body] = body
22
+ ob[:Headers] = header
23
+ ob.each { |_, value| value.dup.force_encoding(ISO_8859_1).encode(UTF_8) if value.is_a?(String) }
24
+ event = NewRelic::Security::Agent::Control::Collector.collect(HTTP_REQUEST, [ob])
25
+ NewRelic::Security::Instrumentation::InstrumentationUtils.add_tracing_data(header, event) if event
26
+ 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
+ return event
32
+ end
33
+
34
+ def do_request_on_exit(event)
35
+ NewRelic::Security::Agent.logger.debug "OnExit : #{self.class}.#{__method__}"
36
+ NewRelic::Security::Agent::Utils.create_exit_event(event)
37
+ rescue => exception
38
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
39
+ ensure
40
+ yield
41
+ end
42
+
43
+ def do_request_async_on_enter(method, uri, query, body, header)
44
+ event = nil
45
+ NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
46
+ ob = {}
47
+ ob[:Method] = method
48
+ unless uri.nil?
49
+ ob[:scheme] = uri.scheme
50
+ ob[:host] = uri.host
51
+ ob[:port] = uri.port
52
+ ob[:URI] = uri.to_s
53
+ ob[:path] = uri.path
54
+ ob[:query] = uri.query
55
+ end
56
+ ob[:Body] = body
57
+ ob[:Headers] = header
58
+ ob.each { |_, value| value.dup.force_encoding(ISO_8859_1).encode(UTF_8) if value.is_a?(String) }
59
+ event = NewRelic::Security::Agent::Control::Collector.collect(HTTP_REQUEST, [ob])
60
+ NewRelic::Security::Instrumentation::InstrumentationUtils.add_tracing_data(header, event) if event
61
+ event
62
+ rescue => exception
63
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
64
+ ensure
65
+ yield
66
+ return event
67
+ end
68
+
69
+ def do_request_async_on_exit(event)
70
+ NewRelic::Security::Agent.logger.debug "OnExit : #{self.class}.#{__method__}"
71
+ NewRelic::Security::Agent::Utils.create_exit_event(event)
72
+ rescue => exception
73
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
74
+ ensure
75
+ yield
76
+ end
77
+
78
+ end
79
+ end
80
+ end
81
+
82
+ NewRelic::Security::Instrumentation::InstrumentationLoader.install_instrumentation(:httpclient, ::HTTPClient, ::NewRelic::Security::Instrumentation::HTTPClient)
@@ -0,0 +1,22 @@
1
+ module NewRelic::Security
2
+ module Instrumentation
3
+ module HTTPClient
4
+ module Prepend
5
+ include NewRelic::Security::Instrumentation::HTTPClient
6
+
7
+ def do_request(method, uri, query, body, header, &block)
8
+ retval = nil
9
+ event = do_request_on_enter(method, uri, query, body, header) { retval = super }
10
+ do_request_on_exit(event) { return retval }
11
+ end
12
+
13
+ def do_request_async(method, uri, query, body, header)
14
+ retval = nil
15
+ event = do_request_async_on_enter(method, uri, query, body, header) { retval = super }
16
+ do_request_async_on_exit(event) { return retval }
17
+ end
18
+
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,21 @@
1
+ module NewRelic::Security
2
+ module Instrumentation
3
+ module HTTPrb
4
+ module Chain
5
+ def self.instrument!
6
+ ::HTTP::Client.class_eval do
7
+ include NewRelic::Security::Instrumentation::HTTPrb
8
+
9
+ alias_method :perform_without_security, :perform
10
+
11
+ def perform(request, options)
12
+ retval = nil
13
+ event = perform_on_enter(request, options) { retval = perform_without_security(request, options) }
14
+ perform_on_exit(event) { return retval }
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,44 @@
1
+ require_relative 'prepend'
2
+ require_relative 'chain'
3
+
4
+ module NewRelic::Security
5
+ module Instrumentation
6
+ module HTTPrb
7
+
8
+ def perform_on_enter(request, options)
9
+ event = nil
10
+ NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
11
+ ob = {}
12
+ ob[:Method] = request.verb
13
+ ob[:scheme] = request.scheme
14
+ ob[:host] = request.uri.host
15
+ ob[:port] = request.uri.port
16
+ ob[:URI] = request.uri.to_s
17
+ ob[:path] = request.uri.path
18
+ ob[:query] = request.uri.query
19
+ ob[:Body] = request.body.source.to_s
20
+ ob[:Headers] = options.headers.to_h
21
+ event = NewRelic::Security::Agent::Control::Collector.collect(HTTP_REQUEST, [ob])
22
+ NewRelic::Security::Instrumentation::InstrumentationUtils.add_tracing_data(options.headers, event) if event
23
+ ob = nil
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 perform_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(:httprb, ::HTTP::Client, ::NewRelic::Security::Instrumentation::HTTPrb)
@@ -0,0 +1,16 @@
1
+ module NewRelic::Security
2
+ module Instrumentation
3
+ module HTTPrb
4
+ module Prepend
5
+ include NewRelic::Security::Instrumentation::HTTPrb
6
+
7
+ def perform(request, options)
8
+ retval = nil
9
+ event = perform_on_enter(request, options) { retval = super }
10
+ perform_on_exit(event) { return retval }
11
+ end
12
+
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,23 @@
1
+ module NewRelic::Security
2
+ module Instrumentation
3
+ module HTTPX
4
+ module Session
5
+ module Chain
6
+ def self.instrument!
7
+ ::HTTPX::Session.class_eval do
8
+ include NewRelic::Security::Instrumentation::HTTPX::Session
9
+
10
+ alias_method :send_requests_without_security, :send_requests
11
+
12
+ def send_requests(*args)
13
+ retval = nil
14
+ event = send_requests_on_enter(*args) { retval = send_requests_without_security(*args) }
15
+ send_requests_on_exit(event) { return retval }
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,51 @@
1
+ require_relative 'prepend'
2
+ require_relative 'chain'
3
+
4
+ module NewRelic::Security
5
+ module Instrumentation
6
+ module HTTPX::Session
7
+
8
+ def send_requests_on_enter(*args)
9
+ event = nil
10
+ NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
11
+ ic_args = []
12
+ args.each do |arg|
13
+ ob = {}
14
+ ob[:Method] = arg.verb
15
+ uri = arg.uri
16
+ ob[:scheme] = uri.scheme
17
+ ob[:host] = uri.host
18
+ ob[:port] = uri.port
19
+ ob[:URI] = uri.to_s
20
+ ob[:path] = uri.path
21
+ ob[:query] = uri.query
22
+ ob[:Body] = arg.body.bytesize.positive? ? arg.body.to_s : ""
23
+ ob[:Headers] = arg.headers
24
+ ob.each { |_, value| value.dup.force_encoding(ISO_8859_1).encode(UTF_8) if value.is_a?(String) }
25
+ ic_args << ob
26
+ end
27
+ event = NewRelic::Security::Agent::Control::Collector.collect(HTTP_REQUEST, ic_args)
28
+ args.each do |arg|
29
+ NewRelic::Security::Instrumentation::InstrumentationUtils.add_tracing_data(arg.headers, event) if event
30
+ end
31
+ event
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 send_requests_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
+ end
48
+ end
49
+ end
50
+
51
+ NewRelic::Security::Instrumentation::InstrumentationLoader.install_instrumentation(:httpx, ::HTTPX::Session, ::NewRelic::Security::Instrumentation::HTTPX::Session)
@@ -0,0 +1,18 @@
1
+ module NewRelic::Security
2
+ module Instrumentation
3
+ module HTTPX
4
+ module Session
5
+ module Prepend
6
+ include NewRelic::Security::Instrumentation::HTTPX::Session
7
+
8
+ def send_requests(*args)
9
+ retval = nil
10
+ event = send_requests_on_enter(*args) { retval = super }
11
+ send_requests_on_exit(event) { return retval }
12
+ end
13
+
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,50 @@
1
+ require 'newrelic_security/instrumentation-security/instrumentation_utils'
2
+
3
+ module NewRelic::Security
4
+ module Instrumentation
5
+ module InstrumentationLoader
6
+ extend self
7
+ def add_instrumentation()
8
+ res = ::NewRelic::Agent.add_instrumentation("#{__dir__}/**/instrumentation.rb")
9
+ NewRelic::Security::Agent.logger.debug "res, res.class #{res.class} #{res.inspect}"
10
+ NewRelic::Security::Agent.logger.debug "Logger print from add instrumentation api."
11
+ NewRelic::Security::Agent.logger.debug "Agent.agent : #{NewRelic::Security::Agent.agent.inspect}"
12
+ NewRelic::Security::Agent.logger.debug "Agent.config : #{NewRelic::Security::Agent::Utils.filtered_log(NewRelic::Security::Agent.config.inspect)}"
13
+ NewRelic::Security::Agent.init_logger.info "[STEP-6] => Application instrumentation applied successfully"
14
+ end
15
+
16
+ def install_instrumentation(supportability_name, target_class, instrumenting_module)
17
+ s_name = "instrumentation.#{supportability_name}".to_sym
18
+ if ::NewRelic::Agent.config[s_name] == :disabled || ::NewRelic::Agent.config[s_name] == 'disabled'
19
+ NewRelic::Security::Agent.logger.info "Skipping New Relic supported #{target_class} instrumentation, as #{s_name} is #{::NewRelic::Agent.config[s_name]}"
20
+ NewRelic::Security::Agent.init_logger.info "Skipping New Relic supported #{target_class} instrumentation, as #{s_name} is #{::NewRelic::Agent.config[s_name]}"
21
+ elsif ::NewRelic::Agent.config[s_name] == :chain || ::NewRelic::Agent.config[s_name] == 'chain'
22
+ NewRelic::Security::Instrumentation::InstrumentationLoader.chain_instrument target_class, Object.const_get("#{instrumenting_module}::Chain")
23
+ else
24
+ NewRelic::Security::Instrumentation::InstrumentationLoader.prepend_instrument target_class, Object.const_get("#{instrumenting_module}::Prepend")
25
+ end
26
+ end
27
+
28
+ def log_and_instrument(method, target_class, instrumenting_module, supportability_name)
29
+ # supportability_name ||= extract_supportability_name(instrumenting_module)
30
+ NewRelic::Security::Agent.logger.info "Installing New Relic supported #{target_class} instrumentation using #{method}"
31
+ NewRelic::Security::Agent.logger.info "Supportability/Instrumentation/#{target_class}/#{method}"
32
+ NewRelic::Security::Agent.init_logger.info "Installing New Relic supported #{target_class} instrumentation using #{method}"
33
+ yield
34
+ end
35
+
36
+ def prepend_instrument(target_class, instrumenting_module, supportability_name = nil)
37
+ log_and_instrument('Prepend', target_class, instrumenting_module, supportability_name) do
38
+ target_class.send(:prepend, instrumenting_module)
39
+ end
40
+ end
41
+
42
+ def chain_instrument(target_class, instrumenting_module, supportability_name = nil)
43
+ log_and_instrument('MethodChaining', target_class, instrumenting_module, supportability_name) do
44
+ instrumenting_module.instrument!
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+