export GF_DATASOURCES_VERSION=v1 export GF_DASHBOARDS_VERSION=v3 export GF_SWARM_DASH_VERSION=v3 export GF_STACKS_DASH_VERSION=v3 export GF_TRAEFIK_DASH_VERSION=v3 export GF_BACKUP_DASH_VERSION=v1 export GF_CUSTOM_INI_VERSION=v4 export LOKI_YML_VERSION=v4 export PROMETHEUS_YML_VERSION=v2 export MATRIX_ALERTMANAGER_CONFIG_VERSION=v1 export MATRIX_ALERTMANAGER_ENTRYPOINT_VERSION=v1 export GF_ALERTS_NODE_VERSION=v3 export GF_ALERTS_LOKI_VERSION=v5 export CONFIG_ALLOY_VERSION=v3 # migrates secrets from old names to new names by reading values from the # running containers on the server and re-inserting them under the new names. # preview changes: abra app cmd --local migrate_secret_names # execute changes: abra app cmd --local migrate_secret_names execute migrate_secret_names() { if ! command -v jq &> /dev/null; then echo "jq is required on your local machine to migrate secret names" echo "It could not be found in your PATH, please install jq to proceed." echo "For example: On a debian/ubuntu system, run `apt install jq`" exit 1 fi # Hardcoded migration mappings: old_secret_name|new_secret_name MIGRATIONS=" grafana_admin_password|gf_adminpasswd grafana_smtp_password|gf_smtp_pass grafana_oidc_client_secret|gf_oidc_secret matrix_access_token|matrix_token loki_aws_secret_access_key|loki_aws_key " # Determine which server the app is deployed on SERVER=$(abra app ls -m | jq -r --arg domain "$APP_NAME" '[.[].apps[] | select(.domain == $domain) | .server] | first' 2>/dev/null) if [ -z "$SERVER" ]; then echo "Error: could not determine server for app '$APP_NAME'" exit 1 fi # Build a lookup table of all secrets currently mounted in this stack. # Each line: LOOKUP=$(ssh "$SERVER" " docker stack services ${STACK_NAME} --format '{{.Name}}' | while read svc; do CID=\$(docker ps --no-trunc -q --filter \"name=\${svc}\" | head -1) docker service inspect \"\$svc\" --format '{{json .Spec.TaskTemplate.ContainerSpec.Secrets}}' | \ jq -r --arg cid \"\$CID\" '.[]? | .SecretID + \" \" + \$cid + \" \" + .SecretName' done | sort -k3 -r " 2>/dev/null) echo "Secret migration plan for: $APP_NAME (server: $SERVER)" echo "" printf " %-24s %-8s %s\n" "OLD NAME" "FOUND" "ACTION" printf " %-24s %-8s %s\n" "--------" "-----" "------" # Check each old name against the lookup table and display the plan ANY_FOUND=false while IFS='|' read -r OLD_NAME NEW_NAME; do [ -z "$OLD_NAME" ] && continue MATCH=$(echo "$LOOKUP" | grep " ${STACK_NAME}_${OLD_NAME}_" | head -1) if [ -n "$MATCH" ]; then printf " %-24s %-8s %s\n" "$OLD_NAME" "yes" "recreate as '$NEW_NAME' version V1" ANY_FOUND=true else printf " %-24s %-8s %s\n" "$OLD_NAME" "no" "nothing (not found on server)" fi done <<< "$MIGRATIONS" echo "" if [ "$ANY_FOUND" = false ]; then echo "No old secrets found on server. Nothing to migrate." return 0 fi if [ "$1" != "execute" ]; then echo "To apply the above changes, run:" echo " abra app cmd --local $APP_NAME migrate_secret_names execute" return 0 fi # read each found secret from its container and re-insert with the new name while IFS='|' read -r OLD_NAME NEW_NAME; do [ -z "$OLD_NAME" ] && continue MATCH=$(echo "$LOOKUP" | grep " ${STACK_NAME}_${OLD_NAME}_" | head -1) [ -z "$MATCH" ] && continue SECRET_ID=$(echo "$MATCH" | awk '{print $1}') CID=$(echo "$MATCH" | awk '{print $2}') SECRET_VALUE=$(ssh "$SERVER" "cat /var/lib/docker/containers/${CID}/mounts/secrets/${SECRET_ID} 2>/dev/null || sudo cat /var/lib/docker/containers/${CID}/mounts/secrets/${SECRET_ID} 2>/dev/null") if [ -z "$SECRET_VALUE" ]; then echo "Error: could not read value for '$OLD_NAME', skipping" continue fi echo "Migrating: '$OLD_NAME' -> '$NEW_NAME' (v1)" printf '%s' "$SECRET_VALUE" | abra app secret insert -C "$APP_NAME" "$NEW_NAME" v1 done <<< "$MIGRATIONS" echo "" echo "Done." }