45 lines
1.5 KiB
Django/Jinja

{# Create a namespace to hold the accumulated CSP parts #}
{% set ns = namespace(csp_parts=[]) %}
{# List of directives to build dynamically (except img-src) #}
{% set directives = [
'default-src',
'connect-src',
'frame-ancestors',
'frame-src',
'script-src',
'style-src',
'font-src'
] %}
{# Build each directive line #}
{% for directive in directives %}
{# Always start with 'self' #}
{% set tokens = ["'self'"] %}
{# Add any unsafe flags for this directive #}
{% for flag in applications | get_csp_flags(application_id, directive) %}
{% set tokens = tokens + [flag] %}
{% endfor %}
{# If Matomo is enabled, allow its script and connect endpoints #}
{% if applications | is_feature_enabled('matomo', application_id)
and directive in ['script-src', 'connect-src'] %}
{% set tokens = tokens + [web_protocol ~ '://' ~ domains.matomo] %}
{% endif %}
{# Append any extra whitelist URLs for this directive #}
{% for url in applications | get_csp_whitelist(application_id, directive) %}
{% set tokens = tokens + [url] %}
{% endfor %}
{# Store the completed directive line in the namespace #}
{% set ns.csp_parts = ns.csp_parts + [directive ~ ' ' ~ (tokens | join(' ')) ~ ';'] %}
{% endfor %}
{# Add the (static) img-src directive #}
{% set ns.csp_parts = ns.csp_parts + ['img-src * data: blob:;'] %}
{# Emit the final header and hide any upstream header #}
add_header Content-Security-Policy "{{ ns.csp_parts | join(' ') }}" always;
proxy_hide_header Content-Security-Policy;