feat(minio): add MinIO
This commit is contained in:
1
justfile
1
justfile
@@ -12,6 +12,7 @@ mod keycloak
|
|||||||
mod jupyterhub
|
mod jupyterhub
|
||||||
mod k8s
|
mod k8s
|
||||||
mod longhorn
|
mod longhorn
|
||||||
|
mod minio
|
||||||
mod postgres
|
mod postgres
|
||||||
mod utils
|
mod utils
|
||||||
mod vault
|
mod vault
|
||||||
|
|||||||
1
minio/.gitignore
vendored
Normal file
1
minio/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
minio-values.yaml
|
||||||
116
minio/justfile
Normal file
116
minio/justfile
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
set fallback := true
|
||||||
|
|
||||||
|
export MINIO_NAMESPACE := env("MINIO_NAMESPACE", "minio")
|
||||||
|
export MINIO_CHART_VERSION := env("MINIO_CHART_VERSION", "5.4.0")
|
||||||
|
export MINIO_OIDC_CLIENT_ID := env("MINIO_OIDC_CLIENT_ID", "minio")
|
||||||
|
export KEYCLOAK_REALM := env("KEYCLOAK_REALM", "buunstack")
|
||||||
|
|
||||||
|
[private]
|
||||||
|
default:
|
||||||
|
@just --list --unsorted --list-submodules
|
||||||
|
|
||||||
|
# Add Helm repository
|
||||||
|
add-helm-repo:
|
||||||
|
# We use charts.min.io instead of operator.min.io because the operator does not support
|
||||||
|
# standalone mode.
|
||||||
|
# helm repo add minio https://operator.min.io/
|
||||||
|
helm repo add minio https://charts.min.io/
|
||||||
|
helm repo update
|
||||||
|
|
||||||
|
# Remove Helm repository
|
||||||
|
remove-helm-repo:
|
||||||
|
helm repo remove minio
|
||||||
|
|
||||||
|
# Create JupyterHub namespace
|
||||||
|
create-namespace:
|
||||||
|
kubectl get namespace ${MINIO_NAMESPACE} &>/dev/null || \
|
||||||
|
kubectl create namespace ${MINIO_NAMESPACE}
|
||||||
|
|
||||||
|
# Delete JupyterHub namespace
|
||||||
|
delete-namespace:
|
||||||
|
kubectl delete namespace ${MINIO_NAMESPACE} --ignore-not-found
|
||||||
|
|
||||||
|
# Add Keycloak policy and mapper
|
||||||
|
add-keycloak-minio-policy:
|
||||||
|
KEYCLOAK_ADMIN_USER=$(just keycloak::admin-username) \
|
||||||
|
KEYCLOAK_ADMIN_PASSWORD=$(just keycloak::admin-password) \
|
||||||
|
KEYCLOAK_REALM=${KEYCLOAK_REALM} \
|
||||||
|
MINIO_OIDC_CLIENT_ID=${MINIO_OIDC_CLIENT_ID} \
|
||||||
|
dotenvx run -f ../.env.local -- tsx ./scripts/add-minio-policy.ts
|
||||||
|
|
||||||
|
# Install MinIO
|
||||||
|
install:
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
export MINIO_HOST=${MINIO_HOST:-}
|
||||||
|
if [ "${MINIO_HOST}" = "" ]; then
|
||||||
|
MINIO_HOST=$(
|
||||||
|
gum input --prompt="MinIO host (FQDN): " --width=100 \
|
||||||
|
--placeholder="e.g., minio.example.com"
|
||||||
|
)
|
||||||
|
fi
|
||||||
|
export MINIO_CONSOLE_HOST=${MINIO_CONSOLE_HOST:-}
|
||||||
|
if [ "${MINIO_CONSOLE_HOST}" = "" ]; then
|
||||||
|
MINIO_CONSOLE_HOST=$(
|
||||||
|
gum input --prompt="MinIO Console host (FQDN): " --width=100 \
|
||||||
|
--placeholder="e.g., minio-console.example.com"
|
||||||
|
)
|
||||||
|
fi
|
||||||
|
just keycloak::create-client ${KEYCLOAK_REALM} ${MINIO_OIDC_CLIENT_ID} \
|
||||||
|
"https://${MINIO_HOST}/oauth_callback,https://${MINIO_CONSOLE_HOST}/oauth_callback"
|
||||||
|
just add-keycloak-minio-policy
|
||||||
|
just create-namespace
|
||||||
|
just add-helm-repo
|
||||||
|
gomplate -f minio-values.gomplate.yaml -o minio-values.yaml
|
||||||
|
helm upgrade --install minio minio/minio \
|
||||||
|
--version ${MINIO_CHART_VERSION} -n ${MINIO_NAMESPACE} --create-namespace --wait \
|
||||||
|
-f minio-values.yaml
|
||||||
|
|
||||||
|
# Uninstall MinIO
|
||||||
|
uninstall:
|
||||||
|
helm uninstall minio -n ${MINIO_NAMESPACE} --wait --ignore-not-found
|
||||||
|
kubectl delete namespace ${MINIO_NAMESPACE} --ignore-not-found
|
||||||
|
|
||||||
|
# List MinIO internal policies and users (for debugging)
|
||||||
|
debug-info:
|
||||||
|
@kubectl -n ${MINIO_NAMESPACE} exec -it deploy/minio -- \
|
||||||
|
bash -c "mc alias set local http://localhost:9000 $(just root-user) $(just root-password) && \
|
||||||
|
echo '--- Policies ---' && \
|
||||||
|
mc admin policy list local && \
|
||||||
|
echo '--- Users ---' && \
|
||||||
|
mc admin user list local"
|
||||||
|
|
||||||
|
# Print MinIO root user
|
||||||
|
root-user:
|
||||||
|
@kubectl -n ${MINIO_NAMESPACE} get secret minio -o jsonpath='{.data.rootUser}' | base64 -d
|
||||||
|
@echo
|
||||||
|
|
||||||
|
# Print MinIO root password
|
||||||
|
root-password:
|
||||||
|
@kubectl -n ${MINIO_NAMESPACE} get secret minio -o jsonpath='{.data.rootPassword}' | base64 -d
|
||||||
|
@echo
|
||||||
|
|
||||||
|
# Create a bucket
|
||||||
|
create-bucket bucket:
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
ROOT_USER=$(just root-user)
|
||||||
|
ROOT_PASSWORD=$(just root-password)
|
||||||
|
kubectl -n ${MINIO_NAMESPACE} exec -it deploy/minio -- \
|
||||||
|
bash -c "mc alias set local http://localhost:9000 ${ROOT_USER} ${ROOT_PASSWORD} && \
|
||||||
|
mc mb --ignore-existing local/{{ bucket }}"
|
||||||
|
|
||||||
|
# Check if a bucket exists (returns exit code 0 if exists, 1 if not)
|
||||||
|
[no-exit-message]
|
||||||
|
bucket-exists bucket:
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
ROOT_USER=$(just root-user)
|
||||||
|
ROOT_PASSWORD=$(just root-password)
|
||||||
|
if kubectl -n ${MINIO_NAMESPACE} exec -it deploy/minio -- \
|
||||||
|
bash -c "mc alias set local http://localhost:9000 ${ROOT_USER} ${ROOT_PASSWORD} >/dev/null 2>&1 && \
|
||||||
|
mc ls local/{{ bucket }} >/dev/null 2>&1"; then
|
||||||
|
exit 0 # Bucket exists
|
||||||
|
else
|
||||||
|
exit 1 # Bucket does not exist
|
||||||
|
fi
|
||||||
40
minio/minio-values.gomplate.yaml
Normal file
40
minio/minio-values.gomplate.yaml
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
mode: standalone
|
||||||
|
|
||||||
|
clusterDomain: {{ .Env.MINIO_HOST }}
|
||||||
|
|
||||||
|
oidc:
|
||||||
|
enabled: true
|
||||||
|
configUrl: "https://{{ .Env.KEYCLOAK_HOST }}/realms/{{ .Env.KEYCLOAK_REALM }}/.well-known/openid-configuration"
|
||||||
|
clientId: "{{ .Env.MINIO_OIDC_CLIENT_ID }}"
|
||||||
|
clientSecret: ""
|
||||||
|
claimName: "minioPolicy"
|
||||||
|
scopes: "openid,profile,email"
|
||||||
|
redirectUri: "https://{{ .Env.MINIO_CONSOLE_HOST }}/oauth_callback"
|
||||||
|
displayName: "Login with Keycloak"
|
||||||
|
|
||||||
|
persistence:
|
||||||
|
size: 50Gi
|
||||||
|
|
||||||
|
ingress:
|
||||||
|
enabled: true
|
||||||
|
ingressClassName: traefik
|
||||||
|
annotations:
|
||||||
|
kubernetes.io/ingress.class: traefik
|
||||||
|
traefik.ingress.kubernetes.io/router.entrypoints: websecure
|
||||||
|
hosts:
|
||||||
|
- {{ .Env.MINIO_HOST }}
|
||||||
|
tls:
|
||||||
|
- hosts:
|
||||||
|
- {{ .Env.MINIO_HOST }}
|
||||||
|
|
||||||
|
consoleIngress:
|
||||||
|
enabled: true
|
||||||
|
ingressClassName: traefik
|
||||||
|
annotations:
|
||||||
|
kubernetes.io/ingress.class: traefik
|
||||||
|
traefik.ingress.kubernetes.io/router.entrypoints: websecure
|
||||||
|
hosts:
|
||||||
|
- {{ .Env.MINIO_CONSOLE_HOST }}
|
||||||
|
tls:
|
||||||
|
- hosts:
|
||||||
|
- {{ .Env.MINIO_CONSOLE_HOST }}
|
||||||
46
minio/scripts/add-minio-policy.ts
Normal file
46
minio/scripts/add-minio-policy.ts
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
// This script is a wrapper for add-attribute-mapper.ts specifically for MinIO policy configuration
|
||||||
|
// It sets the appropriate environment variables and calls the generic script
|
||||||
|
|
||||||
|
import { spawn } from "node:child_process";
|
||||||
|
import invariant from "tiny-invariant";
|
||||||
|
|
||||||
|
const main = async () => {
|
||||||
|
// Validate MinIO-specific environment variables
|
||||||
|
const minioClientId = process.env.MINIO_OIDC_CLIENT_ID;
|
||||||
|
invariant(minioClientId, "MINIO_OIDC_CLIENT_ID environment variable is required");
|
||||||
|
|
||||||
|
const policyValue = process.env.MINIO_POLICY || "readwrite";
|
||||||
|
console.log(`Setting MinIO policy attribute with default value: ${policyValue}`);
|
||||||
|
|
||||||
|
// Set up environment variables for the generic script
|
||||||
|
const env = {
|
||||||
|
...process.env,
|
||||||
|
CLIENT_ID: minioClientId,
|
||||||
|
ATTRIBUTE_NAME: "minioPolicy",
|
||||||
|
ATTRIBUTE_DISPLAY_NAME: "MinIO Policy",
|
||||||
|
ATTRIBUTE_CLAIM_NAME: "minioPolicy",
|
||||||
|
ATTRIBUTE_OPTIONS: "readwrite,readonly,writeonly",
|
||||||
|
ATTRIBUTE_DEFAULT_VALUE: policyValue,
|
||||||
|
MAPPER_NAME: "MinIO Policy",
|
||||||
|
};
|
||||||
|
|
||||||
|
// Call the generic add-attribute-mapper script
|
||||||
|
const child = spawn("npx", ["tsx", "../../keycloak/scripts/add-attribute-mapper.ts"], {
|
||||||
|
cwd: __dirname,
|
||||||
|
env,
|
||||||
|
stdio: "inherit",
|
||||||
|
});
|
||||||
|
|
||||||
|
child.on("error", (error) => {
|
||||||
|
console.error("Failed to execute add-attribute-mapper.ts:", error);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
child.on("exit", (code) => {
|
||||||
|
process.exit(code || 0);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
main();
|
||||||
Reference in New Issue
Block a user