diff --git a/infrastructure/ansible/deploy_logic_push.yml b/infrastructure/ansible/deploy_logic_push.yml index d541479..5f6fdc8 100644 --- a/infrastructure/ansible/deploy_logic_push.yml +++ b/infrastructure/ansible/deploy_logic_push.yml @@ -25,79 +25,75 @@ state: directory mode: '0755' -# 3. Secrets aus Vault (Lokal lookup, Remote copy) -# Nur ausführen, wenn has_secrets: true +# 3. Secrets aus Vault (Lokal lookup) - name: "Lade Secrets aus Vault (Lokal lookup)" set_fact: - app_secrets: "{{ lookup('community.hashi_vault.vault_kv2_get', 'apps/' + app_item.name, engine_mount_point='secret', url=lookup('env', 'VAULT_ADDR') | default('https://10.100.30.11:8200'), token=(vault_token | default(lookup('env', 'VAULT_TOKEN'))), validate_certs=false) | default({}) }}" + vault_response: "{{ lookup('community.hashi_vault.vault_kv2_get', 'apps/' + app_item.name, engine_mount_point='secret', url=lookup('env', 'VAULT_ADDR') | default('https://10.100.30.11:8200'), token=(vault_token | default(lookup('env', 'VAULT_TOKEN'))), validate_certs=false) | default({}) }}" delegate_to: localhost when: app_item.has_secrets | default(false) - ignore_errors: true # Trotzdem ignorieren, falls Vault down ist oder Secret fehlt - -- name: "Setze app_secrets default wenn leer oder skipped" - set_fact: - app_secrets: {} - when: app_secrets is undefined + ignore_errors: true -- name: "Lade Cloudflare Secrets (für Traefik Edge)" +- name: "Extrahiere App Secrets Daten" set_fact: - cf_secrets: "{{ lookup('community.hashi_vault.vault_kv2_get', 'infrastructure/cloudflare', engine_mount_point='secret', url=lookup('env', 'VAULT_ADDR') | default('https://10.100.30.11:8200'), token=(vault_token | default(lookup('env', 'VAULT_TOKEN'))), validate_certs=false) | default({}) }}" + # Versuche secret.data, dann data.data (manchmal unterschiedlich je nach hvac version) + raw_app_secrets: "{{ vault_response.secret | default(vault_response.data | default(vault_response)) | default({}) }}" + +- name: "Lade Cloudflare Secrets (nur für Traefik Edge)" + set_fact: + cf_response: "{{ lookup('community.hashi_vault.vault_kv2_get', 'infrastructure/cloudflare', engine_mount_point='secret', url=lookup('env', 'VAULT_ADDR') | default('https://10.100.30.11:8200'), token=(vault_token | default(lookup('env', 'VAULT_TOKEN'))), validate_certs=false) | default({}) }}" delegate_to: localhost when: app_item.name == 'traefik-edge' ignore_errors: true -- name: "Merge Cloudflare Secrets in App Secrets Payload" +- name: "Extrahiere Cloudflare Secrets Daten" set_fact: - cf_secrets_payload: "{{ cf_secrets.secret | default(cf_secrets.data | default(cf_secrets)) | default({}) }}" - when: app_item.name == 'traefik-edge' and cf_secrets is defined + raw_cf_secrets: "{{ cf_response.secret | default(cf_response.data | default(cf_response)) | default({}) }}" + when: app_item.name == 'traefik-edge' +# 4. ENV Variablen aufbereiten (Datenstruktur bauen) +- name: "Bereite ENV Variablen vor" + set_fact: + env_dict: {} + +- name: "Fülle ENV mit App Secrets" + set_fact: + env_dict: "{{ env_dict | combine({item.key: item.value}) }}" + loop: "{{ raw_app_secrets | dict2items }}" + when: + - raw_app_secrets is mapping + - item.key not in ['data', 'metadata', 'auth', 'lease_id', 'lease_duration', 'renewable', 'request_id', 'wrap_info', 'warnings', 'raw'] + # Filter alte Keys raus + - item.key not in ['CLOUDFLARE_API_KEY', 'CLOUDFLARE_EMAIL'] + +- name: "Mappe Cloudflare Secrets (Traefik Edge)" + set_fact: + env_dict: "{{ env_dict | combine({ + 'CF_DNS_API_TOKEN': raw_cf_secrets['api_token'], + 'CF_ZONE_API_TOKEN': raw_cf_secrets['api_token'], + 'CF_API_EMAIL': raw_cf_secrets['email'] + }) }}" + when: app_item.name == 'traefik-edge' and raw_cf_secrets is defined and raw_cf_secrets['api_token'] is defined + +# 5. Schreibe .env Datei - name: "Erstelle .env Datei auf Remote" copy: dest: "{{ target_dir }}/.env" content: | - {# App Secrets & Cloudflare Secrets zusammenführen #} - {%- set all_secrets = {} -%} - {# 1. App Secrets laden #} - {%- set app_sec_data = app_secrets.secret | default(app_secrets.data | default(app_secrets)) -%} - {%- if app_sec_data is mapping -%} - {%- set _ = all_secrets.update(app_sec_data) -%} - {%- endif -%} - {# 2. Cloudflare Secrets (für Traefik Edge) laden #} - {%- if cf_secrets_payload is defined and cf_secrets_payload is mapping -%} - {%- set _ = all_secrets.update(cf_secrets_payload) -%} - {%- endif -%} - {# 3. Ausgabe #} - {%- for key, value in all_secrets.items() -%} - {%- if key not in ['data', 'metadata', 'auth', 'lease_id', 'lease_duration', 'renewable', 'request_id', 'wrap_info', 'warnings', 'raw'] -%} - {%- if app_item.name == 'traefik-edge' -%} - {%- if key == 'api_token' -%} - CF_DNS_API_TOKEN={{ value }} - CF_ZONE_API_TOKEN={{ value }} - {%- elif key == 'email' -%} - CF_API_EMAIL={{ value }} - {%- elif key in ['CLOUDFLARE_API_KEY', 'CLOUDFLARE_EMAIL'] -%} - {%- else -%} - {{ key | trim }}={{ value }} - {%- endif -%} - {%- else -%} - {{ key | trim }}={{ value }} - {%- endif -%} - {%- endif -%} - {%- endfor -%} + {% for key, value in env_dict.items() %} + {{ key }}={{ value }} + {% endfor %} mode: '0600' - when: (app_item.has_secrets | default(false) and app_secrets | length > 0) or (app_item.name == 'traefik-edge' and cf_secrets_payload is defined) + when: env_dict | length > 0 -# 4. Sync Dateien (Lokal -> Remote) -# Hinweis: 'copy' Modul unterstützt kein 'exclude'. +# 6. Sync Dateien - name: "Synchronisiere App-Dateien (Push)" copy: src: "{{ source_dir }}/" dest: "{{ target_dir }}/" mode: '0644' directory_mode: '0755' - # .env im Source wird überschrieben falls existent -# 5. Docker Compose Deployment (Remote) +# 7. Docker Compose Deployment - name: "Deploy {{ app_item.name }} mit Docker Compose" community.docker.docker_compose_v2: project_src: "{{ target_dir }}"