diff --git a/.devcontainer/.env.sample b/.devcontainer/.env.sample index f4288d359c..c1ac6c27d0 100644 --- a/.devcontainer/.env.sample +++ b/.devcontainer/.env.sample @@ -15,6 +15,10 @@ CONFIG_FILE=??_*.json DJANGO_ADMIN=false DJANGO_ALLOWED_HOSTS=localhost,127.0.0.1,[::1] DJANGO_TRUSTED_ORIGINS=http://localhost,http://127.0.0.1 +DJANGO_CSP_CONNECT_SRC=https://example1.com,https://example2.com +DJANGO_CSP_FONT_SRC=https://example1.com,https://example2.com +DJANGO_CSP_SCRIPT_SRC=https://example1.com,https://example2.com +DJANGO_CSP_STYLE_SRC=https://example1.com,https://example2.com DJANGO_DB=django DJANGO_DEBUG=true DJANGO_INIT_PATH=fixtures/??_*.json diff --git a/.devcontainer/compose.yml b/.devcontainer/compose.yml index ca746ad240..97ef8652ba 100644 --- a/.devcontainer/compose.yml +++ b/.devcontainer/compose.yml @@ -4,16 +4,7 @@ services: client: build: .. image: benefits_client:latest - environment: - - ANALYTICS_KEY - - DJANGO_ADMIN - - DJANGO_ALLOWED_HOSTS - - DJANGO_TRUSTED_ORIGINS - - DJANGO_DB - - DJANGO_DEBUG - - DJANGO_INIT_PATH - - DJANGO_LOG_LEVEL - - DJANGO_SECRET_KEY + env_file: .env ports: - "8000" volumes: @@ -25,17 +16,7 @@ services: context: .. dockerfile: .devcontainer/Dockerfile image: benefits_client:dev - environment: - - ANALYTICS_KEY - - CYPRESS_baseUrl - - DJANGO_ADMIN - - DJANGO_ALLOWED_HOSTS - - DJANGO_TRUSTED_ORIGINS - - DJANGO_DB - - DJANGO_DEBUG - - DJANGO_INIT_PATH - - DJANGO_LOG_LEVEL - - DJANGO_SECRET_KEY + env_file: .env entrypoint: [] command: sleep infinity depends_on: diff --git a/benefits/settings.py b/benefits/settings.py index 1ecb910c95..ba91a28c9c 100644 --- a/benefits/settings.py +++ b/benefits/settings.py @@ -3,6 +3,11 @@ """ import os + +def _filter_empty(ls): + return [s for s in ls if s] + + # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) @@ -14,7 +19,7 @@ ADMIN = os.environ.get("DJANGO_ADMIN", "False").lower() == "true" -ALLOWED_HOSTS = os.environ["DJANGO_ALLOWED_HOSTS"].split(",") +ALLOWED_HOSTS = _filter_empty(os.environ["DJANGO_ALLOWED_HOSTS"].split(",")) # Application definition @@ -62,7 +67,7 @@ CSRF_COOKIE_AGE = None CSRF_COOKIE_SAMESITE = "Strict" CSRF_COOKIE_HTTPONLY = True -CSRF_TRUSTED_ORIGINS = os.environ["DJANGO_TRUSTED_ORIGINS"].split(",") +CSRF_TRUSTED_ORIGINS = _filter_empty(os.environ["DJANGO_TRUSTED_ORIGINS"].split(",")) SESSION_COOKIE_SAMESITE = "Strict" SESSION_ENGINE = "django.contrib.sessions.backends.signed_cookies" @@ -198,25 +203,23 @@ # In particular, note that the inner single-quotes are required! # https://django-csp.readthedocs.io/en/latest/configuration.html#policy-settings + CSP_DEFAULT_SRC = ["'self'"] -CSP_CONNECT_SRC = ["'self'", "https://api.amplitude.com/"] +env_connect_src = _filter_empty(os.environ.get("DJANGO_CSP_CONNECT_SRC", "").split(",")) +CSP_CONNECT_SRC = ["'self'"] +CSP_CONNECT_SRC.extend(env_connect_src) -CSP_FONT_SRC = ["https://california.azureedge.net/cdt/statetemplate/", "https://fonts.gstatic.com/"] +env_font_src = _filter_empty(os.environ.get("DJANGO_CSP_FONT_SRC", "").split(",")) +CSP_FONT_SRC = list(env_font_src) CSP_FRAME_ANCESTORS = ["'none'"] CSP_FRAME_SRC = ["'none'"] -CSP_SCRIPT_SRC = [ - "'unsafe-inline'", - "https://cdn.amplitude.com/libs/", - "https://code.jquery.com/", - "*.littlepay.com", -] +env_script_src = _filter_empty(os.environ.get("DJANGO_CSP_SCRIPT_SRC", "").split(",")) +CSP_SCRIPT_SRC = ["'unsafe-inline'"] +CSP_SCRIPT_SRC.extend(env_script_src) -CSP_STYLE_SRC = [ - "'self'", - "'unsafe-inline'", - "https://california.azureedge.net/cdt/statetemplate/", - "https://fonts.googleapis.com/css", -] +env_style_src = _filter_empty(os.environ.get("DJANGO_CSP_STYLE_SRC", "").split(",")) +CSP_STYLE_SRC = ["'self'", "'unsafe-inline'"] +CSP_STYLE_SRC.extend(env_style_src) diff --git a/tests/cypress/.env.tests b/tests/cypress/.env.tests index 357211fc6e..81d4358284 100644 --- a/tests/cypress/.env.tests +++ b/tests/cypress/.env.tests @@ -2,6 +2,9 @@ DJANGO_ADMIN=false DJANGO_ALLOWED_HOSTS=localhost,127.0.0.1,[::1] DJANGO_TRUSTED_ORIGINS=http://localhost,http://127.0.0.1 +DJANGO_CSP_FONT_SRC=https://california.azureedge.net/cdt/statetemplate/,https://fonts.gstatic.com/ +DJANGO_CSP_SCRIPT_SRC=https://code.jquery.com/ +DJANGO_CSP_STYLE_SRC=https://california.azureedge.net/cdt/statetemplate/,https://fonts.googleapis.com/css DJANGO_DB=django DJANGO_DEBUG=false DJANGO_INIT_PATH=fixtures/??_*.json