110 lines
3.7 KiB
Bash
110 lines
3.7 KiB
Bash
#!/usr/bin/env bash
|
|
# =====================================================
|
|
# VAULT AGENT POST-SCRIPT - Extract TLS Certs from PKI JSON
|
|
# Triggered by template rendering, extracts key/cert/CA chain
|
|
# =====================================================
|
|
set -Eeuo pipefail # Exit on error, undefined vars, pipe failures
|
|
|
|
# === CONFIGURATION ===
|
|
JSON_FILE="${1:-./tls/.issue.json}" # Input: Vault PKI response
|
|
APP_NAME="${2:-app88.test}" # Output filename prefix
|
|
OUT_DIR="${3:-./tls}" # Output directory
|
|
NGINX_CONTAINER="${4:-}" # Optional: Container name for reload
|
|
|
|
echo "[post] Processing ${JSON_FILE} -> ${OUT_DIR}/${APP_NAME}.*"
|
|
|
|
# === VALIDATION ===
|
|
if [[ ! -f "${JSON_FILE}" || ! -s "${JSON_FILE}" ]]; then
|
|
echo "ERROR: JSON file missing or empty: ${JSON_FILE}" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if ! jq empty "${JSON_FILE}" >/dev/null 2>&1; then
|
|
echo "ERROR: Invalid JSON in ${JSON_FILE}" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# === CREATE SECURE TEMPORARY DIRECTORY ===
|
|
TMP_DIR=$(mktemp -d "${OUT_DIR}/.staging.XXXX")
|
|
trap 'rm -rf "${TMP_DIR}"' EXIT # Cleanup on exit
|
|
umask 077 # Owner-only permissions
|
|
|
|
# === EXTRACT PRIVATE KEY ===
|
|
echo "[post] Extracting private key..."
|
|
jq -r '.data.private_key' "${JSON_FILE}" > "${TMP_DIR}/${APP_NAME}.key"
|
|
|
|
# Validate key extraction
|
|
if [[ ! -s "${TMP_DIR}/${APP_NAME}.key" ]]; then
|
|
echo "ERROR: Failed to extract private key" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# === EXTRACT CERTIFICATE + CA CHAIN (ROBUST HANDLING) ===
|
|
echo "[post] Extracting certificate + CA chain..."
|
|
jq -r '
|
|
# Always include the leaf certificate
|
|
.data.certificate,
|
|
|
|
# Handle CA chain (array, string, or null)
|
|
(if (.data.ca_chain | type == "array" and length > 0)
|
|
then (.data.ca_chain | join("\n"))
|
|
else if (.data.ca_chain | type == "string" and .data.ca_chain != "")
|
|
then .data.ca_chain
|
|
else .data.issuing_ca
|
|
end
|
|
end)
|
|
' "${JSON_FILE}" > "${TMP_DIR}/${APP_NAME}.fullchain.pem"
|
|
|
|
# Validate certificate extraction
|
|
if [[ ! -s "${TMP_DIR}/${APP_NAME}.fullchain.pem" ]]; then
|
|
echo "ERROR: Failed to extract certificate chain" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# === INSTALL WITH CORRECT PERMISSIONS ===
|
|
echo "[post] Installing certificates..."
|
|
install -m 600 "${TMP_DIR}/${APP_NAME}.key" "${OUT_DIR}/${APP_NAME}.key"
|
|
install -m 644 "${TMP_DIR}/${APP_NAME}.fullchain.pem" "${OUT_DIR}/${APP_NAME}.fullchain.pem"
|
|
|
|
# === APPLICATION RELOAD (OPTIONAL) ===
|
|
if [[ -n "${NGINX_CONTAINER}" ]]; then
|
|
echo "[post] Reloading application in container: ${NGINX_CONTAINER}"
|
|
|
|
if command -v podman >/dev/null 2>&1; then
|
|
# Podman container reload
|
|
if podman exec "${NGINX_CONTAINER}" nginx -t; then
|
|
podman exec "${NGINX_CONTAINER}" nginx -s reload
|
|
echo "[post] Podman nginx reloaded successfully"
|
|
else
|
|
echo "WARNING: Nginx config test failed, skipping reload" >&2
|
|
fi
|
|
elif command -v docker >/dev/null 2>&1; then
|
|
# Docker container reload
|
|
if docker exec "${NGINX_CONTAINER}" nginx -t; then
|
|
docker exec "${NGINX_CONTAINER}" nginx -s reload
|
|
echo "[post] Docker nginx reloaded successfully"
|
|
else
|
|
echo "WARNING: Nginx config test failed, skipping reload" >&2
|
|
fi
|
|
else
|
|
echo "WARNING: No container runtime found, skipping reload" >&2
|
|
fi
|
|
elif command -v nginx >/dev/null 2>&1; then
|
|
# Local nginx reload
|
|
if nginx -t; then
|
|
nginx -s reload
|
|
echo "[post] Local nginx reloaded successfully"
|
|
else
|
|
echo "WARNING: Nginx config test failed, skipping reload" >&2
|
|
fi
|
|
fi
|
|
|
|
# === VALIDATION ===
|
|
if openssl x509 -noout -in "${OUT_DIR}/${APP_NAME}.fullchain.pem" 2>/dev/null; then
|
|
echo "[post] SUCCESS: Certificate validation passed"
|
|
echo "[post] Wrote: ${OUT_DIR}/${APP_NAME}.key (${APP_NAME}.fullchain.pem)"
|
|
exit 0
|
|
else
|
|
echo "ERROR: Certificate validation failed" >&2
|
|
exit 1
|
|
fi
|