Skip to content

Commit d98d5f2

Browse files
committed
Squashed commit of the following:
commit 3962f54 Author: Uma Annamalai <[email protected]> Date: Thu Jan 4 12:50:58 2024 -0800 Remove case sensitive check in ASGIBrowserMiddleware check. (#1017) * Remove case sensitive check in should_insert_html. * [Mega-Linter] Apply linters fixes * Remove header decoding. --------- Co-authored-by: umaannamalai <[email protected]> commit c3314ae Author: Lalleh Rafeei <[email protected]> Date: Tue Jan 2 17:17:20 2024 -0800 Temporarily pin hypercorn version in tests (#1021) * Temporarily pin hypercorn to <0.16 * Temporarily pin hypercorn to <0.16 * Add comment to tox.ini --------- Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> commit 1357145 Author: Uma Annamalai <[email protected]> Date: Tue Jan 2 16:17:08 2024 -0800 Drop py27 from memcache testing. (#1018) commit 23f969f Author: Timothy Pansino <[email protected]> Date: Wed Dec 20 17:01:50 2023 -0800 Nonced CSP Support (#998) * Add nonce to CSP in browser agent * Adjust nonce position * Add testing for browser timing nonces commit 8bfd2b7 Author: Uma Annamalai <[email protected]> Date: Mon Dec 18 13:58:10 2023 -0800 Remove RPM config workflow. (#1007)
1 parent fb1f47d commit d98d5f2

File tree

7 files changed

+52
-94
lines changed

7 files changed

+52
-94
lines changed

.github/actions/update-rpm-config/action.yml

Lines changed: 0 additions & 69 deletions
This file was deleted.

.github/workflows/deploy-python.yml

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -80,13 +80,3 @@ jobs:
8080
env:
8181
TWINE_USERNAME: __token__
8282
TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }}
83-
84-
- name: Update RPM Config
85-
uses: ./.github/actions/update-rpm-config
86-
with:
87-
agent-language: "python"
88-
target-system: "all"
89-
agent-version: "${{ github.ref_name }}"
90-
dry-run: "false"
91-
production-api-key: ${{ secrets.NEW_RELIC_API_KEY_PRODUCTION }}
92-
staging-api-key: ${{ secrets.NEW_RELIC_API_KEY_STAGING }}

newrelic/api/asgi_application.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,9 @@ def should_insert_html(self, headers):
9797
content_type = None
9898

9999
for header_name, header_value in headers:
100-
# assume header names are lower cased in accordance with ASGI spec
100+
# ASGI spec (https://asgi.readthedocs.io/en/latest/specs/www.html#http) states
101+
# header names should be lower cased, but not required
102+
header_name = header_name.lower()
101103
if header_name == b"content-type":
102104
content_type = header_value
103105
elif header_name == b"content-encoding":
@@ -318,7 +320,6 @@ async def nr_async_asgi(receive, send):
318320
send=send,
319321
source=wrapped,
320322
) as transaction:
321-
322323
# Record details of framework against the transaction for later
323324
# reporting as supportability metrics.
324325
if framework:

newrelic/api/transaction.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1912,17 +1912,17 @@ def add_framework_info(name, version=None):
19121912
transaction.add_framework_info(name, version)
19131913

19141914

1915-
def get_browser_timing_header():
1915+
def get_browser_timing_header(nonce=None):
19161916
transaction = current_transaction()
19171917
if transaction and hasattr(transaction, "browser_timing_header"):
1918-
return transaction.browser_timing_header()
1918+
return transaction.browser_timing_header(nonce)
19191919
return ""
19201920

19211921

1922-
def get_browser_timing_footer():
1922+
def get_browser_timing_footer(nonce=None):
19231923
transaction = current_transaction()
19241924
if transaction and hasattr(transaction, "browser_timing_footer"):
1925-
return transaction.browser_timing_footer()
1925+
return transaction.browser_timing_footer(nonce)
19261926
return ""
19271927

19281928

newrelic/api/web_transaction.py

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,8 @@
3939

4040
_logger = logging.getLogger(__name__)
4141

42-
_js_agent_header_fragment = '<script type="text/javascript">%s</script>'
43-
_js_agent_footer_fragment = '<script type="text/javascript">'\
44-
'window.NREUM||(NREUM={});NREUM.info=%s</script>'
42+
_js_agent_header_fragment = '<script type="text/javascript"%s>%s</script>'
43+
_js_agent_footer_fragment = '<script type="text/javascript"%s>window.NREUM||(NREUM={});NREUM.info=%s</script>'
4544

4645
# Seconds since epoch for Jan 1 2000
4746
JAN_1_2000 = time.mktime((2000, 1, 1, 0, 0, 0, 0, 0, 0))
@@ -156,6 +155,13 @@ def _is_websocket(environ):
156155
return environ.get('HTTP_UPGRADE', '').lower() == 'websocket'
157156

158157

158+
def _encode_nonce(nonce):
159+
if not nonce:
160+
return ""
161+
else:
162+
return ' nonce="%s"' % ensure_str(nonce) # Extra space intentional
163+
164+
159165
class WebTransaction(Transaction):
160166
unicode_error_reported = False
161167
QUEUE_TIME_HEADERS = ('x-request-start', 'x-queue-start')
@@ -386,7 +392,7 @@ def _update_agent_attributes(self):
386392

387393
return super(WebTransaction, self)._update_agent_attributes()
388394

389-
def browser_timing_header(self):
395+
def browser_timing_header(self, nonce=None):
390396
"""Returns the JavaScript header to be included in any HTML
391397
response to perform real user monitoring. This function returns
392398
the header as a native Python string. In Python 2 native strings
@@ -437,7 +443,7 @@ def browser_timing_header(self):
437443
# 'none'.
438444

439445
if self._settings.js_agent_loader:
440-
header = _js_agent_header_fragment % self._settings.js_agent_loader
446+
header = _js_agent_header_fragment % (_encode_nonce(nonce), self._settings.js_agent_loader)
441447

442448
# To avoid any issues with browser encodings, we will make sure
443449
# that the javascript we inject for the browser agent is ASCII
@@ -476,7 +482,7 @@ def browser_timing_header(self):
476482

477483
return header
478484

479-
def browser_timing_footer(self):
485+
def browser_timing_footer(self, nonce=None):
480486
"""Returns the JavaScript footer to be included in any HTML
481487
response to perform real user monitoring. This function returns
482488
the footer as a native Python string. In Python 2 native strings
@@ -541,7 +547,7 @@ def browser_timing_footer(self):
541547
attributes = obfuscate(json_encode(attributes), obfuscation_key)
542548
footer_data['atts'] = attributes
543549

544-
footer = _js_agent_footer_fragment % json_encode(footer_data)
550+
footer = _js_agent_footer_fragment % (_encode_nonce(nonce), json_encode(footer_data))
545551

546552
# To avoid any issues with browser encodings, we will make sure that
547553
# the javascript we inject for the browser agent is ASCII encodable.

tests/agent_features/test_browser.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
get_browser_timing_footer,
3333
get_browser_timing_header,
3434
)
35+
from newrelic.api.web_transaction import web_transaction
3536
from newrelic.api.wsgi_application import wsgi_application
3637
from newrelic.common.encoding_utils import deobfuscate
3738

@@ -1026,3 +1027,31 @@ def test_html_insertion_manual_rum_insertion():
10261027
# footer added by the agent.
10271028

10281029
response.mustcontain(no=["NREUM HEADER", "NREUM.info"])
1030+
1031+
1032+
_test_get_browser_timing_nonces_settings = {
1033+
"browser_monitoring.enabled": True,
1034+
"browser_monitoring.auto_instrument": False,
1035+
"js_agent_loader": "<!-- NREUM HEADER -->",
1036+
}
1037+
1038+
@override_application_settings(_test_get_browser_timing_nonces_settings)
1039+
@web_transaction(scheme="http", host="127.0.0.1", port=80, request_method="GET",
1040+
request_path="/", query_string=None, headers={})
1041+
def test_get_browser_timing_nonces():
1042+
header = get_browser_timing_header("NONCE")
1043+
footer = get_browser_timing_footer("NONCE")
1044+
1045+
assert header == '<script type="text/javascript" nonce="NONCE"><!-- NREUM HEADER --></script>'
1046+
assert '<script type="text/javascript" nonce="NONCE">' in footer
1047+
1048+
1049+
@override_application_settings(_test_get_browser_timing_nonces_settings)
1050+
@web_transaction(scheme="http", host="127.0.0.1", port=80, request_method="GET",
1051+
request_path="/", query_string=None, headers={})
1052+
def test_get_browser_timing_no_nonces():
1053+
header = get_browser_timing_header()
1054+
footer = get_browser_timing_footer()
1055+
1056+
assert header == '<script type="text/javascript"><!-- NREUM HEADER --></script>'
1057+
assert '<script type="text/javascript">' in footer

tox.ini

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ envlist =
5757
kafka-messagebroker_kafkapython-{py27,py38}-kafkapython{020001,020000},
5858
kafka-messagebroker_kafkapython-{pypy27,py27,py37,py38,pypy38}-kafkapythonlatest,
5959
memcached-datastore_bmemcached-{pypy27,py27,py37,py38,py39,py310,py311,py312}-memcached030,
60-
memcached-datastore_memcache-{py27,py37,py38,py39,py310,py311,py312,pypy27,pypy38}-memcached01,
60+
memcached-datastore_memcache-{py37,py38,py39,py310,py311,py312,pypy38}-memcached01,
6161
memcached-datastore_pylibmc-{py27,py37},
6262
memcached-datastore_pymemcache-{py27,py37,py38,py39,py310,py311,py312,pypy27,pypy38},
6363
mongodb-datastore_pymongo-{py27,py37,py38,py39,py310,py311,py312,pypy27}-pymongo03,
@@ -174,7 +174,8 @@ deps =
174174
adapter_gunicorn-aiohttp03-py312: aiohttp==3.9.0rc0
175175
adapter_gunicorn-gunicorn19: gunicorn<20
176176
adapter_gunicorn-gunicornlatest: gunicorn
177-
adapter_hypercorn-hypercornlatest: hypercorn
177+
; Temporarily pinned. Needs to be addressed
178+
adapter_hypercorn-hypercornlatest: hypercorn<0.16
178179
adapter_hypercorn-hypercorn0013: hypercorn<0.14
179180
adapter_hypercorn-hypercorn0012: hypercorn<0.13
180181
adapter_hypercorn-hypercorn0011: hypercorn<0.12

0 commit comments

Comments
 (0)