From 084a483cf2884c69fd88fdd65dee94e25c2c5935 Mon Sep 17 00:00:00 2001 From: Christoph Date: Sun, 22 Feb 2026 00:23:30 +0100 Subject: [PATCH] update.. --- decrypt-vault-strings-from-file.sh | 178 +++++++++++++++-- decrypt-vault-strings-from-file.sh.00 | 55 ++++++ encrypt-vault-string.sh | 7 + encrypt-vault-strings-from-file.sh | 205 ++++++++++++++++++++ host_vars/file-ah-alt.kanzlei-kiel.netz.yml | 13 +- host_vars/file-ah.kanzlei-kiel.netz.yml | 24 ++- 6 files changed, 450 insertions(+), 32 deletions(-) create mode 100755 decrypt-vault-strings-from-file.sh.00 create mode 100755 encrypt-vault-string.sh create mode 100755 encrypt-vault-strings-from-file.sh diff --git a/decrypt-vault-strings-from-file.sh b/decrypt-vault-strings-from-file.sh index c13e88e..3de389e 100755 --- a/decrypt-vault-strings-from-file.sh +++ b/decrypt-vault-strings-from-file.sh @@ -1,54 +1,190 @@ #!/usr/bin/env bash +# +# decrypt-vault-strings-from-file.sh +# +# Zweck: +# - Entschlüsselt entweder: +# (A) eine komplett mit ansible-vault verschlüsselte Datei (ANSIBLE_VAULT Header) +# (B) einzelne YAML "!vault |" Blöcke in einer Datei (z.B. group_vars/host_vars) +# (C) einen einzelnen verschlüsselten String (Argument, Pipe oder interaktiv) +# +# Erwartet eine Vault-Passwortdatei unter: ~/.vault-pass +# +set -euo pipefail + +VAULT_PASS_FILE="${HOME}/.vault-pass" + +######################################## +# Hilfe anzeigen +######################################## +show_help() { + cat </dev/null 2>&1; then + echo "Error: ansible-vault not found in PATH." >&2 + return 1 + fi + + # Prüfen ob Vault-Passwortdatei lesbar ist + #if [[ ! -r "$VAULT_PASS_FILE" ]]; then + # echo "Error: vault password file not readable: $VAULT_PASS_FILE" >&2 + # return 1 + #fi + + ######################################## + # Wenn ein Argument übergeben wurde + ######################################## + if [[ -n "${1:-}" ]]; then + + # --- Fall 1: Argument ist eine Datei --- if [[ -f "$1" ]]; then - if [[ $(head -n1 "$1") == "\$ANSIBLE_VAULT;1.1;AES256" ]]; then - cat "$1" | ansible-vault decrypt --vault-password-file ~/.vault-pass 2> /dev/null + # Wenn Datei eine "komplett verschlüsselte" Vault-Datei ist + # (Header ist die erste Zeile) + if [[ "$(head -n1 "$1")" == "\$ANSIBLE_VAULT;1.1;AES256" ]]; then + # Vollständige Datei entschlüsseln und ausgeben + ansible-vault decrypt --vault-password-file "$VAULT_PASS_FILE" "$1" 2>/dev/null return 0 fi + + # --- Fall 2: Datei enthält einzelne "!vault" Blöcke (z.B. YAML) --- printf 'Reading vault values from file...\n\n' + + # parsing = 0 -> wir sind nicht im Vault-Block + # parsing = 1 -> wir sammeln gerade Vault-Block-Zeilen local parsing=0 local result="" local name="" - local blue=$(tput setaf 4) - local discard=$(tput sgr0) - for line in $(cat $1); do - if [[ $(echo "$line" | grep -c "\!vault") -gt 0 ]] && [[ $parsing -eq 0 ]]; then + + # Farbausgabe (blau) für den jeweiligen Key/Name + local blue + local discard + blue="$(tput setaf 4 || true)" + discard="$(tput sgr0 || true)" + + # Originalscript hat "for line in \$(cat file)" verwendet, + # was nach Whitespace tokenisiert. Um das Verhalten kontrollierter + # beizubehalten, tokenisieren wir hier ebenfalls nach Whitespace: + # + # - Das hilft, wenn Vault-Blöcke eingerückt sind oder YAML Zeichen enthält, + # weil später ohnehin per sed weiter "normalisiert" wird. + # + # WICHTIG: Das ist nicht "echtes" YAML-Parsing, sondern best-effort. + while IFS= read -r token; do + + # Start eines vault blocks erkennen (Token enthält "!vault") + if [[ "$(echo "$token" | grep -c "\!vault")" -gt 0 ]] && [[ $parsing -eq 0 ]]; then parsing=1 - elif [[ $parsing -eq 1 ]] && [[ $( echo $line | grep -c ":") -eq 0 ]]; then - result=$(printf "${result}\n${line}") + + # Im Vault-Block: Token ohne ":" werden gesammelt (Ciphertext-Zeilen) + elif [[ $parsing -eq 1 ]] && [[ "$(echo "$token" | grep -c ":")" -eq 0 ]]; then + result="$(printf "%s\n%s" "$result" "$token")" + + # Sonst: Blockende / neuer Bereich else - if [[ $result != "" ]]; then - printf "\n\n${blue}$name${discard}\n" - printf "$result" | vdecr + # Wenn wir einen gesammelten Block haben -> ausgeben und decrypten + if [[ -n "$result" ]]; then + printf "\n\n%s%s%s\n" "$blue" "$name" "$discard" + # Rekursiver Aufruf: der gesammelte Block wird wie "Stringinput" + # behandelt und im unteren Abschnitt entschlüsselt + printf "%s" "$result" | vdecr name="" result="" parsing=0 fi fi - if [[ $( echo "$line" | grep -c ":") -eq 1 ]]; then - name="$line" + + # Token mit ":" als "Name" merken (typischerweise YAML key:) + if [[ "$(echo "$token" | grep -c ":")" -eq 1 ]]; then + name="$token" fi - done + + # Tokenisierung nach Whitespace (ähnlich dem Original) + done < <(tr -s '[:space:]' '\n' < "$1") + return 0 fi + + # --- Fall 3: Argument ist ein String --- local str="$1" + + # --- Fall 4: String kommt per Pipe (stdin ist kein TTY) --- elif [[ ! -t 0 ]]; then - local str=$(cat) + local str + str="$(cat)" + + # --- Fall 5: Interaktiv --- else printf 'Interactive mode. Paste encrypted string and press Ctrl-D two times to confirm.\n' - local str=$(cat) + local str + str="$(cat)" printf '\n' fi - printf -- "$str" | sed 's/ /\n/g' | \ - sed '/---\|^.*:\|\!vault\||\|^$/d' | \ - ansible-vault decrypt --vault-password-file ~/.vault-pass 2> /dev/null + ######################################## + # String entschlüsseln + # + # Das Script erwartet, dass der Input evtl. als YAML-Fragment kommt, + # und "normalisiert" ihn so, dass ansible-vault decrypt damit klarkommt: + # + # - ersetzt Spaces durch Newlines + # - entfernt YAML-Deko wie "---", "key:", "!vault", "|", leere Zeilen + # - piped den Rest in "ansible-vault decrypt" + ######################################## + printf -- "%s" "$str" | \ + sed 's/ /\n/g' | \ + sed '/---\|^.*:\|\!vault\||\|^$/d' | \ + ansible-vault decrypt --vault-password-file "$VAULT_PASS_FILE" 2>/dev/null + printf '\n' } -vdecr $1 +######################################## +# Main +######################################## +if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then + show_help + exit 0 +fi + +vdecr "${1:-}" diff --git a/decrypt-vault-strings-from-file.sh.00 b/decrypt-vault-strings-from-file.sh.00 new file mode 100755 index 0000000..2b01227 --- /dev/null +++ b/decrypt-vault-strings-from-file.sh.00 @@ -0,0 +1,55 @@ +#!/usr/bin/env bash + +vdecr() { + unset IFS + + if [[ -n "$1" ]]; then + if [[ -f "$1" ]]; then + + if [[ $(head -n1 "$1") == "\$ANSIBLE_VAULT;1.1;AES256" ]]; then + cat "$1" | ansible-vault decrypt 2> /dev/null + return 0 + fi + printf 'Reading vault values from file...\n\n' + local parsing=0 + local result="" + local name="" + local blue=$(tput setaf 4) + local discard=$(tput sgr0) + for line in $(cat $1); do + if [[ $(echo "$line" | grep -c "\!vault") -gt 0 ]] && [[ $parsing -eq 0 ]]; then + parsing=1 + elif [[ $parsing -eq 1 ]] && [[ $( echo $line | grep -c ":") -eq 0 ]]; then + result=$(printf "${result}\n${line}") + else + if [[ $result != "" ]]; then + printf "\n\n${blue}$name${discard}\n" + printf "$result" | vdecr + name="" + result="" + parsing=0 + fi + fi + if [[ $( echo "$line" | grep -c ":") -eq 1 ]]; then + name="$line" + fi + done + return 0 + fi + local str="$1" + elif [[ ! -t 0 ]]; then + local str=$(cat) + else + printf 'Interactive mode. Paste encrypted string and press Ctrl-D two times to confirm.\n' + local str=$(cat) + printf '\n' + fi + + printf -- "$str" | sed 's/ /\n/g' | \ + sed '/---\|^.*:\|\!vault\||\|^$/d' | \ + #ansible-vault decrypt --vault-password-file ~/.vault-pass 2> /dev/null + ansible-vault decrypt 2> /dev/null + printf '\n' +} + +vdecr $1 diff --git a/encrypt-vault-string.sh b/encrypt-vault-string.sh new file mode 100755 index 0000000..6e822f8 --- /dev/null +++ b/encrypt-vault-string.sh @@ -0,0 +1,7 @@ +!/usr/bin/env bash +set -euo pipefail + +read -r -s -p "String zum Verschlüsseln: " PLAINTEXT +echo + +printf '%s' "$PLAINTEXT" | ansible-vault encrypt_string --stdin-name 'secret' diff --git a/encrypt-vault-strings-from-file.sh b/encrypt-vault-strings-from-file.sh new file mode 100755 index 0000000..8bf3f62 --- /dev/null +++ b/encrypt-vault-strings-from-file.sh @@ -0,0 +1,205 @@ +#!/usr/bin/env bash +# +# encrypt-vault-strings-to-file.sh +# +# Gegenstück zu deinem Decrypt-Script. +# +# Funktionen: +# 1. Komplettes File mit ansible-vault encrypt verschlüsseln +# 2. YAML-Datei mit key: value Zeilen in key: !vault | Blöcke umwandeln +# 3. Einzelnen String verschlüsseln (Argument, Pipe oder interaktiv) +# +# Vault-Passwortdatei: ~/.vault-pass +# + +set -euo pipefail + +VAULT_PASS_FILE="${HOME}/.vault-pass" + +######################################## +# Hilfe anzeigen +######################################## +show_help() { +cat <&2 + exit 1 + fi + + ######################################## + # Optionales Output-File (-o) + ######################################## + local out_file="" + if [[ "${1:-}" == "-o" && -n "${2:-}" ]]; then + out_file="$2" + shift 2 + fi + + ######################################## + # --- 1) File als Argument --- + ######################################## + if [[ -n "${1:-}" && -f "$1" ]]; then + local f="$1" + + # Fall A: Datei ist bereits vollständig vault-verschlüsselt + if [[ "$(head -n1 "$f")" == "\$ANSIBLE_VAULT;1.1;AES256"* ]]; then + echo "File already encrypted (ANSIBLE_VAULT header found): $f" >&2 + return 0 + fi + + # Fall B: YAML mit key: value Zeilen + if grep -Eq '^[[:space:]]*[A-Za-z0-9_.-]+:[[:space:]]*[^#].*$' "$f"; then + local tmpout + tmpout="$(mktemp)" + + # Datei zeilenweise lesen + while IFS= read -r line || [[ -n "$line" ]]; do + + # Leere Zeilen oder Kommentare unverändert übernehmen + if [[ -z "$line" || "$line" =~ ^[[:space:]]*# ]]; then + printf '%s\n' "$line" >> "$tmpout" + continue + fi + + # Bereits verschlüsselte !vault Einträge nicht verändern + if echo "$line" | grep -q '\!vault'; then + printf '%s\n' "$line" >> "$tmpout" + continue + fi + + # Einfache key: value Zeilen erkennen + if [[ "$line" =~ ^([[:space:]]*)([A-Za-z0-9_.-]+):[[:space:]]*(.+)$ ]]; then + local indent="${BASH_REMATCH[1]}" + local key="${BASH_REMATCH[2]}" + local value="${BASH_REMATCH[3]}" + + # YAML-Blockindikatoren nicht verändern + if [[ "$value" == "|" || "$value" == ">" || "$value" == "" ]]; then + printf '%s\n' "$line" >> "$tmpout" + continue + fi + + # Leichte Bereinigung von Quotes + value="${value%\"}"; value="${value#\"}" + value="${value%\'}"; value="${value#\'}" + + # Verschlüsselung via ansible-vault encrypt_string + while IFS= read -r enc_line; do + printf '%s%s\n' "$indent" "$enc_line" >> "$tmpout" + done < <( + printf '%s' "$value" | + ansible-vault encrypt_string \ + --stdin-name "$key" \ + --vault-password-file "$VAULT_PASS_FILE" + ) + + else + # Nicht passende Zeilen unverändert übernehmen + printf '%s\n' "$line" >> "$tmpout" + fi + + done < "$f" + + # Output schreiben + if [[ -n "$out_file" ]]; then + mv "$tmpout" "$out_file" + echo "Encrypted YAML written to: $out_file" >&2 + else + cat "$tmpout" + rm -f "$tmpout" + fi + + return 0 + fi + + # Fall C: Normale Datei → komplett verschlüsseln (in-place) + ansible-vault encrypt \ + --vault-password-file "$VAULT_PASS_FILE" \ + "$f" + + echo "Encrypted file in-place: $f" >&2 + return 0 + fi + + ######################################## + # --- 2) String-Verschlüsselung --- + ######################################## + local str="" + local name="secret" + + # String als Argument + if [[ -n "${1:-}" ]]; then + str="$1" + + # String via Pipe + elif [[ ! -t 0 ]]; then + str="$(cat)" + + # Interaktiver Modus + else + echo "Interactive mode." + read -r -p "Variable name (default: secret): " name_in + if [[ -n "$name_in" ]]; then + name="$name_in" + fi + + echo "Paste plaintext and press Ctrl-D to confirm:" + str="$(cat)" + echo + fi + + # Ausgabe als YAML-kompatibler !vault Block + printf '%s' "$str" | + ansible-vault encrypt_string \ + --stdin-name "$name" \ + --vault-password-file "$VAULT_PASS_FILE" +} + +######################################## +# Script starten +######################################## +vencr "$@" diff --git a/host_vars/file-ah-alt.kanzlei-kiel.netz.yml b/host_vars/file-ah-alt.kanzlei-kiel.netz.yml index e306fc2..06eb1bb 100644 --- a/host_vars/file-ah-alt.kanzlei-kiel.netz.yml +++ b/host_vars/file-ah-alt.kanzlei-kiel.netz.yml @@ -34,7 +34,7 @@ network_interfaces: method: static hwaddress: 0c:c4:7a:ea:dd:56 description: - address: 192.168.100.10 + address: 192.168.100.11 netmask: 24 gateway: 192.168.100.254 @@ -282,7 +282,7 @@ default_user: # vars used by roles/common/tasks/nfs.yml # --- -nfs_server: 192.168.100.10 +nfs_server: 192.168.100.11 # --- @@ -290,7 +290,7 @@ nfs_server: 192.168.100.10 # vars used by roles/common/tasks/samba-user.yml # --- -samba_server_ip: 192.168.100.10 +samba_server_ip: 192.168.100.11 samba_server_cidr_prefix: 24 samba_workgroup: AH-ALT @@ -438,6 +438,13 @@ samba_user: - gubitz-partner password: '0-heckert.22%' + - name: schultheis + groups: + - intern + - verwaltung + - gubitz-partner + password: '20.loui-sa/schultheis-26!' + - name: weber groups: - intern diff --git a/host_vars/file-ah.kanzlei-kiel.netz.yml b/host_vars/file-ah.kanzlei-kiel.netz.yml index a074621..4705114 100644 --- a/host_vars/file-ah.kanzlei-kiel.netz.yml +++ b/host_vars/file-ah.kanzlei-kiel.netz.yml @@ -34,7 +34,7 @@ network_interfaces: method: static hwaddress: 7c:c2:55:c0:26:74 description: - address: 192.168.100.20 + address: 192.168.100.10 netmask: 24 gateway: 192.168.100.254 @@ -317,7 +317,7 @@ cron_user_special_time_entries: # vars used by roles/common/tasks/nfs.yml # --- -nfs_server: 192.168.100.20 +nfs_server: 192.168.100.10 # --- @@ -325,7 +325,7 @@ nfs_server: 192.168.100.20 # vars used by roles/common/tasks/samba-user.yml # --- -samba_server_ip: 192.168.100.20 +samba_server_ip: 192.168.100.10 samba_server_cidr_prefix: 24 samba_workgroup: AH @@ -473,6 +473,13 @@ samba_user: - gubitz-partner password: '0-heckert.22%' + - name: schultheis + groups: + - intern + - verwaltung + - gubitz-partner + password: '20.loui-sa/schultheis-26!' + - name: weber groups: - intern @@ -521,15 +528,16 @@ samba_user: groups: [] password: '20-ni-na.stork_%24' + # password: y2F.E-9q-54f - name: back groups: [] password: !vault | $ANSIBLE_VAULT;1.1;AES256 - 63643330373231636537366333326630333265303265653933613835656262323863363038653234 - 3462653135633266373439626263356636646637643035340a653466356235346663626163306363 - 61313164643061306433643738643563303036646334376536626531383965303036386162393832 - 6631333038306462610a356535633265633563633962333137326533633834636331343562633765 - 3631 + 66613731346331613961353639616537656432373562653939623864613431663637643630613131 + 3264633732633962663330646436623532353834646463330a303037303965343762623332633661 + 34313165393831396366393162613166396465383264313831386430313535363832383437373064 + 6231626664316265660a653862386231333465623663633266616663326139356638613034303264 + 6131 # password: 9xFXkdPR_2 - name: sysadm