diff --git a/filter_plugins/configuration_filters.py b/filter_plugins/configuration_filters.py index 4faa71b9..aeb4d919 100644 --- a/filter_plugins/configuration_filters.py +++ b/filter_plugins/configuration_filters.py @@ -33,11 +33,32 @@ def get_csp_flags(applications, application_id: str, directive: str) -> list: tokens.append("'unsafe-inline'") return tokens +def get_docker_compose(path_docker_compose_instances: str, application_id: str) -> dict: + """ + Build the docker_compose dict based on + path_docker_compose_instances and application_id. + """ + base = f"{path_docker_compose_instances}{application_id}/" + + return { + 'directories': { + 'instance': base, + 'env': f"{base}.env/", + 'services': f"{base}services/", + 'volumes': f"{base}volumes/", + 'config': f"{base}config/", + }, + 'files': { + 'env': f"{base}.env/env", + 'docker_compose': f"{base}docker-compose.yml", + } + } class FilterModule(object): def filters(self): return { - 'is_feature_enabled': is_feature_enabled, + 'is_feature_enabled': is_feature_enabled, 'get_csp_whitelist': get_csp_whitelist, 'get_csp_flags': get_csp_flags, + 'get_docker_compose': get_docker_compose, } \ No newline at end of file diff --git a/roles/docker-compose/vars/docker-compose.yml b/roles/docker-compose/vars/docker-compose.yml index 44254b85..6c1fd96a 100644 --- a/roles/docker-compose/vars/docker-compose.yml +++ b/roles/docker-compose/vars/docker-compose.yml @@ -1,14 +1,2 @@ -# Private variable for role. Please use docker_compose.directories.instance instead -_docker_compose_directories_instance: "{{ path_docker_compose_instances }}{{ application_id }}/" - # @See https://chatgpt.com/share/67a23d18-fb54-800f-983c-d6d00752b0b4 -docker_compose: - directories: - instance: "{{_docker_compose_directories_instance}}" # Folder for docker-compose.yml file - env: "{{_docker_compose_directories_instance}}.env/" # Folder for env files - services: "{{_docker_compose_directories_instance}}services/" # Folder for services - volumes: "{{_docker_compose_directories_instance}}volumes/" # Folder for volumes - config: "{{_docker_compose_directories_instance}}config/" # Folder for configuration files - files: - env: "{{_docker_compose_directories_instance}}.env/env" # General env file - docker_compose: "{{_docker_compose_directories_instance}}docker-compose.yml" # Docker Compose file +docker_compose: "{{ path_docker_compose_instances | get_docker_compose(application_id) }}" \ No newline at end of file diff --git a/roles/docker-oauth2-proxy/tasks/main.yml b/roles/docker-oauth2-proxy/tasks/main.yml index 80052edf..aeb4581b 100644 --- a/roles/docker-oauth2-proxy/tasks/main.yml +++ b/roles/docker-oauth2-proxy/tasks/main.yml @@ -1,6 +1,6 @@ -- name: "Transfering oauth2-proxy-keycloak.cfg.j2 to {{docker_compose.directories.volumes}}" +- name: "Transfering oauth2-proxy-keycloak.cfg.j2 to {{(path_docker_compose_instances | get_docker_compose(oauth2_proxy_application_id)).directories.volumes}}" template: src: oauth2-proxy-keycloak.cfg.j2 - dest: "{{docker_compose.directories.volumes}}{{applications[application_id].configuration_file}}" + dest: "{{(path_docker_compose_instances | get_docker_compose(oauth2_proxy_application_id)).directories.volumes}}{{applications[application_id].configuration_file}}" notify: - docker compose project setup \ No newline at end of file diff --git a/roles/docker-oauth2-proxy/templates/container.yml.j2 b/roles/docker-oauth2-proxy/templates/container.yml.j2 index 81e5094e..285ce899 100644 --- a/roles/docker-oauth2-proxy/templates/container.yml.j2 +++ b/roles/docker-oauth2-proxy/templates/container.yml.j2 @@ -1,11 +1,11 @@ {% if applications | is_feature_enabled('oauth2',application_id) %} oauth2-proxy: - image: quay.io/oauth2-proxy/oauth2-proxy:{{applications.oauth2_proxy.version}} + image: quay.io/oauth2-proxy/oauth2-proxy:{{applications['oauth2-proxy'].version}} restart: {{docker_restart_policy}} command: --config /oauth2-proxy.cfg hostname: oauth2-proxy ports: - {{ports.localhost.oauth2_proxy[application_id]}}:4180/tcp volumes: - - "{{docker_compose.directories.volumes}}{{applications.oauth2_proxy.configuration_file}}:/oauth2-proxy.cfg" + - "{{docker_compose.directories.volumes}}{{applications['oauth2-proxy'].configuration_file}}:/oauth2-proxy.cfg" {% endif %} \ No newline at end of file diff --git a/roles/docker-oauth2-proxy/templates/oauth2-proxy-keycloak.cfg.j2 b/roles/docker-oauth2-proxy/templates/oauth2-proxy-keycloak.cfg.j2 index c4eb6d18..0d48282d 100644 --- a/roles/docker-oauth2-proxy/templates/oauth2-proxy-keycloak.cfg.j2 +++ b/roles/docker-oauth2-proxy/templates/oauth2-proxy-keycloak.cfg.j2 @@ -3,18 +3,18 @@ cookie_secret = "{{ applications[oauth2_proxy_application_id].creden email_domains = "{{ primary_domain }}" cookie_secure = "true" # True is necessary to force the cookie set via https upstreams = "http://{{ applications[oauth2_proxy_application_id].oauth2_proxy.application }}:{{ applications[oauth2_proxy_application_id].oauth2_proxy.port }}" -cookie_domains = ["{{ domain }}", "{{ domains.keycloak }}"] # Required so cookie can be read on all subdomains. +cookie_domains = ["{{ domains[oauth2_proxy_application_id] }}", "{{ domains.keycloak }}"] # Required so cookie can be read on all subdomains. whitelist_domains = [".{{ primary_domain }}"] # Required to allow redirection back to original requested target. # keycloak provider client_secret = "{{ oidc.client.secret }}" client_id = "{{ oidc.client.id }}" -redirect_url = "{{ web_protocol }}://{{domain}}/oauth2/callback" +redirect_url = "{{ web_protocol }}://{{domains[oauth2_proxy_application_id]}}/oauth2/callback" oidc_issuer_url = "{{ oidc.client.issuer_url }}" provider = "oidc" provider_display_name = "Keycloak" # role restrictions #cookie_roles = "realm_access.roles" -#allowed_groups = "{{ applications[oauth2_proxy_application_id].allowed_roles }}" # This is not correct here. needs to be placed in applications @todo move there when implementing +#allowed_groups = "{{ applications[application_id].allowed_roles }}" # This is not correct here. needs to be placed in applications @todo move there when implementing # @see https://chatgpt.com/share/67f42607-bf68-800f-b587-bd56fe9067b5 \ No newline at end of file diff --git a/roles/health-csp/README.md b/roles/health-csp/README.md index 528f0e66..9681f50b 100644 --- a/roles/health-csp/README.md +++ b/roles/health-csp/README.md @@ -31,7 +31,7 @@ Set the following variables to customize behavior: ```yaml health_csp_crawler_folder: "{{ path_administrator_scripts }}health-csp/" on_calendar_health_csp_crawler: "daily" -```` +``` ## License diff --git a/roles/health-csp/files/__init__.py b/roles/health-csp/files/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/roles/health-csp/files/health-csp.js b/roles/health-csp/files/health-csp.js deleted file mode 100644 index 82177d26..00000000 --- a/roles/health-csp/files/health-csp.js +++ /dev/null @@ -1,43 +0,0 @@ -const puppeteer = require('puppeteer'); -const domains = process.argv.slice(2); - -(async () => { - let errorCounter = 0; - const browser = await puppeteer.launch({ headless: 'new' }); - - for (const domain of domains) { - const page = await browser.newPage(); - const blockedResources = []; - - page.on('requestfailed', request => { - const reason = request.failure()?.errorText || ''; - if (reason.includes('blocked')) { - blockedResources.push({ url: request.url(), reason }); - } - }); - - try { - const url = `https://${domain}`; - await page.goto(url, { waitUntil: 'networkidle2', timeout: 20000 }); - } catch (e) { - console.error(`${domain}: ERROR visiting site - ${e.message}`); - errorCounter++; - continue; - } - - if (blockedResources.length > 0) { - console.warn(`${domain}: Blocked resources detected:`); - blockedResources.forEach(r => - console.log(` BLOCKED by CSP: ${r.url} (${r.reason})`) - ); - errorCounter++; - } else { - console.log(`${domain}: ✅ No CSP blocks detected.`); - } - - await page.close(); - } - - await browser.close(); - process.exit(errorCounter); -})(); diff --git a/roles/health-csp/files/health_csp.py b/roles/health-csp/files/health-csp.py similarity index 97% rename from roles/health-csp/files/health_csp.py rename to roles/health-csp/files/health-csp.py index 7d3ad844..1e265def 100644 --- a/roles/health-csp/files/health_csp.py +++ b/roles/health-csp/files/health-csp.py @@ -32,7 +32,7 @@ def run_node_checker(script_path, domains): """ try: result = subprocess.run( - ["/usr/bin/node", script_path] + domains, + ["node", script_path] + domains, check=True ) return result.returncode diff --git a/roles/health-csp/tasks/main.yml b/roles/health-csp/tasks/main.yml index bd2b14c3..80df0838 100644 --- a/roles/health-csp/tasks/main.yml +++ b/roles/health-csp/tasks/main.yml @@ -17,9 +17,9 @@ register: puppeteer_check failed_when: puppeteer_check.rc != 0 -- name: copy health_csp.py +- name: copy health-csp.py copy: - src: health_csp.py + src: health-csp.py dest: "{{ health_csp_crawler_script }}" mode: 0755 diff --git a/roles/health-csp/vars/main.yml b/roles/health-csp/vars/main.yml index 35651865..34b2e70e 100644 --- a/roles/health-csp/vars/main.yml +++ b/roles/health-csp/vars/main.yml @@ -1,3 +1,3 @@ health_csp_crawler_folder: "{{ path_administrator_scripts }}health-csp/" -health_csp_crawler_script: "{{ health_csp_crawler_folder }}health_csp.py" +health_csp_crawler_script: "{{ health_csp_crawler_folder }}health-csp.py" health_csp_crawler_node: "{{ health_csp_crawler_folder }}health-csp.js" \ No newline at end of file diff --git a/roles/nginx/meta/main.yml b/roles/nginx/meta/main.yml index b94ba991..d6cf8586 100644 --- a/roles/nginx/meta/main.yml +++ b/roles/nginx/meta/main.yml @@ -1,3 +1,3 @@ dependencies: - health-nginx - - health-csp \ No newline at end of file +# - health-csp \ No newline at end of file diff --git a/roles/nodejs/README.md b/roles/nodejs/README.md index ff92a138..4ab3b9b8 100644 --- a/roles/nodejs/README.md +++ b/roles/nodejs/README.md @@ -13,16 +13,6 @@ Optimized for Archlinux and Debian-based systems, this role ensures the presence - **Node.js Installation:** Installs the latest Node.js version available via the system's package manager. - **Idempotent Execution:** Ensures Node.js is only installed when missing. -## Usage - -Include this role before running any tasks or roles that depend on Node.js: - -```yaml -- name: Ensure Node.js is available - roles: - - nodejs -```` - ## License CyMaIS NonCommercial License (CNCL) diff --git a/tasks/update-repository-with-files.yml b/tasks/update-repository-with-files.yml index db9c8923..be4af438 100644 --- a/tasks/update-repository-with-files.yml +++ b/tasks/update-repository-with-files.yml @@ -2,9 +2,9 @@ # Better load the repositories into /opt/docker/[servicename]/services, build them there and then use a docker-compose file for customizing # @todo Refactor\Remove # @deprecated -- name: "Merge detached_files with applications.oauth2_proxy.configuration_file" +- name: "Merge detached_files with applications['oauth2-proxy'].configuration_file" ansible.builtin.set_fact: - merged_detached_files: "{{ detached_files + [applications.oauth2_proxy.configuration_file] }}" + merged_detached_files: "{{ detached_files + [applications['oauth2-proxy'].configuration_file] }}" when: applications[application_id].get('features', {}).get('oauth2', False) | bool - name: "backup detached files"