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,178 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
require 'socket'
|
3
|
+
require 'openssl'
|
4
|
+
require 'newrelic_security/agent/configuration/default_source'
|
5
|
+
require 'newrelic_security/agent/configuration/environment_source'
|
6
|
+
require 'newrelic_security/agent/configuration/manual_source'
|
7
|
+
require 'newrelic_security/agent/configuration/server_source'
|
8
|
+
require 'newrelic_security/agent/configuration/yaml_source'
|
9
|
+
|
10
|
+
module NewRelic::Security
|
11
|
+
module Agent
|
12
|
+
module Configuration
|
13
|
+
class Manager
|
14
|
+
def initialize
|
15
|
+
@cache = Hash.new
|
16
|
+
@cache[:agent_run_id] = ::NewRelic::Agent.agent.service.agent_id
|
17
|
+
@cache[:linking_metadata] = ::NewRelic::Agent.linking_metadata
|
18
|
+
@cache[:app_name] = ::NewRelic::Agent.config[:app_name][0]
|
19
|
+
@cache[:entity_guid] = ::NewRelic::Agent.config[:entity_guid]
|
20
|
+
@cache[:license_key] = ::NewRelic::Agent.config[:license_key]
|
21
|
+
@cache[:policy] = Hash.new
|
22
|
+
@cache[:account_id] = nil
|
23
|
+
@cache[:application_id] = nil
|
24
|
+
@cache[:primary_application_id] = nil
|
25
|
+
@cache[:log_file_path] = ::NewRelic::Agent.config[:log_file_path]
|
26
|
+
@cache[:fuzz_dir_path] = ::File.join(::File.absolute_path(::NewRelic::Agent.config[:log_file_path]), SEC_HOME_PATH, TMP_DIR)
|
27
|
+
@cache[:log_level] = ::NewRelic::Agent.config[:log_level]
|
28
|
+
@cache[:high_security] = ::NewRelic::Agent.config[:high_security]
|
29
|
+
@cache[:'agent.enabled'] = ::NewRelic::Agent.config[:'security.agent.enabled']
|
30
|
+
@cache[:enabled] = ::NewRelic::Agent.config[:'security.enabled']
|
31
|
+
@cache[:mode] = ::NewRelic::Agent.config[:'security.mode']
|
32
|
+
@cache[:validator_service_url] = ::NewRelic::Agent.config[:'security.validator_service_url']
|
33
|
+
@cache[:'security.detection.rci.enabled'] = ::NewRelic::Agent.config[:'security.detection.rci.enabled']
|
34
|
+
@cache[:'security.detection.rxss.enabled'] = ::NewRelic::Agent.config[:'security.detection.rxss.enabled']
|
35
|
+
@cache[:'security.detection.deserialization.enabled'] = ::NewRelic::Agent.config[:'security.detection.deserialization.enabled']
|
36
|
+
@cache[:framework] = detect_framework
|
37
|
+
@cache[:'security.application_info.port'] = ::NewRelic::Agent.config[:'security.application_info.port'].to_i
|
38
|
+
@cache[:'security.request.body_limit'] = ::NewRelic::Agent.config[:'security.request.body_limit'].to_i > 0 ? ::NewRelic::Agent.config[:'security.request.body_limit'].to_i : 300
|
39
|
+
@cache[:listen_port] = nil
|
40
|
+
@cache[:app_root] = NewRelic::Security::Agent::Utils.app_root
|
41
|
+
@cache[:jruby_objectspace_enabled] = false
|
42
|
+
@cache[:json_version] = :'1.2.0'
|
43
|
+
|
44
|
+
@environment_source = NewRelic::Security::Agent::Configuration::EnvironmentSource.new
|
45
|
+
@server_source = NewRelic::Security::Agent::Configuration::ServerSource.new
|
46
|
+
@manual_source = NewRelic::Security::Agent::Configuration::ManualSource.new
|
47
|
+
@yaml_source = NewRelic::Security::Agent::Configuration::YamlSource.new
|
48
|
+
@default_source = NewRelic::Security::Agent::Configuration::DefaultSource.new
|
49
|
+
rescue Exception => exception
|
50
|
+
# TODO: remove this puts once agent stablizes
|
51
|
+
puts "Exception in Configuration::Manager.initialize : #{exception.inspect} #{exception.backtrace}"
|
52
|
+
end
|
53
|
+
|
54
|
+
def [](key)
|
55
|
+
@cache[key]
|
56
|
+
end
|
57
|
+
|
58
|
+
def has_key?(key)
|
59
|
+
@cache.has_key?(key)
|
60
|
+
end
|
61
|
+
|
62
|
+
def keys
|
63
|
+
@cache.keys
|
64
|
+
end
|
65
|
+
|
66
|
+
def cache
|
67
|
+
@cache
|
68
|
+
end
|
69
|
+
|
70
|
+
def refresh
|
71
|
+
NewRelic::Security::Agent.logger.debug "refreshing agent config"
|
72
|
+
NewRelic::Security::Agent.config = NewRelic::Security::Agent::Configuration::Manager.new
|
73
|
+
# TODO: add validator received config also after the new, else collector#40 throws error
|
74
|
+
end
|
75
|
+
|
76
|
+
def save_uuid
|
77
|
+
@cache[:uuid] = generate_uuid
|
78
|
+
end
|
79
|
+
|
80
|
+
def update_server_config
|
81
|
+
@cache[:agent_run_id] = ::NewRelic::Agent.agent.service.agent_id
|
82
|
+
@cache[:linking_metadata] = ::NewRelic::Agent.linking_metadata
|
83
|
+
server_source = ::NewRelic::Agent.config.instance_variable_get(:@server_source) if defined?(::NewRelic::Agent)
|
84
|
+
@cache[:account_id] = server_source[:account_id]
|
85
|
+
@cache[:application_id] = server_source[:application_id]
|
86
|
+
@cache[:entity_guid] = server_source[:entity_guid]
|
87
|
+
@cache[:primary_application_id] = server_source[:primary_application_id]
|
88
|
+
@cache[:extraction_key] = generate_key(@cache[:entity_guid])
|
89
|
+
rescue Exception => exception
|
90
|
+
NewRelic::Security::Agent.logger.error "Exception in update_server_config : #{exception.inspect} #{exception.backtrace}"
|
91
|
+
end
|
92
|
+
|
93
|
+
def update_port=(listen_port)
|
94
|
+
@cache[:listen_port] = listen_port
|
95
|
+
end
|
96
|
+
|
97
|
+
def app_server=(app_server)
|
98
|
+
@cache[:app_server] = app_server
|
99
|
+
end
|
100
|
+
|
101
|
+
def jruby_objectspace_enabled=(jruby_objectspace_enabled)
|
102
|
+
@cache[:jruby_objectspace_enabled] = jruby_objectspace_enabled
|
103
|
+
end
|
104
|
+
|
105
|
+
def disable_security
|
106
|
+
@cache[:enabled] = false
|
107
|
+
NewRelic::Security::Agent.logger.info "Security Agent is now INACTIVE for #{NewRelic::Security::Agent.config[:uuid]}\n"
|
108
|
+
NewRelic::Security::Agent.init_logger.info "Security Agent is now INACTIVE for #{NewRelic::Security::Agent.config[:uuid]}\n"
|
109
|
+
end
|
110
|
+
|
111
|
+
def enable_security
|
112
|
+
@cache[:enabled] = true
|
113
|
+
NewRelic::Security::Agent.logger.info "Security Agent is now ACTIVE for #{NewRelic::Security::Agent.config[:uuid]}\n"
|
114
|
+
NewRelic::Security::Agent.init_logger.info "Security Agent is now ACTIVE for #{NewRelic::Security::Agent.config[:uuid]}\n"
|
115
|
+
NewRelic::Security::Agent.agent.event_processor.send_critical_message("Security Agent is now ACTIVE for #{NewRelic::Security::Agent.config[:uuid]}", "INFO", caller_locations[0].to_s, Thread.current.name, nil)
|
116
|
+
end
|
117
|
+
|
118
|
+
private
|
119
|
+
|
120
|
+
def detect_framework
|
121
|
+
return :rails if defined?(::Rails)
|
122
|
+
return :padrino if defined?(::Padrino)
|
123
|
+
return :sinatra if defined?(::Sinatra)
|
124
|
+
return :roda if defined?(::Roda)
|
125
|
+
return :grape if defined?(::Grape)
|
126
|
+
end
|
127
|
+
|
128
|
+
def generate_uuid
|
129
|
+
if defined?(::Puma::Cluster)
|
130
|
+
ObjectSpace.each_object(::Puma::Cluster) { |z| return fetch_or_create_uuid if !z.preload? && z.instance_variable_get(:@options)[:workers] >= 1 }
|
131
|
+
end
|
132
|
+
if defined?(::Unicorn::HttpServer)
|
133
|
+
ObjectSpace.each_object(::Unicorn::HttpServer) { |z| return fetch_or_create_uuid if !z.preload_app && z.worker_processes >= 1 }
|
134
|
+
end
|
135
|
+
if defined?(::PhusionPassenger::App) && ::PhusionPassenger::App.options[SPAWN_METHOD].match?(/#{DIRECT}/i)
|
136
|
+
return create_uuid
|
137
|
+
end
|
138
|
+
::SecureRandom.uuid
|
139
|
+
rescue Exception => exception
|
140
|
+
NewRelic::Security::Agent.logger.error "Exception in generate_uuid : #{exception.inspect} #{exception.backtrace}"
|
141
|
+
end
|
142
|
+
|
143
|
+
def create_uuid
|
144
|
+
hostname = ::Socket.gethostname
|
145
|
+
ip_addr = Socket.ip_address_list.detect{|intf| intf.ipv4_private?}.ip_address.to_s
|
146
|
+
process_identity = ::Gem.win_platform? ? ::Process.pid : ::Process.getpgrp
|
147
|
+
[hostname, ip_addr, process_identity].join(HYPHEN)
|
148
|
+
end
|
149
|
+
|
150
|
+
def fetch_or_create_uuid
|
151
|
+
process_identity = ::Gem.win_platform? ? ::Process.pid : ::Process.getpgrp
|
152
|
+
tmp_dir = ::File.join(@cache[:log_file_path], SEC_HOME_PATH, TMP_DIR)
|
153
|
+
if ::File.directory?(tmp_dir)
|
154
|
+
uuid_file_name = ::File.join(@cache[:log_file_path], SEC_HOME_PATH, TMP_DIR, process_identity.to_s)
|
155
|
+
else
|
156
|
+
::FileUtils.mkdir_p(TMP_DIR) unless ::File.directory?(TMP_DIR)
|
157
|
+
uuid_file_name = ::File.join(TMP_DIR, process_identity.to_s)
|
158
|
+
end
|
159
|
+
if ::File.exist?(uuid_file_name)
|
160
|
+
sleep 0.01
|
161
|
+
return ::File.read(uuid_file_name)
|
162
|
+
end
|
163
|
+
File.open(uuid_file_name, 'w', 0644) {|f|
|
164
|
+
ret = f.flock(File::LOCK_EX|File::LOCK_NB)
|
165
|
+
f.write(::SecureRandom.uuid) if ret == 0
|
166
|
+
}
|
167
|
+
::File.read(uuid_file_name)
|
168
|
+
rescue Exception => exception
|
169
|
+
NewRelic::Security::Agent.logger.error "Exception in uuid file creation : #{exception.inspect} #{exception.backtrace}"
|
170
|
+
end
|
171
|
+
|
172
|
+
def generate_key(entity_guid)
|
173
|
+
::OpenSSL::PKCS5.pbkdf2_hmac(entity_guid, entity_guid[0..15], 1024, 32, SHA1)
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'digest'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module NewRelic::Security
|
6
|
+
module Agent
|
7
|
+
module Control
|
8
|
+
|
9
|
+
PROC_SELF_EXE = '/proc/self/exe'
|
10
|
+
PROC_SELF_CMDLINE = '/proc/self/cmdline'
|
11
|
+
STATIC = 'STATIC'
|
12
|
+
COLON = ':'
|
13
|
+
RUBYLIB = 'RUBYLIB'
|
14
|
+
BACKSLASH000 = '\000'
|
15
|
+
KIND = 'kind'
|
16
|
+
|
17
|
+
class AppInfo
|
18
|
+
attr_reader :jsonName
|
19
|
+
|
20
|
+
def initialize
|
21
|
+
@collectorType = RUBY
|
22
|
+
@language = Ruby
|
23
|
+
@jsonName = :applicationinfo
|
24
|
+
@collectorVersion = NewRelic::Security::VERSION
|
25
|
+
@buildNumber = nil
|
26
|
+
@jsonVersion = NewRelic::Security::Agent.config[:json_version]
|
27
|
+
@startTime = current_time_millis
|
28
|
+
@applicationUUID = NewRelic::Security::Agent.config[:uuid]
|
29
|
+
@framework = NewRelic::Security::Agent.config[:framework]
|
30
|
+
@groupName = NewRelic::Security::Agent.config[:mode]
|
31
|
+
@userProvidedApplicationInfo = Hash.new
|
32
|
+
@policyVersion = nil
|
33
|
+
@userDir = nil
|
34
|
+
@libraryPath = library_path
|
35
|
+
@bootLibraryPath = EMPTY_STRING
|
36
|
+
@binaryName = binary_name
|
37
|
+
@binaryVersion = binary_version
|
38
|
+
@pid = pid
|
39
|
+
@cpid = cpid
|
40
|
+
@binaryPath = binary_path
|
41
|
+
@agentAttachmentType = STATIC
|
42
|
+
@sha256 = sha_256
|
43
|
+
@runCommand = run_command
|
44
|
+
@cmdline = [run_command]
|
45
|
+
@procStartTime = current_time_millis
|
46
|
+
@osArch = os_arch
|
47
|
+
@osName = os_name
|
48
|
+
@osVersion = os_version
|
49
|
+
@serverInfo = Hash.new # TODO: Fill this
|
50
|
+
@identifier = Hash.new # TODO: Fill this
|
51
|
+
@linkingMetadata = add_linking_metadata
|
52
|
+
end
|
53
|
+
|
54
|
+
def as_json
|
55
|
+
instance_variables.map! do |ivar|
|
56
|
+
[ivar[1..-1].to_sym, instance_variable_get(ivar)]
|
57
|
+
end.to_h
|
58
|
+
end
|
59
|
+
|
60
|
+
def to_json
|
61
|
+
as_json.to_json
|
62
|
+
end
|
63
|
+
|
64
|
+
def update_app_info
|
65
|
+
@identifier[KIND] = 'HOST' # TODO: Added other identifier details
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
def current_time_millis
|
71
|
+
(Time.now.to_f * 1000).to_i
|
72
|
+
end
|
73
|
+
|
74
|
+
def library_path
|
75
|
+
ENV[RUBYLIB].split(COLON)
|
76
|
+
end
|
77
|
+
|
78
|
+
def binary_name
|
79
|
+
RUBY_ENGINE
|
80
|
+
end
|
81
|
+
|
82
|
+
def binary_version
|
83
|
+
RUBY_VERSION
|
84
|
+
end
|
85
|
+
|
86
|
+
def pid
|
87
|
+
return ::Process.pid if ::Gem.win_platform?
|
88
|
+
::Process.getpgrp
|
89
|
+
end
|
90
|
+
|
91
|
+
def cpid
|
92
|
+
Process.pid
|
93
|
+
end
|
94
|
+
|
95
|
+
def binary_path
|
96
|
+
return ::File.realpath(PROC_SELF_EXE) if ::File.exist?(PROC_SELF_EXE)
|
97
|
+
nil
|
98
|
+
end
|
99
|
+
|
100
|
+
def sha_256
|
101
|
+
return ::Digest::SHA256.file(binary_path).hexdigest if binary_path
|
102
|
+
nil
|
103
|
+
end
|
104
|
+
|
105
|
+
def run_command
|
106
|
+
return ::File.read(PROC_SELF_CMDLINE).delete(BACKSLASH000) if File.exist?(PROC_SELF_CMDLINE)
|
107
|
+
$PROGRAM_NAME
|
108
|
+
end
|
109
|
+
|
110
|
+
def os_arch
|
111
|
+
::Gem::Platform.local.cpu
|
112
|
+
end
|
113
|
+
|
114
|
+
def os_name
|
115
|
+
::Gem::Platform.local.os
|
116
|
+
end
|
117
|
+
|
118
|
+
def os_version
|
119
|
+
::Gem::Platform.local.version
|
120
|
+
end
|
121
|
+
|
122
|
+
def add_linking_metadata
|
123
|
+
linking_metadata = Hash.new
|
124
|
+
linking_metadata[:agentRunId] = NewRelic::Security::Agent.config[:agent_run_id]
|
125
|
+
linking_metadata.merge!(NewRelic::Security::Agent.config[:linking_metadata])
|
126
|
+
# TODO: add other fields as well in linking metadata, for event and heathcheck as well
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'set'
|
4
|
+
require 'json'
|
5
|
+
|
6
|
+
module NewRelic::Security
|
7
|
+
module Agent
|
8
|
+
module Control
|
9
|
+
|
10
|
+
|
11
|
+
class ApplicationURLMappings
|
12
|
+
attr_reader :jsonName
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
@collectorType = RUBY
|
16
|
+
@language = Ruby
|
17
|
+
@jsonName = :'sec-application-url-mapping'
|
18
|
+
@eventType = :'sec-application-url-mapping'
|
19
|
+
@collectorVersion = NewRelic::Security::VERSION
|
20
|
+
@buildNumber = nil
|
21
|
+
@jsonVersion = NewRelic::Security::Agent.config[:json_version]
|
22
|
+
@timestamp = current_time_millis
|
23
|
+
@applicationUUID = NewRelic::Security::Agent.config[:uuid]
|
24
|
+
@framework = NewRelic::Security::Agent.config[:framework]
|
25
|
+
@groupName = NewRelic::Security::Agent.config[:mode]
|
26
|
+
@policyVersion = nil
|
27
|
+
@linkingMetadata = add_linking_metadata
|
28
|
+
@mappings = []
|
29
|
+
end
|
30
|
+
|
31
|
+
def as_json
|
32
|
+
instance_variables.map! do |ivar|
|
33
|
+
[ivar[1..-1].to_sym, instance_variable_get(ivar)]
|
34
|
+
end.to_h
|
35
|
+
end
|
36
|
+
|
37
|
+
def to_json
|
38
|
+
as_json.to_json
|
39
|
+
end
|
40
|
+
|
41
|
+
def update_application_url_mappings
|
42
|
+
maps = ::Set.new
|
43
|
+
NewRelic::Security::Agent.agent.route_map.each do |mapping|
|
44
|
+
method, path = mapping.split('@')
|
45
|
+
maps << { :method => method, :path => path }
|
46
|
+
end
|
47
|
+
@mappings = maps.to_a
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def current_time_millis
|
53
|
+
(Time.now.to_f * 1000).to_i
|
54
|
+
end
|
55
|
+
|
56
|
+
def add_linking_metadata
|
57
|
+
linking_metadata = {}
|
58
|
+
linking_metadata[:agentRunId] = NewRelic::Security::Agent.config[:agent_run_id]
|
59
|
+
linking_metadata.merge!(NewRelic::Security::Agent.config[:linking_metadata])
|
60
|
+
# TODO: add other fields as well in linking metadata, for event and heathcheck as well
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'digest'
|
3
|
+
require 'pathname'
|
4
|
+
|
5
|
+
module NewRelic::Security
|
6
|
+
module Agent
|
7
|
+
module Control
|
8
|
+
module Collector
|
9
|
+
|
10
|
+
COVERAGE = 101
|
11
|
+
MARSHAL_RB = 'marshal.rb'
|
12
|
+
LOAD = 'load'
|
13
|
+
PSYCH_RB = 'psych.rb'
|
14
|
+
MARSHAL_LOAD = 'marshal_load'
|
15
|
+
EVAL = 'eval'
|
16
|
+
|
17
|
+
extend self
|
18
|
+
|
19
|
+
def collect(case_type, args, event_category = nil, **keyword_args)
|
20
|
+
return unless NewRelic::Security::Agent.config[:enabled]
|
21
|
+
return if NewRelic::Security::Agent::Control::HTTPContext.get_context.nil? && NewRelic::Security::Agent::Control::GRPCContext.get_context.nil?
|
22
|
+
args.map! { |file| Pathname.new(file).relative? ? File.join(Dir.pwd, file) : file } if [FILE_OPERATION, FILE_INTEGRITY].include?(case_type)
|
23
|
+
|
24
|
+
event = NewRelic::Security::Agent::Control::Event.new(case_type, args, event_category)
|
25
|
+
stk = caller_locations[1..COVERAGE]
|
26
|
+
event.sourceMethod = stk[0].label
|
27
|
+
|
28
|
+
event.copy_http_info(NewRelic::Security::Agent::Control::HTTPContext.get_context) if NewRelic::Security::Agent::Control::HTTPContext.get_context
|
29
|
+
event.copy_grpc_info(NewRelic::Security::Agent::Control::GRPCContext.get_context) if NewRelic::Security::Agent::Control::GRPCContext.get_context
|
30
|
+
event.isIASTEnable = true if NewRelic::Security::Agent::Utils.is_IAST?
|
31
|
+
event.isIASTRequest = true if NewRelic::Security::Agent::Utils.is_IAST_request?(event.httpRequest[:headers])
|
32
|
+
event.parentId = event.httpRequest[:headers][NR_CSEC_PARENT_ID] if event.httpRequest[:headers].key?(NR_CSEC_PARENT_ID)
|
33
|
+
find_deserialisation(event, stk) if case_type != REFLECTED_XSS && NewRelic::Security::Agent.config[:'security.detection.deserialization.enabled']
|
34
|
+
find_rci(event, stk) if case_type != REFLECTED_XSS && NewRelic::Security::Agent.config[:'security.detection.rci.enabled']
|
35
|
+
route = nil
|
36
|
+
if case_type == REFLECTED_XSS
|
37
|
+
event.httpResponse[:contentType] = keyword_args[:response_header]
|
38
|
+
route = NewRelic::Security::Agent::Control::HTTPContext.get_context.route
|
39
|
+
if route && NewRelic::Security::Agent.agent.route_map.include?(route)
|
40
|
+
event.stacktrace << route
|
41
|
+
end
|
42
|
+
end
|
43
|
+
# In rails 5 method name keeps chaning for same api call (ex: _app_views_sqli_sqlinjectionattackcase_html_erb__1999281606898621405_2624809100).
|
44
|
+
# Hence, considering only frame absolute_path & lineno for apiId calculation.
|
45
|
+
user_frame_index = get_user_frame_index(stk)
|
46
|
+
event.apiId = "#{case_type}-#{calculate_api_id(stk[0..user_frame_index].map { |frame| "#{frame.absolute_path}:#{frame.lineno}" }, event.httpRequest[:method], route)}"
|
47
|
+
stk.delete_if {|frame| frame.path.match(/newrelic_security/) || frame.path.match(/new_relic/)}
|
48
|
+
user_frame_index = get_user_frame_index(stk)
|
49
|
+
return if case_type != REFLECTED_XSS && user_frame_index == -1 # TODO: Add log message here: "Filtered because User Stk frame NOT FOUND \r\n"
|
50
|
+
if user_frame_index != -1
|
51
|
+
event.userMethodName = stk[user_frame_index].label.to_s
|
52
|
+
event.userFileName = stk[user_frame_index].path
|
53
|
+
event.lineNumber = stk[user_frame_index].lineno
|
54
|
+
else
|
55
|
+
event.sourceMethod = stk[0].label.to_s
|
56
|
+
event.userMethodName = stk[0].label.to_s
|
57
|
+
event.userFileName = stk[0].path
|
58
|
+
event.lineNumber = stk[0].lineno
|
59
|
+
end
|
60
|
+
event.stacktrace = stk[0..user_frame_index].map(&:to_s)
|
61
|
+
NewRelic::Security::Agent.agent.event_processor.send_event(event)
|
62
|
+
if event.httpRequest[:headers].key?(NR_CSEC_FUZZ_REQUEST_ID) && event.apiId == event.httpRequest[:headers][NR_CSEC_FUZZ_REQUEST_ID].split(COLON_IAST_COLON)[0]
|
63
|
+
NewRelic::Security::Agent.agent.iast_client.completed_requests[event.parentId] << event.id if NewRelic::Security::Agent.agent.iast_client.completed_requests[event.parentId]
|
64
|
+
end
|
65
|
+
event
|
66
|
+
rescue Exception => exception
|
67
|
+
NewRelic::Security::Agent.logger.error "Exception in event collector: #{exception.inspect} #{exception.backtrace}"
|
68
|
+
NewRelic::Security::Agent.agent.event_processor.send_critical_message(exception.message, "SEVERE", caller_locations[0].to_s, Thread.current.name, exception)
|
69
|
+
if NewRelic::Security::Agent::Utils.is_IAST_request?(event.httpRequest[:headers])
|
70
|
+
NewRelic::Security::Agent.agent.iast_event_stats.error_count.increment
|
71
|
+
else
|
72
|
+
NewRelic::Security::Agent.agent.rasp_event_stats.error_count.increment
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def get_user_frame_index(stk)
|
79
|
+
return -1 if NewRelic::Security::Agent.config[:app_root].nil?
|
80
|
+
stk.each_with_index do |val, index|
|
81
|
+
return index if val.path.start_with?(NewRelic::Security::Agent.config[:app_root])
|
82
|
+
end
|
83
|
+
return -1
|
84
|
+
end
|
85
|
+
|
86
|
+
def calculate_api_id(stk, method, route)
|
87
|
+
stk << route if route
|
88
|
+
::Digest::SHA256.hexdigest("#{stk.join(PIPE)}|#{method}").to_s
|
89
|
+
rescue Exception => e
|
90
|
+
NewRelic::Security::Agent.logger.error "Exception in calculate_api_id : #{e} #{e.backtrace}"
|
91
|
+
nil
|
92
|
+
end
|
93
|
+
|
94
|
+
def find_deserialisation(event, stk)
|
95
|
+
stk.each_with_index { |val, index|
|
96
|
+
if (val.path.end_with?(MARSHAL_RB) && val.label == LOAD) || (val.path.end_with?(PSYCH_RB) && val.label == LOAD) || (val.label == MARSHAL_LOAD)
|
97
|
+
event.metaData[:triggerViaDeserialisation] = true
|
98
|
+
event.metaData[:rciMethodsCalls] = stk[0..index].collect { |frame| frame.label }
|
99
|
+
return
|
100
|
+
end
|
101
|
+
}
|
102
|
+
end
|
103
|
+
|
104
|
+
def find_rci(event, stk)
|
105
|
+
stk.each_with_index { |val, index|
|
106
|
+
if val.label == EVAL
|
107
|
+
event.metaData[:triggerViaRCI] = true
|
108
|
+
event.metaData[:rciMethodsCalls] = stk[0..index].collect { |frame| frame.label }
|
109
|
+
return
|
110
|
+
end
|
111
|
+
}
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module NewRelic::Security
|
4
|
+
module Agent
|
5
|
+
module Control
|
6
|
+
module ControlCommand
|
7
|
+
|
8
|
+
extend self
|
9
|
+
|
10
|
+
def handle_ic_command(message)
|
11
|
+
message_json = parse_message(message)
|
12
|
+
define_transform_keys unless message_json.respond_to?(:transform_keys)
|
13
|
+
message_object = message_json.transform_keys(&:to_sym)
|
14
|
+
return if message_object.nil?
|
15
|
+
|
16
|
+
if message_object.has_key?(:controlCommand)
|
17
|
+
case message_object[:controlCommand]
|
18
|
+
when 4
|
19
|
+
|
20
|
+
when 5
|
21
|
+
NewRelic::Security::Agent.logger.debug "Control command : '5', #{message_object}"
|
22
|
+
when 6
|
23
|
+
|
24
|
+
when 7
|
25
|
+
NewRelic::Security::Agent.logger.debug "Control command : '7', #{message_object}"
|
26
|
+
when 10
|
27
|
+
NewRelic::Security::Agent.logger.debug "Control command : '10', #{message_object}"
|
28
|
+
when 11
|
29
|
+
NewRelic::Security::Agent.logger.debug "Control command : '11', #{message_object.to_json}"
|
30
|
+
NewRelic::Security::Agent.config.update_port = message_object[:reflectedMetaData][LISTEN_PORT].to_i unless NewRelic::Security::Agent.config[:listen_port]
|
31
|
+
NewRelic::Security::Agent.agent.iast_client.last_fuzz_cc_timestamp = current_time_millis
|
32
|
+
fuzz_request = NewRelic::Security::Agent::Control::FuzzRequest.new(message_object[:id])
|
33
|
+
fuzz_request.request = prepare_fuzz_request(message_object)
|
34
|
+
fuzz_request.case_type = message_object[:arguments][1]
|
35
|
+
fuzz_request.reflected_metadata = message_object[:reflectedMetaData]
|
36
|
+
NewRelic::Security::Agent.agent.iast_client.pending_request_ids << message_object[:id]
|
37
|
+
NewRelic::Security::Agent.agent.iast_client.enqueue(fuzz_request)
|
38
|
+
fuzz_request = nil
|
39
|
+
when 12
|
40
|
+
NewRelic::Security::Agent.logger.info "Validator asked to reconnect(CC#12), calling reconnect_at_will"
|
41
|
+
reconnect_at_will
|
42
|
+
when 13
|
43
|
+
NewRelic::Security::Agent.logger.debug "Control command : '13', #{message_object}"
|
44
|
+
NewRelic::Security::Agent.logger.debug "Received IAST cooldown. Waiting for next : #{message_object[:data]} Seconds"
|
45
|
+
NewRelic::Security::Agent.agent.iast_client.cooldown_till_timestamp = current_time_millis + (message_object[:data] * 1000)
|
46
|
+
when 14
|
47
|
+
NewRelic::Security::Agent.logger.debug "Control command : '14', #{message_object}"
|
48
|
+
NewRelic::Security::Agent.logger.debug "Purging confirmed IAST processed records count : #{message_object[:arguments].size}"
|
49
|
+
message_object[:arguments].each { |processed_id| NewRelic::Security::Agent.agent.iast_client.completed_requests.delete(processed_id) }
|
50
|
+
when 100
|
51
|
+
NewRelic::Security::Agent.logger.debug "Control command : '100', #{message_object.to_json}"
|
52
|
+
::NewRelic::Agent.instance.events.notify(:security_policy_received, message_object[:data])
|
53
|
+
# TODO: Update policy from file here, if enabled.
|
54
|
+
when 101
|
55
|
+
|
56
|
+
when 102
|
57
|
+
NewRelic::Security::Agent.logger.error "Update policy failed at validator with error : #{message_object}"
|
58
|
+
# TODO: Apply initial policy here
|
59
|
+
when 1006
|
60
|
+
# TODO: abnormal closure in which case LC anyway have to reconnect
|
61
|
+
when 1013
|
62
|
+
# TODO: ndicates that the service is experiencing overload. A client should only connect to a different IP (when there are multiple for the target) or reconnect to the same IP upon user action.
|
63
|
+
else
|
64
|
+
NewRelic::Security::Agent.logger.error "Unrecognized control command : #{message_object}"
|
65
|
+
end
|
66
|
+
else
|
67
|
+
NewRelic::Security::Agent.logger.error "Control command is missing in IC message : #{message_object}"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def define_transform_keys
|
72
|
+
::Hash.class_eval do
|
73
|
+
def transform_keys
|
74
|
+
result = {}
|
75
|
+
each_key do |key|
|
76
|
+
result[yield(key)] = self[key]
|
77
|
+
end
|
78
|
+
result
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
def parse_message(message)
|
86
|
+
JSON.parse(message)
|
87
|
+
rescue JSON::ParserError => error
|
88
|
+
NewRelic::Security::Agent.logger.error "Error in parsing IC message : #{error.inspect}"
|
89
|
+
NewRelic::Security::Agent.agent.event_processor.send_critical_message(exception.message, "SEVERE", caller_locations[0].to_s, Thread.current.name, exception)
|
90
|
+
nil
|
91
|
+
end
|
92
|
+
|
93
|
+
def reconnect_at_will
|
94
|
+
NewRelic::Security::Agent.agent.iast_client.fuzzQ.clear if NewRelic::Security::Agent.agent.iast_client
|
95
|
+
NewRelic::Security::Agent.agent.iast_client.completed_requests.clear if NewRelic::Security::Agent.agent.iast_client
|
96
|
+
NewRelic::Security::Agent.agent.iast_client.pending_request_ids.clear if NewRelic::Security::Agent.agent.iast_client
|
97
|
+
NewRelic::Security::Agent.config.disable_security
|
98
|
+
Thread.new { NewRelic::Security::Agent.agent.reconnect(0) }
|
99
|
+
end
|
100
|
+
|
101
|
+
def current_time_millis
|
102
|
+
(Time.now.to_f * 1000).to_i
|
103
|
+
end
|
104
|
+
|
105
|
+
def prepare_fuzz_request(message_object)
|
106
|
+
message_object[:arguments][0].gsub!(NR_CSEC_VALIDATOR_HOME_TMP, NewRelic::Security::Agent.config[:fuzz_dir_path])
|
107
|
+
message_object[:arguments][0].gsub!(NR_CSEC_VALIDATOR_FILE_SEPARATOR, ::File::SEPARATOR)
|
108
|
+
prepared_fuzz_request = ::JSON.parse(message_object[:arguments][0])
|
109
|
+
prepared_fuzz_request[HEADERS][NR_CSEC_PARENT_ID] = message_object[:id]
|
110
|
+
prepared_fuzz_request
|
111
|
+
rescue Exception => exception # rubocop:disable Lint/RescueException
|
112
|
+
NewRelic::Security::Agent.logger.error "Exception in preparing fuzz request : #{exception.inspect} #{exception.backtrace}"
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|