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,91 @@
1
+ # frozen_string_literal: true
2
+ require 'logger'
3
+
4
+ module NewRelic::Security
5
+ module Agent
6
+ module Logging
7
+ INIT_LOG_FILE_NAME = 'ruby-security-collector-init.log'
8
+
9
+ class AgentInitLogger
10
+ def initialize
11
+ create_log_to_file
12
+ end
13
+
14
+ def fatal(msg)
15
+ @init_logger.fatal(msg)
16
+ end
17
+
18
+ def error(msg)
19
+ @init_logger.error(msg)
20
+ end
21
+
22
+ def warn(msg)
23
+ @init_logger.warn(msg)
24
+ end
25
+
26
+ def info(msg)
27
+ @init_logger.info(msg)
28
+ end
29
+
30
+ def debug(msg)
31
+ @init_logger.debug(msg)
32
+ end
33
+
34
+ private
35
+
36
+ def prepped_logger(target)
37
+ @logger = ::Logger.new(target)
38
+ @logger.level = AgentLogger.log_level_for(NewRelic::Security::Agent.config[:log_level])
39
+ set_log_format! if target == STDOUT
40
+ @logger.instance_variable_set(:@skip_instrumenting, true)
41
+ @logger.freeze
42
+ @logger
43
+ end
44
+
45
+ LOG_LEVELS = {
46
+ "debug" => ::Logger::DEBUG,
47
+ "info" => ::Logger::INFO,
48
+ "warn" => ::Logger::WARN,
49
+ "error" => ::Logger::ERROR,
50
+ "fatal" => ::Logger::FATAL
51
+ }
52
+
53
+ def self.log_level_for(level)
54
+ LOG_LEVELS.fetch(level.to_s.downcase, ::Logger::INFO)
55
+ end
56
+
57
+ def create_log_to_file
58
+ log_dir = ::File.join(NewRelic::Security::Agent.config[:log_file_path], SEC_HOME_PATH, LOGS_DIR)
59
+ path = ::File.directory?(log_dir)
60
+ if wants_stdout?
61
+ @init_logger = prepped_logger(STDOUT)
62
+ warn("Using standard out for logging due to config `log_file_path` or serverless_mode")
63
+ elsif path
64
+ file_path = "#{log_dir}/#{INIT_LOG_FILE_NAME}"
65
+ begin
66
+ @init_logger = prepped_logger(file_path)
67
+ rescue => e
68
+ @init_logger = prepped_logger(STDOUT)
69
+ warn("Failed creating logger for file #{file_path}, using standard out for logging. #{e}")
70
+ end
71
+ else
72
+ @init_logger = prepped_logger(STDOUT)
73
+ warn("Error creating log directory #{::File.join(NewRelic::Security::Agent.config[:log_file_path], SEC_HOME_PATH, LOGS_DIR)}, using standard out for logging.")
74
+ end
75
+ end
76
+
77
+ def wants_stdout?
78
+ NewRelic::Security::Agent.config[:log_file_path].casecmp(STANDARD_OUT) == 0 ||
79
+ ::NewRelic::Agent.config[:'serverless_mode.enabled']
80
+ end
81
+
82
+ def set_log_format!
83
+ @logger.formatter = proc do |severity, datetime, progname, msg|
84
+ "** [NewRelic][Security]#{msg}\n"
85
+ end
86
+ end
87
+
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,92 @@
1
+ # frozen_string_literal: true
2
+ require 'logger'
3
+
4
+ module NewRelic::Security
5
+ module Agent
6
+ module Logging
7
+ LOG_FILE_SIZE = 50 * 1024 * 1024
8
+ MAX_LOG_FILES = 3
9
+
10
+ class AgentLogger
11
+ def initialize
12
+ create_log_to_file
13
+ end
14
+
15
+ def fatal(msg)
16
+ @logger.fatal(msg)
17
+ end
18
+
19
+ def error(msg)
20
+ @logger.error(msg)
21
+ end
22
+
23
+ def warn(msg)
24
+ @logger.warn(msg)
25
+ end
26
+
27
+ def info(msg)
28
+ @logger.info(msg)
29
+ end
30
+
31
+ def debug(msg)
32
+ @logger.debug(msg)
33
+ end
34
+
35
+ private
36
+
37
+ def prepped_logger(target)
38
+ @logger = ::Logger.new(target, MAX_LOG_FILES, LOG_FILE_SIZE)
39
+ @logger.level = AgentLogger.log_level_for(NewRelic::Security::Agent.config[:log_level])
40
+ set_log_format! if target == STDOUT
41
+ @logger.instance_variable_set(:@skip_instrumenting, true)
42
+ @logger.freeze
43
+ @logger
44
+ end
45
+
46
+ LOG_LEVELS = {
47
+ "debug" => ::Logger::DEBUG,
48
+ "info" => ::Logger::INFO,
49
+ "warn" => ::Logger::WARN,
50
+ "error" => ::Logger::ERROR,
51
+ "fatal" => ::Logger::FATAL
52
+ }
53
+
54
+ def self.log_level_for(level)
55
+ LOG_LEVELS.fetch(level.to_s.downcase, ::Logger::INFO)
56
+ end
57
+
58
+ def create_log_to_file
59
+ log_dir = ::File.join(NewRelic::Security::Agent.config[:log_file_path], SEC_HOME_PATH, LOGS_DIR)
60
+ path = ::File.directory?(log_dir)
61
+ if wants_stdout?
62
+ @logger = prepped_logger(STDOUT)
63
+ warn("Using standard out for logging due to config `log_file_path` or serverless_mode")
64
+ elsif path
65
+ file_path = "#{log_dir}/#{LOG_FILE_NAME}"
66
+ begin
67
+ @logger = prepped_logger(file_path)
68
+ rescue => e
69
+ @logger = prepped_logger(STDOUT)
70
+ warn("Failed creating logger for file #{file_path}, using standard out for logging. #{e}")
71
+ end
72
+ else
73
+ @logger = prepped_logger(STDOUT)
74
+ warn("Error creating log directory #{::File.join(NewRelic::Security::Agent.config[:log_file_path], SEC_HOME_PATH, LOGS_DIR)}, using standard out for logging.")
75
+ end
76
+ end
77
+
78
+ def wants_stdout?
79
+ NewRelic::Security::Agent.config[:log_file_path].casecmp(STANDARD_OUT) == 0 ||
80
+ ::NewRelic::Agent.config[:'serverless_mode.enabled']
81
+ end
82
+
83
+ def set_log_format!
84
+ @logger.formatter = proc do |severity, datetime, progname, msg|
85
+ "** [NewRelic][Security]#{msg}\n"
86
+ end
87
+ end
88
+
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,21 @@
1
+ module NewRelic::Security
2
+ module Agent
3
+ module Logging
4
+ class NullLogger
5
+ def fatal(msg); end
6
+
7
+ def error(msg); end
8
+
9
+ def warn(msg); end
10
+
11
+ def info(msg); end
12
+
13
+ def debug(msg); end
14
+
15
+ # def method_missing(method, *args, &blk)
16
+ # nil
17
+ # end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,50 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh
3
+ MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
4
+ d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
5
+ QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT
6
+ MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
7
+ b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG
8
+ 9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB
9
+ CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97
10
+ nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt
11
+ 43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P
12
+ T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4
13
+ gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO
14
+ BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR
15
+ TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw
16
+ DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr
17
+ hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg
18
+ 06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF
19
+ PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls
20
+ YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
21
+ CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
22
+ -----END CERTIFICATE-----
23
+ -----BEGIN CERTIFICATE-----
24
+ MIIEvjCCA6agAwIBAgIQBtjZBNVYQ0b2ii+nVCJ+xDANBgkqhkiG9w0BAQsFADBh
25
+ MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
26
+ d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
27
+ QTAeFw0yMTA0MTQwMDAwMDBaFw0zMTA0MTMyMzU5NTlaME8xCzAJBgNVBAYTAlVT
28
+ MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxKTAnBgNVBAMTIERpZ2lDZXJ0IFRMUyBS
29
+ U0EgU0hBMjU2IDIwMjAgQ0ExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
30
+ AQEAwUuzZUdwvN1PWNvsnO3DZuUfMRNUrUpmRh8sCuxkB+Uu3Ny5CiDt3+PE0J6a
31
+ qXodgojlEVbbHp9YwlHnLDQNLtKS4VbL8Xlfs7uHyiUDe5pSQWYQYE9XE0nw6Ddn
32
+ g9/n00tnTCJRpt8OmRDtV1F0JuJ9x8piLhMbfyOIJVNvwTRYAIuE//i+p1hJInuW
33
+ raKImxW8oHzf6VGo1bDtN+I2tIJLYrVJmuzHZ9bjPvXj1hJeRPG/cUJ9WIQDgLGB
34
+ Afr5yjK7tI4nhyfFK3TUqNaX3sNk+crOU6JWvHgXjkkDKa77SU+kFbnO8lwZV21r
35
+ eacroicgE7XQPUDTITAHk+qZ9QIDAQABo4IBgjCCAX4wEgYDVR0TAQH/BAgwBgEB
36
+ /wIBADAdBgNVHQ4EFgQUt2ui6qiqhIx56rTaD5iyxZV2ufQwHwYDVR0jBBgwFoAU
37
+ A95QNVbRTLtm8KPiGxvDl7I90VUwDgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQG
38
+ CCsGAQUFBwMBBggrBgEFBQcDAjB2BggrBgEFBQcBAQRqMGgwJAYIKwYBBQUHMAGG
39
+ GGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBABggrBgEFBQcwAoY0aHR0cDovL2Nh
40
+ Y2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0R2xvYmFsUm9vdENBLmNydDBCBgNV
41
+ HR8EOzA5MDegNaAzhjFodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRH
42
+ bG9iYWxSb290Q0EuY3JsMD0GA1UdIAQ2MDQwCwYJYIZIAYb9bAIBMAcGBWeBDAEB
43
+ MAgGBmeBDAECATAIBgZngQwBAgIwCAYGZ4EMAQIDMA0GCSqGSIb3DQEBCwUAA4IB
44
+ AQCAMs5eC91uWg0Kr+HWhMvAjvqFcO3aXbMM9yt1QP6FCvrzMXi3cEsaiVi6gL3z
45
+ ax3pfs8LulicWdSQ0/1s/dCYbbdxglvPbQtaCdB73sRD2Cqk3p5BJl+7j5nL3a7h
46
+ qG+fh/50tx8bIKuxT8b1Z11dmzzp/2n3YWzW2fP9NsarA4h20ksudYbj/NhVfSbC
47
+ EXffPgK2fPOre3qGNm+499iTcc+G33Mw+nur7SpZyEKEOxEXGlLzyQ4UfaJbcme6
48
+ ce1XR2bFuAJKZTRei9AqPCCcUZlM51Ke92sRKw2Sfh3oius2FkOH6ipjv3U/697E
49
+ A7sKPPcw7+uvTPyLNhBzPvOk
50
+ -----END CERTIFICATE-----
@@ -0,0 +1,219 @@
1
+ # frozen_string_literal: true
2
+ require 'fileutils'
3
+ require 'socket'
4
+ require 'openssl'
5
+
6
+ module NewRelic::Security
7
+ module Agent
8
+ module Utils
9
+ extend self
10
+
11
+ ENABLED = 'enabled'
12
+ VULNERABLE = 'VULNERABLE'
13
+ AES_256_CBC = 'AES-256-CBC'
14
+ H_ASTERIK = 'H*'
15
+ ASTERISK = '*'
16
+
17
+ def is_IAST?
18
+ return false if NewRelic::Security::Agent.config[:policy].empty?
19
+ return NewRelic::Security::Agent.config[:policy][VULNERABILITY_SCAN][IAST_SCAN][ENABLED] if NewRelic::Security::Agent.config[:policy][VULNERABILITY_SCAN][ENABLED]
20
+ false
21
+ end
22
+
23
+ def is_IAST_request?(headers)
24
+ return true if headers&.key?(NR_CSEC_FUZZ_REQUEST_ID)
25
+ false
26
+ end
27
+
28
+ def parse_fuzz_header(ctxt)
29
+ headers = ctxt.headers if ctxt
30
+ if is_IAST? && is_IAST_request?(headers)
31
+ fuzz_request = headers[NR_CSEC_FUZZ_REQUEST_ID].split(COLON_IAST_COLON)
32
+ if fuzz_request.length() >= 7
33
+ decrypted_data = decrypt_data(fuzz_request[6], fuzz_request[7]) if fuzz_request[6] && fuzz_request[7] && !fuzz_request[6].empty? && !fuzz_request[7].empty?
34
+ if decrypted_data
35
+ NewRelic::Security::Agent.logger.debug "Encrypted data: #{fuzz_request[6]}, decrypted data: #{decrypted_data}, Sha256: #{fuzz_request[7]}"
36
+ decrypted_data.split(COMMA).each do |filename|
37
+ begin
38
+ filename.gsub!(NR_CSEC_VALIDATOR_HOME_TMP, NewRelic::Security::Agent.config[:fuzz_dir_path])
39
+ filename.gsub!(NR_CSEC_VALIDATOR_FILE_SEPARATOR, ::File::SEPARATOR)
40
+ dirname = ::File.dirname(filename)
41
+ ::FileUtils.mkdir_p(dirname, :mode => 0770) unless ::File.directory?(dirname)
42
+ ctxt&.fuzz_files << filename
43
+ ::File.open(filename, ::File::WRONLY | ::File::CREAT | ::File::EXCL) do |fd|
44
+ # puts "Ownership acquired by : #{Process.pid}"
45
+ end unless ::File.exist?(filename)
46
+ rescue
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+
54
+ def decrypt_data(name, sha)
55
+ cipher = ::OpenSSL::Cipher.new AES_256_CBC
56
+ cipher.decrypt
57
+ cipher.key = NewRelic::Security::Agent.config[:extraction_key]
58
+ decrypted = cipher.update [name].pack(H_ASTERIK)
59
+ decrypted << cipher.final
60
+ fname = decrypted[16..-1]
61
+ return fname if ::Digest::SHA256.hexdigest(fname) == sha
62
+ nil
63
+ rescue Exception => exception
64
+ NewRelic::Security::Agent.logger.error "Exception in decrypt_data: #{exception.inspect} #{exception.backtrace}"
65
+ end
66
+
67
+ def delete_created_files(ctxt)
68
+ return unless ctxt
69
+ headers = ctxt.headers
70
+ if is_IAST? && is_IAST_request?(headers)
71
+ ctxt.fuzz_files.each do |file|
72
+ begin
73
+ ::File.delete(file)
74
+ rescue
75
+ end
76
+ end
77
+ end
78
+ end
79
+
80
+ def create_exit_event(event)
81
+ return unless event
82
+ return unless is_IAST?
83
+ return unless is_IAST_request?(event.httpRequest[:headers])
84
+ if event.httpRequest[:headers][NR_CSEC_FUZZ_REQUEST_ID].include?(event.apiId) && event.httpRequest[:headers][NR_CSEC_FUZZ_REQUEST_ID].include?(VULNERABLE)
85
+ exit_event = NewRelic::Security::Agent::Control::ExitEvent.new
86
+ exit_event.executionId = event.id
87
+ exit_event.caseType = event.caseType
88
+ exit_event.k2RequestIdentifier = event.httpRequest[:headers][NR_CSEC_FUZZ_REQUEST_ID]
89
+ NewRelic::Security::Agent.agent.event_processor.send_exit_event(exit_event)
90
+ end
91
+ rescue Exception => exception
92
+ NewRelic::Security::Agent.logger.error "Exception in create_exit_event: #{exception.inspect} #{exception.backtrace}"
93
+ NewRelic::Security::Agent.agent.exit_event_stats.error_count.increment
94
+ end
95
+
96
+ def get_app_routes(framework, router = nil)
97
+ enable_object_space_in_jruby
98
+ if framework == :rails
99
+ ::Rails.application.routes.routes.each do |route|
100
+ if route.verb.is_a?(::Regexp)
101
+ method = route.verb.inspect.match(/[a-zA-Z]+/)
102
+ NewRelic::Security::Agent.agent.route_map << "#{method}@#{route.path.spec.to_s.gsub(/\(\.:format\)/, "")}" if method
103
+ else
104
+ route.verb.split("|").each { |m|
105
+ NewRelic::Security::Agent.agent.route_map << "#{m}@#{route.path.spec.to_s.gsub(/\(\.:format\)/, "")}"
106
+ }
107
+ end
108
+ end
109
+ elsif framework == :sinatra
110
+ ::Sinatra::Application.routes.each do |method, routes|
111
+ routes.map { |r| r.first.to_s }.map do |route|
112
+ NewRelic::Security::Agent.agent.route_map << "#{method}@#{route}"
113
+ end
114
+ end
115
+ elsif framework == :grape
116
+ ObjectSpace.each_object(::Grape::Endpoint) { |z|
117
+ z.instance_variable_get(:@routes)&.each { |route|
118
+ http_method = route.instance_variable_get(:@request_method) ? route.instance_variable_get(:@request_method) : route.instance_variable_get(:@options)[:method]
119
+ NewRelic::Security::Agent.agent.route_map << "#{http_method}@#{route.pattern.origin}"
120
+ }
121
+ }
122
+ elsif framework == :padrino
123
+ if router.instance_of?(::Padrino::PathRouter::Router)
124
+ router.instance_variable_get(:@routes).each do |route|
125
+ NewRelic::Security::Agent.agent.route_map << "#{route.instance_variable_get(:@verb)}@#{route.matcher.instance_variable_get(:@path)}"
126
+ end
127
+ end
128
+ elsif framework == :roda
129
+ NewRelic::Security::Agent.logger.warn "TODO: Roda is a routing tree web toolkit, which generates route dynamically, hence route extraction is not possible."
130
+ else
131
+ NewRelic::Security::Agent.logger.error "Unable to get app routes as Framework not detected"
132
+ end
133
+ disable_object_space_in_jruby if NewRelic::Security::Agent.config[:jruby_objectspace_enabled]
134
+ NewRelic::Security::Agent.logger.debug "ALL ROUTES : #{NewRelic::Security::Agent.agent.route_map}"
135
+ NewRelic::Security::Agent.agent.event_processor&.send_application_url_mappings
136
+ rescue Exception => exception
137
+ NewRelic::Security::Agent.logger.error "Error in get app routes : #{exception.inspect} #{exception.backtrace}"
138
+ end
139
+
140
+ def app_port(env)
141
+ listen_port = nil
142
+ if env.key?('puma.socket')
143
+ NewRelic::Security::Agent.config.app_server = :puma
144
+ if env['puma.socket'].is_a?(TCPSocket)
145
+ listen_port = env['puma.socket'].addr[1]
146
+ NewRelic::Security::Agent.logger.debug "Detected port from puma.socket TCPSocket : #{listen_port}"
147
+ elsif env['puma.socket'].is_a?(Puma::MiniSSL::Socket)
148
+ listen_port = env['puma.socket'].instance_variable_get(:@socket).addr[1]
149
+ NewRelic::Security::Agent.logger.debug "Detected port from puma.socket Puma::MiniSSL::Socket TCPSocket : #{listen_port}"
150
+ end
151
+ end
152
+ if env.key?('unicorn.socket') && env['unicorn.socket'].is_a?(::Unicorn::TCPClient)
153
+ NewRelic::Security::Agent.config.app_server = :unicorn
154
+ listen_port, _ = ::Socket.unpack_sockaddr_in(env['unicorn.socket'].getsockname)
155
+ NewRelic::Security::Agent.logger.debug "Detected port from unicorn.socket Unicorn::TCPClient : #{listen_port}"
156
+ end
157
+ ObjectSpace.each_object(::Falcon::Server) { |z|
158
+ NewRelic::Security::Agent.config.app_server = :falcon
159
+ listen_port = z.endpoint.instance_variable_get(:@specification)[1]
160
+ NewRelic::Security::Agent.logger.debug "Detected port from Falcon::Server : #{listen_port}"
161
+ } if defined?(::Falcon::Server)
162
+ ObjectSpace.each_object(::Thin::Backends::TcpServer) { |z|
163
+ NewRelic::Security::Agent.config.app_server = :thin
164
+ listen_port = z.instance_variable_get(:@port)
165
+ NewRelic::Security::Agent.logger.debug "Detected port from Thin::Backends::TcpServer : #{listen_port}"
166
+ } if defined?(::Thin::Backends::TcpServer)
167
+ ObjectSpace.each_object(::WEBrick::GenericServer) { |z|
168
+ NewRelic::Security::Agent.config.app_server = :webrick
169
+ listen_port = z.instance_variable_get(:@config)[:Port]
170
+ NewRelic::Security::Agent.logger.debug "Detected port from WEBrick::GenericServer : #{listen_port}"
171
+ } if defined?(::WEBrick::GenericServer)
172
+ if NewRelic::Security::Agent.config[:'security.application_info.port'] != 0
173
+ listen_port = NewRelic::Security::Agent.config[:'security.application_info.port']
174
+ NewRelic::Security::Agent.logger.info "Using application listen port from newrelic.yml security.application_info.port : #{listen_port}"
175
+ end
176
+ if listen_port
177
+ NewRelic::Security::Agent.logger.info "Detected application listen_port : #{listen_port}"
178
+ else
179
+ NewRelic::Security::Agent.logger.warn "Unable to detect application listen port, IAST can not run without application listen port. Please provide application listen port in security.application_info.port in newrelic.yml"
180
+ end
181
+ disable_object_space_in_jruby if NewRelic::Security::Agent.config[:jruby_objectspace_enabled]
182
+ listen_port
183
+ rescue Exception => exception
184
+ NewRelic::Security::Agent.logger.error "Exception in port detection : #{exception.inspect} #{exception.backtrace}"
185
+ end
186
+
187
+ def app_root
188
+ #so far assuming it as Rails
189
+ #TBD, determing the frame work then use appropriate APIs
190
+ #val = Rails.root
191
+ root = nil
192
+ root = ::Rack::Directory.new(EMPTY_STRING).root.to_s if defined? ::Rack::Directory
193
+ root
194
+ end
195
+
196
+ def enable_object_space_in_jruby
197
+ if RUBY_ENGINE == 'jruby' && !JRuby.objectspace
198
+ JRuby.objectspace = true
199
+ NewRelic::Security::Agent.config.jruby_objectspace_enabled = true
200
+ end
201
+ end
202
+
203
+ def disable_object_space_in_jruby
204
+ if RUBY_ENGINE == 'jruby' && JRuby.objectspace
205
+ JRuby.objectspace = false
206
+ NewRelic::Security::Agent.config.jruby_objectspace_enabled = false
207
+ end
208
+ end
209
+
210
+ def license_key
211
+ NewRelic::Security::Agent.config[:license_key]
212
+ end
213
+
214
+ def filtered_log(log)
215
+ log.gsub(license_key, ASTERISK * license_key.size)
216
+ end
217
+ end
218
+ end
219
+ end
@@ -0,0 +1,57 @@
1
+ module NewRelic::Security
2
+ module Agent
3
+ extend self
4
+
5
+ require 'newrelic_security/constants'
6
+ require 'newrelic_security/agent/logging/logger'
7
+ require 'newrelic_security/agent/logging/init_logger'
8
+ require 'newrelic_security/agent/configuration/manager'
9
+ require 'newrelic_security/agent/agent'
10
+ require 'newrelic_security/agent/utils/agent_utils'
11
+
12
+ @agent = nil
13
+ @logger = nil
14
+ @config = nil
15
+ @event_subscriber = nil
16
+
17
+ # puts "NewRelic::Agent.agent : #{::NewRelic::Agent.agent.inspect}"
18
+ # puts "NewRelic::Agent.config : #{::NewRelic::Agent.config.inspect}"
19
+ # puts "NewRelic::Agent.config : #{::NewRelic::Agent.config.instance_variables}"
20
+
21
+ def agent()
22
+ return @agent if @agent
23
+ puts "Agent unavailable as it hasn't been started."
24
+ nil
25
+ end
26
+
27
+ def logger
28
+ @logger ||= NewRelic::Security::Agent::Logging::AgentLogger.new
29
+ end
30
+
31
+ def logger=(log)
32
+ @logger = log
33
+ end
34
+
35
+ def init_logger
36
+ @init_logger ||= NewRelic::Security::Agent::Logging::AgentInitLogger.new
37
+ end
38
+
39
+ def init_logger=(log)
40
+ @init_logger = log
41
+ end
42
+
43
+ def config
44
+ @config ||= NewRelic::Security::Agent::Configuration::Manager.new
45
+ end
46
+
47
+ def config=(new_config)
48
+ @config = new_config
49
+ end
50
+
51
+ @agent = NewRelic::Security::Agent::Agent.new unless @agent
52
+ NewRelic::Agent.instance.events.notify(:server_source_configuration_added) if NewRelic::Agent.agent.connected?
53
+ NewRelic::Security::Agent.logger.debug "Creating security agent instance initially : #{@agent.inspect}"
54
+ NewRelic::Security::Agent.init_logger.info "[STEP-1] => Security agent is starting : #{@agent.inspect}"
55
+ NewRelic::Security::Agent.init_logger.info "[STEP-2] => Generating unique identifier : #{@config[:uuid]}"
56
+ end
57
+ end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NewRelic::Security
4
+ EMPTY_STRING = ""
5
+ RUBY = 'RUBY'
6
+ Ruby = 'Ruby'
7
+ LANGUAGE_COLLECTOR = 'LANGUAGE_COLLECTOR'
8
+ STANDARD_OUT = 'STDOUT'
9
+ NR_CSEC_VALIDATOR_HOME_TMP = '{{NR_CSEC_VALIDATOR_HOME_TMP}}'
10
+ NR_CSEC_VALIDATOR_FILE_SEPARATOR = '{{NR_CSEC_VALIDATOR_FILE_SEPARATOR}}'
11
+ SEC_HOME_PATH = 'nr-security-home'
12
+ LOGS_DIR = 'logs'
13
+ TMP_DIR = 'tmp'
14
+ LOG_FILE_NAME = 'ruby-security-collector.log'
15
+ NR_SECURITY_HOME_TMP = 'nr-security-home/tmp/'
16
+ NR_CSEC_FUZZ_REQUEST_ID = 'nr-csec-fuzz-request-id'
17
+ NR_CSEC_TRACING_DATA = 'nr-csec-tracing-data'
18
+ NR_CSEC_PARENT_ID = 'nr-csec-parent-id'
19
+ COLON_IAST_COLON = ':IAST:'
20
+ NOSQL_DB_COMMAND = 'NOSQL_DB_COMMAND'
21
+ SQL_DB_COMMAND = 'SQL_DB_COMMAND'
22
+ FILE_OPERATION = 'FILE_OPERATION'
23
+ FILE_INTEGRITY = 'FILE_INTEGRITY'
24
+ SYSTEM_COMMAND = 'SYSTEM_COMMAND'
25
+ REFLECTED_XSS = 'REFLECTED_XSS'
26
+ HTTP_REQUEST = 'HTTP_REQUEST'
27
+ XPATH = 'XPATH'
28
+ LDAP = 'LDAP'
29
+ MONGO = 'MONGO'
30
+ SQLITE = 'SQLITE'
31
+ MYSQL = 'MYSQL'
32
+ POSTGRES = 'POSTGRES'
33
+ ISO_8859_1 = 'ISO-8859-1'
34
+ UTF_8 = 'UTF-8'
35
+ RAILS = 'rails'
36
+ PUMA = 'puma'
37
+ CLUSTER = 'cluster'
38
+ UNICORN = 'unicorn'
39
+ WORKER = 'worker'
40
+ HYPHEN = '-'
41
+ COMMA = ','
42
+ SLASH = '/'
43
+ AT_THE_RATE = '@'
44
+ SPAWN_METHOD = 'spawn_method'
45
+ DIRECT = 'direct'
46
+ LISTEN_PORT = 'listen_port'
47
+ PIPE = '|'
48
+ READ = 'read'
49
+ DELETE = 'delete'
50
+ WRITE = 'write'
51
+ BINWRITE = 'binwrite'
52
+ PROTOCOL = 'protocol'
53
+ HTTPS = 'https'
54
+ REQUEST_METHOD = 'REQUEST_METHOD'
55
+ PATH_INFO = 'PATH_INFO'
56
+ CONTENT_TYPE = 'CONTENT_TYPE'
57
+ REQUEST_URI = 'REQUEST_URI'
58
+ SERVER_PORT = 'SERVER_PORT'
59
+ X_FORWARDED_FOR = 'x-forwarded-for'
60
+ REMOTE_ADDR = 'REMOTE_ADDR'
61
+ RACK_URL_SCHEME = 'rack.url_scheme'
62
+ CONTENT_TYPE1 = 'content-Type'
63
+ PULL = 'PULL'
64
+ SHA1 = 'sha1'
65
+ VULNERABILITY_SCAN = 'vulnerabilityScan'
66
+ IAST_SCAN = 'iastScan'
67
+ end
@@ -0,0 +1,70 @@
1
+ module NewRelic::Security
2
+ module Instrumentation
3
+ module ActiveRecord
4
+ module ConnectionAdapters
5
+ module Mysql2Adapter
6
+ module Chain
7
+
8
+ def self.instrument!
9
+ ::ActiveRecord::ConnectionAdapters::Mysql2Adapter.class_eval do
10
+ include NewRelic::Security::Instrumentation::ActiveRecord::ConnectionAdapters::Mysql2Adapter
11
+
12
+ if RUBY_ENGINE == 'jruby'
13
+ alias_method :execute_without_security, :execute
14
+
15
+ def execute(sql, name = nil)
16
+ retval = nil
17
+ event = execute_on_enter(sql, name) { retval = execute_without_security(sql, name) }
18
+ execute_on_exit(event) { return retval }
19
+ end
20
+
21
+ alias_method :exec_insert_without_security, :exec_insert
22
+
23
+ def exec_insert(*var)
24
+ retval = nil
25
+ event = exec_insert_on_enter(*var) { retval = exec_insert_without_security(*var) }
26
+ exec_insert_on_exit(event) { return retval }
27
+ end
28
+
29
+ alias_method :exec_update_without_security, :exec_update
30
+
31
+ def exec_update(*var)
32
+ retval = nil
33
+ event = exec_update_on_enter(*var) { retval = exec_update_without_security(*var) }
34
+ exec_update_on_exit(event) { return retval }
35
+ end
36
+
37
+ alias_method :exec_query_without_security, :exec_query
38
+
39
+ if ::Rails.version < '5'
40
+ def exec_query(*var)
41
+ retval = nil
42
+ event = exec_query_on_enter(*var) { retval = exec_query_without_security(*var) }
43
+ exec_query_on_exit(event) { return retval }
44
+ end
45
+ else
46
+ def exec_query(*var, **key_vars)
47
+ retval = nil
48
+ event = exec_query_on_enter(*var, **key_vars) { retval = exec_query_without_security(*var, **key_vars) }
49
+ exec_query_on_exit(event) { return retval }
50
+ end
51
+ end
52
+
53
+ alias_method :exec_delete_without_security, :exec_delete
54
+
55
+ def exec_delete(*var)
56
+ retval = nil
57
+ event = exec_delete_on_enter(*var) { retval = exec_delete_without_security(*var) }
58
+ exec_delete_on_exit(event) { return retval }
59
+ end
60
+ end
61
+
62
+ end
63
+ end
64
+
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end