Files

76 lines
3.6 KiB
Bash

nodes_wait 60 || true
# ans CMD: run CMD as greg in his project directory.
ans() { setsid -w timeout -k 5 180 runuser -l greg -c "cd ~/ansible && $*" </dev/null; }
A=/home/greg/ansible
OUT=$LAB_STATE/check.out
# view [PASSWORD]: secret.yml decrypted with vault-pass.txt, or with PASSWORD.
view() {
if [ $# -eq 0 ]; then ans ansible-vault view secret.yml --vault-password-file vault-pass.txt
else ans "ansible-vault view secret.yml --vault-password-file <(echo '$1')"; fi
}
# The vault's user_password, if the password file opens it.
PW=$(view 2>/dev/null | python3 -c 'import sys, yaml
d = yaml.safe_load(sys.stdin)
print(d.get("user_password", "") if isinstance(d, dict) else "")' 2>/dev/null)
# pw_ok: vaultuser's password on node1 is $PW.
pw_ok() {
local h; h=$(in_node node1 getent shadow vaultuser | cut -d: -f2)
[ -n "$PW" ] && [ -n "$h" ] && PW=$PW H=$h python3 -W ignore -c 'import crypt, os, sys
sys.exit(crypt.crypt(os.environ["PW"], os.environ["H"]) != os.environ["H"])'
}
# A terminal for --ask-vault-pass: askpass FILE CMD... answers the prompt
# once with the password in FILE and exits with CMD's status (99 if no
# prompt came).
cat >"$LAB_STATE/askpass.py" <<'P'
import os, pty, select, sys, time
pw, cmd = open(sys.argv[1]).read().strip(), sys.argv[2:]
pid, fd = pty.fork()
if pid == 0:
os.execvp(cmd[0], cmd)
buf, sent, end = b"", False, time.time() + 60
while time.time() < end:
if not select.select([fd], [], [], 1)[0]:
continue
try:
d = os.read(fd, 4096)
except OSError:
break
if not d:
break
buf += d
if not sent and b"assword:" in buf:
os.write(fd, pw.encode() + b"\n")
sent = True
sys.stdout.write(buf.decode(errors="replace"))
if time.time() >= end:
os.kill(pid, 9)
_, st = os.waitpid(pid, 0)
sys.exit(os.waitstatus_to_exitcode(st) if sent else 99)
P
chmod 644 "$LAB_STATE/askpass.py"
navcfg() {
python3 -c 'import sys, yaml
n = (yaml.safe_load(open(sys.argv[1])) or {}).get("ansible-navigator", {})
ok = n.get("mode") == "stdout" and (n.get("playbook-artifact") or {}).get("enable") in (False, "false")
sys.exit(0 if ok else 1)' $A/ansible-navigator.yml
}
task 1 "An encrypted secret.yml, and vaultuser on node1 with its password"
need "$A/vault-pass.txt exists with mode 600" "[ \"\$(stat -c %a $A/vault-pass.txt)\" = 600 ]"
need "$A/secret.yml is encrypted (starts with \$ANSIBLE_VAULT)" "head -1 $A/secret.yml | grep -q '^\\\$ANSIBLE_VAULT'"
need "vault-pass.txt opens secret.yml, which sets user_password" '[ -n "$PW" ]'
need "$A/vault.yml exists and uses secret.yml" "grep -q secret.yml $A/vault.yml"
need "vaultuser exists on node1" 'in_node node1 id vaultuser'
need "vaultuser's password on node1 is user_password from the vault" pw_ok
task 2 "A new vault password, in vault-pass.txt"
need "vault-pass.txt opens secret.yml" '[ -n "$PW" ]'
need "vault-pass.txt doesn't hold RedhatVault any more" "! grep -qx RedhatVault $A/vault-pass.txt"
need "RedhatVault no longer opens secret.yml" '! view RedhatVault'
task 3 "vault.yml runs in ansible-navigator, with the password file and the prompt"
need "ansible-navigator.yml sets mode: stdout and playbook artifacts off" navcfg
need "ansible-navigator run vault.yml --vault-password-file vault-pass.txt works" 'ans ansible-navigator run vault.yml --vault-password-file vault-pass.txt >"$OUT" && grep -q "PLAY RECAP" "$OUT"'
need "ansible-navigator run vault.yml --ask-vault-pass asks and works" "[ -n \"\$PW\" ] && ans python3 -I $LAB_STATE/askpass.py vault-pass.txt ansible-navigator run vault.yml --ask-vault-pass >\"\$OUT\" && grep -q 'PLAY RECAP' \"\$OUT\""
rm -f "$OUT"