Add create-secrets.sh helper for Docker Swarm secret provisioning
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/push/woodpecker Pipeline was successful
This commit is contained in:
@@ -0,0 +1,76 @@
|
|||||||
|
#!/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
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user