Give every project its own credentials on the shared services
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.
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
#!/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'
|
||||
Reference in New Issue
Block a user