fix(minio): fix OIDC and add public access recipes

This commit is contained in:
Masaki Yatsu
2025-12-10 13:26:41 +09:00
parent 1924e56ad7
commit a8599b66f4
4 changed files with 197 additions and 2 deletions

View File

@@ -221,6 +221,83 @@ just minio::bucket-exists mybucket
This returns exit code 0 if the bucket exists, 1 otherwise. This returns exit code 0 if the bucket exists, 1 otherwise.
## Public Access
MinIO allows you to configure anonymous (public) access to buckets or specific prefixes for serving static content like images.
### Set Public Download Access
Enable public read access for a bucket or prefix:
```bash
# Set public access for entire bucket
just minio::set-public-download mybucket
# Set public access for specific prefix only
just minio::set-public-download mybucket/public
```
After setting public access, files can be accessed without authentication:
```text
https://your-minio-host/mybucket/public/image.png
```
### Check Public Access Status
View current anonymous access policy:
```bash
just minio::show-public-access mybucket
```
Possible values:
- `private`: No anonymous access (default)
- `download`: Public read access
- `upload`: Public write access
- `public`: Public read and write access
- `custom`: Custom policy applied
### Remove Public Access
Revoke anonymous access:
```bash
just minio::remove-public-access mybucket/public
```
### Using mc Commands
```bash
# Set public download (read-only)
mc anonymous set download myminio/mybucket/public
# Set public upload (write-only)
mc anonymous set upload myminio/mybucket/uploads
# Set full public access (read and write)
mc anonymous set public myminio/mybucket
# Remove public access
mc anonymous set none myminio/mybucket
# Check current policy
mc anonymous get myminio/mybucket
```
### Presigned URLs (Temporary Access)
For temporary access to private objects, use presigned URLs:
```bash
# Generate URL valid for 7 days
mc share download myminio/mybucket/private-file.pdf --expire=168h
# Generate upload URL
mc share upload myminio/mybucket/uploads/ --expire=1h
```
## User Management ## User Management
### Create MinIO User ### Create MinIO User

View File

@@ -47,6 +47,7 @@ create-root-credentials:
gomplate -f minio-root-external-secret.gomplate.yaml | kubectl apply -f - gomplate -f minio-root-external-secret.gomplate.yaml | kubectl apply -f -
echo "Waiting for ExternalSecret to sync..." echo "Waiting for ExternalSecret to sync..."
sleep 2
kubectl wait --for=condition=Ready externalsecret/minio \ kubectl wait --for=condition=Ready externalsecret/minio \
-n ${MINIO_NAMESPACE} --timeout=60s -n ${MINIO_NAMESPACE} --timeout=60s
else else
@@ -96,7 +97,12 @@ install:
--placeholder="e.g., minio-console.example.com" --placeholder="e.g., minio-console.example.com"
) )
fi fi
# Generate OIDC client secret for confidential client
OIDC_CLIENT_SECRET=$(just utils::random-password)
just keycloak::create-client realm=${KEYCLOAK_REALM} client_id=${MINIO_OIDC_CLIENT_ID} \ just keycloak::create-client realm=${KEYCLOAK_REALM} client_id=${MINIO_OIDC_CLIENT_ID} \
client_secret="${OIDC_CLIENT_SECRET}" \
redirect_url="https://${MINIO_HOST}/oauth_callback,https://${MINIO_CONSOLE_HOST}/oauth_callback" redirect_url="https://${MINIO_HOST}/oauth_callback,https://${MINIO_CONSOLE_HOST}/oauth_callback"
just add-keycloak-minio-policy just add-keycloak-minio-policy
just create-namespace just create-namespace
@@ -105,6 +111,28 @@ install:
pod-security.kubernetes.io/enforce=restricted --overwrite pod-security.kubernetes.io/enforce=restricted --overwrite
just create-root-credentials just create-root-credentials
# Store OIDC client secret
if helm status external-secrets -n ${EXTERNAL_SECRETS_NAMESPACE} &>/dev/null; then
echo "Storing OIDC client secret in Vault..."
just vault::put minio/oidc client_id="${MINIO_OIDC_CLIENT_ID}" client_secret="${OIDC_CLIENT_SECRET}"
kubectl delete externalsecret minio-oidc -n ${MINIO_NAMESPACE} --ignore-not-found
gomplate -f minio-oidc-external-secret.gomplate.yaml | kubectl apply -f -
echo "Waiting for ExternalSecret to sync..."
sleep 2
kubectl wait --for=condition=Ready externalsecret/minio-oidc \
-n ${MINIO_NAMESPACE} --timeout=60s
else
echo "Creating OIDC client secret directly..."
kubectl delete secret minio-oidc -n ${MINIO_NAMESPACE} --ignore-not-found
kubectl create secret generic minio-oidc -n ${MINIO_NAMESPACE} \
--from-literal=clientId="${MINIO_OIDC_CLIENT_ID}" \
--from-literal=clientSecret="${OIDC_CLIENT_SECRET}"
if helm status vault -n ${K8S_VAULT_NAMESPACE} &>/dev/null; then
just vault::put minio/oidc client_id="${MINIO_OIDC_CLIENT_ID}" client_secret="${OIDC_CLIENT_SECRET}"
fi
fi
just add-helm-repo just add-helm-repo
gomplate -f minio-values.gomplate.yaml -o minio-values.yaml gomplate -f minio-values.gomplate.yaml -o minio-values.yaml
helm upgrade --install minio minio/minio \ helm upgrade --install minio minio/minio \
@@ -260,3 +288,70 @@ grant-policy user='' policy='':
mc admin policy attach local ${POLICY} --user=${USER}" mc admin policy attach local ${POLICY} --user=${USER}"
echo "✅ Policy ${POLICY} granted to user ${USER}" echo "✅ Policy ${POLICY} granted to user ${USER}"
# Set public download access for a bucket or prefix
set-public-download path='':
#!/bin/bash
set -euo pipefail
PATH_ARG="{{ path }}"
while [ -z "${PATH_ARG}" ]; do
PATH_ARG=$(
gum input --prompt="Bucket/prefix path: " --width=100 \
--placeholder="e.g., my-bucket/public"
)
done
ROOT_USER=$(just root-username)
ROOT_PASSWORD=$(just root-password)
kubectl -n ${MINIO_NAMESPACE} exec deploy/minio -- \
mc alias set local http://localhost:9000 ${ROOT_USER} ${ROOT_PASSWORD}
kubectl -n ${MINIO_NAMESPACE} exec deploy/minio -- \
mc anonymous set download local/${PATH_ARG}
echo "✅ Public download access enabled for ${PATH_ARG}"
# Remove public access from a bucket or prefix
remove-public-access path='':
#!/bin/bash
set -euo pipefail
PATH_ARG="{{ path }}"
while [ -z "${PATH_ARG}" ]; do
PATH_ARG=$(
gum input --prompt="Bucket/prefix path: " --width=100 \
--placeholder="e.g., my-bucket/public"
)
done
ROOT_USER=$(just root-username)
ROOT_PASSWORD=$(just root-password)
kubectl -n ${MINIO_NAMESPACE} exec deploy/minio -- \
mc alias set local http://localhost:9000 ${ROOT_USER} ${ROOT_PASSWORD}
kubectl -n ${MINIO_NAMESPACE} exec deploy/minio -- \
mc anonymous set none local/${PATH_ARG}
echo "✅ Public access removed from ${PATH_ARG}"
# Show anonymous access policy for a bucket or prefix
show-public-access path='':
#!/bin/bash
set -euo pipefail
PATH_ARG="{{ path }}"
while [ -z "${PATH_ARG}" ]; do
PATH_ARG=$(
gum input --prompt="Bucket/prefix path: " --width=100 \
--placeholder="e.g., my-bucket"
)
done
ROOT_USER=$(just root-username)
ROOT_PASSWORD=$(just root-password)
kubectl -n ${MINIO_NAMESPACE} exec deploy/minio -- \
mc alias set local http://localhost:9000 ${ROOT_USER} ${ROOT_PASSWORD}
kubectl -n ${MINIO_NAMESPACE} exec deploy/minio -- \
mc anonymous get local/${PATH_ARG}

View File

@@ -0,0 +1,22 @@
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: minio-oidc
namespace: {{ .Env.MINIO_NAMESPACE }}
spec:
refreshInterval: 1h
secretStoreRef:
name: vault-secret-store
kind: ClusterSecretStore
target:
name: minio-oidc
creationPolicy: Owner
data:
- secretKey: clientId
remoteRef:
key: minio/oidc
property: client_id
- secretKey: clientSecret
remoteRef:
key: minio/oidc
property: client_secret

View File

@@ -7,8 +7,9 @@ existingSecret: "minio"
oidc: oidc:
enabled: true enabled: true
configUrl: "https://{{ .Env.KEYCLOAK_HOST }}/realms/{{ .Env.KEYCLOAK_REALM }}/.well-known/openid-configuration" configUrl: "https://{{ .Env.KEYCLOAK_HOST }}/realms/{{ .Env.KEYCLOAK_REALM }}/.well-known/openid-configuration"
clientId: "{{ .Env.MINIO_OIDC_CLIENT_ID }}" existingClientSecretName: "minio-oidc"
clientSecret: "" existingClientIdKey: "clientId"
existingClientSecretKey: "clientSecret"
claimName: "minioPolicy" claimName: "minioPolicy"
scopes: "openid,profile,email" scopes: "openid,profile,email"
redirectUri: "https://{{ .Env.MINIO_CONSOLE_HOST }}/oauth_callback" redirectUri: "https://{{ .Env.MINIO_CONSOLE_HOST }}/oauth_callback"