Files
compose-files/deploy/create-secrets.sh
2026-06-20 23:18:57 -07:00

77 lines
2.7 KiB
Bash

#!/bin/bash
################################################################################
# create-secrets.sh — Docker Swarm secret provisioning helper
#
# Usage:
# source deploy/create-secrets.sh
# create_or_update_secret "secret_name" "secret_value"
#
# What it does:
# - Creates a Docker secret if it does not already exist
# - Detects value changes via a SHA256 checksum stored as a secret label
# - If the value has changed: removes the old secret and recreates it
# - If the value is unchanged: skips silently (no service disruption)
#
# Important notes:
# - Docker Swarm has no native "update secret" API. Changing a secret
# requires removing and recreating it, then redeploying all services
# that reference it. This script handles removal + recreation, but the
# stack redeploy still happens via the normal deploy step.
# - Secrets are stored encrypted in Swarm's Raft consensus database and
# automatically replicated across all nodes.
# - The checksum label is NOT the secret value — it is a SHA256 hash used
# only to detect whether the value has changed, avoiding unnecessary
# secret rotation.
################################################################################
create_or_update_secret() {
local NAME="$1"
local VALUE="$2"
if [ -z "$NAME" ]; then
echo " [ERROR] create_or_update_secret: NAME is required"
return 1
fi
if [ -z "$VALUE" ]; then
echo " [WARN] $NAME: value is empty, skipping"
return 0
fi
# Compute SHA256 of the new value (no trailing newline to keep hash stable)
local NEW_HASH
NEW_HASH=$(printf '%s' "$VALUE" | sha256sum | cut -d' ' -f1)
if docker secret inspect "$NAME" >/dev/null 2>&1; then
# Secret exists — check if value has changed via stored checksum label
local OLD_HASH
OLD_HASH=$(docker secret inspect "$NAME" \
--format '{{index .Spec.Labels "checksum"}}' 2>/dev/null || echo "")
if [ "$NEW_HASH" = "$OLD_HASH" ]; then
echo " [SKIP] $NAME (unchanged)"
return 0
fi
# Value changed — must remove and recreate (Docker limitation)
echo " [UPDATE] $NAME (value changed, rotating)"
docker secret rm "$NAME" >/dev/null 2>&1 || {
echo " [ERROR] $NAME: failed to remove existing secret"
echo " Secret may be in use by a running service."
echo " Scale down the service first, then re-run."
return 1
}
else
echo " [CREATE] $NAME"
fi
# Create the secret with checksum label for future change detection
printf '%s' "$VALUE" | docker secret create \
--label "checksum=${NEW_HASH}" \
--label "managed-by=woodpecker" \
"$NAME" - >/dev/null && echo " [OK] $NAME" || {
echo " [ERROR] $NAME: failed to create secret"
return 1
}
}