diff --git a/roles/docker-portfolio/vars/configuration.yml b/roles/docker-portfolio/vars/configuration.yml index 9a687dbe..ee79acb2 100644 --- a/roles/docker-portfolio/vars/configuration.yml +++ b/roles/docker-portfolio/vars/configuration.yml @@ -1,4 +1,15 @@ features: matomo: true css: true - landingpage_iframe: false \ No newline at end of file + landingpage_iframe: false +csp: + whitelist: + script-src: + - https://cdn.jsdelivr.net + - https://kit.fontawesome.com + style-src: + - https://cdn.jsdelivr.net + font-src: + - https://ka-f.fontawesome.com + frame-src: + - "{{ web_protocol }}://*.{{primary_domain}}" diff --git a/roles/docker-presentation/vars/configuration.yml b/roles/docker-presentation/vars/configuration.yml index 04faf2cb..cc7b62d5 100644 --- a/roles/docker-presentation/vars/configuration.yml +++ b/roles/docker-presentation/vars/configuration.yml @@ -1,4 +1,16 @@ features: matomo: true css: true - landingpage_iframe: true \ No newline at end of file + landingpage_iframe: true + +csp: + whitelist: + script-src: + - https://cdnjs.cloudflare.com + - https://code.jquery.com + - https://cdn.jsdelivr.net + style-src: + - https://cdnjs.cloudflare.com + - https://cdn.jsdelivr.net + font-src: + - https://cdnjs.cloudflare.com \ No newline at end of file diff --git a/roles/nginx-docker-reverse-proxy/templates/headers/content_security_policy.conf.j2 b/roles/nginx-docker-reverse-proxy/templates/headers/content_security_policy.conf.j2 index 7d297053..954c60f5 100644 --- a/roles/nginx-docker-reverse-proxy/templates/headers/content_security_policy.conf.j2 +++ b/roles/nginx-docker-reverse-proxy/templates/headers/content_security_policy.conf.j2 @@ -12,7 +12,7 @@ 'font-src' ] %} -{# Loop over each directive and build its value from 'self', any unsafe flags, and whitelisted URLs #} +{# Loop over each directive and build its value from 'self', any unsafe flags, whitelist URLs, and optional Matomo #} {%- for directive in directives %} {# Start with the 'self' source #} {%- set tokens = ["'self'"] %} @@ -22,19 +22,24 @@ {%- set tokens = tokens + [flag] %} {%- endfor %} + {# If Matomo feature is enabled, whitelist its script and connect sources #} + {%- if applications | is_feature_enabled('matomo', application_id) and directive in ['script-src','connect-src'] %} + {%- set tokens = tokens + ['{{ web_protocol }}://{{ domains.matomo }}'] %} + {%- endif %} + {# Add any extra hosts/URLs from csp.whitelist. #} {%- for url in applications | get_csp_whitelist(application_id, directive) %} {%- set tokens = tokens + [url] %} {%- endfor %} {# Combine into a single directive line and append to csp_parts #} - {%- set csp_parts = csp_parts + [(directive ~ " " ~ (tokens | join(' ')) ~ ";")] %} + {%- set csp_parts = csp_parts + [directive ~ ' ' ~ (tokens | join(' ')) ~ ';'] %} {%- endfor %} {# Preserve original img-src directive logic (do not loop) #} -{%- set img_src = "img-src * data: blob:" %} -{%- set csp_parts = csp_parts + [img_src ~ ";"] %} +{%- set img_src = 'img-src * data: blob:' %} +{%- set csp_parts = csp_parts + [img_src ~ ';'] %} {# Emit the assembled Content-Security-Policy header and hide any upstream CSP header #} add_header Content-Security-Policy "{{ csp_parts | join(' ') }}" always; -proxy_hide_header Content-Security-Policy; \ No newline at end of file +proxy_hide_header Content-Security-Policy;