added new secret logic for vms
This commit is contained in:
88
VAULT_RESET.md
Normal file
88
VAULT_RESET.md
Normal file
@@ -0,0 +1,88 @@
|
||||
# Vault Reset Guide
|
||||
|
||||
Dieses Dokument beschreibt, wie du HashiCorp Vault komplett zurücksetzt, falls das **Root Token** verloren gegangen ist oder die Instanz irreparabel beschädigt scheint.
|
||||
|
||||
**⚠️ ACHTUNG: DATENVERLUST!**
|
||||
Dieser Vorgang löscht unwiderruflich:
|
||||
* Alle gespeicherten Secrets (Passwörter, Tokens).
|
||||
* Alle konfigurierten User, Policies und Engines.
|
||||
* Das Zertifikat (CA).
|
||||
|
||||
Du musst anschließend alle Secrets neu einspielen (via `setup_vault_secrets.sh`).
|
||||
|
||||
---
|
||||
|
||||
## Schritt 1: Vault Container & Daten löschen
|
||||
|
||||
Führe dies auf deinem Management-Host (`vm-management-200`) aus. Wir nutzen SSH, um die Daten auf dem Vault-Server (`vm-docker-apps-301`) zu löschen.
|
||||
|
||||
```bash
|
||||
# 1. Container stoppen und entfernen
|
||||
ssh -i ~/.ssh/id_ed25519_ansible_prod ansible@10.100.30.11 "docker stop vault-prod && docker rm vault-prod"
|
||||
|
||||
# 2. Persistente Daten löschen (File Storage & Zertifikate)
|
||||
ssh -i ~/.ssh/id_ed25519_ansible_prod ansible@10.100.30.11 "sudo rm -rf /opt/vault/file/* /opt/vault/certs/*"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Schritt 2: Neu-Deployment
|
||||
|
||||
Jetzt lassen wir Ansible den Container neu starten. Da die Verzeichnisse leer sind, wird das `entrypoint.sh` Skript:
|
||||
1. Neue Zertifikate generieren.
|
||||
2. Vault neu initialisieren.
|
||||
3. Neue Unseal-Keys und ein neues Root-Token erstellen.
|
||||
|
||||
```bash
|
||||
# Wechsel in das Ansible Verzeichnis
|
||||
cd infrastructure/ansible
|
||||
|
||||
# Playbook ausführen (ignoriere 'Permission denied' Fehler bei Secrets, da Vault leer ist)
|
||||
ansible-playbook -i inventory.ini deploy.yml
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Schritt 3: Neue Zugangsdaten abholen
|
||||
|
||||
Der neue Vault ist nun gestartet. Wir müssen uns die neuen "Schlüssel zum Königreich" holen.
|
||||
|
||||
```bash
|
||||
# 1. Neues Root Token auslesen
|
||||
# (ACHTUNG: Speichere dieses Token sofort in deinem Passwort-Manager!)
|
||||
ssh -i ~/.ssh/id_ed25519_ansible_prod ansible@10.100.30.11 "sudo cat /opt/vault/file/init_keys.json"
|
||||
|
||||
# 2. Neues CA Zertifikat holen
|
||||
# (Sonst vertraut dein PC dem neuen Vault nicht)
|
||||
scp -i ~/.ssh/id_ed25519_ansible_prod ansible@10.100.30.11:/opt/vault/certs/ca.crt ../../vault-ca.crt
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Schritt 4: Secrets wiederherstellen
|
||||
|
||||
Nun nutzen wir unser Setup-Skript, um die Secrets aus deiner (hoffentlich noch vorhandenen oder neu erstellten) `bootstrap.tfvars` wieder einzuspielen.
|
||||
|
||||
1. **Vorbereitung:**
|
||||
Falls du `terraform/bootstrap.tfvars` gelöscht hattest, musst du sie neu erstellen (siehe `README.md` -> Phase 1).
|
||||
|
||||
2. **Import:**
|
||||
```bash
|
||||
cd ../.. # Ins Root des Repos
|
||||
./setup_vault_secrets.sh
|
||||
```
|
||||
* Gib das **neue** Root-Token ein (aus Schritt 3).
|
||||
* Das Skript aktiviert die Engines und schreibt die Secrets neu.
|
||||
|
||||
---
|
||||
|
||||
## Schritt 5: Clients aktualisieren
|
||||
|
||||
Da wir eine neue CA haben, musst du das Zertifikat ggf. neu verteilen:
|
||||
|
||||
* **Browser:** Importiere das neue `vault-ca.crt` in Firefox/Chrome.
|
||||
* **Linux Desktop:** Kopiere es nach `/usr/local/share/ca-certificates/` und führe `update-ca-certificates` aus.
|
||||
* **Terraform:** Das Environment (`VAULT_CACERT`) zeigt meist eh auf die Datei im Repo (`./vault-ca.crt`), die wir in Schritt 3 überschrieben haben -> Sollte direkt gehen.
|
||||
|
||||
🎉 **Fertig!** Dein Vault ist frisch aufgesetzt.
|
||||
|
||||
@@ -54,4 +54,4 @@
|
||||
include_tasks: deploy_logic_push.yml
|
||||
loop: "{{ host_config.apps }}"
|
||||
loop_control:
|
||||
loop_var: app_name
|
||||
loop_var: app_item
|
||||
|
||||
@@ -4,19 +4,19 @@
|
||||
# 1. Validierung
|
||||
- name: "Prüfe App im Katalog"
|
||||
stat:
|
||||
path: "{{ apps_catalog_path }}/{{ app_name }}"
|
||||
path: "{{ apps_catalog_path }}/{{ app_item.name }}"
|
||||
register: catalog_entry
|
||||
|
||||
- name: "Skip if missing"
|
||||
debug:
|
||||
msg: "App {{ app_name }} nicht gefunden."
|
||||
msg: "App {{ app_item.name }} nicht gefunden."
|
||||
when: not catalog_entry.stat.exists
|
||||
|
||||
# 2. Setup
|
||||
- name: "Setze Pfade"
|
||||
set_fact:
|
||||
source_dir: "{{ apps_catalog_path }}/{{ app_name }}"
|
||||
target_dir: "{{ base_deploy_path }}/{{ app_name }}"
|
||||
source_dir: "{{ apps_catalog_path }}/{{ app_item.name }}"
|
||||
target_dir: "{{ base_deploy_path }}/{{ app_item.name }}"
|
||||
when: catalog_entry.stat.exists
|
||||
|
||||
- name: "Erstelle Zielverzeichnis"
|
||||
@@ -30,9 +30,9 @@
|
||||
# Im Pull-Mode brauchen wir ein Token. Wir lesen es aus /root/.vault-token oder ENV
|
||||
- name: "Lade Secrets (Lokal)"
|
||||
set_fact:
|
||||
app_secrets: "{{ lookup('community.hashi_vault.vault_kv2_get', 'apps/' + app_name, engine_mount_point='secret', url=vault_addr, token_path='/root/.vault-token') | default({}) }}"
|
||||
app_secrets: "{{ lookup('community.hashi_vault.vault_kv2_get', 'apps/' + app_item.name, engine_mount_point='secret', url=vault_addr, token_path='/root/.vault-token') | default({}) }}"
|
||||
ignore_errors: true
|
||||
when: catalog_entry.stat.exists
|
||||
when: catalog_entry.stat.exists and app_item.has_secrets | default(false)
|
||||
|
||||
- name: "Erstelle .env"
|
||||
copy:
|
||||
@@ -42,7 +42,7 @@
|
||||
{{ key }}={{ value }}
|
||||
{% endfor %}
|
||||
mode: '0600'
|
||||
when: catalog_entry.stat.exists and app_secrets is defined and app_secrets | length > 0
|
||||
when: catalog_entry.stat.exists and app_item.has_secrets | default(false) and app_secrets is defined and app_secrets | length > 0
|
||||
|
||||
# 4. Sync Files (Local Copy)
|
||||
- name: "Sync Files"
|
||||
@@ -64,4 +64,3 @@
|
||||
environment:
|
||||
PATH: "/usr/bin:/usr/local/bin:/snap/bin:{{ ansible_env.PATH }}"
|
||||
when: catalog_entry.stat.exists
|
||||
|
||||
|
||||
@@ -2,22 +2,22 @@
|
||||
# Push-Logik: Wir kopieren von Localhost -> Remote Host
|
||||
|
||||
# 1. Validierung (Lokal)
|
||||
- name: "Prüfe ob App '{{ app_name }}' im Katalog existiert (Lokal)"
|
||||
- name: "Prüfe ob App '{{ app_item.name }}' im Katalog existiert (Lokal)"
|
||||
stat:
|
||||
path: "{{ apps_catalog_path }}/{{ app_name }}"
|
||||
path: "{{ apps_catalog_path }}/{{ app_item.name }}"
|
||||
delegate_to: localhost
|
||||
register: catalog_entry
|
||||
|
||||
- name: "Fehler: App fehlt im Katalog"
|
||||
fail:
|
||||
msg: "App '{{ app_name }}' nicht gefunden in {{ apps_catalog_path }}"
|
||||
msg: "App '{{ app_item.name }}' nicht gefunden in {{ apps_catalog_path }}"
|
||||
when: not catalog_entry.stat.exists
|
||||
|
||||
# 2. Setup Pfade (Remote)
|
||||
- name: "Setze Zielpfad"
|
||||
set_fact:
|
||||
source_dir: "{{ apps_catalog_path }}/{{ app_name }}"
|
||||
target_dir: "{{ base_deploy_path }}/{{ app_name }}"
|
||||
source_dir: "{{ apps_catalog_path }}/{{ app_item.name }}"
|
||||
target_dir: "{{ base_deploy_path }}/{{ app_item.name }}"
|
||||
|
||||
- name: "Erstelle Zielverzeichnis auf Remote"
|
||||
file:
|
||||
@@ -26,18 +26,19 @@
|
||||
mode: '0755'
|
||||
|
||||
# 3. Secrets aus Vault (Lokal lookup, Remote copy)
|
||||
# Nur ausführen, wenn has_secrets: true
|
||||
- name: "Lade Secrets aus Vault (Lokal lookup)"
|
||||
set_fact:
|
||||
app_secrets: "{{ lookup('community.hashi_vault.vault_kv2_get', 'apps/' + app_name, engine_mount_point='secret', url=lookup('env', 'VAULT_ADDR') | default('https://10.100.30.11:8200'), token=lookup('env', 'VAULT_TOKEN')) | default({}) }}"
|
||||
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=lookup('env', 'VAULT_TOKEN'), validate_certs=false) | default({}) }}"
|
||||
delegate_to: localhost
|
||||
ignore_errors: true
|
||||
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"
|
||||
- name: "Setze app_secrets default wenn leer oder skipped"
|
||||
set_fact:
|
||||
app_secrets: {}
|
||||
when: app_secrets is undefined
|
||||
|
||||
|
||||
- name: "Erstelle .env Datei auf Remote"
|
||||
copy:
|
||||
dest: "{{ target_dir }}/.env"
|
||||
@@ -46,11 +47,10 @@
|
||||
{{ key }}={{ value }}
|
||||
{% endfor %}
|
||||
mode: '0600'
|
||||
when: app_secrets | length > 0
|
||||
when: app_item.has_secrets | default(false) and app_secrets | length > 0
|
||||
|
||||
# 4. Sync Dateien (Lokal -> Remote)
|
||||
# Hinweis: 'copy' Modul unterstützt kein 'exclude'. Für Excludes brauchen wir 'synchronize' (rsync)
|
||||
# oder wir kopieren alles und ignorieren .env Konflikte (da copy sowieso überschreibt)
|
||||
# Hinweis: 'copy' Modul unterstützt kein 'exclude'.
|
||||
- name: "Synchronisiere App-Dateien (Push)"
|
||||
copy:
|
||||
src: "{{ source_dir }}/"
|
||||
@@ -59,9 +59,8 @@
|
||||
directory_mode: '0755'
|
||||
# .env im Source wird überschrieben falls existent
|
||||
|
||||
|
||||
# 5. Docker Compose Deployment (Remote)
|
||||
- name: "Deploy {{ app_name }} mit Docker Compose"
|
||||
- name: "Deploy {{ app_item.name }} mit Docker Compose"
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: "{{ target_dir }}"
|
||||
state: present
|
||||
@@ -71,5 +70,3 @@
|
||||
environment:
|
||||
PATH: "/usr/bin:/usr/local/bin:/snap/bin:{{ ansible_env.PATH }}"
|
||||
register: compose_result
|
||||
|
||||
|
||||
|
||||
@@ -59,10 +59,9 @@
|
||||
# 4. Bereinigung (Pruning)
|
||||
- name: "Ermittle zu löschende Apps"
|
||||
set_fact:
|
||||
# Apps die installiert sind, aber nicht in wanted_apps stehen
|
||||
# ACHTUNG: 'vault' sollte ggf. geschützt werden, wenn es manuell läuft?
|
||||
# Da wir Vault aber auch via GitOps managen (in der Liste), ist das ok.
|
||||
apps_to_remove: "{{ installed_apps | difference(wanted_apps) }}"
|
||||
# wanted_apps ist jetzt eine Liste von Objekten. Wir brauchen nur die Namen.
|
||||
# installed_apps | difference(wanted_apps | map(attribute='name') | list)
|
||||
apps_to_remove: "{{ installed_apps | difference(wanted_apps | map(attribute='name') | list) }}"
|
||||
|
||||
- name: "Pruning Loop"
|
||||
include_tasks: prune_logic.yml
|
||||
@@ -85,4 +84,4 @@
|
||||
include_tasks: deploy_logic_pull.yml
|
||||
loop: "{{ wanted_apps }}"
|
||||
loop_control:
|
||||
loop_var: app_name
|
||||
loop_var: app_item
|
||||
|
||||
@@ -12,5 +12,4 @@ services:
|
||||
- proxy-sub
|
||||
|
||||
networks:
|
||||
proxy-sub:
|
||||
external: true
|
||||
proxy-sub:
|
||||
@@ -1,7 +1,10 @@
|
||||
apps:
|
||||
- vault
|
||||
- traefik-sub
|
||||
- whoami
|
||||
# Hier einfach weitere Apps aus dem Katalog hinzufügen:
|
||||
# - nextcloud
|
||||
# - monitoring
|
||||
- name: vault
|
||||
has_secrets: false # Vault verwaltet sich selbst (initial)
|
||||
- name: traefik-sub
|
||||
has_secrets: false # Aktuell keine Secrets nötig
|
||||
- name: whoami
|
||||
has_secrets: false
|
||||
# Beispiel für später:
|
||||
# - name: nextcloud
|
||||
# has_secrets: true
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
apps:
|
||||
- traefik-edge
|
||||
- whoami
|
||||
- name: traefik-edge
|
||||
has_secrets: true # Benötigt Cloudflare Token
|
||||
|
||||
@@ -7,9 +7,36 @@ VAULT_CA_LOCAL="./vault-ca.crt"
|
||||
|
||||
# Check if bootstrap vars exist
|
||||
if [ ! -f "$BOOTSTRAP_VARS" ]; then
|
||||
echo "Fehler: $BOOTSTRAP_VARS nicht gefunden."
|
||||
echo "Bitte stelle sicher, dass du im Root des Repos bist und die Datei existiert."
|
||||
exit 1
|
||||
echo "⚠️ Warnung: $BOOTSTRAP_VARS nicht gefunden."
|
||||
read -p "Soll eine neue leere Bootstrap-Datei erstellt werden? (y/n) " -n 1 -r
|
||||
echo ""
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
cat > "$BOOTSTRAP_VARS" << EOF
|
||||
# terraform/bootstrap.tfvars
|
||||
use_vault = false
|
||||
|
||||
# Proxmox Credentials
|
||||
proxmox_api_url = "https://10.100.0.2:8006/api2/json"
|
||||
proxmox_api_token_id = "root@pam!terraform"
|
||||
proxmox_api_token_secret = "CHANGE_ME"
|
||||
|
||||
# OPNsense Credentials
|
||||
opnsense_uri = "https://10.100.0.1:4443"
|
||||
opnsense_api_key = "CHANGE_ME"
|
||||
opnsense_api_secret = "CHANGE_ME"
|
||||
|
||||
# VM User Config
|
||||
ci_user = "ansible"
|
||||
ci_password = "InitialPassword123!"
|
||||
ssh_public_key = "ssh-ed25519 CHANGE_ME"
|
||||
EOF
|
||||
echo "✅ Datei erstellt. Bitte editiere '$BOOTSTRAP_VARS' und trage deine Secrets ein."
|
||||
echo "Führe das Skript danach erneut aus."
|
||||
exit 0
|
||||
else
|
||||
echo "Abbruch."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check for Vault CA
|
||||
|
||||
54
vault-ca.crt
54
vault-ca.crt
@@ -1,33 +1,33 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
EEUWC8tQVPJ1frfcPDKjuwI=
|
||||
Q0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCocczUOKJI0j4hwQsP
|
||||
yJgljyJewd9oy71z5NrxNCxdbGlz9B7TwMZ1pEo+JRQBiMnx46zoIfPnHVkGYEW+
|
||||
9KDY0JmxqePOt+vfI9lgKw8AijI2ZMEfEVeRx5lFdKQ6zanWI0wTGyrXTV0H0zcn
|
||||
ir8up9Xbe79TpicN2OGTWcTnUVx0c0wTXp9Jr273iTQ1LjRl/9jud1aQQXGbYecn
|
||||
xqbdKTY8z/5dqQdw2Us5KXS2Q7GLEcJzFN65Ffg8Fo7MxbceCswf5DolhQZMU+5U
|
||||
q2dpB7BgTdm857RliveQk4OwDXuNkuPwkqomJyDYkaW7DeJqMIeXh2BXOPhfTj33
|
||||
0o1dxXyqbU34yB1tzJ33LIS7ef/p+CfyFrn8HRmfAxUxZkpheSuh1xXiuXRVlRea
|
||||
U89BSvSjSqi8FRy9FcdavKkaRbfmCYb2ra0vIundNDKTZVgEW2NJwp8CIUrFePYe
|
||||
3iPVKEglMZFANobl9OfQqq+O0opi4K7KUrrT9/rqRBKpluyVOZHTpyExpdCipQdx
|
||||
J5RuKEje5bjjTy2Ckom6v6G6BH9CVmvEVsT2VTgPHzmaZfO0ycEOJZZg81ODZCgw
|
||||
tVIH5TpG69sgrD7CSbntastgLXuWI0IO6qb/vfBnvo8z9rfOZB1371ZWbJgAA8S4
|
||||
eH7CNOM/b7ywIUEZIUfnE2jdBwIDAQABo1MwUTAdBgNVHQ4EFgQUkgHnLvktGrP5
|
||||
vgdystgellkE80gwHwYDVR0jBBgwFoAUkgHnLvktGrP5vgdystgellkE80gwDwYD
|
||||
VR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEABzH2VRDrUYTZOVZvlb6U
|
||||
gerjh2X7e+LKhG/kDXy8GHz6XohUBzXENLq7Bdm58qRJ8Yq40xM9uZJdlWONkJO1
|
||||
L8QHbARf7o8REZkfV9YuRMgzh5SCAqNqUlSsVX60WvGPvjZSIFRRmY+3wRyOariG
|
||||
6INmTGbaFnjNsKMS9jx09SgMuBMlg4GgGmi5SIyPJIOeCgExdK3EXEjIe52tta/O
|
||||
i8wm9pkbRDOS4kk59ZESAfUe0wMlT5OIcIoq5bQVKScbLofW5Q18M2hzztDN9f7J
|
||||
6XdjsoBK35S2GcgBeWRmJ/i/woxxjnG51bZ4vahNlBwmQJ5KnLG4qP/6nBDJHv38
|
||||
WlF1vdH0bY+aYx6yJrNjRmKuuo67wzYc6IsePHMkTYfht3LC+CaTHxFmZZ4G5uft
|
||||
71fRiDRSZeRZR/wemfhiRBhdJzeE7ZRh8sEnw9q2j4hSi6x33xysR0WJdtT7p11F
|
||||
FgfSiLoNhJnHHTKhICCStny/oQD61YtFI2Ha2IlwdHzM3Bg+DFr/CxO7liHXcvt0
|
||||
aM2R5E5hsmGjki7yvXQqTJG/j+VXq59ZPr1xQSPsSvZaGXkPMqMJ22Cw/N6s50cM
|
||||
wpy4v9n0Es6v+CZN1Leo0WtmXDakwYUWI1ZI0yeoxOz9mFEWp/NDHVazOMynEWIw
|
||||
QvPra+e4ulgvnKYRngLwp9w=
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
Reference in New Issue
Block a user