newrelic_security 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.github/ISSUE_TEMPLATE/bug_report.md +38 -0
- data/.github/ISSUE_TEMPLATE/enhancement.md +27 -0
- data/.github/actions/simplecov-report/LICENSE +22 -0
- data/.github/actions/simplecov-report/README.md +36 -0
- data/.github/actions/simplecov-report/__tests__/.keep +0 -0
- data/.github/actions/simplecov-report/__tests__/main.test.ts +3 -0
- data/.github/actions/simplecov-report/action.yml +25 -0
- data/.github/actions/simplecov-report/dist/index.js +10238 -0
- data/.github/actions/simplecov-report/dummy_coverage/.last_run.json +5 -0
- data/.github/actions/simplecov-report/jest.config.js +11 -0
- data/.github/actions/simplecov-report/package.json +51 -0
- data/.github/actions/simplecov-report/src/main.ts +54 -0
- data/.github/actions/simplecov-report/src/report.ts +28 -0
- data/.github/actions/simplecov-report/tsconfig.json +12 -0
- data/.github/workflows/pr_ci.yml +77 -0
- data/.github/workflows/release.yml +51 -0
- data/.github/workflows/repolinter.yml +31 -0
- data/.github/workflows/rubocop.yml +17 -0
- data/.github/workflows/scripts/rubygems-authenticate.py +13 -0
- data/.github/workflows/scripts/rubygems-publish.rb +33 -0
- data/.gitignore +72 -0
- data/.rubocop.yml +9 -0
- data/.rubocop_todo.yml +1414 -0
- data/.simplecov +16 -0
- data/CHANGELOG.md +69 -0
- data/CONTRIBUTING.md +22 -0
- data/Gemfile +6 -0
- data/Gemfile_test +58 -0
- data/LICENSE +43 -0
- data/README.md +133 -0
- data/README_agent.md +44 -0
- data/Rakefile +28 -0
- data/THIRD_PARTY_NOTICES.md +36 -0
- data/lib/newrelic_security/agent/agent.rb +109 -0
- data/lib/newrelic_security/agent/configuration/default_source.rb +8 -0
- data/lib/newrelic_security/agent/configuration/environment_source.rb +8 -0
- data/lib/newrelic_security/agent/configuration/manager.rb +178 -0
- data/lib/newrelic_security/agent/configuration/manual_source.rb +8 -0
- data/lib/newrelic_security/agent/configuration/server_source.rb +8 -0
- data/lib/newrelic_security/agent/configuration/yaml_source.rb +8 -0
- data/lib/newrelic_security/agent/control/app_info.rb +132 -0
- data/lib/newrelic_security/agent/control/application_url_mappings.rb +66 -0
- data/lib/newrelic_security/agent/control/collector.rb +117 -0
- data/lib/newrelic_security/agent/control/control_command.rb +117 -0
- data/lib/newrelic_security/agent/control/critical_message.rb +58 -0
- data/lib/newrelic_security/agent/control/event.rb +149 -0
- data/lib/newrelic_security/agent/control/event_counter.rb +28 -0
- data/lib/newrelic_security/agent/control/event_processor.rb +134 -0
- data/lib/newrelic_security/agent/control/event_stats.rb +26 -0
- data/lib/newrelic_security/agent/control/event_subscriber.rb +28 -0
- data/lib/newrelic_security/agent/control/exit_event.rb +38 -0
- data/lib/newrelic_security/agent/control/fuzz_request.rb +18 -0
- data/lib/newrelic_security/agent/control/grpc_context.rb +57 -0
- data/lib/newrelic_security/agent/control/health_check.rb +136 -0
- data/lib/newrelic_security/agent/control/http_context.rb +73 -0
- data/lib/newrelic_security/agent/control/iast_client.rb +151 -0
- data/lib/newrelic_security/agent/control/iast_data_transfer_request.rb +32 -0
- data/lib/newrelic_security/agent/control/reflected_xss.rb +258 -0
- data/lib/newrelic_security/agent/control/websocket_client.rb +131 -0
- data/lib/newrelic_security/agent/logging/init_logger.rb +91 -0
- data/lib/newrelic_security/agent/logging/logger.rb +92 -0
- data/lib/newrelic_security/agent/logging/null_logger.rb +21 -0
- data/lib/newrelic_security/agent/resources/cert.pem +50 -0
- data/lib/newrelic_security/agent/utils/agent_utils.rb +219 -0
- data/lib/newrelic_security/agent.rb +57 -0
- data/lib/newrelic_security/constants.rb +67 -0
- data/lib/newrelic_security/instrumentation-security/active_record/mysql2_adapter/chain.rb +70 -0
- data/lib/newrelic_security/instrumentation-security/active_record/mysql2_adapter/instrumentation.rb +187 -0
- data/lib/newrelic_security/instrumentation-security/active_record/mysql2_adapter/prepend.rb +54 -0
- data/lib/newrelic_security/instrumentation-security/active_record/postgresql_adapter/chain.rb +60 -0
- data/lib/newrelic_security/instrumentation-security/active_record/postgresql_adapter/instrumentation.rb +143 -0
- data/lib/newrelic_security/instrumentation-security/active_record/postgresql_adapter/prepend.rb +48 -0
- data/lib/newrelic_security/instrumentation-security/active_record/sqlite3_adapter/chain.rb +72 -0
- data/lib/newrelic_security/instrumentation-security/active_record/sqlite3_adapter/instrumentation.rb +187 -0
- data/lib/newrelic_security/instrumentation-security/active_record/sqlite3_adapter/prepend.rb +54 -0
- data/lib/newrelic_security/instrumentation-security/async-http/chain.rb +21 -0
- data/lib/newrelic_security/instrumentation-security/async-http/instrumentation.rb +46 -0
- data/lib/newrelic_security/instrumentation-security/async-http/prepend.rb +16 -0
- data/lib/newrelic_security/instrumentation-security/curb/chain.rb +26 -0
- data/lib/newrelic_security/instrumentation-security/curb/instrumentation.rb +52 -0
- data/lib/newrelic_security/instrumentation-security/curb/prepend.rb +18 -0
- data/lib/newrelic_security/instrumentation-security/dir/chain.rb +42 -0
- data/lib/newrelic_security/instrumentation-security/dir/instrumentation.rb +102 -0
- data/lib/newrelic_security/instrumentation-security/dir/prepend.rb +28 -0
- data/lib/newrelic_security/instrumentation-security/ethon/chain.rb +53 -0
- data/lib/newrelic_security/instrumentation-security/ethon/instrumentation.rb +122 -0
- data/lib/newrelic_security/instrumentation-security/ethon/prepend.rb +39 -0
- data/lib/newrelic_security/instrumentation-security/excon/chain.rb +23 -0
- data/lib/newrelic_security/instrumentation-security/excon/instrumentation.rb +44 -0
- data/lib/newrelic_security/instrumentation-security/excon/prepend.rb +17 -0
- data/lib/newrelic_security/instrumentation-security/file/chain.rb +34 -0
- data/lib/newrelic_security/instrumentation-security/file/instrumentation.rb +62 -0
- data/lib/newrelic_security/instrumentation-security/file/prepend.rb +22 -0
- data/lib/newrelic_security/instrumentation-security/grape/chain.rb +42 -0
- data/lib/newrelic_security/instrumentation-security/grape/instrumentation.rb +56 -0
- data/lib/newrelic_security/instrumentation-security/grape/prepend.rb +30 -0
- data/lib/newrelic_security/instrumentation-security/grpc/client/chain.rb +47 -0
- data/lib/newrelic_security/instrumentation-security/grpc/client/instrumentation.rb +37 -0
- data/lib/newrelic_security/instrumentation-security/grpc/client/prepend.rb +36 -0
- data/lib/newrelic_security/instrumentation-security/grpc/server/chain.rb +62 -0
- data/lib/newrelic_security/instrumentation-security/grpc/server/instrumentation.rb +65 -0
- data/lib/newrelic_security/instrumentation-security/grpc/server/prepend.rb +46 -0
- data/lib/newrelic_security/instrumentation-security/httpclient/chain.rb +30 -0
- data/lib/newrelic_security/instrumentation-security/httpclient/instrumentation.rb +82 -0
- data/lib/newrelic_security/instrumentation-security/httpclient/prepend.rb +22 -0
- data/lib/newrelic_security/instrumentation-security/httprb/chain.rb +21 -0
- data/lib/newrelic_security/instrumentation-security/httprb/instrumentation.rb +44 -0
- data/lib/newrelic_security/instrumentation-security/httprb/prepend.rb +16 -0
- data/lib/newrelic_security/instrumentation-security/httpx/chain.rb +23 -0
- data/lib/newrelic_security/instrumentation-security/httpx/instrumentation.rb +51 -0
- data/lib/newrelic_security/instrumentation-security/httpx/prepend.rb +18 -0
- data/lib/newrelic_security/instrumentation-security/instrumentation_loader.rb +50 -0
- data/lib/newrelic_security/instrumentation-security/instrumentation_utils.rb +165 -0
- data/lib/newrelic_security/instrumentation-security/io/chain.rb +113 -0
- data/lib/newrelic_security/instrumentation-security/io/instrumentation.rb +300 -0
- data/lib/newrelic_security/instrumentation-security/io/prepend.rb +86 -0
- data/lib/newrelic_security/instrumentation-security/kernel/chain.rb +65 -0
- data/lib/newrelic_security/instrumentation-security/kernel/instrumentation.rb +167 -0
- data/lib/newrelic_security/instrumentation-security/kernel/prepend.rb +50 -0
- data/lib/newrelic_security/instrumentation-security/mongo/chain.rb +106 -0
- data/lib/newrelic_security/instrumentation-security/mongo/instrumentation.rb +273 -0
- data/lib/newrelic_security/instrumentation-security/mongo/prepend.rb +77 -0
- data/lib/newrelic_security/instrumentation-security/mysql2/chain.rb +53 -0
- data/lib/newrelic_security/instrumentation-security/mysql2/instrumentation.rb +84 -0
- data/lib/newrelic_security/instrumentation-security/mysql2/prepend.rb +37 -0
- data/lib/newrelic_security/instrumentation-security/net_http/chain.rb +21 -0
- data/lib/newrelic_security/instrumentation-security/net_http/instrumentation.rb +60 -0
- data/lib/newrelic_security/instrumentation-security/net_http/prepend.rb +16 -0
- data/lib/newrelic_security/instrumentation-security/net_ldap/chain.rb +21 -0
- data/lib/newrelic_security/instrumentation-security/net_ldap/instrumentation.rb +42 -0
- data/lib/newrelic_security/instrumentation-security/net_ldap/prepend.rb +16 -0
- data/lib/newrelic_security/instrumentation-security/nokogiri/chain.rb +46 -0
- data/lib/newrelic_security/instrumentation-security/nokogiri/instrumentation.rb +36 -0
- data/lib/newrelic_security/instrumentation-security/nokogiri/prepend.rb +31 -0
- data/lib/newrelic_security/instrumentation-security/padrino/chain.rb +26 -0
- data/lib/newrelic_security/instrumentation-security/padrino/instrumentation.rb +42 -0
- data/lib/newrelic_security/instrumentation-security/padrino/prepend.rb +20 -0
- data/lib/newrelic_security/instrumentation-security/patron/chain.rb +23 -0
- data/lib/newrelic_security/instrumentation-security/patron/instrumentation.rb +50 -0
- data/lib/newrelic_security/instrumentation-security/patron/prepend.rb +18 -0
- data/lib/newrelic_security/instrumentation-security/pg/chain.rb +49 -0
- data/lib/newrelic_security/instrumentation-security/pg/instrumentation.rb +102 -0
- data/lib/newrelic_security/instrumentation-security/pg/prepend.rb +36 -0
- data/lib/newrelic_security/instrumentation-security/pty/chain.rb +31 -0
- data/lib/newrelic_security/instrumentation-security/pty/instrumentation.rb +52 -0
- data/lib/newrelic_security/instrumentation-security/pty/prepend.rb +22 -0
- data/lib/newrelic_security/instrumentation-security/rails/chain.rb +46 -0
- data/lib/newrelic_security/instrumentation-security/rails/instrumentation.rb +67 -0
- data/lib/newrelic_security/instrumentation-security/rails/prepend.rb +33 -0
- data/lib/newrelic_security/instrumentation-security/roda/chain.rb +22 -0
- data/lib/newrelic_security/instrumentation-security/roda/instrumentation.rb +41 -0
- data/lib/newrelic_security/instrumentation-security/roda/prepend.rb +16 -0
- data/lib/newrelic_security/instrumentation-security/sinatra/chain.rb +29 -0
- data/lib/newrelic_security/instrumentation-security/sinatra/instrumentation.rb +49 -0
- data/lib/newrelic_security/instrumentation-security/sinatra/prepend.rb +21 -0
- data/lib/newrelic_security/instrumentation-security/sqlite3/chain.rb +79 -0
- data/lib/newrelic_security/instrumentation-security/sqlite3/instrumentation.rb +164 -0
- data/lib/newrelic_security/instrumentation-security/sqlite3/prepend.rb +56 -0
- data/lib/newrelic_security/newrelic-security-api/api.rb +72 -0
- data/lib/newrelic_security/version.rb +5 -0
- data/lib/newrelic_security/websocket-client-simple/client.rb +128 -0
- data/lib/newrelic_security/websocket-client-simple/event_emitter.rb +72 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/error.rb +129 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/exception_handler.rb +32 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/frame/base.rb +62 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/frame/data.rb +49 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/frame/handler/base.rb +41 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/frame/handler/handler03.rb +224 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/frame/handler/handler04.rb +18 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/frame/handler/handler05.rb +15 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/frame/handler/handler07.rb +78 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/frame/handler/handler75.rb +78 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/frame/handler.rb +15 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/frame/incoming/client.rb +17 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/frame/incoming/server.rb +17 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/frame/incoming.rb +52 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/frame/outgoing/client.rb +17 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/frame/outgoing/server.rb +17 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/frame/outgoing.rb +35 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/frame.rb +11 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/handshake/base.rb +142 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/handshake/client.rb +130 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/handshake/handler/base.rb +49 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/handshake/handler/client.rb +32 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/handshake/handler/client01.rb +20 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/handshake/handler/client04.rb +63 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/handshake/handler/client11.rb +22 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/handshake/handler/client75.rb +39 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/handshake/handler/client76.rb +105 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/handshake/handler/server.rb +10 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/handshake/handler/server04.rb +56 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/handshake/handler/server75.rb +40 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/handshake/handler/server76.rb +75 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/handshake/handler.rb +21 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/handshake/server.rb +179 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/handshake.rb +10 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/nice_inspect.rb +12 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket/version.rb +5 -0
- data/lib/newrelic_security/websocket-client-simple/websocket-ruby/lib/websocket.rb +50 -0
- data/lib/newrelic_security.rb +6 -0
- data/lib/tasks/all.rb +8 -0
- data/lib/tasks/coverage_report.rake +27 -0
- data/newrelic_security.gemspec +51 -0
- metadata +342 -0
@@ -0,0 +1,91 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'logger'
|
3
|
+
|
4
|
+
module NewRelic::Security
|
5
|
+
module Agent
|
6
|
+
module Logging
|
7
|
+
INIT_LOG_FILE_NAME = 'ruby-security-collector-init.log'
|
8
|
+
|
9
|
+
class AgentInitLogger
|
10
|
+
def initialize
|
11
|
+
create_log_to_file
|
12
|
+
end
|
13
|
+
|
14
|
+
def fatal(msg)
|
15
|
+
@init_logger.fatal(msg)
|
16
|
+
end
|
17
|
+
|
18
|
+
def error(msg)
|
19
|
+
@init_logger.error(msg)
|
20
|
+
end
|
21
|
+
|
22
|
+
def warn(msg)
|
23
|
+
@init_logger.warn(msg)
|
24
|
+
end
|
25
|
+
|
26
|
+
def info(msg)
|
27
|
+
@init_logger.info(msg)
|
28
|
+
end
|
29
|
+
|
30
|
+
def debug(msg)
|
31
|
+
@init_logger.debug(msg)
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def prepped_logger(target)
|
37
|
+
@logger = ::Logger.new(target)
|
38
|
+
@logger.level = AgentLogger.log_level_for(NewRelic::Security::Agent.config[:log_level])
|
39
|
+
set_log_format! if target == STDOUT
|
40
|
+
@logger.instance_variable_set(:@skip_instrumenting, true)
|
41
|
+
@logger.freeze
|
42
|
+
@logger
|
43
|
+
end
|
44
|
+
|
45
|
+
LOG_LEVELS = {
|
46
|
+
"debug" => ::Logger::DEBUG,
|
47
|
+
"info" => ::Logger::INFO,
|
48
|
+
"warn" => ::Logger::WARN,
|
49
|
+
"error" => ::Logger::ERROR,
|
50
|
+
"fatal" => ::Logger::FATAL
|
51
|
+
}
|
52
|
+
|
53
|
+
def self.log_level_for(level)
|
54
|
+
LOG_LEVELS.fetch(level.to_s.downcase, ::Logger::INFO)
|
55
|
+
end
|
56
|
+
|
57
|
+
def create_log_to_file
|
58
|
+
log_dir = ::File.join(NewRelic::Security::Agent.config[:log_file_path], SEC_HOME_PATH, LOGS_DIR)
|
59
|
+
path = ::File.directory?(log_dir)
|
60
|
+
if wants_stdout?
|
61
|
+
@init_logger = prepped_logger(STDOUT)
|
62
|
+
warn("Using standard out for logging due to config `log_file_path` or serverless_mode")
|
63
|
+
elsif path
|
64
|
+
file_path = "#{log_dir}/#{INIT_LOG_FILE_NAME}"
|
65
|
+
begin
|
66
|
+
@init_logger = prepped_logger(file_path)
|
67
|
+
rescue => e
|
68
|
+
@init_logger = prepped_logger(STDOUT)
|
69
|
+
warn("Failed creating logger for file #{file_path}, using standard out for logging. #{e}")
|
70
|
+
end
|
71
|
+
else
|
72
|
+
@init_logger = prepped_logger(STDOUT)
|
73
|
+
warn("Error creating log directory #{::File.join(NewRelic::Security::Agent.config[:log_file_path], SEC_HOME_PATH, LOGS_DIR)}, using standard out for logging.")
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def wants_stdout?
|
78
|
+
NewRelic::Security::Agent.config[:log_file_path].casecmp(STANDARD_OUT) == 0 ||
|
79
|
+
::NewRelic::Agent.config[:'serverless_mode.enabled']
|
80
|
+
end
|
81
|
+
|
82
|
+
def set_log_format!
|
83
|
+
@logger.formatter = proc do |severity, datetime, progname, msg|
|
84
|
+
"** [NewRelic][Security]#{msg}\n"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'logger'
|
3
|
+
|
4
|
+
module NewRelic::Security
|
5
|
+
module Agent
|
6
|
+
module Logging
|
7
|
+
LOG_FILE_SIZE = 50 * 1024 * 1024
|
8
|
+
MAX_LOG_FILES = 3
|
9
|
+
|
10
|
+
class AgentLogger
|
11
|
+
def initialize
|
12
|
+
create_log_to_file
|
13
|
+
end
|
14
|
+
|
15
|
+
def fatal(msg)
|
16
|
+
@logger.fatal(msg)
|
17
|
+
end
|
18
|
+
|
19
|
+
def error(msg)
|
20
|
+
@logger.error(msg)
|
21
|
+
end
|
22
|
+
|
23
|
+
def warn(msg)
|
24
|
+
@logger.warn(msg)
|
25
|
+
end
|
26
|
+
|
27
|
+
def info(msg)
|
28
|
+
@logger.info(msg)
|
29
|
+
end
|
30
|
+
|
31
|
+
def debug(msg)
|
32
|
+
@logger.debug(msg)
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def prepped_logger(target)
|
38
|
+
@logger = ::Logger.new(target, MAX_LOG_FILES, LOG_FILE_SIZE)
|
39
|
+
@logger.level = AgentLogger.log_level_for(NewRelic::Security::Agent.config[:log_level])
|
40
|
+
set_log_format! if target == STDOUT
|
41
|
+
@logger.instance_variable_set(:@skip_instrumenting, true)
|
42
|
+
@logger.freeze
|
43
|
+
@logger
|
44
|
+
end
|
45
|
+
|
46
|
+
LOG_LEVELS = {
|
47
|
+
"debug" => ::Logger::DEBUG,
|
48
|
+
"info" => ::Logger::INFO,
|
49
|
+
"warn" => ::Logger::WARN,
|
50
|
+
"error" => ::Logger::ERROR,
|
51
|
+
"fatal" => ::Logger::FATAL
|
52
|
+
}
|
53
|
+
|
54
|
+
def self.log_level_for(level)
|
55
|
+
LOG_LEVELS.fetch(level.to_s.downcase, ::Logger::INFO)
|
56
|
+
end
|
57
|
+
|
58
|
+
def create_log_to_file
|
59
|
+
log_dir = ::File.join(NewRelic::Security::Agent.config[:log_file_path], SEC_HOME_PATH, LOGS_DIR)
|
60
|
+
path = ::File.directory?(log_dir)
|
61
|
+
if wants_stdout?
|
62
|
+
@logger = prepped_logger(STDOUT)
|
63
|
+
warn("Using standard out for logging due to config `log_file_path` or serverless_mode")
|
64
|
+
elsif path
|
65
|
+
file_path = "#{log_dir}/#{LOG_FILE_NAME}"
|
66
|
+
begin
|
67
|
+
@logger = prepped_logger(file_path)
|
68
|
+
rescue => e
|
69
|
+
@logger = prepped_logger(STDOUT)
|
70
|
+
warn("Failed creating logger for file #{file_path}, using standard out for logging. #{e}")
|
71
|
+
end
|
72
|
+
else
|
73
|
+
@logger = prepped_logger(STDOUT)
|
74
|
+
warn("Error creating log directory #{::File.join(NewRelic::Security::Agent.config[:log_file_path], SEC_HOME_PATH, LOGS_DIR)}, using standard out for logging.")
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def wants_stdout?
|
79
|
+
NewRelic::Security::Agent.config[:log_file_path].casecmp(STANDARD_OUT) == 0 ||
|
80
|
+
::NewRelic::Agent.config[:'serverless_mode.enabled']
|
81
|
+
end
|
82
|
+
|
83
|
+
def set_log_format!
|
84
|
+
@logger.formatter = proc do |severity, datetime, progname, msg|
|
85
|
+
"** [NewRelic][Security]#{msg}\n"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module NewRelic::Security
|
2
|
+
module Agent
|
3
|
+
module Logging
|
4
|
+
class NullLogger
|
5
|
+
def fatal(msg); end
|
6
|
+
|
7
|
+
def error(msg); end
|
8
|
+
|
9
|
+
def warn(msg); end
|
10
|
+
|
11
|
+
def info(msg); end
|
12
|
+
|
13
|
+
def debug(msg); end
|
14
|
+
|
15
|
+
# def method_missing(method, *args, &blk)
|
16
|
+
# nil
|
17
|
+
# end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
2
|
+
MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh
|
3
|
+
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
|
4
|
+
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
|
5
|
+
QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT
|
6
|
+
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
|
7
|
+
b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG
|
8
|
+
9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB
|
9
|
+
CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97
|
10
|
+
nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt
|
11
|
+
43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P
|
12
|
+
T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4
|
13
|
+
gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO
|
14
|
+
BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR
|
15
|
+
TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw
|
16
|
+
DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr
|
17
|
+
hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg
|
18
|
+
06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF
|
19
|
+
PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls
|
20
|
+
YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
|
21
|
+
CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
|
22
|
+
-----END CERTIFICATE-----
|
23
|
+
-----BEGIN CERTIFICATE-----
|
24
|
+
MIIEvjCCA6agAwIBAgIQBtjZBNVYQ0b2ii+nVCJ+xDANBgkqhkiG9w0BAQsFADBh
|
25
|
+
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
|
26
|
+
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
|
27
|
+
QTAeFw0yMTA0MTQwMDAwMDBaFw0zMTA0MTMyMzU5NTlaME8xCzAJBgNVBAYTAlVT
|
28
|
+
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxKTAnBgNVBAMTIERpZ2lDZXJ0IFRMUyBS
|
29
|
+
U0EgU0hBMjU2IDIwMjAgQ0ExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
|
30
|
+
AQEAwUuzZUdwvN1PWNvsnO3DZuUfMRNUrUpmRh8sCuxkB+Uu3Ny5CiDt3+PE0J6a
|
31
|
+
qXodgojlEVbbHp9YwlHnLDQNLtKS4VbL8Xlfs7uHyiUDe5pSQWYQYE9XE0nw6Ddn
|
32
|
+
g9/n00tnTCJRpt8OmRDtV1F0JuJ9x8piLhMbfyOIJVNvwTRYAIuE//i+p1hJInuW
|
33
|
+
raKImxW8oHzf6VGo1bDtN+I2tIJLYrVJmuzHZ9bjPvXj1hJeRPG/cUJ9WIQDgLGB
|
34
|
+
Afr5yjK7tI4nhyfFK3TUqNaX3sNk+crOU6JWvHgXjkkDKa77SU+kFbnO8lwZV21r
|
35
|
+
eacroicgE7XQPUDTITAHk+qZ9QIDAQABo4IBgjCCAX4wEgYDVR0TAQH/BAgwBgEB
|
36
|
+
/wIBADAdBgNVHQ4EFgQUt2ui6qiqhIx56rTaD5iyxZV2ufQwHwYDVR0jBBgwFoAU
|
37
|
+
A95QNVbRTLtm8KPiGxvDl7I90VUwDgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQG
|
38
|
+
CCsGAQUFBwMBBggrBgEFBQcDAjB2BggrBgEFBQcBAQRqMGgwJAYIKwYBBQUHMAGG
|
39
|
+
GGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBABggrBgEFBQcwAoY0aHR0cDovL2Nh
|
40
|
+
Y2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0R2xvYmFsUm9vdENBLmNydDBCBgNV
|
41
|
+
HR8EOzA5MDegNaAzhjFodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRH
|
42
|
+
bG9iYWxSb290Q0EuY3JsMD0GA1UdIAQ2MDQwCwYJYIZIAYb9bAIBMAcGBWeBDAEB
|
43
|
+
MAgGBmeBDAECATAIBgZngQwBAgIwCAYGZ4EMAQIDMA0GCSqGSIb3DQEBCwUAA4IB
|
44
|
+
AQCAMs5eC91uWg0Kr+HWhMvAjvqFcO3aXbMM9yt1QP6FCvrzMXi3cEsaiVi6gL3z
|
45
|
+
ax3pfs8LulicWdSQ0/1s/dCYbbdxglvPbQtaCdB73sRD2Cqk3p5BJl+7j5nL3a7h
|
46
|
+
qG+fh/50tx8bIKuxT8b1Z11dmzzp/2n3YWzW2fP9NsarA4h20ksudYbj/NhVfSbC
|
47
|
+
EXffPgK2fPOre3qGNm+499iTcc+G33Mw+nur7SpZyEKEOxEXGlLzyQ4UfaJbcme6
|
48
|
+
ce1XR2bFuAJKZTRei9AqPCCcUZlM51Ke92sRKw2Sfh3oius2FkOH6ipjv3U/697E
|
49
|
+
A7sKPPcw7+uvTPyLNhBzPvOk
|
50
|
+
-----END CERTIFICATE-----
|
@@ -0,0 +1,219 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'fileutils'
|
3
|
+
require 'socket'
|
4
|
+
require 'openssl'
|
5
|
+
|
6
|
+
module NewRelic::Security
|
7
|
+
module Agent
|
8
|
+
module Utils
|
9
|
+
extend self
|
10
|
+
|
11
|
+
ENABLED = 'enabled'
|
12
|
+
VULNERABLE = 'VULNERABLE'
|
13
|
+
AES_256_CBC = 'AES-256-CBC'
|
14
|
+
H_ASTERIK = 'H*'
|
15
|
+
ASTERISK = '*'
|
16
|
+
|
17
|
+
def is_IAST?
|
18
|
+
return false if NewRelic::Security::Agent.config[:policy].empty?
|
19
|
+
return NewRelic::Security::Agent.config[:policy][VULNERABILITY_SCAN][IAST_SCAN][ENABLED] if NewRelic::Security::Agent.config[:policy][VULNERABILITY_SCAN][ENABLED]
|
20
|
+
false
|
21
|
+
end
|
22
|
+
|
23
|
+
def is_IAST_request?(headers)
|
24
|
+
return true if headers&.key?(NR_CSEC_FUZZ_REQUEST_ID)
|
25
|
+
false
|
26
|
+
end
|
27
|
+
|
28
|
+
def parse_fuzz_header(ctxt)
|
29
|
+
headers = ctxt.headers if ctxt
|
30
|
+
if is_IAST? && is_IAST_request?(headers)
|
31
|
+
fuzz_request = headers[NR_CSEC_FUZZ_REQUEST_ID].split(COLON_IAST_COLON)
|
32
|
+
if fuzz_request.length() >= 7
|
33
|
+
decrypted_data = decrypt_data(fuzz_request[6], fuzz_request[7]) if fuzz_request[6] && fuzz_request[7] && !fuzz_request[6].empty? && !fuzz_request[7].empty?
|
34
|
+
if decrypted_data
|
35
|
+
NewRelic::Security::Agent.logger.debug "Encrypted data: #{fuzz_request[6]}, decrypted data: #{decrypted_data}, Sha256: #{fuzz_request[7]}"
|
36
|
+
decrypted_data.split(COMMA).each do |filename|
|
37
|
+
begin
|
38
|
+
filename.gsub!(NR_CSEC_VALIDATOR_HOME_TMP, NewRelic::Security::Agent.config[:fuzz_dir_path])
|
39
|
+
filename.gsub!(NR_CSEC_VALIDATOR_FILE_SEPARATOR, ::File::SEPARATOR)
|
40
|
+
dirname = ::File.dirname(filename)
|
41
|
+
::FileUtils.mkdir_p(dirname, :mode => 0770) unless ::File.directory?(dirname)
|
42
|
+
ctxt&.fuzz_files << filename
|
43
|
+
::File.open(filename, ::File::WRONLY | ::File::CREAT | ::File::EXCL) do |fd|
|
44
|
+
# puts "Ownership acquired by : #{Process.pid}"
|
45
|
+
end unless ::File.exist?(filename)
|
46
|
+
rescue
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def decrypt_data(name, sha)
|
55
|
+
cipher = ::OpenSSL::Cipher.new AES_256_CBC
|
56
|
+
cipher.decrypt
|
57
|
+
cipher.key = NewRelic::Security::Agent.config[:extraction_key]
|
58
|
+
decrypted = cipher.update [name].pack(H_ASTERIK)
|
59
|
+
decrypted << cipher.final
|
60
|
+
fname = decrypted[16..-1]
|
61
|
+
return fname if ::Digest::SHA256.hexdigest(fname) == sha
|
62
|
+
nil
|
63
|
+
rescue Exception => exception
|
64
|
+
NewRelic::Security::Agent.logger.error "Exception in decrypt_data: #{exception.inspect} #{exception.backtrace}"
|
65
|
+
end
|
66
|
+
|
67
|
+
def delete_created_files(ctxt)
|
68
|
+
return unless ctxt
|
69
|
+
headers = ctxt.headers
|
70
|
+
if is_IAST? && is_IAST_request?(headers)
|
71
|
+
ctxt.fuzz_files.each do |file|
|
72
|
+
begin
|
73
|
+
::File.delete(file)
|
74
|
+
rescue
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def create_exit_event(event)
|
81
|
+
return unless event
|
82
|
+
return unless is_IAST?
|
83
|
+
return unless is_IAST_request?(event.httpRequest[:headers])
|
84
|
+
if event.httpRequest[:headers][NR_CSEC_FUZZ_REQUEST_ID].include?(event.apiId) && event.httpRequest[:headers][NR_CSEC_FUZZ_REQUEST_ID].include?(VULNERABLE)
|
85
|
+
exit_event = NewRelic::Security::Agent::Control::ExitEvent.new
|
86
|
+
exit_event.executionId = event.id
|
87
|
+
exit_event.caseType = event.caseType
|
88
|
+
exit_event.k2RequestIdentifier = event.httpRequest[:headers][NR_CSEC_FUZZ_REQUEST_ID]
|
89
|
+
NewRelic::Security::Agent.agent.event_processor.send_exit_event(exit_event)
|
90
|
+
end
|
91
|
+
rescue Exception => exception
|
92
|
+
NewRelic::Security::Agent.logger.error "Exception in create_exit_event: #{exception.inspect} #{exception.backtrace}"
|
93
|
+
NewRelic::Security::Agent.agent.exit_event_stats.error_count.increment
|
94
|
+
end
|
95
|
+
|
96
|
+
def get_app_routes(framework, router = nil)
|
97
|
+
enable_object_space_in_jruby
|
98
|
+
if framework == :rails
|
99
|
+
::Rails.application.routes.routes.each do |route|
|
100
|
+
if route.verb.is_a?(::Regexp)
|
101
|
+
method = route.verb.inspect.match(/[a-zA-Z]+/)
|
102
|
+
NewRelic::Security::Agent.agent.route_map << "#{method}@#{route.path.spec.to_s.gsub(/\(\.:format\)/, "")}" if method
|
103
|
+
else
|
104
|
+
route.verb.split("|").each { |m|
|
105
|
+
NewRelic::Security::Agent.agent.route_map << "#{m}@#{route.path.spec.to_s.gsub(/\(\.:format\)/, "")}"
|
106
|
+
}
|
107
|
+
end
|
108
|
+
end
|
109
|
+
elsif framework == :sinatra
|
110
|
+
::Sinatra::Application.routes.each do |method, routes|
|
111
|
+
routes.map { |r| r.first.to_s }.map do |route|
|
112
|
+
NewRelic::Security::Agent.agent.route_map << "#{method}@#{route}"
|
113
|
+
end
|
114
|
+
end
|
115
|
+
elsif framework == :grape
|
116
|
+
ObjectSpace.each_object(::Grape::Endpoint) { |z|
|
117
|
+
z.instance_variable_get(:@routes)&.each { |route|
|
118
|
+
http_method = route.instance_variable_get(:@request_method) ? route.instance_variable_get(:@request_method) : route.instance_variable_get(:@options)[:method]
|
119
|
+
NewRelic::Security::Agent.agent.route_map << "#{http_method}@#{route.pattern.origin}"
|
120
|
+
}
|
121
|
+
}
|
122
|
+
elsif framework == :padrino
|
123
|
+
if router.instance_of?(::Padrino::PathRouter::Router)
|
124
|
+
router.instance_variable_get(:@routes).each do |route|
|
125
|
+
NewRelic::Security::Agent.agent.route_map << "#{route.instance_variable_get(:@verb)}@#{route.matcher.instance_variable_get(:@path)}"
|
126
|
+
end
|
127
|
+
end
|
128
|
+
elsif framework == :roda
|
129
|
+
NewRelic::Security::Agent.logger.warn "TODO: Roda is a routing tree web toolkit, which generates route dynamically, hence route extraction is not possible."
|
130
|
+
else
|
131
|
+
NewRelic::Security::Agent.logger.error "Unable to get app routes as Framework not detected"
|
132
|
+
end
|
133
|
+
disable_object_space_in_jruby if NewRelic::Security::Agent.config[:jruby_objectspace_enabled]
|
134
|
+
NewRelic::Security::Agent.logger.debug "ALL ROUTES : #{NewRelic::Security::Agent.agent.route_map}"
|
135
|
+
NewRelic::Security::Agent.agent.event_processor&.send_application_url_mappings
|
136
|
+
rescue Exception => exception
|
137
|
+
NewRelic::Security::Agent.logger.error "Error in get app routes : #{exception.inspect} #{exception.backtrace}"
|
138
|
+
end
|
139
|
+
|
140
|
+
def app_port(env)
|
141
|
+
listen_port = nil
|
142
|
+
if env.key?('puma.socket')
|
143
|
+
NewRelic::Security::Agent.config.app_server = :puma
|
144
|
+
if env['puma.socket'].is_a?(TCPSocket)
|
145
|
+
listen_port = env['puma.socket'].addr[1]
|
146
|
+
NewRelic::Security::Agent.logger.debug "Detected port from puma.socket TCPSocket : #{listen_port}"
|
147
|
+
elsif env['puma.socket'].is_a?(Puma::MiniSSL::Socket)
|
148
|
+
listen_port = env['puma.socket'].instance_variable_get(:@socket).addr[1]
|
149
|
+
NewRelic::Security::Agent.logger.debug "Detected port from puma.socket Puma::MiniSSL::Socket TCPSocket : #{listen_port}"
|
150
|
+
end
|
151
|
+
end
|
152
|
+
if env.key?('unicorn.socket') && env['unicorn.socket'].is_a?(::Unicorn::TCPClient)
|
153
|
+
NewRelic::Security::Agent.config.app_server = :unicorn
|
154
|
+
listen_port, _ = ::Socket.unpack_sockaddr_in(env['unicorn.socket'].getsockname)
|
155
|
+
NewRelic::Security::Agent.logger.debug "Detected port from unicorn.socket Unicorn::TCPClient : #{listen_port}"
|
156
|
+
end
|
157
|
+
ObjectSpace.each_object(::Falcon::Server) { |z|
|
158
|
+
NewRelic::Security::Agent.config.app_server = :falcon
|
159
|
+
listen_port = z.endpoint.instance_variable_get(:@specification)[1]
|
160
|
+
NewRelic::Security::Agent.logger.debug "Detected port from Falcon::Server : #{listen_port}"
|
161
|
+
} if defined?(::Falcon::Server)
|
162
|
+
ObjectSpace.each_object(::Thin::Backends::TcpServer) { |z|
|
163
|
+
NewRelic::Security::Agent.config.app_server = :thin
|
164
|
+
listen_port = z.instance_variable_get(:@port)
|
165
|
+
NewRelic::Security::Agent.logger.debug "Detected port from Thin::Backends::TcpServer : #{listen_port}"
|
166
|
+
} if defined?(::Thin::Backends::TcpServer)
|
167
|
+
ObjectSpace.each_object(::WEBrick::GenericServer) { |z|
|
168
|
+
NewRelic::Security::Agent.config.app_server = :webrick
|
169
|
+
listen_port = z.instance_variable_get(:@config)[:Port]
|
170
|
+
NewRelic::Security::Agent.logger.debug "Detected port from WEBrick::GenericServer : #{listen_port}"
|
171
|
+
} if defined?(::WEBrick::GenericServer)
|
172
|
+
if NewRelic::Security::Agent.config[:'security.application_info.port'] != 0
|
173
|
+
listen_port = NewRelic::Security::Agent.config[:'security.application_info.port']
|
174
|
+
NewRelic::Security::Agent.logger.info "Using application listen port from newrelic.yml security.application_info.port : #{listen_port}"
|
175
|
+
end
|
176
|
+
if listen_port
|
177
|
+
NewRelic::Security::Agent.logger.info "Detected application listen_port : #{listen_port}"
|
178
|
+
else
|
179
|
+
NewRelic::Security::Agent.logger.warn "Unable to detect application listen port, IAST can not run without application listen port. Please provide application listen port in security.application_info.port in newrelic.yml"
|
180
|
+
end
|
181
|
+
disable_object_space_in_jruby if NewRelic::Security::Agent.config[:jruby_objectspace_enabled]
|
182
|
+
listen_port
|
183
|
+
rescue Exception => exception
|
184
|
+
NewRelic::Security::Agent.logger.error "Exception in port detection : #{exception.inspect} #{exception.backtrace}"
|
185
|
+
end
|
186
|
+
|
187
|
+
def app_root
|
188
|
+
#so far assuming it as Rails
|
189
|
+
#TBD, determing the frame work then use appropriate APIs
|
190
|
+
#val = Rails.root
|
191
|
+
root = nil
|
192
|
+
root = ::Rack::Directory.new(EMPTY_STRING).root.to_s if defined? ::Rack::Directory
|
193
|
+
root
|
194
|
+
end
|
195
|
+
|
196
|
+
def enable_object_space_in_jruby
|
197
|
+
if RUBY_ENGINE == 'jruby' && !JRuby.objectspace
|
198
|
+
JRuby.objectspace = true
|
199
|
+
NewRelic::Security::Agent.config.jruby_objectspace_enabled = true
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
def disable_object_space_in_jruby
|
204
|
+
if RUBY_ENGINE == 'jruby' && JRuby.objectspace
|
205
|
+
JRuby.objectspace = false
|
206
|
+
NewRelic::Security::Agent.config.jruby_objectspace_enabled = false
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
def license_key
|
211
|
+
NewRelic::Security::Agent.config[:license_key]
|
212
|
+
end
|
213
|
+
|
214
|
+
def filtered_log(log)
|
215
|
+
log.gsub(license_key, ASTERISK * license_key.size)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module NewRelic::Security
|
2
|
+
module Agent
|
3
|
+
extend self
|
4
|
+
|
5
|
+
require 'newrelic_security/constants'
|
6
|
+
require 'newrelic_security/agent/logging/logger'
|
7
|
+
require 'newrelic_security/agent/logging/init_logger'
|
8
|
+
require 'newrelic_security/agent/configuration/manager'
|
9
|
+
require 'newrelic_security/agent/agent'
|
10
|
+
require 'newrelic_security/agent/utils/agent_utils'
|
11
|
+
|
12
|
+
@agent = nil
|
13
|
+
@logger = nil
|
14
|
+
@config = nil
|
15
|
+
@event_subscriber = nil
|
16
|
+
|
17
|
+
# puts "NewRelic::Agent.agent : #{::NewRelic::Agent.agent.inspect}"
|
18
|
+
# puts "NewRelic::Agent.config : #{::NewRelic::Agent.config.inspect}"
|
19
|
+
# puts "NewRelic::Agent.config : #{::NewRelic::Agent.config.instance_variables}"
|
20
|
+
|
21
|
+
def agent()
|
22
|
+
return @agent if @agent
|
23
|
+
puts "Agent unavailable as it hasn't been started."
|
24
|
+
nil
|
25
|
+
end
|
26
|
+
|
27
|
+
def logger
|
28
|
+
@logger ||= NewRelic::Security::Agent::Logging::AgentLogger.new
|
29
|
+
end
|
30
|
+
|
31
|
+
def logger=(log)
|
32
|
+
@logger = log
|
33
|
+
end
|
34
|
+
|
35
|
+
def init_logger
|
36
|
+
@init_logger ||= NewRelic::Security::Agent::Logging::AgentInitLogger.new
|
37
|
+
end
|
38
|
+
|
39
|
+
def init_logger=(log)
|
40
|
+
@init_logger = log
|
41
|
+
end
|
42
|
+
|
43
|
+
def config
|
44
|
+
@config ||= NewRelic::Security::Agent::Configuration::Manager.new
|
45
|
+
end
|
46
|
+
|
47
|
+
def config=(new_config)
|
48
|
+
@config = new_config
|
49
|
+
end
|
50
|
+
|
51
|
+
@agent = NewRelic::Security::Agent::Agent.new unless @agent
|
52
|
+
NewRelic::Agent.instance.events.notify(:server_source_configuration_added) if NewRelic::Agent.agent.connected?
|
53
|
+
NewRelic::Security::Agent.logger.debug "Creating security agent instance initially : #{@agent.inspect}"
|
54
|
+
NewRelic::Security::Agent.init_logger.info "[STEP-1] => Security agent is starting : #{@agent.inspect}"
|
55
|
+
NewRelic::Security::Agent.init_logger.info "[STEP-2] => Generating unique identifier : #{@config[:uuid]}"
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module NewRelic::Security
|
4
|
+
EMPTY_STRING = ""
|
5
|
+
RUBY = 'RUBY'
|
6
|
+
Ruby = 'Ruby'
|
7
|
+
LANGUAGE_COLLECTOR = 'LANGUAGE_COLLECTOR'
|
8
|
+
STANDARD_OUT = 'STDOUT'
|
9
|
+
NR_CSEC_VALIDATOR_HOME_TMP = '{{NR_CSEC_VALIDATOR_HOME_TMP}}'
|
10
|
+
NR_CSEC_VALIDATOR_FILE_SEPARATOR = '{{NR_CSEC_VALIDATOR_FILE_SEPARATOR}}'
|
11
|
+
SEC_HOME_PATH = 'nr-security-home'
|
12
|
+
LOGS_DIR = 'logs'
|
13
|
+
TMP_DIR = 'tmp'
|
14
|
+
LOG_FILE_NAME = 'ruby-security-collector.log'
|
15
|
+
NR_SECURITY_HOME_TMP = 'nr-security-home/tmp/'
|
16
|
+
NR_CSEC_FUZZ_REQUEST_ID = 'nr-csec-fuzz-request-id'
|
17
|
+
NR_CSEC_TRACING_DATA = 'nr-csec-tracing-data'
|
18
|
+
NR_CSEC_PARENT_ID = 'nr-csec-parent-id'
|
19
|
+
COLON_IAST_COLON = ':IAST:'
|
20
|
+
NOSQL_DB_COMMAND = 'NOSQL_DB_COMMAND'
|
21
|
+
SQL_DB_COMMAND = 'SQL_DB_COMMAND'
|
22
|
+
FILE_OPERATION = 'FILE_OPERATION'
|
23
|
+
FILE_INTEGRITY = 'FILE_INTEGRITY'
|
24
|
+
SYSTEM_COMMAND = 'SYSTEM_COMMAND'
|
25
|
+
REFLECTED_XSS = 'REFLECTED_XSS'
|
26
|
+
HTTP_REQUEST = 'HTTP_REQUEST'
|
27
|
+
XPATH = 'XPATH'
|
28
|
+
LDAP = 'LDAP'
|
29
|
+
MONGO = 'MONGO'
|
30
|
+
SQLITE = 'SQLITE'
|
31
|
+
MYSQL = 'MYSQL'
|
32
|
+
POSTGRES = 'POSTGRES'
|
33
|
+
ISO_8859_1 = 'ISO-8859-1'
|
34
|
+
UTF_8 = 'UTF-8'
|
35
|
+
RAILS = 'rails'
|
36
|
+
PUMA = 'puma'
|
37
|
+
CLUSTER = 'cluster'
|
38
|
+
UNICORN = 'unicorn'
|
39
|
+
WORKER = 'worker'
|
40
|
+
HYPHEN = '-'
|
41
|
+
COMMA = ','
|
42
|
+
SLASH = '/'
|
43
|
+
AT_THE_RATE = '@'
|
44
|
+
SPAWN_METHOD = 'spawn_method'
|
45
|
+
DIRECT = 'direct'
|
46
|
+
LISTEN_PORT = 'listen_port'
|
47
|
+
PIPE = '|'
|
48
|
+
READ = 'read'
|
49
|
+
DELETE = 'delete'
|
50
|
+
WRITE = 'write'
|
51
|
+
BINWRITE = 'binwrite'
|
52
|
+
PROTOCOL = 'protocol'
|
53
|
+
HTTPS = 'https'
|
54
|
+
REQUEST_METHOD = 'REQUEST_METHOD'
|
55
|
+
PATH_INFO = 'PATH_INFO'
|
56
|
+
CONTENT_TYPE = 'CONTENT_TYPE'
|
57
|
+
REQUEST_URI = 'REQUEST_URI'
|
58
|
+
SERVER_PORT = 'SERVER_PORT'
|
59
|
+
X_FORWARDED_FOR = 'x-forwarded-for'
|
60
|
+
REMOTE_ADDR = 'REMOTE_ADDR'
|
61
|
+
RACK_URL_SCHEME = 'rack.url_scheme'
|
62
|
+
CONTENT_TYPE1 = 'content-Type'
|
63
|
+
PULL = 'PULL'
|
64
|
+
SHA1 = 'sha1'
|
65
|
+
VULNERABILITY_SCAN = 'vulnerabilityScan'
|
66
|
+
IAST_SCAN = 'iastScan'
|
67
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module NewRelic::Security
|
2
|
+
module Instrumentation
|
3
|
+
module ActiveRecord
|
4
|
+
module ConnectionAdapters
|
5
|
+
module Mysql2Adapter
|
6
|
+
module Chain
|
7
|
+
|
8
|
+
def self.instrument!
|
9
|
+
::ActiveRecord::ConnectionAdapters::Mysql2Adapter.class_eval do
|
10
|
+
include NewRelic::Security::Instrumentation::ActiveRecord::ConnectionAdapters::Mysql2Adapter
|
11
|
+
|
12
|
+
if RUBY_ENGINE == 'jruby'
|
13
|
+
alias_method :execute_without_security, :execute
|
14
|
+
|
15
|
+
def execute(sql, name = nil)
|
16
|
+
retval = nil
|
17
|
+
event = execute_on_enter(sql, name) { retval = execute_without_security(sql, name) }
|
18
|
+
execute_on_exit(event) { return retval }
|
19
|
+
end
|
20
|
+
|
21
|
+
alias_method :exec_insert_without_security, :exec_insert
|
22
|
+
|
23
|
+
def exec_insert(*var)
|
24
|
+
retval = nil
|
25
|
+
event = exec_insert_on_enter(*var) { retval = exec_insert_without_security(*var) }
|
26
|
+
exec_insert_on_exit(event) { return retval }
|
27
|
+
end
|
28
|
+
|
29
|
+
alias_method :exec_update_without_security, :exec_update
|
30
|
+
|
31
|
+
def exec_update(*var)
|
32
|
+
retval = nil
|
33
|
+
event = exec_update_on_enter(*var) { retval = exec_update_without_security(*var) }
|
34
|
+
exec_update_on_exit(event) { return retval }
|
35
|
+
end
|
36
|
+
|
37
|
+
alias_method :exec_query_without_security, :exec_query
|
38
|
+
|
39
|
+
if ::Rails.version < '5'
|
40
|
+
def exec_query(*var)
|
41
|
+
retval = nil
|
42
|
+
event = exec_query_on_enter(*var) { retval = exec_query_without_security(*var) }
|
43
|
+
exec_query_on_exit(event) { return retval }
|
44
|
+
end
|
45
|
+
else
|
46
|
+
def exec_query(*var, **key_vars)
|
47
|
+
retval = nil
|
48
|
+
event = exec_query_on_enter(*var, **key_vars) { retval = exec_query_without_security(*var, **key_vars) }
|
49
|
+
exec_query_on_exit(event) { return retval }
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
alias_method :exec_delete_without_security, :exec_delete
|
54
|
+
|
55
|
+
def exec_delete(*var)
|
56
|
+
retval = nil
|
57
|
+
event = exec_delete_on_enter(*var) { retval = exec_delete_without_security(*var) }
|
58
|
+
exec_delete_on_exit(event) { return retval }
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|