newrelic_security 0.1.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/pr_ci.yml +2 -2
- data/CHANGELOG.md +82 -0
- data/THIRD_PARTY_NOTICES.md +8 -0
- data/lib/newrelic_security/agent/agent.rb +24 -4
- data/lib/newrelic_security/agent/configuration/manager.rb +51 -8
- data/lib/newrelic_security/agent/control/app_info.rb +2 -0
- data/lib/newrelic_security/agent/control/application_runtime_error.rb +95 -0
- data/lib/newrelic_security/agent/control/application_url_mappings.rb +2 -0
- data/lib/newrelic_security/agent/control/collector.rb +34 -3
- data/lib/newrelic_security/agent/control/control_command.rb +2 -3
- data/lib/newrelic_security/agent/control/critical_message.rb +2 -0
- data/lib/newrelic_security/agent/control/error_reporting.rb +74 -0
- data/lib/newrelic_security/agent/control/event.rb +26 -4
- data/lib/newrelic_security/agent/control/event_processor.rb +26 -0
- data/lib/newrelic_security/agent/control/event_subscriber.rb +2 -8
- data/lib/newrelic_security/agent/control/exit_event.rb +2 -0
- data/lib/newrelic_security/agent/control/grpc_context.rb +2 -1
- data/lib/newrelic_security/agent/control/health_check.rb +5 -0
- data/lib/newrelic_security/agent/control/http_context.rb +16 -7
- data/lib/newrelic_security/agent/control/iast_client.rb +24 -11
- data/lib/newrelic_security/agent/control/iast_data_transfer_request.rb +2 -0
- data/lib/newrelic_security/agent/control/scan_scheduler.rb +77 -0
- data/lib/newrelic_security/agent/control/websocket_client.rb +23 -0
- data/lib/newrelic_security/agent/utils/agent_utils.rb +14 -9
- data/lib/newrelic_security/constants.rb +2 -2
- data/lib/newrelic_security/instrumentation-security/async-http/instrumentation.rb +2 -13
- data/lib/newrelic_security/instrumentation-security/curb/instrumentation.rb +1 -14
- data/lib/newrelic_security/instrumentation-security/ethon/chain.rb +0 -6
- data/lib/newrelic_security/instrumentation-security/ethon/instrumentation.rb +7 -42
- data/lib/newrelic_security/instrumentation-security/ethon/prepend.rb +0 -4
- data/lib/newrelic_security/instrumentation-security/excon/instrumentation.rb +3 -13
- data/lib/newrelic_security/instrumentation-security/grape/chain.rb +7 -2
- data/lib/newrelic_security/instrumentation-security/grape/instrumentation.rb +3 -1
- data/lib/newrelic_security/instrumentation-security/grape/prepend.rb +7 -1
- data/lib/newrelic_security/instrumentation-security/grpc/server/instrumentation.rb +3 -2
- data/lib/newrelic_security/instrumentation-security/httpclient/instrumentation.rb +4 -28
- data/lib/newrelic_security/instrumentation-security/httprb/instrumentation.rb +1 -12
- data/lib/newrelic_security/instrumentation-security/httpx/instrumentation.rb +1 -15
- data/lib/newrelic_security/instrumentation-security/instrumentation_utils.rb +0 -17
- data/lib/newrelic_security/instrumentation-security/net_http/instrumentation.rb +6 -23
- data/lib/newrelic_security/instrumentation-security/net_ldap/instrumentation.rb +1 -1
- data/lib/newrelic_security/instrumentation-security/padrino/chain.rb +17 -0
- data/lib/newrelic_security/instrumentation-security/padrino/instrumentation.rb +15 -2
- data/lib/newrelic_security/instrumentation-security/padrino/prepend.rb +12 -0
- data/lib/newrelic_security/instrumentation-security/patron/instrumentation.rb +2 -15
- data/lib/newrelic_security/instrumentation-security/rails/chain.rb +26 -2
- data/lib/newrelic_security/instrumentation-security/rails/instrumentation.rb +29 -3
- data/lib/newrelic_security/instrumentation-security/rails/prepend.rb +18 -0
- data/lib/newrelic_security/instrumentation-security/roda/chain.rb +7 -2
- data/lib/newrelic_security/instrumentation-security/roda/instrumentation.rb +3 -1
- data/lib/newrelic_security/instrumentation-security/roda/prepend.rb +7 -1
- data/lib/newrelic_security/instrumentation-security/sinatra/chain.rb +6 -0
- data/lib/newrelic_security/instrumentation-security/sinatra/instrumentation.rb +9 -0
- data/lib/newrelic_security/instrumentation-security/sinatra/prepend.rb +4 -0
- data/lib/newrelic_security/instrumentation-security/sqlite3/instrumentation.rb +4 -4
- data/lib/newrelic_security/newrelic-security-api/api.rb +1 -1
- data/lib/newrelic_security/parse-cron/cron_parser.rb +294 -0
- data/lib/newrelic_security/version.rb +1 -1
- data/newrelic_security.gemspec +1 -1
- metadata +8 -4
@@ -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[
|
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(*
|
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[
|
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
|
-
|
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
|
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(*
|
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(
|
8
|
+
def request_on_enter(_params)
|
9
9
|
event = nil
|
10
10
|
NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
|
11
|
-
|
12
|
-
|
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
|
@@ -12,10 +12,15 @@ module NewRelic::Security
|
|
12
12
|
|
13
13
|
def call(env)
|
14
14
|
retval = nil
|
15
|
-
event = call_on_enter(env)
|
15
|
+
event = call_on_enter(env) do
|
16
|
+
begin
|
17
|
+
retval = call_without_security(env)
|
18
|
+
ensure
|
19
|
+
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, nil)
|
20
|
+
end
|
21
|
+
end
|
16
22
|
call_on_exit(event, retval) { return retval }
|
17
23
|
end
|
18
|
-
|
19
24
|
end
|
20
25
|
end
|
21
26
|
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(:grape) if NewRelic::Security::Agent.agent.route_map.empty?
|
13
14
|
NewRelic::Security::Agent::Control::HTTPContext.set_context(env)
|
@@ -24,6 +25,7 @@ module NewRelic::Security
|
|
24
25
|
# NewRelic::Security::Agent.logger.debug "\n\nHTTP Context : #{::NewRelic::Agent::Tracer.current_transaction.instance_variable_get(:@security_context_data).inspect}\n\n"
|
25
26
|
NewRelic::Security::Agent::Control::ReflectedXSS.check_xss(NewRelic::Security::Agent::Control::HTTPContext.get_context, retval) if NewRelic::Security::Agent.config[:'security.detection.rxss.enabled']
|
26
27
|
NewRelic::Security::Agent::Utils.delete_created_files(NewRelic::Security::Agent::Control::HTTPContext.get_context)
|
28
|
+
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])
|
27
29
|
NewRelic::Security::Agent::Control::HTTPContext.reset_context
|
28
30
|
NewRelic::Security::Agent.logger.debug "Exit event : #{event}"
|
29
31
|
rescue => exception
|
@@ -40,7 +42,7 @@ module NewRelic::Security
|
|
40
42
|
def prepare_env_from_route_on_enter(route)
|
41
43
|
NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
|
42
44
|
ctxt = NewRelic::Security::Agent::Control::HTTPContext.get_context
|
43
|
-
http_method = route.instance_variable_get(:@request_method)
|
45
|
+
http_method = route.instance_variable_get(:@request_method) || route.instance_variable_get(:@options)[:method]
|
44
46
|
ctxt.route = "#{http_method}@#{route.options[:namespace]}" unless ctxt.nil?
|
45
47
|
rescue => exception
|
46
48
|
NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
|
@@ -8,7 +8,13 @@ module NewRelic::Security
|
|
8
8
|
|
9
9
|
def call(env)
|
10
10
|
retval = nil
|
11
|
-
event = call_on_enter(env)
|
11
|
+
event = call_on_enter(env) do
|
12
|
+
begin
|
13
|
+
retval = super(env)
|
14
|
+
ensure
|
15
|
+
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, nil)
|
16
|
+
end
|
17
|
+
end
|
12
18
|
call_on_exit(event, retval) { return retval }
|
13
19
|
end
|
14
20
|
|
@@ -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,
|
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
|
-
|
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
|
-
|
12
|
-
|
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
|
-
|
47
|
-
|
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
|
-
|
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
|
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
|
@@ -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
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
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.
|
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}"
|
@@ -21,6 +21,23 @@ module NewRelic::Security
|
|
21
21
|
end
|
22
22
|
end
|
23
23
|
end
|
24
|
+
|
25
|
+
module Router
|
26
|
+
module Chain
|
27
|
+
def self.instrument!
|
28
|
+
::Padrino::Router.class_eval do
|
29
|
+
include NewRelic::Security::Instrumentation::Padrino::Router
|
30
|
+
|
31
|
+
alias_method :call_without_security, :call
|
32
|
+
|
33
|
+
def call(env, &block)
|
34
|
+
retval = call_without_security(env, &block)
|
35
|
+
call_on_exit(retval) { return retval }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
24
41
|
end
|
25
42
|
end
|
26
43
|
end
|
@@ -8,12 +8,13 @@ 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)
|
14
15
|
NewRelic::Security::Agent::Control::HTTPContext.set_context(extracted_env)
|
15
16
|
ctxt = NewRelic::Security::Agent::Control::HTTPContext.get_context
|
16
|
-
ctxt.route = "#{extracted_env[REQUEST_METHOD]
|
17
|
+
ctxt.route = "#{extracted_env[REQUEST_METHOD]}@#{extracted_env[PATH_INFO]}" if ctxt
|
17
18
|
NewRelic::Security::Agent::Utils.parse_fuzz_header(NewRelic::Security::Agent::Control::HTTPContext.get_context)
|
18
19
|
rescue => exception
|
19
20
|
NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
|
@@ -27,6 +28,7 @@ module NewRelic::Security
|
|
27
28
|
# NewRelic::Security::Agent.logger.debug "\n\nHTTP Context : #{::NewRelic::Agent::Tracer.current_transaction.instance_variable_get(:@security_context_data).inspect}\n\n"
|
28
29
|
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
30
|
NewRelic::Security::Agent::Utils.delete_created_files(NewRelic::Security::Agent::Control::HTTPContext.get_context)
|
31
|
+
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])
|
30
32
|
NewRelic::Security::Agent::Control::HTTPContext.reset_context
|
31
33
|
NewRelic::Security::Agent.logger.debug "Exit event : #{event}"
|
32
34
|
rescue => exception
|
@@ -34,9 +36,20 @@ module NewRelic::Security
|
|
34
36
|
ensure
|
35
37
|
yield
|
36
38
|
end
|
37
|
-
|
39
|
+
end
|
40
|
+
|
41
|
+
module Padrino::Router
|
42
|
+
def call_on_exit(retval)
|
43
|
+
NewRelic::Security::Agent.logger.debug "OnExit : #{self.class}.#{__method__}"
|
44
|
+
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])
|
45
|
+
rescue => exception
|
46
|
+
NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
|
47
|
+
ensure
|
48
|
+
yield
|
49
|
+
end
|
38
50
|
end
|
39
51
|
end
|
40
52
|
end
|
41
53
|
|
42
54
|
NewRelic::Security::Instrumentation::InstrumentationLoader.install_instrumentation(:padrino, ::Padrino::PathRouter::Router, ::NewRelic::Security::Instrumentation::Padrino::PathRouter::Router)
|
55
|
+
NewRelic::Security::Instrumentation::InstrumentationLoader.install_instrumentation(:padrino, ::Padrino::Router, ::NewRelic::Security::Instrumentation::Padrino::Router)
|
@@ -15,6 +15,18 @@ module NewRelic::Security
|
|
15
15
|
end
|
16
16
|
end
|
17
17
|
end
|
18
|
+
|
19
|
+
module Router
|
20
|
+
module Prepend
|
21
|
+
include NewRelic::Security::Instrumentation::Padrino::Router
|
22
|
+
|
23
|
+
def call(env, &block)
|
24
|
+
retval = super
|
25
|
+
call_on_exit(retval) { return retval }
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
18
30
|
end
|
19
31
|
end
|
20
32
|
end
|
@@ -7,25 +7,12 @@ module NewRelic::Security
|
|
7
7
|
module Instrumentation
|
8
8
|
module Patron::Session
|
9
9
|
|
10
|
-
def request_on_enter(
|
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
|
@@ -29,12 +29,36 @@ module NewRelic::Security
|
|
29
29
|
include NewRelic::Security::Instrumentation::ActionDispatch::Journey::Router
|
30
30
|
|
31
31
|
alias_method :find_routes_without_security, :find_routes
|
32
|
-
|
32
|
+
|
33
33
|
def find_routes(req)
|
34
34
|
retval = nil
|
35
35
|
event = find_routes_on_enter(req) { retval = find_routes_without_security(req) }
|
36
36
|
find_routes_on_exit(event, retval) { return retval }
|
37
|
-
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
module ActionDispatch
|
46
|
+
module Routing
|
47
|
+
module RouteSet
|
48
|
+
module Dispatcher
|
49
|
+
module Chain
|
50
|
+
def self.instrument!
|
51
|
+
::ActionDispatch::Routing::RouteSet::Dispatcher.class_eval do
|
52
|
+
include NewRelic::Security::Instrumentation::ActionDispatch::Routing::RouteSet::Dispatcher
|
53
|
+
|
54
|
+
alias_method :serve_without_security, :serve
|
55
|
+
|
56
|
+
def serve(req)
|
57
|
+
retval = nil
|
58
|
+
event = serve_on_enter(req) { retval = serve_without_security(req) }
|
59
|
+
serve_on_exit(event, retval) { return retval }
|
60
|
+
end
|
61
|
+
end
|
38
62
|
end
|
39
63
|
end
|
40
64
|
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)
|
@@ -24,6 +25,7 @@ module NewRelic::Security
|
|
24
25
|
# NewRelic::Security::Agent.logger.debug "\n\nHTTP Context : #{::NewRelic::Agent::Tracer.current_transaction.instance_variable_get(:@security_context_data).inspect}\n\n"
|
25
26
|
NewRelic::Security::Agent::Control::ReflectedXSS.check_xss(NewRelic::Security::Agent::Control::HTTPContext.get_context, retval) if NewRelic::Security::Agent.config[:'security.detection.rxss.enabled']
|
26
27
|
NewRelic::Security::Agent::Utils.delete_created_files(NewRelic::Security::Agent::Control::HTTPContext.get_context)
|
28
|
+
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])
|
27
29
|
NewRelic::Security::Agent::Control::HTTPContext.reset_context
|
28
30
|
NewRelic::Security::Agent.logger.debug "Exit event : #{event}"
|
29
31
|
rescue => exception
|
@@ -31,11 +33,11 @@ module NewRelic::Security
|
|
31
33
|
ensure
|
32
34
|
yield
|
33
35
|
end
|
34
|
-
|
36
|
+
|
35
37
|
end
|
36
38
|
|
37
39
|
module ActionDispatch::Journey::Router
|
38
|
-
|
40
|
+
|
39
41
|
def find_routes_on_enter(req)
|
40
42
|
event = nil
|
41
43
|
NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
|
@@ -45,7 +47,7 @@ module NewRelic::Security
|
|
45
47
|
yield
|
46
48
|
return event
|
47
49
|
end
|
48
|
-
|
50
|
+
|
49
51
|
def find_routes_on_exit(event, retval)
|
50
52
|
NewRelic::Security::Agent.logger.debug "OnExit : #{self.class}.#{__method__}"
|
51
53
|
|
@@ -60,8 +62,32 @@ module NewRelic::Security
|
|
60
62
|
yield
|
61
63
|
end
|
62
64
|
end
|
65
|
+
|
66
|
+
module ActionDispatch::Routing::RouteSet::Dispatcher
|
67
|
+
|
68
|
+
def serve_on_enter(req)
|
69
|
+
event = nil
|
70
|
+
NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
|
71
|
+
ctxt = NewRelic::Security::Agent::Control::HTTPContext.get_context
|
72
|
+
ctxt.route = "#{ctxt.method}@#{req.route_uri_pattern.to_s.gsub(/\(\.:format\)/, EMPTY_STRING)}" if ctxt && req.respond_to?(:route_uri_pattern)
|
73
|
+
rescue => exception
|
74
|
+
NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
|
75
|
+
ensure
|
76
|
+
yield
|
77
|
+
return event
|
78
|
+
end
|
79
|
+
|
80
|
+
def serve_on_exit(event, retval)
|
81
|
+
NewRelic::Security::Agent.logger.debug "OnExit : #{self.class}.#{__method__}"
|
82
|
+
rescue => exception
|
83
|
+
NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
|
84
|
+
ensure
|
85
|
+
yield
|
86
|
+
end
|
87
|
+
end
|
63
88
|
end
|
64
89
|
end
|
65
90
|
|
66
91
|
NewRelic::Security::Instrumentation::InstrumentationLoader.install_instrumentation(:rails, ::Rails::Engine, ::NewRelic::Security::Instrumentation::Rails::Engine)
|
67
92
|
NewRelic::Security::Instrumentation::InstrumentationLoader.install_instrumentation(:rails, ::ActionDispatch::Journey::Router, ::NewRelic::Security::Instrumentation::ActionDispatch::Journey::Router)
|
93
|
+
NewRelic::Security::Instrumentation::InstrumentationLoader.install_instrumentation(:rails, ::ActionDispatch::Routing::RouteSet::Dispatcher, ::NewRelic::Security::Instrumentation::ActionDispatch::Routing::RouteSet::Dispatcher)
|
@@ -29,5 +29,23 @@ module NewRelic::Security
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
end
|
32
|
+
|
33
|
+
module ActionDispatch
|
34
|
+
module Routing
|
35
|
+
module RouteSet
|
36
|
+
module Dispatcher
|
37
|
+
module Prepend
|
38
|
+
include NewRelic::Security::Instrumentation::ActionDispatch::Routing::RouteSet::Dispatcher
|
39
|
+
|
40
|
+
def serve(req)
|
41
|
+
retval = nil
|
42
|
+
event = serve_on_enter(req) { retval = super }
|
43
|
+
serve_on_exit(event, retval) { return retval }
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
32
50
|
end
|
33
51
|
end
|
@@ -10,10 +10,15 @@ module NewRelic::Security
|
|
10
10
|
|
11
11
|
def _roda_handle_main_route(*args)
|
12
12
|
retval = nil
|
13
|
-
event = _roda_handle_main_route_on_enter(
|
13
|
+
event = _roda_handle_main_route_on_enter(env) do
|
14
|
+
begin
|
15
|
+
retval = _roda_handle_main_route_without_security(*args)
|
16
|
+
ensure
|
17
|
+
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, nil)
|
18
|
+
end
|
19
|
+
end
|
14
20
|
_roda_handle_main_route_on_exit(event, retval) { return retval }
|
15
21
|
end
|
16
|
-
|
17
22
|
end
|
18
23
|
end
|
19
24
|
end
|