Files
ouranos/ansible/certbot/vault-upload-hook.sh.j2
Robert Helewka 0a053c1cd6 Refactor HAProxy configuration and certificate management
- Updated HAProxy configuration template to reflect changes for the Taurus Production Environment, including SSL settings and rate limiting for specific endpoints.
- Introduced new playbooks for certificate distribution and validation with OCI Vault, ensuring certificates are correctly managed and renewed.
- Added hooks for uploading renewed certificates to OCI Vault and validating their integrity.
- Enhanced the HAProxy configuration playbook to ensure proper service management and verification of the HAProxy service.
- Updated inventory variables for certificate management and ensured compatibility with the new structure.
2026-03-17 13:13:38 -04:00

116 lines
4.2 KiB
Django/Jinja

#!/bin/bash
# Certbot post-renewal hook for OCI Vault upload
# Managed by Ansible - DO NOT EDIT MANUALLY
#
# This script uploads renewed certificates to OCI Vault so that
# fornax can distribute them to target hosts via Ansible.
#
# Uses Instance Principal authentication (no config file needed).
# Called by certbot --deploy-hook after each successful renewal.
set -euo pipefail
CERT_DIR="{{ certbot_directory }}/config/live"
LOG_PREFIX="[$(date '+%Y-%m-%d %H:%M:%S')] [vault-upload]"
echo "${LOG_PREFIX} Starting vault upload hook"
# RENEWED_LINEAGE is set by certbot to the path of the renewed cert
# e.g. /srv/certbot/config/live/bootes.helu.ca
if [[ -z "${RENEWED_LINEAGE:-}" ]]; then
echo "${LOG_PREFIX} ERROR: RENEWED_LINEAGE not set — not running under certbot?"
exit 1
fi
CERT_NAME=$(basename "${RENEWED_LINEAGE}")
FULLCHAIN="${RENEWED_LINEAGE}/fullchain.pem"
PRIVKEY="${RENEWED_LINEAGE}/privkey.pem"
OCI="{{ certbot_directory }}/.venv/bin/oci"
COMPARTMENT_ID="{{ oci_govern_compartment_id }}"
VAULT_ID="{{ oci_vault_id }}"
# Convert dots to hyphens to match Terraform secret naming (e.g. pan.helu.ca → pan-helu-ca)
VAULT_PREFIX="${CERT_NAME//./-}"
echo "${LOG_PREFIX} Processing certificate: ${CERT_NAME} (vault prefix: ${VAULT_PREFIX})"
if [[ ! -f "${FULLCHAIN}" ]] || [[ ! -f "${PRIVKEY}" ]]; then
echo "${LOG_PREFIX} ERROR: Certificate files not found in ${RENEWED_LINEAGE}"
exit 1
fi
# Look up secret OCIDs by name (Terraform creates secrets named {domain-hyphens}-fullchain/-privkey)
lookup_secret_id() {
local secret_name="$1"
local result
if ! result=$(${OCI} vault secret list \
--auth instance_principal \
--compartment-id "${COMPARTMENT_ID}" \
--vault-id "${VAULT_ID}" \
--name "${secret_name}" \
--lifecycle-state ACTIVE \
--all \
--query 'data[0].id' \
--raw-output 2>&1); then
echo "${LOG_PREFIX} ERROR: OCI CLI failed looking up secret '${secret_name}': ${result}" >&2
return 1
fi
echo "${result}"
}
FULLCHAIN_SECRET_ID=$(lookup_secret_id "${VAULT_PREFIX}-fullchain") || true
PRIVKEY_SECRET_ID=$(lookup_secret_id "${VAULT_PREFIX}-privkey") || true
if [[ -z "${FULLCHAIN_SECRET_ID}" ]] || [[ "${FULLCHAIN_SECRET_ID}" == "null" ]] || \
[[ -z "${PRIVKEY_SECRET_ID}" ]] || [[ "${PRIVKEY_SECRET_ID}" == "null" ]]; then
echo "${LOG_PREFIX} ERROR: Could not find vault secrets for ${VAULT_PREFIX} (fullchain=${FULLCHAIN_SECRET_ID:-missing}, privkey=${PRIVKEY_SECRET_ID:-missing})"
echo "${LOG_PREFIX} Ensure 'terraform apply' has been run on bootes_certificates.tf"
exit 1
fi
echo "${LOG_PREFIX} Found secret OCIDs for ${VAULT_PREFIX}"
# Upload fullchain to OCI Vault
FULLCHAIN_B64=$(base64 -w 0 < "${FULLCHAIN}")
if ! upload_output=$(${OCI} vault secret update-base64 \
--auth instance_principal \
--secret-id "${FULLCHAIN_SECRET_ID}" \
--secret-content-content "${FULLCHAIN_B64}" 2>&1); then
echo "${LOG_PREFIX} ERROR: Failed to upload fullchain for ${CERT_NAME}: ${upload_output}"
exit 1
fi
echo "${LOG_PREFIX} Uploaded fullchain for ${CERT_NAME}"
# Upload private key to OCI Vault
PRIVKEY_B64=$(base64 -w 0 < "${PRIVKEY}")
if ! upload_output=$(${OCI} vault secret update-base64 \
--auth instance_principal \
--secret-id "${PRIVKEY_SECRET_ID}" \
--secret-content-content "${PRIVKEY_B64}" 2>&1); then
echo "${LOG_PREFIX} ERROR: Failed to upload privkey for ${CERT_NAME}: ${upload_output}"
exit 1
fi
echo "${LOG_PREFIX} Uploaded privkey for ${CERT_NAME}"
{% if certbot_local_cert_name is defined %}
# Also combine cert for local HAProxy if this is the local cert
if [[ "${CERT_NAME}" == "{{ certbot_local_cert_name }}" ]]; then
echo "${LOG_PREFIX} Combining local cert for HAProxy: ${CERT_NAME}"
HAPROXY_CERT="{{ haproxy_cert_path }}"
cat "${FULLCHAIN}" "${PRIVKEY}" > "${HAPROXY_CERT}.tmp"
mv "${HAPROXY_CERT}.tmp" "${HAPROXY_CERT}"
chown {{ certbot_user }}:{{ haproxy_group }} "${HAPROXY_CERT}"
chmod 640 "${HAPROXY_CERT}"
if systemctl is-active --quiet haproxy; then
echo "${LOG_PREFIX} Reloading HAProxy..."
systemctl reload haproxy
fi
fi
{% endif %}
# Update certificate metrics
{{ certbot_directory }}/hooks/cert-metrics.sh
echo "${LOG_PREFIX} Vault upload hook completed successfully"