newrelic_security 0.2.0 → 0.4.0

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