vault-ops/infra/versions/05_issue_admin_client_cert_admin-v1.0.sh
2026-04-14 11:45:15 +07:00

111 lines
3.7 KiB
Bash
Executable file
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/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