111 lines
3.7 KiB
Bash
Executable file
111 lines
3.7 KiB
Bash
Executable file
#!/usr/bin/env bash
|
||
set -Eeuo pipefail
|
||
# 05_issue_admin_client_cert_admin.sh
|
||
#
|
||
# Zweck:
|
||
# Mit vorhandenen Admin-Rechten (VAULT_TOKEN) ein ADMIN-mTLS-Client-Zert
|
||
# aus der Intermediate-PKI ausstellen und nach
|
||
# /root/vault/tls-admin/<env>/admin.{crt,key,issuing_ca.pem} schreiben.
|
||
|
||
if [[ -t 1 ]]; then
|
||
B=$'\e[1m'; R=$'\e[0m'; G=$'\e[32m'; Y=$'\e[33m'; E=$'\e[31m'
|
||
else
|
||
B= R= G= Y= E=
|
||
fi
|
||
ok(){ echo -e "🟩 ${G}${B}$*${R}"; }
|
||
warn(){ echo -e "🟨 ${Y}${B}$*${R}"; }
|
||
die(){ echo -e "🟥 ${E}${B}$*${R}" >&2; exit 1; }
|
||
|
||
need(){ command -v "$1" >/dev/null 2>&1 || die "missing: $1"; }
|
||
need vault; need jq; need python3; need install
|
||
|
||
: "${VAULT_TOKEN:?Set VAULT_TOKEN (admin token for this env, via vault-run-home-safe)}"
|
||
|
||
# --- TLS-Umgebung sane machen (wichtig für prod beim ersten Lauf) ---
|
||
if [[ -n "${VAULT_CLIENT_CERT:-}" && ! -r "$VAULT_CLIENT_CERT" ]]; then
|
||
warn "VAULT_CLIENT_CERT points to unreadable file: $VAULT_CLIENT_CERT – ignoring"
|
||
unset VAULT_CLIENT_CERT
|
||
fi
|
||
if [[ -n "${VAULT_CLIENT_KEY:-}" && ! -r "$VAULT_CLIENT_KEY" ]]; then
|
||
warn "VAULT_CLIENT_KEY points to unreadable file: $VAULT_CLIENT_KEY – ignoring"
|
||
unset VAULT_CLIENT_KEY
|
||
fi
|
||
if [[ -n "${VAULT_CACERT:-}" && ! -r "$VAULT_CACERT" ]]; then
|
||
warn "VAULT_CACERT points to unreadable file: $VAULT_CACERT – ignoring"
|
||
unset VAULT_CACERT
|
||
fi
|
||
|
||
# Wenn weder CA noch Client-Cert da ist: für diesen lokalen Call Verify aus
|
||
if [[ -z "${VAULT_CACERT:-}" && -z "${VAULT_CLIENT_CERT:-}" ]]; then
|
||
warn "No CA / client cert; setting VAULT_SKIP_VERIFY=1 for local admin cert issue"
|
||
export VAULT_SKIP_VERIFY=1
|
||
fi
|
||
|
||
CFG="./config/apps.yaml"
|
||
ENV_NAME="test"
|
||
CN="vault-admin-setup"
|
||
TTL="180h"
|
||
|
||
while [[ $# -gt 0 ]]; do
|
||
case "$1" in
|
||
--config) CFG="$2"; shift 2;;
|
||
--env) ENV_NAME="$2"; shift 2;;
|
||
--cn) CN="$2"; shift 2;;
|
||
--ttl) TTL="$2"; shift 2;;
|
||
-h|--help) sed -n '1,200p' "$0"; exit 0;;
|
||
*) die "Unknown arg: $1";;
|
||
esac
|
||
done
|
||
|
||
CFG_ABS="$(readlink -f "$CFG")" || die "cannot resolve $CFG"
|
||
CFGJSON="$(python3 - <<PY
|
||
import yaml, json; print(json.dumps(yaml.safe_load(open("$CFG_ABS","r",encoding="utf-8"))))
|
||
PY
|
||
)"
|
||
jqenv(){ echo "$CFGJSON" | jq -r ".environments.\"$ENV_NAME\"$1"; }
|
||
|
||
VAULT_ADDR_CFG="$(jqenv '.vault_addr')"
|
||
INT_MOUNT="$(jqenv '.pki_mount')"
|
||
[[ "$VAULT_ADDR_CFG" != "null" && "$INT_MOUNT" != "null" ]] || \
|
||
die "incomplete config: vault_addr/pki_mount in apps.yaml for env=$ENV_NAME"
|
||
|
||
export VAULT_ADDR="$VAULT_ADDR_CFG"
|
||
|
||
ROLE="admin-client"
|
||
ok "Env=${ENV_NAME} Vault=${VAULT_ADDR} PKI_MOUNT=${INT_MOUNT} role=${ROLE} CN=${CN} TTL=${TTL}"
|
||
|
||
# Rolle best-effort setzen
|
||
vault write "${INT_MOUNT}/roles/${ROLE}" \
|
||
server_flag=false client_flag=true \
|
||
allow_any_name=true key_usage="DigitalSignature" ext_key_usage="ClientAuth" \
|
||
max_ttl="720h" >/dev/null 2>&1 || warn "could not configure role ${ROLE}, continuing"
|
||
|
||
RESP="$(vault write -format=json "${INT_MOUNT}/issue/${ROLE}" common_name="${CN}" ttl="${TTL}")" \
|
||
|| die "issue failed"
|
||
CERT="$(echo "$RESP" | jq -r .data.certificate)"
|
||
KEY="$(echo "$RESP" | jq -r .data.private_key)"
|
||
ISSUING_CA="$(vault read -field=certificate "${INT_MOUNT}/cert/ca")"
|
||
|
||
OUT="/root/vault/tls-admin/${ENV_NAME}"
|
||
mkdir -p "$OUT"
|
||
|
||
echo "${KEY}" | install -m 0600 /dev/stdin "${OUT}/admin.key"
|
||
echo "${CERT}" | install -m 0644 /dev/stdin "${OUT}/admin.crt"
|
||
echo "${ISSUING_CA}" | install -m 0644 /dev/stdin "${OUT}/issuing_ca.pem"
|
||
|
||
ok "Wrote:"
|
||
echo " - ${OUT}/admin.key (0600)"
|
||
echo " - ${OUT}/admin.crt (0644)"
|
||
echo " - ${OUT}/issuing_ca.pem (issuer of admin.crt)"
|
||
|
||
cat <<EOT
|
||
|
||
Use (root):
|
||
|
||
export VAULT_CLIENT_CERT='${OUT}/admin.crt'
|
||
export VAULT_CLIENT_KEY='${OUT}/admin.key'
|
||
# VAULT_CACERT / VAULT_TLS_SERVER_NAME kommen aus /root/vault/env/${ENV_NAME}.env
|
||
vault status
|
||
|
||
EOT
|
||
|