#!/usr/bin/env bash # rotate-cloudflare-token.sh - Rotate the Cloudflare DNS-01 token out of git and into Vault # # infrastructure/cert-manager/manifests/secret-cf-token.yaml used to contain a live # Cloudflare API token committed in plaintext. It's now an ExternalSecret pulling # from Vault at secret/cloudflare-dns-token#token - this script populates that path. # # This does NOT create or revoke the Cloudflare token itself - that's a manual step # in the Cloudflare dashboard, deliberately not automated here since it's a live, # outward-facing credential change: # # 1. Cloudflare dashboard -> My Profile -> API Tokens -> Create Token # Scope: Zone:DNS:Edit, restricted to the kube.huskypup.net zone only # 2. Run this script with the new token # 3. Confirm cert-manager can still issue certs (kubectl get certificaterequests -A) # 4. THEN go back to Cloudflare and revoke the old token # (the one that was committed in git - assume it's compromised) # # Usage: # ./scripts/rotate-cloudflare-token.sh # # Prerequisites: # - Vault initialized and unsealed # - kubectl configured for the home cluster set -euo pipefail NEW_TOKEN="${1:?Usage: $0 }" echo "=== Cloudflare DNS-01 Token Rotation ===" echo "Storing new token in Vault at secret/cloudflare-dns-token..." ROOT_TOKEN=$(kubectl -n vault get secret vault-init-keys -o jsonpath='{.data.VAULT_ROOT_TOKEN}' | base64 -d) kubectl exec -n vault vault-0 -- env "VAULT_TOKEN=${ROOT_TOKEN}" \ vault kv put secret/cloudflare-dns-token token="${NEW_TOKEN}" echo "Forcing ExternalSecret refresh..." kubectl -n cert-manager annotate externalsecret cloudflare-token-secret \ force-sync="$(date +%s)" --overwrite echo "" echo "=== Done ===" echo "Next:" echo " 1. Verify: kubectl -n cert-manager get secret cloudflare-token-secret -o jsonpath='{.data.cloudflare-token}' | base64 -d" echo " 2. Verify a cert still renews cleanly (or delete one Certificate to force a test issuance)" echo " 3. Revoke the OLD token in the Cloudflare dashboard once confirmed working"