newrelic_security 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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