newrelic_security 0.2.0 → 0.4.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 (58) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/pr_ci.yml +4 -4
  3. data/.github/workflows/release.yml +1 -1
  4. data/.github/workflows/rubocop.yml +1 -1
  5. data/CHANGELOG.md +90 -1
  6. data/Gemfile_test +3 -0
  7. data/README.md +1 -0
  8. data/THIRD_PARTY_NOTICES.md +8 -0
  9. data/lib/newrelic_security/agent/agent.rb +22 -4
  10. data/lib/newrelic_security/agent/configuration/manager.rb +65 -7
  11. data/lib/newrelic_security/agent/control/application_runtime_error.rb +1 -1
  12. data/lib/newrelic_security/agent/control/collector.rb +41 -4
  13. data/lib/newrelic_security/agent/control/control_command.rb +2 -3
  14. data/lib/newrelic_security/agent/control/error_reporting.rb +8 -6
  15. data/lib/newrelic_security/agent/control/event.rb +15 -1
  16. data/lib/newrelic_security/agent/control/event_processor.rb +25 -14
  17. data/lib/newrelic_security/agent/control/event_subscriber.rb +6 -8
  18. data/lib/newrelic_security/agent/control/health_check.rb +4 -0
  19. data/lib/newrelic_security/agent/control/http_context.rb +10 -6
  20. data/lib/newrelic_security/agent/control/iast_client.rb +24 -11
  21. data/lib/newrelic_security/agent/control/reflected_xss.rb +3 -4
  22. data/lib/newrelic_security/agent/control/scan_scheduler.rb +77 -0
  23. data/lib/newrelic_security/agent/control/websocket_client.rb +71 -16
  24. data/lib/newrelic_security/agent/utils/agent_utils.rb +25 -17
  25. data/lib/newrelic_security/constants.rb +1 -2
  26. data/lib/newrelic_security/instrumentation-security/async-http/instrumentation.rb +2 -13
  27. data/lib/newrelic_security/instrumentation-security/curb/instrumentation.rb +1 -14
  28. data/lib/newrelic_security/instrumentation-security/ethon/chain.rb +0 -6
  29. data/lib/newrelic_security/instrumentation-security/ethon/instrumentation.rb +7 -42
  30. data/lib/newrelic_security/instrumentation-security/ethon/prepend.rb +0 -4
  31. data/lib/newrelic_security/instrumentation-security/excon/instrumentation.rb +3 -13
  32. data/lib/newrelic_security/instrumentation-security/grape/instrumentation.rb +1 -0
  33. data/lib/newrelic_security/instrumentation-security/graphql/chain.rb +26 -0
  34. data/lib/newrelic_security/instrumentation-security/graphql/instrumentation.rb +28 -0
  35. data/lib/newrelic_security/instrumentation-security/graphql/prepend.rb +18 -0
  36. data/lib/newrelic_security/instrumentation-security/grpc/server/instrumentation.rb +3 -2
  37. data/lib/newrelic_security/instrumentation-security/httpclient/instrumentation.rb +4 -28
  38. data/lib/newrelic_security/instrumentation-security/httprb/instrumentation.rb +1 -12
  39. data/lib/newrelic_security/instrumentation-security/httpx/instrumentation.rb +1 -15
  40. data/lib/newrelic_security/instrumentation-security/instrumentation_utils.rb +0 -17
  41. data/lib/newrelic_security/instrumentation-security/io/chain.rb +2 -2
  42. data/lib/newrelic_security/instrumentation-security/io/prepend.rb +1 -1
  43. data/lib/newrelic_security/instrumentation-security/net_http/instrumentation.rb +6 -23
  44. data/lib/newrelic_security/instrumentation-security/net_ldap/instrumentation.rb +1 -1
  45. data/lib/newrelic_security/instrumentation-security/padrino/instrumentation.rb +1 -0
  46. data/lib/newrelic_security/instrumentation-security/patron/instrumentation.rb +2 -15
  47. data/lib/newrelic_security/instrumentation-security/rack/chain.rb +24 -0
  48. data/lib/newrelic_security/instrumentation-security/rack/instrumentation.rb +44 -0
  49. data/lib/newrelic_security/instrumentation-security/rack/prepend.rb +18 -0
  50. data/lib/newrelic_security/instrumentation-security/rails/instrumentation.rb +1 -0
  51. data/lib/newrelic_security/instrumentation-security/roda/instrumentation.rb +1 -0
  52. data/lib/newrelic_security/instrumentation-security/sinatra/instrumentation.rb +1 -0
  53. data/lib/newrelic_security/newrelic-security-api/api.rb +1 -1
  54. data/lib/newrelic_security/parse-cron/cron_parser.rb +294 -0
  55. data/lib/newrelic_security/version.rb +1 -1
  56. data/lib/newrelic_security/websocket-client-simple/client.rb +5 -1
  57. data/newrelic_security.gemspec +1 -1
  58. metadata +15 -7
@@ -12,20 +12,7 @@ module NewRelic::Security
12
12
  self.requests.each {
13
13
  |key, req|
14
14
  uri = NewRelic::Security::Instrumentation::InstrumentationUtils.parse_uri(req.url)
15
- ob = {}
16
- if uri
17
- ob[:Method] = nil
18
- ob[:scheme] = uri.scheme
19
- ob[:host] = uri.host
20
- ob[:port] = uri.port
21
- ob[:URI] = uri.to_s
22
- ob[:path] = uri.path
23
- ob[:query] = uri.query
24
- ob[:Body] = req.post_body
25
- ob[:Headers] = req.headers
26
- ob.each { |_, value| value.dup.force_encoding(ISO_8859_1).encode(UTF_8) if value.is_a?(String) }
27
- ic_args.push(ob)
28
- end
15
+ ic_args.push(uri.to_s) if uri
29
16
  }
30
17
  event = NewRelic::Security::Agent::Control::Collector.collect(HTTP_REQUEST, ic_args)
31
18
  self.requests.each { |key, req| NewRelic::Security::Instrumentation::InstrumentationUtils.add_tracing_data(req.headers, event) } if event
@@ -7,12 +7,6 @@ module NewRelic::Security
7
7
  ::Ethon::Easy.class_eval do
8
8
  include NewRelic::Security::Instrumentation::Ethon::Easy
9
9
 
10
- alias_method :fabricate_without_security, :fabricate
11
-
12
- def fabricate(url, action_name, options)
13
- fabricate_on_enter(url, action_name, options) { return fabricate_without_security(url, action_name, options) }
14
- end
15
-
16
10
  alias_method(:headers_equals_without_security, :headers=)
17
11
 
18
12
  def headers=(headers)
@@ -7,46 +7,25 @@ module NewRelic::Security
7
7
  module Ethon
8
8
  module Easy
9
9
 
10
- def fabricate_on_enter(url, action_name, options)
11
- NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
12
- NewRelic::Security::Agent::Control::HTTPContext.get_context.cache[self.object_id] = { :method => action_name } if NewRelic::Security::Agent::Control::HTTPContext.get_context
13
- NewRelic::Security::Agent::Control::HTTPContext.get_context.cache[self.object_id][:body] = options[:body] if NewRelic::Security::Agent::Control::HTTPContext.get_context
14
- rescue => exception
15
- NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
16
- ensure
17
- yield
18
- end
19
-
20
10
  def headers_equals_on_enter(headers)
21
11
  NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
22
- NewRelic::Security::Agent::Control::HTTPContext.get_context.cache[self.object_id][:headers] = headers if NewRelic::Security::Agent::Control::HTTPContext.get_context && NewRelic::Security::Agent::Control::HTTPContext.get_context.cache[self.object_id]
12
+ NewRelic::Security::Agent::Control::HTTPContext.get_context.cache[object_id][:headers] = headers if NewRelic::Security::Agent::Control::HTTPContext.get_context && NewRelic::Security::Agent::Control::HTTPContext.get_context.cache[object_id]
23
13
  rescue => exception
24
14
  NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
25
15
  ensure
26
16
  yield
27
17
  end
28
18
 
29
- def perform_on_enter(*args)
19
+ def perform_on_enter(*_args)
30
20
  event = nil
31
21
  NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
32
- context = NewRelic::Security::Agent::Control::HTTPContext.get_context.cache[self.object_id] if NewRelic::Security::Agent::Control::HTTPContext.get_context
22
+ context = NewRelic::Security::Agent::Control::HTTPContext.get_context.cache[object_id] if NewRelic::Security::Agent::Control::HTTPContext.get_context
33
23
  uri = ::URI.parse(url)
34
- ob = {}
35
- ob[:Method] = context[:method] if context
36
- ob[:scheme] = uri.scheme
37
- ob[:host] = uri.host
38
- ob[:port] = uri.port
39
- ob[:URI] = uri.to_s
40
- ob[:path] = uri.path
41
- ob[:query] = uri.query
42
- ob[:Body] = context[:body] if context
43
- ob[:Headers] = context[:headers] if context
44
- ob.each { |_, value| value.dup.force_encoding(ISO_8859_1).encode(UTF_8) if value.is_a?(String) }
45
- event = NewRelic::Security::Agent::Control::Collector.collect(HTTP_REQUEST, [ob])
24
+ event = NewRelic::Security::Agent::Control::Collector.collect(HTTP_REQUEST, [uri.to_s])
46
25
  headers_copy = {}
47
26
  headers_copy.merge!(context[:headers]) if context&.key?(:headers)
48
27
  NewRelic::Security::Instrumentation::InstrumentationUtils.add_tracing_data(headers_copy, event) if event
49
- self.headers = headers_copy if self.headers
28
+ self.headers = headers_copy if headers
50
29
  event
51
30
  rescue => exception
52
31
  NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
@@ -67,27 +46,13 @@ module NewRelic::Security
67
46
 
68
47
  module Multi
69
48
 
70
- def perform_on_enter(*args)
49
+ def perform_on_enter(*_args)
71
50
  event = nil
72
51
  NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
73
52
  ic_args = []
74
53
  easy_handles.each do |easy|
75
- context = NewRelic::Security::Agent::Control::HTTPContext.get_context.cache[easy.object_id] if NewRelic::Security::Agent::Control::HTTPContext.get_context
76
54
  uri = NewRelic::Security::Instrumentation::InstrumentationUtils.parse_uri(easy.url)
77
- if uri
78
- ob = {}
79
- ob[:Method] = context[:method] if context
80
- ob[:scheme] = uri.scheme
81
- ob[:host] = uri.host
82
- ob[:port] = uri.port
83
- ob[:URI] = easy.url.to_s
84
- ob[:path] = uri.path
85
- ob[:query] = uri.query
86
- ob[:Body] = context[:body] if context
87
- ob[:Headers] = context[:headers] if context
88
- ob.each { |_, value| value.dup.force_encoding(ISO_8859_1).encode(UTF_8) if value.is_a?(String) }
89
- ic_args << ob
90
- end
55
+ ic_args << easy.url.to_s if uri
91
56
  end
92
57
  event = NewRelic::Security::Agent::Control::Collector.collect(HTTP_REQUEST, ic_args) unless ic_args.empty?
93
58
  easy_handles.each do |easy|
@@ -4,10 +4,6 @@ module NewRelic::Security
4
4
  module Easy
5
5
  module Prepend
6
6
  include NewRelic::Security::Instrumentation::Ethon::Easy
7
-
8
- def fabricate(url, action_name, options)
9
- fabricate_on_enter(url, action_name, options) { return super }
10
- end
11
7
 
12
8
  def headers=(headers)
13
9
  headers_equals_on_enter(headers) { return super }
@@ -5,21 +5,11 @@ module NewRelic::Security
5
5
  module Instrumentation
6
6
  module Excon::Connection
7
7
 
8
- def request_on_enter(params)
8
+ def request_on_enter(_params)
9
9
  event = nil
10
10
  NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
11
- ob = {}
12
- ob[:Method] = params[:method]
13
- ob[:scheme] = self.data[:scheme]
14
- ob[:host] = self.data[:host]
15
- ob[:port] = self.data[:port]
16
- ob[:URI] = self.data[:query].nil? ? "#{self.data[:host]}#{self.data[:path]}" : "#{self.data[:host]}#{self.data[:path]}?#{self.data[:query]}"
17
- ob[:path] = self.data[:path]
18
- ob[:query] = self.data[:query]
19
- ob[:Body] = self.data[:body]
20
- ob[:Headers] = self.data[:headers]
21
- ob.each { |_, value| value.dup.force_encoding(ISO_8859_1).encode(UTF_8) if value.is_a?(String) }
22
- event = NewRelic::Security::Agent::Control::Collector.collect(HTTP_REQUEST, [ob])
11
+ uri = "#{self.data[:scheme]}://#{self.data[:host]}#{self.data[:path]}"
12
+ event = NewRelic::Security::Agent::Control::Collector.collect(HTTP_REQUEST, [uri])
23
13
  NewRelic::Security::Instrumentation::InstrumentationUtils.add_tracing_data(self.data[:headers], event) if event
24
14
  event
25
15
  rescue => exception
@@ -8,6 +8,7 @@ module NewRelic::Security
8
8
  def call_on_enter(env)
9
9
  event = nil
10
10
  NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
11
+ return unless NewRelic::Security::Agent.config[:enabled]
11
12
  NewRelic::Security::Agent.config.update_port = NewRelic::Security::Agent::Utils.app_port(env) unless NewRelic::Security::Agent.config[:listen_port]
12
13
  NewRelic::Security::Agent::Utils.get_app_routes(:grape) if NewRelic::Security::Agent.agent.route_map.empty?
13
14
  NewRelic::Security::Agent::Control::HTTPContext.set_context(env)
@@ -0,0 +1,26 @@
1
+ module NewRelic::Security
2
+ module Instrumentation
3
+ module GraphQL
4
+ module Query
5
+ module Executor
6
+ module Chain
7
+ def self.instrument!
8
+ ::GraphQL::Query::Executor.class_eval do
9
+ class << self
10
+ include NewRelic::Security::Instrumentation::GraphQL::Query::Executor
11
+
12
+ alias_method :execute_without_security, :execute
13
+
14
+ def execute
15
+ execute_on_enter { return execute_without_security }
16
+ end
17
+
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,28 @@
1
+ require_relative 'prepend'
2
+ require_relative 'chain'
3
+
4
+ module NewRelic::Security
5
+ module Instrumentation
6
+ module GraphQL::Query::Executor
7
+
8
+ GRAPHQL_QUERY = 'GRAPHQL_QUERY'.freeze
9
+ GRAPHQL_VARIABLE = 'GRAPHQL_VARIABLE'.freeze
10
+ STAR_DOT_QUERY = '*.query'.freeze
11
+ STAR_DOT_VARIABLES = '*.variables'.freeze
12
+
13
+ def execute_on_enter
14
+ NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
15
+ ctxt = NewRelic::Security::Agent::Control::HTTPContext.get_context
16
+ ctxt.custom_data_type[STAR_DOT_QUERY] = GRAPHQL_QUERY if query.query_string
17
+ ctxt.custom_data_type[STAR_DOT_VARIABLES] = GRAPHQL_VARIABLE if query.instance_variable_get(:@provided_variables)
18
+ rescue => exception
19
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
20
+ ensure
21
+ yield
22
+ end
23
+
24
+ end
25
+ end
26
+ end
27
+
28
+ NewRelic::Security::Instrumentation::InstrumentationLoader.install_instrumentation(:graphql, ::GraphQL::Query::Executor, ::NewRelic::Security::Instrumentation::GraphQL::Query::Executor)
@@ -0,0 +1,18 @@
1
+ module NewRelic::Security
2
+ module Instrumentation
3
+ module GraphQL
4
+ module Query
5
+ module Executor
6
+ module Prepend
7
+ include NewRelic::Security::Instrumentation::GraphQL::Query::Executor
8
+
9
+ def execute
10
+ execute_on_enter { return super }
11
+ end
12
+
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -6,7 +6,7 @@ module NewRelic::Security
6
6
  module Instrumentation
7
7
  module GRPC
8
8
  module RpcDesc
9
- def grpc_server_on_enter(active_call, mth, inter_ctx, is_grpc_client_stream, is_grpc_server_stream)
9
+ def grpc_server_on_enter(active_call, mth, _inter_ctx, is_grpc_client_stream, is_grpc_server_stream)
10
10
  event = nil
11
11
  NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
12
12
  grpc_request = {}
@@ -14,10 +14,11 @@ module NewRelic::Security
14
14
  grpc_request[:peer] = active_call.peer
15
15
  # puts "mth : #{mth.class} #{mth.methods}"
16
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
+ NewRelic::Security::Agent::Utils.get_app_routes(:grpc, mth) if NewRelic::Security::Agent.agent.route_map.empty?
17
18
  grpc_request[:method] = "#{mth.owner}/#{mth.original_name}"
18
19
  grpc_request[:is_grpc_client_stream] = is_grpc_client_stream
19
20
  grpc_request[:is_grpc_server_stream] = is_grpc_server_stream
20
- is_grpc_client_stream ? grpc_request[:body] = [] : grpc_request[:body] = ::String.new
21
+ grpc_request[:body] = is_grpc_client_stream ? [] : ::String.new
21
22
  NewRelic::Security::Agent::Control::GRPCContext.set_context(grpc_request)
22
23
  NewRelic::Security::Agent::Utils.parse_fuzz_header(NewRelic::Security::Agent::Control::GRPCContext.get_context)
23
24
  rescue => exception
@@ -8,20 +8,8 @@ module NewRelic::Security
8
8
  def do_request_on_enter(method, uri, query, body, header)
9
9
  event = nil
10
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])
11
+ uri_s = uri.to_s unless uri.nil?
12
+ event = NewRelic::Security::Agent::Control::Collector.collect(HTTP_REQUEST, [uri_s])
25
13
  NewRelic::Security::Instrumentation::InstrumentationUtils.add_tracing_data(header, event) if event
26
14
  event
27
15
  rescue => exception
@@ -43,20 +31,8 @@ module NewRelic::Security
43
31
  def do_request_async_on_enter(method, uri, query, body, header)
44
32
  event = nil
45
33
  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])
34
+ uri_s = uri.to_s unless uri.nil?
35
+ event = NewRelic::Security::Agent::Control::Collector.collect(HTTP_REQUEST, [uri_s])
60
36
  NewRelic::Security::Instrumentation::InstrumentationUtils.add_tracing_data(header, event) if event
61
37
  event
62
38
  rescue => exception
@@ -8,19 +8,8 @@ module NewRelic::Security
8
8
  def perform_on_enter(request, options)
9
9
  event = nil
10
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])
11
+ event = NewRelic::Security::Agent::Control::Collector.collect(HTTP_REQUEST, [request.uri.to_s])
22
12
  NewRelic::Security::Instrumentation::InstrumentationUtils.add_tracing_data(options.headers, event) if event
23
- ob = nil
24
13
  event
25
14
  rescue => exception
26
15
  NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
@@ -9,21 +9,7 @@ module NewRelic::Security
9
9
  event = nil
10
10
  NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
11
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
12
+ args.each { |arg| ic_args << arg.uri.to_s }
27
13
  event = NewRelic::Security::Agent::Control::Collector.collect(HTTP_REQUEST, ic_args)
28
14
  args.each do |arg|
29
15
  NewRelic::Security::Instrumentation::InstrumentationUtils.add_tracing_data(arg.headers, event) if event
@@ -143,23 +143,6 @@ module NewRelic::Security
143
143
  return nil
144
144
  end
145
145
 
146
- def parse_typhoeus_request(request)
147
- ob = {}
148
- ob[:Method] = request.options[:method].nil? ? :get : request.options[:method]
149
- ob[:URI] = request.base_url
150
- ob[:Body] = request.options[:body]
151
- ob[:Headers] = request.options[:headers]
152
- uri_parsed = parse_uri(request.base_url)
153
- if !uri_parsed.nil?
154
- ob[:scheme] = uri_parsed.scheme
155
- ob[:host] = uri_parsed.host
156
- ob[:port] = uri_parsed.port
157
- ob[:path] = uri_parsed.path
158
- ob[:query] = uri_parsed.query
159
- end
160
- ob
161
- end
162
-
163
146
  end
164
147
  end
165
148
  end
@@ -99,9 +99,9 @@ module NewRelic::Security
99
99
 
100
100
  alias_method :popen_without_security, :popen
101
101
 
102
- def popen(*var)
102
+ def popen(*var, &block)
103
103
  retval = nil
104
- event = popen_on_enter(*var) { retval = popen_without_security(*var) }
104
+ event = popen_on_enter(*var) { retval = popen_without_security(*var, &block) }
105
105
  popen_on_exit(event) { return retval }
106
106
  end
107
107
  end
@@ -75,7 +75,7 @@ module NewRelic::Security
75
75
  binwrite_on_exit(event, retval) { return retval }
76
76
  end
77
77
 
78
- def popen(*var)
78
+ def popen(*var, &block)
79
79
  retval = nil
80
80
  event = popen_on_enter(*var) { retval = super }
81
81
  popen_on_exit(event) { return retval }
@@ -13,30 +13,13 @@ module NewRelic::Security
13
13
  def transport_request_on_enter(req)
14
14
  event = nil
15
15
  NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
16
- ob = {}
17
- ob[:Method] = req.method
18
- if req.uri != nil && URI === req.uri
19
- uri = req.uri
20
- ob[:scheme] = uri.scheme
21
- ob[:host] = uri.host
22
- ob[:port] = uri.port
23
- ob[:URI] = uri.to_s
24
- ob[:path] = uri.path
25
- ob[:query] = uri.query
26
- else
27
- ob[:scheme] = self.use_ssl? ? HTTPS : HTTP
28
- ob[:host] = self.address
29
- ob[:port] = self.port
30
- ob[:path] = req.path
31
- ob[:query] = nil
32
- ob[:URI] = "#{self.use_ssl? ? HTTPS_COLON_SLASH_SLAH : HTTP_COLON_SLASH_SLAH }#{self.address}:#{self.port}#{req.path}"
33
- end
34
- ob[:Body] = req.body
35
- ob[:Headers] = req.to_hash.transform_values! { |v| v.join}
36
- ob.each { |_, value| value.dup.force_encoding(ISO_8859_1).encode(UTF_8) if value.is_a?(String) }
37
- event = NewRelic::Security::Agent::Control::Collector.collect(HTTP_REQUEST, [ob])
16
+ uri = if req.uri && URI === req.uri
17
+ req.uri.to_s
18
+ else
19
+ "#{self.use_ssl? ? HTTPS_COLON_SLASH_SLAH : HTTP_COLON_SLASH_SLAH }#{self.address}:#{self.port}#{req.path}"
20
+ end
21
+ event = NewRelic::Security::Agent::Control::Collector.collect(HTTP_REQUEST, [uri])
38
22
  NewRelic::Security::Instrumentation::InstrumentationUtils.add_tracing_data(req, event) if event
39
- ob = nil
40
23
  event
41
24
  rescue => exception
42
25
  NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
@@ -18,7 +18,7 @@ module NewRelic::Security
18
18
  # to know the capabilities of Ldap server. In these
19
19
  # situations they don't provide the query parameter, so we filter
20
20
  # this event
21
- NewRelic::Security::Agent.logger.info "Filtered #{self.class}.#{__method__} because of insufficient args. args : #{args}\n"
21
+ NewRelic::Security::Agent.logger.debug "Filtered #{self.class}.#{__method__} because of insufficient args. args : #{args}\n"
22
22
  end
23
23
  rescue => exception
24
24
  NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
@@ -8,6 +8,7 @@ module NewRelic::Security
8
8
  def call_on_enter(env)
9
9
  event = nil
10
10
  NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
11
+ return unless NewRelic::Security::Agent.config[:enabled]
11
12
  NewRelic::Security::Agent.config.update_port = NewRelic::Security::Agent::Utils.app_port(env) unless NewRelic::Security::Agent.config[:listen_port]
12
13
  NewRelic::Security::Agent::Utils.get_app_routes(:padrino, self) if NewRelic::Security::Agent.agent.route_map.empty?
13
14
  extracted_env = env.instance_variable_get(:@env)
@@ -7,25 +7,12 @@ module NewRelic::Security
7
7
  module Instrumentation
8
8
  module Patron::Session
9
9
 
10
- def request_on_enter(action, url, headers, options)
10
+ def request_on_enter(_action, url, headers, _options)
11
11
  event = nil
12
12
  NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
13
- ob = {}
14
- ob[:Method] = action
15
13
  final_url = self.base_url.nil? ? url : "#{self.base_url}#{url}"
16
14
  uri = NewRelic::Security::Instrumentation::InstrumentationUtils.parse_uri(final_url)
17
- if uri
18
- ob[:scheme] = uri.scheme
19
- ob[:host] = uri.host
20
- ob[:port] = uri.port
21
- ob[:URI] = uri.to_s
22
- ob[:path] = uri.path
23
- ob[:query] = uri.query
24
- ob[:Body] = options[:data]
25
- ob[:Headers] = headers
26
- ob.each { |_, value| value.dup.force_encoding(ISO_8859_1).encode(UTF_8) if value.is_a?(String) }
27
- event = NewRelic::Security::Agent::Control::Collector.collect(HTTP_REQUEST, [ob])
28
- end
15
+ event = NewRelic::Security::Agent::Control::Collector.collect(HTTP_REQUEST, [uri.to_s]) if uri
29
16
  NewRelic::Security::Instrumentation::InstrumentationUtils.add_tracing_data(headers, event) if event
30
17
  event
31
18
  rescue => exception
@@ -0,0 +1,24 @@
1
+ module NewRelic::Security
2
+ module Instrumentation
3
+ module Rack
4
+ module Builder
5
+ module Chain
6
+ def self.instrument!
7
+ ::Rack::Builder.class_eval do
8
+ include NewRelic::Security::Instrumentation::Rack::Builder
9
+
10
+ alias_method :call_without_security, :call
11
+
12
+ def call(env)
13
+ retval = nil
14
+ event = call_on_enter(env) { retval = call_without_security(env) }
15
+ call_on_exit(event, retval) { return retval }
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ end
24
+ end
@@ -0,0 +1,44 @@
1
+ require_relative 'prepend'
2
+ require_relative 'chain'
3
+
4
+ module NewRelic::Security
5
+ module Instrumentation
6
+ module Rack::Builder
7
+
8
+ def call_on_enter(env)
9
+ event = nil
10
+ NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
11
+ return unless NewRelic::Security::Agent.config[:enabled]
12
+ NewRelic::Security::Agent.config.update_port = NewRelic::Security::Agent::Utils.app_port(env) unless NewRelic::Security::Agent.config[:listen_port]
13
+ NewRelic::Security::Agent::Utils.get_app_routes(:rack) if NewRelic::Security::Agent.agent.route_map.empty?
14
+ NewRelic::Security::Agent::Control::HTTPContext.set_context(env)
15
+ ctxt = NewRelic::Security::Agent::Control::HTTPContext.get_context
16
+ ctxt.route = "#{env[REQUEST_METHOD]}@#{env[PATH_INFO]}" if ctxt
17
+ NewRelic::Security::Agent::Utils.parse_fuzz_header(NewRelic::Security::Agent::Control::HTTPContext.get_context)
18
+ rescue => exception
19
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
20
+ ensure
21
+ yield
22
+ return event
23
+ end
24
+
25
+ def call_on_exit(event, retval)
26
+ NewRelic::Security::Agent.logger.debug "OnExit : #{self.class}.#{__method__}"
27
+ # NewRelic::Security::Agent.logger.debug "\n\nHTTP Context : #{::NewRelic::Agent::Tracer.current_transaction.instance_variable_get(:@security_context_data).inspect}\n\n"
28
+ NewRelic::Security::Agent::Control::ReflectedXSS.check_xss(NewRelic::Security::Agent::Control::HTTPContext.get_context, retval) if NewRelic::Security::Agent.config[:'security.detection.rxss.enabled']
29
+ NewRelic::Security::Agent::Utils.delete_created_files(NewRelic::Security::Agent::Control::HTTPContext.get_context)
30
+ NewRelic::Security::Agent.agent.error_reporting&.report_unhandled_or_5xx_exceptions(NewRelic::Security::Agent::Control::HTTPContext.get_current_transaction, NewRelic::Security::Agent::Control::HTTPContext.get_context, retval[0])
31
+ NewRelic::Security::Agent::Control::HTTPContext.reset_context
32
+ NewRelic::Security::Agent.logger.debug "Exit event : #{event}"
33
+ rescue => exception
34
+ NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
35
+ ensure
36
+ yield
37
+ end
38
+
39
+ end
40
+
41
+ end
42
+ end
43
+
44
+ NewRelic::Security::Instrumentation::InstrumentationLoader.install_instrumentation(:rack, NewRelic::Security::Agent.config[:app_class].class, ::NewRelic::Security::Instrumentation::Rack::Builder) if NewRelic::Security::Agent.config[:framework] == :rack
@@ -0,0 +1,18 @@
1
+ module NewRelic::Security
2
+ module Instrumentation
3
+ module Rack
4
+ module Builder
5
+ module Prepend
6
+ include NewRelic::Security::Instrumentation::Rack::Builder
7
+
8
+ def call(env, &block)
9
+ retval = nil
10
+ event = call_on_enter(env) { retval = super }
11
+ call_on_exit(event, retval) { return retval }
12
+ end
13
+
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -8,6 +8,7 @@ module NewRelic::Security
8
8
  def call_on_enter(env)
9
9
  event = nil
10
10
  NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
11
+ return unless NewRelic::Security::Agent.config[:enabled]
11
12
  NewRelic::Security::Agent.config.update_port = NewRelic::Security::Agent::Utils.app_port(env) unless NewRelic::Security::Agent.config[:listen_port]
12
13
  NewRelic::Security::Agent::Utils.get_app_routes(:rails) if NewRelic::Security::Agent.agent.route_map.empty?
13
14
  NewRelic::Security::Agent::Control::HTTPContext.set_context(env)
@@ -8,6 +8,7 @@ module NewRelic::Security
8
8
  def _roda_handle_main_route_on_enter(env)
9
9
  event = nil
10
10
  NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
11
+ return unless NewRelic::Security::Agent.config[:enabled]
11
12
  NewRelic::Security::Agent.config.update_port = NewRelic::Security::Agent::Utils.app_port(env) unless NewRelic::Security::Agent.config[:listen_port]
12
13
  NewRelic::Security::Agent::Utils.get_app_routes(:roda) if NewRelic::Security::Agent.agent.route_map.empty?
13
14
  NewRelic::Security::Agent::Control::HTTPContext.set_context(env)
@@ -8,6 +8,7 @@ module NewRelic::Security
8
8
  def call_on_enter(env)
9
9
  event = nil
10
10
  NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
11
+ return unless NewRelic::Security::Agent.config[:enabled]
11
12
  NewRelic::Security::Agent.config.update_port = NewRelic::Security::Agent::Utils.app_port(env) unless NewRelic::Security::Agent.config[:listen_port]
12
13
  NewRelic::Security::Agent::Utils.get_app_routes(:sinatra) if NewRelic::Security::Agent.agent.route_map.empty?
13
14
  NewRelic::Security::Agent::Control::HTTPContext.set_context(env)
@@ -14,7 +14,7 @@ module NewRelic::Security
14
14
  # @api public
15
15
  #
16
16
  def is_security_active?
17
- NewRelic::Security::Agent.config[:'agent.enabled'] && NewRelic::Security::Agent.config[:enabled]
17
+ NewRelic::Security::Agent.config[:'agent.enabled'] && NewRelic::Security::Agent.config[:'security.enabled'] && NewRelic::Security::Agent.config[:enabled]
18
18
  end
19
19
 
20
20
  #