Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integration of Newrelic Ruby Security agent #2752

Merged
merged 64 commits into from
Jul 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
d04d5ac
k2
fallwith Apr 28, 2023
b930ca7
New Relic
fallwith Apr 28, 2023
8803079
Merge branch 'dev' into k2
fallwith May 4, 2023
fcd8604
add security.applicationinfo.port
fallwith May 9, 2023
9d56dfe
description for security.applicationinfo.port
fallwith May 9, 2023
2e8db5d
NewRelic::Control::SecurityInterface
fallwith May 11, 2023
27fd636
security interface and gem dependency
fallwith May 11, 2023
4d208f2
Merge pull request #2005 from newrelic/security_interface
fallwith May 11, 2023
c9c7c06
gemspec: remove blank line
fallwith May 11, 2023
8caad2d
SecurityInterface: Ruby <= 2.4 compatibility
fallwith May 11, 2023
31619c6
Merge pull request #2006 from newrelic/security_interface_older_rubies
fallwith May 11, 2023
a37646c
Merge branch 'dev' into k2
fallwith May 11, 2023
9764d2c
Merge branch 'dev' into k2
fallwith May 31, 2023
ca1ad1b
unit tests for SecurityInterface
fallwith Jun 1, 2023
9b22388
Merge pull request #2043 from newrelic/k2_security_interface_tests
fallwith Jun 1, 2023
96fa214
security interface tests: skip MiniTest 4
fallwith Jun 1, 2023
2e68347
Merge pull request #2045 from newrelic/security_interface_tests
fallwith Jun 1, 2023
561b92a
Update lib/new_relic/agent/configuration/default_source.rb
fallwith Jun 2, 2023
dca3f03
Update lib/new_relic/agent/configuration/default_source.rb
fallwith Jun 2, 2023
042017f
Update lib/new_relic/agent/configuration/default_source.rb
fallwith Jun 2, 2023
5ace3bf
Update lib/new_relic/agent/configuration/default_source.rb
fallwith Jun 2, 2023
0e7bc16
more security agent config descriptions
fallwith Jun 2, 2023
075f2ae
still more security agent config
fallwith Jun 2, 2023
91b4beb
the The
fallwith Jun 3, 2023
6567ddc
updated security config: application_info
prateeksen Jun 5, 2023
b0a8c86
set allow_nil to true for security.application_info.port
prateeksen Jun 6, 2023
009e9c2
Merge pull request #2047 from newrelic/k2-config-update
prateeksen Jun 6, 2023
54970dc
add handling security disable of high security enabled
prateeksen Jun 8, 2023
d5dda8a
update security_interface_test for high_security config changes
prateeksen Jun 8, 2023
120d615
security agent tests: updates to 3 param checks
fallwith Jun 8, 2023
e7bb788
Merge pull request #2060 from newrelic/k2-disable-on-high-security-en…
fallwith Jun 8, 2023
36b3bc4
CI: upgrade to setup-ruby v1.151.0
fallwith Jun 8, 2023
d7cde65
Merge branch 'dev' into k2
fallwith Jun 20, 2023
d0f2f49
Merge branch 'dev' into k2
fallwith Jun 20, 2023
d9d66b1
Add supportability enabed/disabled metric
hannahramadan Oct 24, 2023
944d421
Remove scratch work
hannahramadan Oct 24, 2023
5546674
2 supportability metrics
hannahramadan Oct 24, 2023
92f3b0f
Fix test
hannahramadan Oct 24, 2023
6d7b411
Reset supportability metrics
hannahramadan Oct 25, 2023
da5b18c
Add supportability metrics enabled method
hannahramadan Oct 25, 2023
47ef119
Merge branch 'dev' into supportability_metrics
hannahramadan Oct 26, 2023
51da1f4
regenerate rubocop todo
hannahramadan Oct 26, 2023
c311176
regenerate todo
hannahramadan Oct 26, 2023
ec33d21
appease rubocop once more
hannahramadan Oct 26, 2023
3cff631
Merge pull request #2286 from newrelic/supportability_metrics
hannahramadan Oct 27, 2023
7a71f62
Merge pull request #2395 from newrelic/dev
prateeksen Jan 12, 2024
9ef6733
Merge branch 'dev' into k2
prateeksen Jan 19, 2024
5f4ffcc
Merge branch 'dev' into k2
prateeksen Apr 15, 2024
78036b9
add allowlist[IAST RASP] for security.mode & new security config secu…
prateeksen Apr 15, 2024
82fb2fb
Merge branch 'dev' into k2
prateeksen May 13, 2024
863aeee
log security config when IAST is disabled
prateeksen May 13, 2024
33dbbf5
Merge branch 'dev' into k2
prateeksen Jul 8, 2024
0008a94
Update UTs for SecurityInterface
prateeksen Jul 11, 2024
36b4a41
Merge branch 'dev' into k2
prateeksen Jul 16, 2024
5840f64
security.enabled should be checked in Security agent only and not in …
prateeksen Jul 16, 2024
4a0bfe9
Merge branch 'dev' into k2
prateeksen Jul 17, 2024
37d26c9
add config reset to prevent leaky tests
tannalynn Jul 17, 2024
9e552c9
reset metrics for tests
tannalynn Jul 17, 2024
863c5f1
Update lib/new_relic/agent/configuration/default_source.rb
prateeksen Jul 18, 2024
d933a5d
Update lib/new_relic/control/security_interface.rb
prateeksen Jul 18, 2024
db297b8
PR review suggestions incorporated
prateeksen Jul 18, 2024
bd0d524
add RASP in allowlist for dev and testing
prateeksen Jul 22, 2024
5d9c813
Update lib/new_relic/agent/configuration/default_source.rb
prateeksen Jul 22, 2024
7c0b475
Update lib/new_relic/agent/configuration/default_source.rb
prateeksen Jul 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 10 additions & 5 deletions .rubocop_todo.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# This configuration was generated by
# `rubocop --auto-gen-config`
# on 2023-05-18 21:20:20 UTC using RuboCop version 1.51.0.
# on 2023-10-26 22:54:31 UTC using RuboCop version 1.54.0.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
# versions of RuboCop, may require this file to be generated again.

# Offense count: 30
# Offense count: 31
# Configuration parameters: EnforcedStyle, AllowedGems, Include.
# SupportedStyles: Gemfile, gems.rb, gemspec
# Include: **/*.gemspec, **/Gemfile, **/gems.rb
Expand All @@ -15,15 +15,20 @@ Gemspec/DevelopmentDependencies:
- 'infinite_tracing/newrelic-infinite_tracing.gemspec'
- 'newrelic_rpm.gemspec'

# Offense count: 416
# Offense count: 443
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes.
Metrics/AbcSize:
Max: 40
Exclude:
- 'lib/new_relic/agent/configuration/default_source.rb'
- infinite_tracing/test/**/*
- lib/new_relic/cli/commands/deployments.rb
- test/**/*

Metrics/CollectionLiteralLength:
Exclude:
- 'lib/new_relic/agent/configuration/default_source.rb'

# Offense count: 7
Minitest/AssertRaisesCompoundBody:
Exclude:
Expand All @@ -37,15 +42,15 @@ Minitest/DuplicateTestRun:
- 'test/multiverse/suites/rails/error_tracing_test.rb'
- 'test/multiverse/suites/sinatra/ignoring_test.rb'

# Offense count: 276
# Offense count: 284
Minitest/MultipleAssertions:
Max: 28

# Offense count: 19
Minitest/TestFileName:
Enabled: false

# Offense count: 22
# Offense count: 20
# This cop supports safe autocorrection (--autocorrect).
Minitest/TestMethodName:
Enabled: false
Expand Down
1 change: 1 addition & 0 deletions lib/new_relic/agent/agent_logger.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

require 'thread'
require 'logger'
require 'singleton'
require 'new_relic/agent/hostname'
require 'new_relic/agent/log_once'
require 'new_relic/agent/instrumentation/logger/instrumentation'
Expand Down
80 changes: 79 additions & 1 deletion lib/new_relic/agent/configuration/default_source.rb
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ def self.transform_for(key)
value_from_defaults(key, :transform)
end

def self.config_search_paths # rubocop:disable Metrics/AbcSize
def self.config_search_paths
proc {
yaml = 'newrelic.yml'
config_yaml = File.join('config', yaml)
Expand Down Expand Up @@ -2570,6 +2570,84 @@ def self.enforce_fallback(allowed_values: nil, fallback: nil)
:type => Integer,
:allowed_from_server => false,
:description => 'This value represents the total amount of memory available to the host (not the process), in mebibytes (1024 squared or 1,048,576 bytes).'
},
# security agent
:'security.agent.enabled' => {
:default => false,
:external => true,
:public => true,
:type => Boolean,
:allowed_from_server => false,
:description => "If `true`, the security agent is loaded (a Ruby 'require' is performed)"
},
:'security.enabled' => {
:default => false,
:external => true,
:public => true,
:type => Boolean,
:allowed_from_server => false,
:description => 'If `true`, the security agent is started (the agent runs in its event loop)'
},
:'security.mode' => {
fallwith marked this conversation as resolved.
Show resolved Hide resolved
:default => 'IAST',
:external => true,
:public => true,
:type => String,
:allowed_from_server => true,
:allowlist => %w[IAST RASP],
:description => 'Defines the mode for the security agent to operate in. Currently only `IAST` is supported',
:dynamic_name => true
},
:'security.validator_service_url' => {
:default => 'wss://csec.nr-data.net',
:external => true,
:public => true,
:type => String,
:allowed_from_server => true,
:description => 'Defines the endpoint URL for posting security-related data',
:dynamic_name => true
},
:'security.detection.rci.enabled' => {
:default => true,
:external => true,
:public => true,
:type => Boolean,
:allowed_from_server => false,
:description => 'If `true`, enables RCI (remote code injection) detection'
},
:'security.detection.rxss.enabled' => {
:default => true,
:external => true,
:public => true,
:type => Boolean,
:allowed_from_server => false,
:description => 'If `true`, enables RXSS (reflected cross-site scripting) detection'
},
:'security.detection.deserialization.enabled' => {
:default => true,
:external => true,
:public => true,
:type => Boolean,
:allowed_from_server => false,
:description => 'If `true`, enables deserialization detection'
},
:'security.application_info.port' => {
:default => nil,
:allow_nil => true,
:public => true,
:type => Integer,
:external => true,
:allowed_from_server => false,
:description => 'The port the application is listening on. This setting is mandatory for Passenger servers. Other servers should be detected by default.'
},
:'security.request.body_limit' => {
:default => 300,
:allow_nil => true,
:public => true,
:type => Integer,
:external => true,
:allowed_from_server => false,
:description => 'Defines the request body limit to process in security events (in KB). The default value is 300, for 300KB.'
}
}.freeze
# rubocop:enable Metrics/CollectionLiteralLength
Expand Down
1 change: 1 addition & 0 deletions lib/new_relic/agent/database/obfuscator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
# frozen_string_literal: true

require 'singleton'
require 'new_relic/agent/database/obfuscation_helpers'

module NewRelic
Expand Down
3 changes: 3 additions & 0 deletions lib/new_relic/agent/instrumentation/rack/instrumentation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class << builder_class
attr_accessor :_nr_deferred_detection_ran
end
builder_class._nr_deferred_detection_ran = false
NewRelic::Control::SecurityInterface.instance.wait = true
end

def deferred_dependency_check
Expand All @@ -21,6 +22,8 @@ def deferred_dependency_check
NewRelic::Agent.logger.info('Doing deferred dependency-detection before Rack startup')
DependencyDetection.detect!
self.class._nr_deferred_detection_ran = true
NewRelic::Control::SecurityInterface.instance.wait = false
NewRelic::Control::SecurityInterface.instance.init_agent
end

def check_for_late_instrumentation(app)
Expand Down
2 changes: 1 addition & 1 deletion lib/new_relic/control.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
require 'new_relic/language_support'
require 'new_relic/helper'

require 'singleton'
require 'erb'
require 'socket'
require 'net/https'
Expand All @@ -18,6 +17,7 @@
require 'new_relic/control/instrumentation'
require 'new_relic/control/class_methods'
require 'new_relic/control/instance_methods'
require 'new_relic/control/security_interface'

require 'new_relic/agent'
require 'new_relic/delayed_job_injection'
Expand Down
1 change: 1 addition & 0 deletions lib/new_relic/control/instance_methods.rb
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ def init_plugin(options = {})
init_config(options)
NewRelic::Agent.agent = NewRelic::Agent::Agent.instance
init_instrumentation
init_security_agent
end

def determine_env(options)
Expand Down
4 changes: 4 additions & 0 deletions lib/new_relic/control/private_instance_methods.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ def init_instrumentation
DependencyDetection.detect!
end
end

def init_security_agent
SecurityInterface.instance.init_agent
end
end
end
end
57 changes: 57 additions & 0 deletions lib/new_relic/control/security_interface.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# This file is distributed under New Relic's license terms.
# See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
# frozen_string_literal: true

require 'singleton'

module NewRelic
class Control
class SecurityInterface
include Singleton

attr_accessor :wait

SUPPORTABILITY_PREFIX_SECURITY = 'Supportability/Ruby/SecurityAgent/Enabled/'
SUPPORTABILITY_PREFIX_SECURITY_AGENT = 'Supportability/Ruby/SecurityAgent/Agent/Enabled/'
ENABLED = 'enabled'
DISABLED = 'disabled'

def agent_started?
(@agent_started ||= false) == true
end

def waiting?
(@wait ||= false) == true
end

def init_agent
return if agent_started? || waiting?

record_supportability_metrics

if Agent.config[:'security.agent.enabled'] && !Agent.config[:high_security]
Agent.logger.info('Invoking New Relic security module')
require 'newrelic_security'

@agent_started = true
else
Agent.logger.info('New Relic Security is completely disabled by one of the user-provided configurations: `security.agent.enabled` or `high_security`. Not loading security capabilities.')
Agent.logger.info("high_security = #{Agent.config[:high_security]}")
Agent.logger.info("security.agent.enabled = #{Agent.config[:'security.agent.enabled']}")
end
rescue LoadError
Agent.logger.info('New Relic security agent not found - skipping')
rescue StandardError => exception
Agent.logger.error("Exception in New Relic security module loading: #{exception} #{exception.backtrace}")
end

def record_supportability_metrics
Agent.config[:'security.agent.enabled'] ? security_agent_metric(ENABLED) : security_agent_metric(DISABLED)
end

def security_agent_metric(setting)
NewRelic::Agent.record_metric_once(SUPPORTABILITY_PREFIX_SECURITY_AGENT + setting)
end
end
end
end
49 changes: 49 additions & 0 deletions newrelic.yml
Original file line number Diff line number Diff line change
Expand Up @@ -853,6 +853,55 @@ common: &default_settings
# Foundry environment.
# utilization.detect_pcf: true

#
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hannahramadan we'll likely need some help here getting these comments moved into default_source.rb and/or the newrelic.yml auto-generator so that these changes aren't lost the next time the file is auto-generated.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fallwith roger that! I'll make a ticket for this

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great suggestion, @fallwith. Thank you for making the ticket, @hannahramadan! I think we may also want to consider adding this content to the auto-generated configuration docs that get published on the New Relic Docs website.

# BEGIN security agent
#
# NOTE: At this time, the security agent is intended for use only within
# a dedicated security testing environment with data that can tolerate
# modification or deletion. The security agent is available as a
# separate Ruby gem, newrelic_security. It is recommended that this
# separate gem only be introduced to a security testing environment
# by leveraging Bundler grouping like so:
#
# # Gemfile
# gem 'newrelic_rpm' # New Relic APM observability agent
# gem 'newrelic-infinite_tracing' # New Relic Infinite Tracing
#
# group :security do
# gem 'newrelic_security' # New Relic security agent
# end
#
# NOTE: All "security.*" configuration parameters are related only to the
# security agent, and all other configuration parameters that may
# have "security" in the name some where are related to the APM agent.
#

# If true, the security agent is loaded (a Ruby 'require' is performed)
# security.agent.enabled: false

# If true, the security agent is started (the agent runs in its event loop)
# security.enabled: false

# Defines the mode for the security agent to operate in. Currently only 'IAST' is supported
# security.mode: IAST

# Defines the endpoint URL for posting security related data
# security.validator_service_url: wss://csec.nr-data.net

# If `true`, enables RCI(Remote Code Injection) detection
# security.detection.rci.enabled: true

# If `true`, enables RXSS(Reflected Cross-site Scripting) detection
# security.detection.rxss.enabled: true

# If `true`, enables deserialization detection
# security.detection.deserialization.enabled: true

# The port the application is listening on. This setting is mandatory for Passenger servers. Other servers should be detected by default.
# security.application_info.port: nil

# END security agent

# Environment-specific settings are in this section.
# RAILS_ENV or RACK_ENV (as appropriate) is used to determine the environment.
# If your application has other named environments, configure them here.
Expand Down
Loading
Loading