diff --git a/app/__init__.py b/app/__init__.py index 48e122bd8..441ff5dd4 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -141,7 +141,9 @@ navigation = { def _csp(config): asset_domain = config["ASSET_DOMAIN"] logo_domain = config["LOGO_CDN_DOMAIN"] - return { + api_host_name = config["API_HOST_NAME"] + + csp = { "default-src": ["'self'", asset_domain], "frame-src": [ "https://www.youtube.com", @@ -165,13 +167,22 @@ def _csp(config): "'self'", "https://gov-bam.nr-data.net", "https://www.google-analytics.com", - "http://localhost:6011", - "ws://localhost:6011", ], "style-src": ["'self'", asset_domain], "img-src": ["'self'", asset_domain, logo_domain], } + if api_host_name: + csp["connect-src"].append(api_host_name) + # this is for web socket + if api_host_name.startswith("http://"): + ws_url = api_host_name.replace("http://", "ws://") + csp["connect-src"].append(ws_url) + elif api_host_name.startswith("https://"): + ws_url = api_host_name.replace("https://", "wss://") + csp["connect-src"].append(ws_url) + return csp + def create_app(application): @application.after_request diff --git a/pytest.ini b/pytest.ini index 5e9b75af8..2266104c6 100644 --- a/pytest.ini +++ b/pytest.ini @@ -5,7 +5,7 @@ log_level = 999 env = NOTIFY_ENVIRONMENT=test ADMIN_CLIENT_SECRET=dev-notify-secret-key - API_HOST_NAME=test + API_HOST_NAME=http://you-forgot-to-mock-an-api-call-to DANGEROUS_SALT=dev-notify-salt SECRET_KEY=dev-notify-secret-key ZENDESK_API_KEY=test diff --git a/tests/app/main/views/test_headers.py b/tests/app/main/views/test_headers.py index c84fdc094..ae5b3f448 100644 --- a/tests/app/main/views/test_headers.py +++ b/tests/app/main/views/test_headers.py @@ -1,5 +1,7 @@ from re import search +from flask import current_app + def test_owasp_useful_headers_set( client_request, @@ -26,9 +28,20 @@ def test_owasp_useful_headers_set( ) assert search(r"'nonce-[^']+';", csp) assert search( - r"connect-src 'self' https:\/\/gov-bam\.nr-data\.net https:\/\/www\.google-analytics\." - r"com http:\/\/localhost:6011 ws:\/\/localhost:6011;", + r"connect-src 'self' https:\/\/gov-bam\.nr-data\.net https:\/\/www\.google-analytics\.", csp, ) assert search(r"style-src 'self' static\.example\.com 'nonce-.*';", csp) assert search(r"img-src 'self' static\.example\.com static-logos\.test\.com", csp) + api_host_name = current_app.config.get("API_HOST_NAME") + assert api_host_name is not None, f"API_HOST_NAME: {api_host_name} — is missing" + + assert api_host_name in csp + if api_host_name.startswith("http://"): + assert api_host_name.replace("http://", "ws://") in csp + elif api_host_name.startswith("https://"): + assert api_host_name.replace("https://", "wss://") in csp + else: + raise AssertionError( + f"Unexpected API_HOST_NAME format: {api_host_name} — must start with 'http://' or 'https://'" + )