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.
- checksums.yaml +4 -4
- data/.github/workflows/pr_ci.yml +4 -4
- data/.github/workflows/release.yml +1 -1
- data/.github/workflows/rubocop.yml +1 -1
- data/CHANGELOG.md +90 -1
- data/Gemfile_test +3 -0
- data/README.md +1 -0
- data/THIRD_PARTY_NOTICES.md +8 -0
- data/lib/newrelic_security/agent/agent.rb +22 -4
- data/lib/newrelic_security/agent/configuration/manager.rb +65 -7
- data/lib/newrelic_security/agent/control/application_runtime_error.rb +1 -1
- data/lib/newrelic_security/agent/control/collector.rb +41 -4
- data/lib/newrelic_security/agent/control/control_command.rb +2 -3
- data/lib/newrelic_security/agent/control/error_reporting.rb +8 -6
- data/lib/newrelic_security/agent/control/event.rb +15 -1
- data/lib/newrelic_security/agent/control/event_processor.rb +25 -14
- data/lib/newrelic_security/agent/control/event_subscriber.rb +6 -8
- data/lib/newrelic_security/agent/control/health_check.rb +4 -0
- data/lib/newrelic_security/agent/control/http_context.rb +10 -6
- data/lib/newrelic_security/agent/control/iast_client.rb +24 -11
- data/lib/newrelic_security/agent/control/reflected_xss.rb +3 -4
- data/lib/newrelic_security/agent/control/scan_scheduler.rb +77 -0
- data/lib/newrelic_security/agent/control/websocket_client.rb +71 -16
- data/lib/newrelic_security/agent/utils/agent_utils.rb +25 -17
- data/lib/newrelic_security/constants.rb +1 -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/instrumentation.rb +1 -0
- data/lib/newrelic_security/instrumentation-security/graphql/chain.rb +26 -0
- data/lib/newrelic_security/instrumentation-security/graphql/instrumentation.rb +28 -0
- data/lib/newrelic_security/instrumentation-security/graphql/prepend.rb +18 -0
- 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/io/chain.rb +2 -2
- data/lib/newrelic_security/instrumentation-security/io/prepend.rb +1 -1
- 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/instrumentation.rb +1 -0
- data/lib/newrelic_security/instrumentation-security/patron/instrumentation.rb +2 -15
- data/lib/newrelic_security/instrumentation-security/rack/chain.rb +24 -0
- data/lib/newrelic_security/instrumentation-security/rack/instrumentation.rb +44 -0
- data/lib/newrelic_security/instrumentation-security/rack/prepend.rb +18 -0
- data/lib/newrelic_security/instrumentation-security/rails/instrumentation.rb +1 -0
- data/lib/newrelic_security/instrumentation-security/roda/instrumentation.rb +1 -0
- data/lib/newrelic_security/instrumentation-security/sinatra/instrumentation.rb +1 -0
- 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/lib/newrelic_security/websocket-client-simple/client.rb +5 -1
- data/newrelic_security.gemspec +1 -1
- 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
|
-
|
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[
|
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
|
@@ -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,
|
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
|
@@ -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
|
@@ -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}"
|
@@ -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(
|
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
|
#
|