diff --git a/filter_plugins/csp_filters.py b/filter_plugins/csp_filters.py index 55742cd2..6420ee36 100644 --- a/filter_plugins/csp_filters.py +++ b/filter_plugins/csp_filters.py @@ -97,8 +97,11 @@ class FilterModule(object): for directive in directives: tokens = ["'self'"] + # unsafe-eval / unsafe-inline flags - tokens += self.get_csp_flags(applications, application_id, directive) + flags = self.get_csp_flags(applications, application_id, directive) + tokens += flags + # Matomo integration if ( self.is_feature_enabled(applications, matomo_feature_name, application_id) @@ -107,11 +110,15 @@ class FilterModule(object): matomo_domain = domains.get('matomo') if matomo_domain: tokens.append(f"{web_protocol}://{matomo_domain}") + # whitelist tokens += self.get_csp_whitelist(applications, application_id, directive) - # inline hashes from config - for snippet in self.get_csp_inline_content(applications, application_id, directive): - tokens.append(self.get_csp_hash(snippet)) + + # only add hashes if 'unsafe-inline' is NOT in flags + if "'unsafe-inline'" not in flags: + for snippet in self.get_csp_inline_content(applications, application_id, directive): + tokens.append(self.get_csp_hash(snippet)) + parts.append(f"{directive} {' '.join(tokens)};") # static img-src diff --git a/roles/backup-docker-to-local/tasks/main.yml b/roles/backup-docker-to-local/tasks/main.yml index f0552672..d4671e4d 100644 --- a/roles/backup-docker-to-local/tasks/main.yml +++ b/roles/backup-docker-to-local/tasks/main.yml @@ -14,6 +14,7 @@ - name: Set fact for backup_docker_to_local_folder set_fact: backup_docker_to_local_folder: "{{ pkgmgr_output.stdout }}/" + changed_when: false when: run_once_backup_docker_to_local is not defined - name: configure backup-docker-to-local-everything.cymais.service diff --git a/roles/cleanup-failed-docker-backups/tasks/main.yml b/roles/cleanup-failed-docker-backups/tasks/main.yml index aced5ced..7c48b57d 100644 --- a/roles/cleanup-failed-docker-backups/tasks/main.yml +++ b/roles/cleanup-failed-docker-backups/tasks/main.yml @@ -14,6 +14,7 @@ - name: Set fact for backup_docker_to_local_cleanup_script set_fact: backup_docker_to_local_cleanup_script: "{{ pkgmgr_output.stdout.rstrip('/') ~ '/cleanup-all.sh' }}" + changed_when: false when: run_once_cleanup_failed_docker_backups is not defined - name: configure cleanup-failed-docker-backups.cymais.service diff --git a/roles/nginx-https-get-cert/tasks/main.yml b/roles/nginx-https-get-cert/tasks/main.yml index 99cd234a..e534160a 100644 --- a/roles/nginx-https-get-cert/tasks/main.yml +++ b/roles/nginx-https-get-cert/tasks/main.yml @@ -24,10 +24,12 @@ debug: "{{ enable_debug | default(false) }}" register: cert_folder_result delegate_to: "{{ inventory_hostname }}" + changed_when: false - name: Set fact set_fact: ssl_cert_folder: "{{ cert_folder_result.folder }}" + changed_when: false - name: Ensure ssl_cert_folder is set fail: diff --git a/roles/nginx-modifier-matomo/tasks/main.yml b/roles/nginx-modifier-matomo/tasks/main.yml index bd02c0ca..83e9a08a 100644 --- a/roles/nginx-modifier-matomo/tasks/main.yml +++ b/roles/nginx-modifier-matomo/tasks/main.yml @@ -25,6 +25,7 @@ set_fact: matomo_site_id: "{{ site_check.json[0].idsite }}" when: "(site_check.json | length) > 0" + changed_when: false - name: Add site to Matomo and get ID if not exists uri: @@ -42,6 +43,7 @@ set_fact: matomo_site_id: "{{ add_site.json.value }}" when: "matomo_site_id is not defined or matomo_site_id is none" + changed_when: false - name: Set the Matomo tracking code from a template file set_fact: diff --git a/roles/nginx-redirect-domains/tasks/redirect-domain.yml b/roles/nginx-redirect-domains/tasks/redirect-domain.yml index 5e3ea9a8..f91d5fb4 100644 --- a/roles/nginx-redirect-domains/tasks/redirect-domain.yml +++ b/roles/nginx-redirect-domains/tasks/redirect-domain.yml @@ -2,7 +2,7 @@ include_role: name: nginx-https-get-cert -- name: configure nginx redirect configurations +- name: "Deploying NGINX redirect configuration for {{ domain }}" template: src: redirect.domain.nginx.conf.j2 dest: "{{ nginx.directories.http.servers }}{{ domain }}.conf" diff --git a/tests/unit/test_csp_filters.py b/tests/unit/test_csp_filters.py index 6b0bce36..b13fa57a 100644 --- a/tests/unit/test_csp_filters.py +++ b/tests/unit/test_csp_filters.py @@ -122,14 +122,20 @@ class TestCspFilters(unittest.TestCase): # passing a non-decodable object self.filter.get_csp_hash(None) - def test_build_csp_header_includes_hashes(self): + def test_build_csp_header_includes_hashes_only_if_no_unsafe_inline(self): + """ + script-src has unsafe-inline = False -> hash should be included + style-src has unsafe-inline = True -> hash should NOT be included + """ header = self.filter.build_csp_header(self.apps, 'app1', self.domains, web_protocol='https') - # check that the script-src directive includes our inline hash + + # script-src includes hash because 'unsafe-inline' is False script_hash = self.filter.get_csp_hash("console.log('hello');") self.assertIn(script_hash, header) - # check that the style-src directive includes its inline hash + + # style-src does NOT include hash because 'unsafe-inline' is True style_hash = self.filter.get_csp_hash("body { background: #fff; }") - self.assertIn(style_hash, header) + self.assertNotIn(style_hash, header) if __name__ == '__main__': unittest.main() \ No newline at end of file