Every project used the Postgres superuser, the RabbitMQ administrator, an admin S3 identity and the Zitadel instance-admin PAT, so any one of them could read or change the others' data. A new one-shot, `provision` (runs on every `up`, idempotent), gives each project in x-projects its own: - Postgres role, owner of its database. No database is open to PUBLIC anymore, so a role can only connect to its own. An existing database and everything in it is handed over to the project's role. - RabbitMQ user, with permissions on its own vhost only. - Zitadel service account, PROJECT_OWNER of its own project only; its PAT is written to zitadel/.output/<project>/ for that project's zitadel-init to mount instead of the admin PAT. SeaweedFS renders one S3 identity per project, limited to its bucket, and refuses to start with a clear message on a malformed or repeated key. The admin accounts stay with this stack. postgres-init is gone: provision creates the databases. *.sh files are checked out with LF so they run in the Linux containers from a Windows checkout.
61 lines
2.3 KiB
Bash
61 lines
2.3 KiB
Bash
#!/bin/sh
|
|
# Prints SeaweedFS's S3 identity config (JSON) from the environment:
|
|
#
|
|
# infra S3_ACCESS_KEY / S3_SECRET_KEY, admin on every bucket (for
|
|
# operating the stack, not for projects)
|
|
# <project> <PROJECT>_S3_ACCESS_KEY / _SECRET_KEY, limited to the bucket
|
|
# <PROJECT>_S3_BUCKET (it may create it, nothing else)
|
|
#
|
|
# A project without keys gets no identity. Runs in the SeaweedFS container on
|
|
# every start, so the credentials can't drift from the env file.
|
|
set -eu
|
|
|
|
upper() { echo "$1" | tr '[:lower:]' '[:upper:]'; }
|
|
setting() { eval "printf '%s' \"\${$(upper "$1")_$2:-}\""; }
|
|
|
|
# The values go into JSON as they are: keep them to characters that need no
|
|
# escaping (what `openssl rand -hex` / -base64 produce).
|
|
check() {
|
|
case "$2" in
|
|
'' | *[!A-Za-z0-9_+/=.-]*) echo "seaweedfs-s3-config: $1 must be non-empty and only use A-Z a-z 0-9 _ + / = . -" >&2; exit 1 ;;
|
|
esac
|
|
}
|
|
|
|
identity() {
|
|
printf ' {"name": "%s", "credentials": [{"accessKey": "%s", "secretKey": "%s"}], "actions": [%s]}' "$1" "$2" "$3" "$4"
|
|
}
|
|
|
|
# SeaweedFS refuses to start (and keeps restarting) on a repeated access key,
|
|
# e.g. two values left at CHANGE_ME: say which ones instead.
|
|
seen=" "
|
|
unique() {
|
|
case "$seen" in
|
|
*" $2 "*) echo "seaweedfs-s3-config: $1 repeats an access key already used above; every identity needs its own" >&2; exit 1 ;;
|
|
esac
|
|
seen="$seen$2 "
|
|
}
|
|
|
|
check S3_ACCESS_KEY "$S3_ACCESS_KEY"
|
|
unique S3_ACCESS_KEY "$S3_ACCESS_KEY"
|
|
check S3_SECRET_KEY "$S3_SECRET_KEY"
|
|
printf '{\n "identities": [\n'
|
|
identity infra "$S3_ACCESS_KEY" "$S3_SECRET_KEY" '"Admin", "Read", "Write"'
|
|
|
|
for project in $PROJECTS; do
|
|
access=$(setting "$project" S3_ACCESS_KEY)
|
|
[ -n "$access" ] || continue
|
|
secret=$(setting "$project" S3_SECRET_KEY)
|
|
bucket=$(setting "$project" S3_BUCKET)
|
|
prefix=$(upper "$project")
|
|
check "${prefix}_S3_ACCESS_KEY" "$access"
|
|
check "${prefix}_S3_SECRET_KEY" "$secret"
|
|
check "${prefix}_S3_BUCKET" "$bucket"
|
|
unique "${prefix}_S3_ACCESS_KEY" "$access"
|
|
# Admin:<bucket> is what lets it create (and configure) that one bucket.
|
|
printf ',\n'
|
|
identity "$project" "$access" "$secret" \
|
|
"\"Admin:$bucket\", \"Read:$bucket\", \"Write:$bucket\", \"List:$bucket\", \"Tagging:$bucket\""
|
|
echo "seaweedfs-s3-config: $project -> bucket $bucket" >&2
|
|
done
|
|
printf '\n ]\n}\n'
|