Skip to content
Closed
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
3 changes: 0 additions & 3 deletions newrelic/api/asgi_application.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,9 +222,6 @@ def __init__(self, application, scope, receive, send, source=None):
source=source,
)

if self._settings:
self.capture_params = self._settings.capture_params

async def send(self, event):
if event["type"] == "http.response.body" and not event.get("more_body", False):
try:
Expand Down
49 changes: 8 additions & 41 deletions newrelic/api/transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
resolve_logging_context_attributes,
truncate,
)
from newrelic.core.attribute_filter import DST_ALL, DST_ERROR_COLLECTOR, DST_NONE, DST_TRANSACTION_TRACER
from newrelic.core.attribute_filter import DST_ALL, DST_NONE
from newrelic.core.config import CUSTOM_EVENT_RESERVOIR_SIZE, LOG_EVENT_RESERVOIR_SIZE, ML_EVENT_RESERVOIR_SIZE
from newrelic.core.custom_event import create_custom_event
from newrelic.core.log_event_node import LogEventNode
Expand Down Expand Up @@ -257,8 +257,6 @@ def __init__(self, application, enabled=None, source=None):
self.suppress_apdex = False
self.suppress_transaction_trace = False

self.capture_params = None

self.apdex = 0

self.rum_token = None
Expand Down Expand Up @@ -928,45 +926,12 @@ def distributed_trace_intrinsics(self):
def filter_request_parameters(self, params):
# Request parameters are a special case of agent attributes, so
# they must be filtered separately

# There are 3 cases we need to handle:
#
# 1. LEGACY: capture_params = False
#
# Don't add request parameters at all, which means they will not
# go through the AttributeFilter.
#
# 2. LEGACY: capture_params = True
#
# Filter request parameters through the AttributeFilter, but
# set the destinations to `TRANSACTION_TRACER | ERROR_COLLECTOR`.
#
# If the user does not add any additional attribute filtering
# rules, this will result in the same outcome as the old
# capture_params = True behavior. They will be added to transaction
# traces and error traces.
#
# 3. CURRENT: capture_params is None
#
# Filter request parameters through the AttributeFilter, but set
# the destinations to NONE.
#
# That means by default, request parameters won't get included in
# any destination. But, it will allow user added include/exclude
# attribute filtering rules to be applied to the request parameters.
attributes_request = []

if self.capture_params is None:
attributes_request = create_attributes(params, DST_NONE, self.attribute_filter)
elif self.capture_params:
attributes_request = create_attributes(
params, DST_ERROR_COLLECTOR | DST_TRANSACTION_TRACER, self.attribute_filter
)
attributes_request = create_attributes(params, DST_NONE, self.attribute_filter)
return attributes_request

@property
def request_parameters(self):
if (self.capture_params is None) or self.capture_params:
if self.settings.attributes.enabled:
if self._request_params:
r_attrs = {}

Expand Down Expand Up @@ -1842,10 +1807,12 @@ def suppress_apdex_metric(flag=True):
def capture_request_params(flag=True):
transaction = current_transaction()
if transaction and transaction.settings:
if transaction.settings.high_security:
_logger.warning("Cannot modify capture_params in High Security Mode.")
if flag and transaction.settings.high_security:
_logger.warning("Cannot enable request parameter collection in High Security Mode.")
elif flag:
transaction._agent_attributes.update(transaction.request_parameters())
else:
transaction.capture_params = flag
transaction._request_params.clear()


def add_custom_attribute(key, value):
Expand Down
17 changes: 5 additions & 12 deletions newrelic/api/web_transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -618,9 +618,6 @@ def __init__(self, application, environ, source=None):
self.ignore_transaction = _lookup_environ_setting(environ, "newrelic.ignore_transaction", False)
self.suppress_apdex = _lookup_environ_setting(environ, "newrelic.suppress_apdex_metric", False)
self.suppress_transaction_trace = _lookup_environ_setting(environ, "newrelic.suppress_transaction_trace", False)
self.capture_params = _lookup_environ_setting(
environ, "newrelic.capture_request_params", settings.capture_params
)
self.autorum_disabled = _lookup_environ_setting(
environ, "newrelic.disable_browser_autorum", not settings.browser_monitoring.auto_instrument
)
Expand All @@ -631,15 +628,11 @@ def __init__(self, application, environ, source=None):
# is a per request configuration and would create a lot
# of noise.

if settings.high_security:
self.capture_params = False

# LEGACY: capture_params = False
#
# Don't add request parameters at all, which means they will not
# go through the AttributeFilter.
if self.capture_params is False:
self._request_params.clear()
# By the time we get here, HSM should have already blocked
# the population of self._request_params

# if settings.high_security:
# self._request_params.clear()

# Extract from the WSGI environ dictionary
# details of the URL path. This will be set as
Expand Down
42 changes: 10 additions & 32 deletions newrelic/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,6 @@ def _process_configuration(section):
_process_setting(section, "monitor_mode", "getboolean", None)
_process_setting(section, "developer_mode", "getboolean", None)
_process_setting(section, "high_security", "getboolean", None)
_process_setting(section, "capture_params", "getboolean", None)
_process_setting(section, "capture_environ", "getboolean", None)
_process_setting(section, "include_environ", "get", _map_split_strings)
_process_setting(section, "max_stack_trace_lines", "getint", None)
Expand Down Expand Up @@ -686,21 +685,6 @@ def translate_deprecated_settings(settings, cached_settings):

delete_setting(settings, old_key)

# The 'capture_params' setting is deprecated, but since it affects
# attribute filter default destinations, it is not translated here. We
# log a message, but keep the capture_params setting.
#
# See newrelic.core.transaction:Transaction.agent_attributes to see how
# it is used.

if "capture_params" in cached:
_logger.info(
"Deprecated setting found: capture_params. Please use "
"new setting: attributes.exclude. To disable capturing all "
'request parameters, add "request.parameters.*" to '
"attributes.exclude."
)

if "cross_application_tracer.enabled" in cached:
# CAT Deprecation Warning
_logger.info(
Expand All @@ -727,22 +711,16 @@ def apply_local_high_security_mode_setting(settings):
"setting was %r. The new setting is %r."
)

# capture_params is a deprecated setting for users, and has three
# possible values:
#
# True: For backward compatibility.
# False: For backward compatibility.
# None: The current default setting.
#
# In High Security, capture_params must be False, but we only need
# to log if the customer has actually used the deprecated setting
# and set it to True.

if settings.capture_params:
settings.capture_params = False
_logger.info(log_template, "capture_params", True, False)
elif settings.capture_params is None:
settings.capture_params = False
# Check to see if `request.parameters.*` or any variant that would
# capture request parameters is in `attributes.include`. If so,
# remove them and log this change so that users do not think this
# is silently failing.
no_request_parameters_in_attributes_include = [
attr for attr in settings.attributes.include if not attr.startswith("request.parameters.")
]
if settings.attributes.enabled and (settings.attributes.include != no_request_parameters_in_attributes_include):
_logger.info(log_template, "attributes.include", str(settings.attributes.include), str(no_request_parameters_in_attributes_include))
settings.attributes.include = no_request_parameters_in_attributes_include

if settings.transaction_tracer.record_sql == "raw":
settings.transaction_tracer.record_sql = "obfuscated"
Expand Down
12 changes: 10 additions & 2 deletions newrelic/core/agent_protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,6 @@ class AgentProtocol:
PARAMS_ALLOWLIST = frozenset(("method", "protocol_version", "marshal_format", "run_id"))

SECURITY_SETTINGS = (
"capture_params",
"transaction_tracer.record_sql",
"strip_exception_messages.enabled",
"custom_insights_events.enabled",
Expand Down Expand Up @@ -298,7 +297,6 @@ def _connect_payload(app_name, linked_applications, environment, settings):
connect_settings["ai_monitoring.enabled"] = settings["ai_monitoring.enabled"]

security_settings = {}
security_settings["capture_params"] = settings["capture_params"]
security_settings["transaction_tracer"] = {}
security_settings["transaction_tracer"]["record_sql"] = settings["transaction_tracer.record_sql"]

Expand Down Expand Up @@ -427,6 +425,11 @@ def _apply_high_security_mode_fixups(cls, server_settings, local_settings):
if setting in server_settings:
del server_settings[setting]

# TODO: Override attributes.include setting for high security mode.
# Go through server side settings and find all items prepended
# with "request.parameters.". Remove those attributes and
# override server_settings["attributes.include"] with new list

# When server side configuration is disabled, there will be no
# agent_config value in server_settings, so no more fix-ups
# are required.
Expand All @@ -452,6 +455,11 @@ def _apply_high_security_mode_fixups(cls, server_settings, local_settings):
fetch_config_setting(local_settings, setting),
)

# TODO: Override attributes.exclude setting for high security mode.
# Go through server side agent config settings and find all items
# prepended with "request.parameters.". Remove those attributes and
# override server_settings["agent_config"]["attributes.include"] with new list

return server_settings

@classmethod
Expand Down
2 changes: 0 additions & 2 deletions newrelic/core/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -758,8 +758,6 @@ def default_otlp_host(host):
_settings.apdex_t = _environ_as_float("NEW_RELIC_APDEX_T", 0.5)
_settings.web_transactions_apdex = {}

_settings.capture_params = None

_settings.capture_environ = True
_settings.include_environ = [
"REQUEST_METHOD",
Expand Down
43 changes: 17 additions & 26 deletions tests/agent_features/test_attribute.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,23 @@ def test_intrinsics():
_forgone_agent = []


# This test demonstrates that when environ["newrelic.capture_request_params"]
# is set to True and settings.attributes.include has not been set to include
# request parameters, then request parameters will be captured.

required_agent_request_param = ["request.parameters.key-1"]


@validate_attributes("agent", required_agent_request_param, _forgone_agent)
def test_agent_capture_request_params_environ():
target_application = webtest.TestApp(target_wsgi_application)

response = target_application.get(
"/", params="key-1=value-1", extra_environ={"newrelic.capture_request_params": True}
)
assert response.body == b"Hello World!"


@validate_attributes("agent", _required_agent, _forgone_agent)
def test_agent():
target_application = webtest.TestApp(target_wsgi_application)
Expand Down Expand Up @@ -111,32 +128,6 @@ def test_user_add_attribute():
assert response.body == b"Hello World!"


_settings_legacy_false = {"capture_params": False}
_required_request_legacy_false = []
_forgone_request_legacy_false = ["request.parameters.foo"]


@override_application_settings(_settings_legacy_false)
@validate_attributes("agent", _required_request_legacy_false, _forgone_request_legacy_false)
def test_capture_request_params_legacy_false():
target_application = webtest.TestApp(target_wsgi_application)
response = target_application.get("/?foo=bar")
assert response.body == b"Hello World!"


_settings_legacy_true = {"capture_params": True}
_required_request_legacy_true = ["request.parameters.foo"]
_forgone_request_legacy_true = []


@override_application_settings(_settings_legacy_true)
@validate_attributes("agent", _required_request_legacy_true, _forgone_request_legacy_true)
def test_capture_request_params_legacy_true():
target_application = webtest.TestApp(target_wsgi_application)
response = target_application.get("/?foo=bar")
assert response.body == b"Hello World!"


_required_request_default = ["request.parameters.foo"]
_forgone_request_default = []

Expand Down
Loading
Loading