All checks were successful
Deploy storage stack / deploy (push) Successful in 20s
The datacenter bingo photos sat under bingo/ in asxpio-invoices, next to the invoice PDFs, guarded only by a prefix policy. Move them to a datacenterbingo-photos bucket: asxpio's user gets read-write for the admin's uploads, the bingo user read-only on the whole bucket. Existing objects are mirrored over with their keys unchanged, so the database rows stay valid. Both users keep their old access until the apps are switched and the old prefix is removed. Assisted-by: Claude:opus-5
99 lines
3.1 KiB
Bash
99 lines
3.1 KiB
Bash
#!/bin/sh
|
|
# Idempotent MinIO bootstrap: bucket + per-app service account scoped to that
|
|
# bucket. Re-running just refreshes the policy and resets the access key.
|
|
set -eu
|
|
|
|
mc alias set local http://minio:9000 "${MINIO_ROOT_USER}" "${MINIO_ROOT_PASSWORD}"
|
|
|
|
ensure_bucket() {
|
|
bucket="$1"
|
|
if ! mc ls "local/${bucket}" >/dev/null 2>&1; then
|
|
mc mb "local/${bucket}"
|
|
fi
|
|
mc anonymous set none "local/${bucket}" >/dev/null
|
|
}
|
|
|
|
write_policy() {
|
|
name="$1"
|
|
bucket="$2"
|
|
cat > "/tmp/${name}.json" <<EOF
|
|
{
|
|
"Version": "2012-10-17",
|
|
"Statement": [
|
|
{
|
|
"Effect": "Allow",
|
|
"Action": ["s3:ListBucket", "s3:GetBucketLocation"],
|
|
"Resource": ["arn:aws:s3:::${bucket}"]
|
|
},
|
|
{
|
|
"Effect": "Allow",
|
|
"Action": ["s3:GetObject", "s3:PutObject", "s3:DeleteObject"],
|
|
"Resource": ["arn:aws:s3:::${bucket}/*"]
|
|
}
|
|
]
|
|
}
|
|
EOF
|
|
mc admin policy create local "${name}" "/tmp/${name}.json" 2>/dev/null \
|
|
|| mc admin policy update local "${name}" "/tmp/${name}.json"
|
|
}
|
|
|
|
# Read-only on one prefix of a bucket.
|
|
write_ro_prefix_policy() {
|
|
name="$1"
|
|
bucket="$2"
|
|
prefix="$3"
|
|
cat > "/tmp/${name}.json" <<EOF
|
|
{
|
|
"Version": "2012-10-17",
|
|
"Statement": [
|
|
{
|
|
"Effect": "Allow",
|
|
"Action": ["s3:GetObject"],
|
|
"Resource": ["arn:aws:s3:::${bucket}/${prefix}*"]
|
|
}
|
|
]
|
|
}
|
|
EOF
|
|
mc admin policy create local "${name}" "/tmp/${name}.json" 2>/dev/null \
|
|
|| mc admin policy update local "${name}" "/tmp/${name}.json"
|
|
}
|
|
|
|
# $3: one or more policy names, space-separated.
|
|
ensure_user() {
|
|
access="$1"
|
|
secret="$2"
|
|
policies="$3"
|
|
if mc admin user info local "${access}" >/dev/null 2>&1; then
|
|
# Rotate secret to match desired state.
|
|
mc admin user remove local "${access}" >/dev/null
|
|
fi
|
|
mc admin user add local "${access}" "${secret}"
|
|
# shellcheck disable=SC2086 # word-split the policy list on purpose
|
|
mc admin policy attach local ${policies} --user "${access}" 2>/dev/null || true
|
|
}
|
|
|
|
ensure_bucket "asxpio-invoices"
|
|
write_policy "asxpio-invoices-rw" "asxpio-invoices"
|
|
|
|
# Datacenter bingo photos: uploaded and resized by asxpio's admin, served by
|
|
# datacenterbingo. Keys keep their bingo/ prefix, so DB rows stay valid.
|
|
ensure_bucket "datacenterbingo-photos"
|
|
write_policy "datacenterbingo-photos-rw" "datacenterbingo-photos"
|
|
write_ro_prefix_policy "datacenterbingo-photos-ro" "datacenterbingo-photos" ""
|
|
|
|
# Migration from asxpio-invoices/bingo/: copy whatever is missing. Remove
|
|
# this (and the old bingo-ro policy below) once the old prefix is deleted.
|
|
if mc ls "local/asxpio-invoices/bingo/" 2>/dev/null | grep -q .; then
|
|
mc mirror --quiet "local/asxpio-invoices/bingo" "local/datacenterbingo-photos/bingo"
|
|
fi
|
|
|
|
ensure_user "${ASXPIO_S3_ACCESS_KEY}" "${ASXPIO_S3_SECRET_KEY}" "asxpio-invoices-rw datacenterbingo-photos-rw"
|
|
|
|
if [ -n "${BINGO_S3_ACCESS_KEY:-}" ] && [ -n "${BINGO_S3_SECRET_KEY:-}" ]; then
|
|
write_ro_prefix_policy "asxpio-invoices-bingo-ro" "asxpio-invoices" "bingo/"
|
|
ensure_user "${BINGO_S3_ACCESS_KEY}" "${BINGO_S3_SECRET_KEY}" "datacenterbingo-photos-ro asxpio-invoices-bingo-ro"
|
|
else
|
|
echo "minio-init: BINGO_S3_* unset, skipping bingo user"
|
|
fi
|
|
|
|
echo "minio-init: done"
|