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

don't log the license key even in debug/audit #2339

Merged
merged 3 commits into from
Dec 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions lib/new_relic/agent/configuration/default_source.rb
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,7 @@ def self.enforce_fallback(allowed_values: nil, fallback: nil)
:public => true,
:type => String,
:allowed_from_server => false,
:exclude_from_reported_settings => true,
:description => 'Your New Relic <InlinePopover type="licenseKey" />.'
},
:log_level => {
Expand Down
13 changes: 7 additions & 6 deletions lib/new_relic/agent/configuration/manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ def apply_mask(hash)
end

def to_collector_hash
DottedHash.new(apply_mask(flattened)).to_hash.delete_if do |k, v|
DottedHash.new(apply_mask(flattened)).to_hash.delete_if do |k, _v|
default = DEFAULTS[k]
if default
default[:exclude_from_reported_settings]
Expand Down Expand Up @@ -376,12 +376,13 @@ def new_cache
end

def log_config(direction, source)
# Just generating this log message (specifically calling
# flattened.inspect) is expensive enough that we don't want to do it
# unless we're actually going to be logging the message based on our
# current log level.
# Just generating this log message (specifically calling `flattened`)
# is expensive enough that we don't want to do it unless we're
# actually going to be logging the message based on our current log
# level, so use a `do` block.
::NewRelic::Agent.logger.debug do
"Updating config (#{direction}) from #{source.class}. Results: #{flattened.inspect}"
hash = flattened.delete_if { |k, _h| DEFAULTS.fetch(k, {}).fetch(:exclude_from_reported_settings, false) }
kaylareopelle marked this conversation as resolved.
Show resolved Hide resolved
"Updating config (#{direction}) from #{source.class}. Results: #{hash.inspect}"
end
end

Expand Down
14 changes: 8 additions & 6 deletions lib/new_relic/agent/new_relic_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ def prep_request(opts)
else
request = Net::HTTP::Post.new(opts[:uri], headers)
end
@audit_logger.log_request_headers(opts[:uri], headers)
@audit_logger.log_request_headers(filtered_uri(opts[:uri]), headers)
request['user-agent'] = user_agent
request.content_type = 'application/octet-stream'
request.body = opts[:data]
Expand All @@ -431,7 +431,7 @@ def relay_request(request, opts)
rescue *CONNECTION_ERRORS => e
close_shared_connection
if attempts < MAX_ATTEMPTS
::NewRelic::Agent.logger.debug("Retrying request to #{opts[:collector]}#{opts[:uri]} after #{e}")
::NewRelic::Agent.logger.debug("Retrying request to #{opts[:collector]}#{filtered_uri(opts[:uri])} after #{e}")
retry
else
raise ServerConnectionException, "Recoverable error talking to #{@collector} after #{attempts} attempts: #{e}"
Expand All @@ -444,7 +444,7 @@ def relay_request(request, opts)

def attempt_request(request, opts)
conn = http_connection
::NewRelic::Agent.logger.debug("Sending request to #{opts[:collector]}#{opts[:uri]} with #{request.method}")
::NewRelic::Agent.logger.debug("Sending request to #{opts[:collector]}#{filtered_uri(opts[:uri])} with #{request.method}")
conn.request(request)
end

Expand Down Expand Up @@ -689,9 +689,7 @@ def prep_collector(method)

def invoke_remote_send_request(method, payload, data, encoding)
uri = remote_method_uri(method)
full_uri = "#{@collector}#{uri}"

@audit_logger.log_request(full_uri, payload, @marshaller)
@audit_logger.log_request("#{@collector}#{filtered_uri(uri)}", payload, @marshaller)
request_send_ts = Process.clock_gettime(Process::CLOCK_MONOTONIC)
response = send_request(:data => data,
:uri => uri,
Expand All @@ -700,6 +698,10 @@ def invoke_remote_send_request(method, payload, data, encoding)
:endpoint => method)
[response, request_send_ts, Process.clock_gettime(Process::CLOCK_MONOTONIC)]
end

def filtered_uri(uri)
uri.gsub(license_key, ASTERISK * license_key.size)
end
end
end
end
2 changes: 2 additions & 0 deletions lib/new_relic/constants.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
# frozen_string_literal: true

module NewRelic
ASTERISK = '*'
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice! After this PR, let's consider replacing the two places the agent references '*' with this constant.


PRIORITY_PRECISION = 6

EMPTY_ARRAY = [].freeze
Expand Down
7 changes: 7 additions & 0 deletions test/new_relic/agent/configuration/manager_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,13 @@ def test_unsatisfied_values_stay_cached
end
end

def test_logger_does_not_receive_excluded_settings
log = with_array_logger(:debug) { @manager.log_config('direction', 'source') }.array.join('')

assert_includes(log, ':app_name')
refute_includes(log, ':license_key')
end

private

def assert_parsed_labels(expected)
Expand Down
9 changes: 9 additions & 0 deletions test/new_relic/agent/connect/request_builder_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,13 @@ def test_enviroment_metadata
ensure
ENV[key] = nil
end

def test_excluded_config_settings_are_in_fact_excluded
excluded = NewRelic::Agent::Configuration::DEFAULTS.select { |k, h|
k if h.fetch(:exclude_from_reported_settings, false)
}

refute @request_builder.connect_payload[:settings].keys.detect { |k| excluded.include?(k) },
"Did not expect the request builder's connect payload to include any excluded config settings"
end
end
9 changes: 9 additions & 0 deletions test/new_relic/agent/new_relic_service_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -275,11 +275,13 @@ def test_preconnect_never_uses_redirect_host
initial_connect_log = with_array_logger(level = :debug) { @service.connect }

assert_log_contains initial_connect_log, 'Sending request to localhost'
assert_log_contains initial_connect_log, Regexp.escape('license_key=***********')

# If we need to reconnect, preconnect should use the locally configured collector again
reconnect_log = with_array_logger(level = :debug) { @service.preconnect }

assert_log_contains reconnect_log, 'Sending request to somewhere.example.com'
assert_log_contains reconnect_log, Regexp.escape('license_key=***********')
end

def test_preconnect_with_no_token_and_no_lasp
Expand Down Expand Up @@ -1029,6 +1031,13 @@ def test_headers_cleared_on_subsequent_connect
refute_includes header_keys, 'x-nr-metadata'
end

def test_filtered_uri
base = 'https://cdpr_cp2077.com?license_key='
filtered = @service.send(:filtered_uri, base + @service.send(:license_key))

assert_equal base + '***********', filtered
end

def build_stats_hash(items = {})
hash = NewRelic::Agent::StatsHash.new
items.each do |key, value|
Expand Down
Loading