Skip to content

Commit

Permalink
add support for async-http http client
Browse files Browse the repository at this point in the history
  • Loading branch information
prateeksen committed Jan 12, 2024
1 parent 6633f52 commit 04835d9
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 1 deletion.
21 changes: 21 additions & 0 deletions lib/newrelic_security/instrumentation-security/async-http/chain.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
module NewRelic::Security
module Instrumentation
module AsyncHttp
module Chain
def self.instrument!
::Async::HTTP::Internet.class_eval do
include NewRelic::Security::Instrumentation::AsyncHttp

alias_method :call_without_security, :call

def call(method, url, headers = nil, body = nil)
retval = nil
event = call_on_enter(method, url, headers = nil, body = nil) { retval = call_without_security(method, url, headers, body) }
call_on_exit(event) { return retval }
end
end
end
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
require_relative 'prepend'
require_relative 'chain'
require 'uri'

module NewRelic::Security
module Instrumentation
module AsyncHttp

def call_on_enter(method, url, headers, body)
event = nil
NewRelic::Security::Agent.logger.debug "OnEnter : #{self.class}.#{__method__}"
ob = {}
ob[:Method] = method
uri = ::URI.parse url
ob[:scheme] = uri.scheme
ob[:host] = uri.host
ob[:port] = uri.port
ob[:URI] = uri.to_s
ob[:path] = uri.path
ob[:query] = uri.query
ob[:Body] = body.respond_to?(:join) ? body.join.to_s : body.to_s
ob[:Headers] = headers.to_h
ob.each { |_, value| value.dup.force_encoding(ISO_8859_1).encode(UTF_8) if value.is_a?(String) }
event = NewRelic::Security::Agent::Control::Collector.collect(HTTP_REQUEST, [ob])
NewRelic::Security::Instrumentation::InstrumentationUtils.append_tracing_data(headers, event) if event
event
rescue => exception
NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
ensure
yield
return event
end

def call_on_exit(event)
NewRelic::Security::Agent.logger.debug "OnExit : #{self.class}.#{__method__}"
NewRelic::Security::Agent::Utils.create_exit_event(event)
rescue => exception
NewRelic::Security::Agent.logger.error "Exception in hook in #{self.class}.#{__method__}, #{exception.inspect}, #{exception.backtrace}"
ensure
yield
end
end
end
end

NewRelic::Security::Instrumentation::InstrumentationLoader.install_instrumentation(:async_http, ::Async::HTTP::Internet, ::NewRelic::Security::Instrumentation::AsyncHttp)
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
module NewRelic::Security
module Instrumentation
module AsyncHttp
module Prepend
include NewRelic::Security::Instrumentation::AsyncHttp

def call(method, url, headers = nil, body = nil)
retval = nil
event = call_on_enter(method, url, headers, body) { retval = super }
call_on_exit(event) { return retval }
end

end
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,12 @@ def read_filter?(fname, abs_path)

def add_tracing_data(req, event)
req[NR_CSEC_TRACING_DATA] = "#{event.httpRequest[:headers][NR_CSEC_TRACING_DATA]} #{NewRelic::Security::Agent.config[:uuid]}/#{event.apiId}/#{event.id};"
req[NR_CSEC_FUZZ_REQUEST_ID] = event.httpRequest[:headers][NR_CSEC_FUZZ_REQUEST_ID] unless event.httpRequest[:headers][NR_CSEC_FUZZ_REQUEST_ID]
req[NR_CSEC_FUZZ_REQUEST_ID] = event.httpRequest[:headers][NR_CSEC_FUZZ_REQUEST_ID] if event.httpRequest[:headers][NR_CSEC_FUZZ_REQUEST_ID]
end

def append_tracing_data(req, event)
req.append([NR_CSEC_TRACING_DATA, "#{event.httpRequest[:headers][NR_CSEC_TRACING_DATA]} #{NewRelic::Security::Agent.config[:uuid]}/#{event.apiId}/#{event.id};"])
req.append([NR_CSEC_FUZZ_REQUEST_ID, event.httpRequest[:headers][NR_CSEC_FUZZ_REQUEST_ID]]) if event.httpRequest[:headers][NR_CSEC_FUZZ_REQUEST_ID]
end

end
Expand Down

0 comments on commit 04835d9

Please sign in to comment.