refactor: 폴더 구조 변경
This commit is contained in:
Executable
+331
@@ -0,0 +1,331 @@
|
||||
#!/usr/bin/env bash
|
||||
# Provision the docker-registry MinIO dependency after the Tenant is ready.
|
||||
#
|
||||
# The registry credential is generated by MinIO as an access key with an inline,
|
||||
# bucket-scoped policy. The generated secret is captured once and written to
|
||||
# Vault through stdin. Root and application credentials are never passed as
|
||||
# command-line arguments.
|
||||
#
|
||||
# Required env:
|
||||
# REPO_ROOT
|
||||
# ENV_NAME
|
||||
#
|
||||
# Optional env:
|
||||
# DOCKER_REGISTRY_BUCKET default: docker-registry
|
||||
# PF_LOCAL_PORT default: 9900
|
||||
# MINIO_NAMESPACE default: mnt
|
||||
# MINIO_SERVICE default: minio
|
||||
# MINIO_SCHEME lab default: http; other envs: https
|
||||
# MINIO_SERVICE_PORT lab default: 80; other envs: 443
|
||||
# MINIO_TLS_INSECURE default: no
|
||||
# ALLOW_INSECURE_MINIO_TLS required when non-lab explicitly uses insecure TLS
|
||||
|
||||
set -Eeuo pipefail
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# shellcheck source=../lib/common.sh
|
||||
. "$SCRIPT_DIR/../lib/common.sh"
|
||||
# shellcheck source=../lib/vault.sh
|
||||
. "$SCRIPT_DIR/../lib/vault.sh"
|
||||
|
||||
: "${DOCKER_REGISTRY_BUCKET:=docker-registry}"
|
||||
: "${PF_LOCAL_PORT:=9900}"
|
||||
: "${MINIO_NAMESPACE:=mnt}"
|
||||
: "${MINIO_SERVICE:=minio}"
|
||||
ENV_NAME="${ENV_NAME:-}"
|
||||
|
||||
MC_ALIAS="minio-provision"
|
||||
REGISTRY_CHECK_ALIAS="registry-check"
|
||||
MC_CONFIG_DIR=""
|
||||
PF_PID=""
|
||||
CREATED_ACCESS_KEY=""
|
||||
ACCESS_KEY_PERSISTED="no"
|
||||
ROOT_USER=""
|
||||
ROOT_PASSWORD=""
|
||||
POLICY_FILE=""
|
||||
MC_GLOBAL_ARGS=()
|
||||
|
||||
resolve_transport_defaults() {
|
||||
case "$ENV_NAME" in
|
||||
lab)
|
||||
: "${MINIO_SCHEME:=http}"
|
||||
: "${MINIO_SERVICE_PORT:=80}"
|
||||
: "${MINIO_TLS_INSECURE:=no}"
|
||||
;;
|
||||
*)
|
||||
: "${MINIO_SCHEME:=https}"
|
||||
: "${MINIO_SERVICE_PORT:=443}"
|
||||
: "${MINIO_TLS_INSECURE:=no}"
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$MINIO_SCHEME" in
|
||||
http | https) ;;
|
||||
*) die "MINIO_SCHEME은 http 또는 https만 허용됩니다: $MINIO_SCHEME" ;;
|
||||
esac
|
||||
case "$MINIO_TLS_INSECURE" in
|
||||
yes | no) ;;
|
||||
*) die "MINIO_TLS_INSECURE는 yes 또는 no만 허용됩니다." ;;
|
||||
esac
|
||||
|
||||
if [[ "$ENV_NAME" != "lab" && "$MINIO_TLS_INSECURE" == "yes" &&
|
||||
"${ALLOW_INSECURE_MINIO_TLS:-}" != "yes" ]]; then
|
||||
die "lab 외 환경에서 TLS 검증 비활성화는 ALLOW_INSECURE_MINIO_TLS=yes 가 추가로 필요합니다."
|
||||
fi
|
||||
}
|
||||
|
||||
cleanup_port_forward() {
|
||||
if [[ -n "${PF_PID:-}" ]] && kill -0 "$PF_PID" 2>/dev/null; then
|
||||
kill "$PF_PID" 2>/dev/null || true
|
||||
wait "$PF_PID" 2>/dev/null || true
|
||||
fi
|
||||
}
|
||||
|
||||
mc_cmd() {
|
||||
mc "${MC_GLOBAL_ARGS[@]}" "$@"
|
||||
}
|
||||
|
||||
cleanup_created_access_key() {
|
||||
if [[ -z "${CREATED_ACCESS_KEY:-}" || "$ACCESS_KEY_PERSISTED" == "yes" ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
warn "Vault 기록 전 실패: 이번 실행에서 만든 MinIO access key 정리"
|
||||
mc_cmd admin accesskey rm "$MC_ALIAS" "$CREATED_ACCESS_KEY" >/dev/null 2>&1 \
|
||||
|| warn "생성한 access key 자동 정리 실패 — MinIO IAM을 점검하세요."
|
||||
}
|
||||
|
||||
wait_minio_ready() {
|
||||
log "MinIO Tenant Pod Ready 대기"
|
||||
retry 30 5 kubectl -n "$MINIO_NAMESPACE" wait --for=condition=Ready --timeout=10s \
|
||||
pod -l "v1.min.io/tenant=$MINIO_SERVICE"
|
||||
}
|
||||
|
||||
start_port_forward() {
|
||||
log "port-forward 생성 (127.0.0.1:${PF_LOCAL_PORT} -> svc/${MINIO_SERVICE}:${MINIO_SERVICE_PORT})"
|
||||
kubectl -n "$MINIO_NAMESPACE" port-forward \
|
||||
"svc/${MINIO_SERVICE}" "${PF_LOCAL_PORT}:${MINIO_SERVICE_PORT}" \
|
||||
>/dev/null 2>&1 &
|
||||
PF_PID=$!
|
||||
trap_cleanup_fn cleanup_port_forward
|
||||
|
||||
local curl_args=(-fsS --max-time 2)
|
||||
if [[ "$MINIO_SCHEME" == "https" && "$MINIO_TLS_INSECURE" == "yes" ]]; then
|
||||
curl_args+=(-k)
|
||||
fi
|
||||
retry 15 1 curl "${curl_args[@]}" \
|
||||
"${MINIO_SCHEME}://127.0.0.1:${PF_LOCAL_PORT}/minio/health/live" \
|
||||
-o /dev/null
|
||||
log "MinIO health endpoint 응답 확인"
|
||||
}
|
||||
|
||||
read_root_credentials() {
|
||||
local env_blob
|
||||
env_blob="$(
|
||||
vault_exec kv get -format=json secret/minio/tenant-env \
|
||||
| jq -r '.data.data["config.env"]'
|
||||
)"
|
||||
ROOT_USER="$(
|
||||
printf '%s\n' "$env_blob" \
|
||||
| sed -n 's/^export MINIO_ROOT_USER="\(.*\)"$/\1/p'
|
||||
)"
|
||||
ROOT_PASSWORD="$(
|
||||
printf '%s\n' "$env_blob" \
|
||||
| sed -n 's/^export MINIO_ROOT_PASSWORD="\(.*\)"$/\1/p'
|
||||
)"
|
||||
unset env_blob
|
||||
|
||||
[[ -n "$ROOT_USER" && -n "$ROOT_PASSWORD" ]] \
|
||||
|| die "MinIO root 자격증명 파싱 실패 — secret/minio/tenant-env 확인"
|
||||
}
|
||||
|
||||
init_mc_config() {
|
||||
MC_CONFIG_DIR="$(mktemp -d -t project-infra-mc.XXXXXX)"
|
||||
chmod 700 "$MC_CONFIG_DIR"
|
||||
trap_cleanup_path "$MC_CONFIG_DIR"
|
||||
|
||||
MC_GLOBAL_ARGS=(--config-dir "$MC_CONFIG_DIR")
|
||||
if [[ "$MINIO_SCHEME" == "https" && "$MINIO_TLS_INSECURE" == "yes" ]]; then
|
||||
MC_GLOBAL_ARGS+=(--insecure)
|
||||
fi
|
||||
|
||||
mc_cmd admin accesskey create --help >/dev/null \
|
||||
|| die "현재 mc는 'admin accesskey create'를 지원하지 않습니다."
|
||||
}
|
||||
|
||||
import_mc_alias() {
|
||||
local alias_name="$1"
|
||||
local endpoint="$2"
|
||||
local access_key="$3"
|
||||
local secret_key="$4"
|
||||
|
||||
# NUL-delimited stdin keeps both credentials out of jq and mc argv.
|
||||
printf '%s\0%s\0%s\0' "$endpoint" "$access_key" "$secret_key" \
|
||||
| jq -Rs '
|
||||
split("\u0000") |
|
||||
{
|
||||
url: .[0],
|
||||
accessKey: .[1],
|
||||
secretKey: .[2],
|
||||
api: "s3v4",
|
||||
path: "auto"
|
||||
}
|
||||
' \
|
||||
| mc_cmd alias import "$alias_name" >/dev/null
|
||||
}
|
||||
|
||||
configure_root_alias() {
|
||||
local endpoint="${MINIO_SCHEME}://127.0.0.1:${PF_LOCAL_PORT}"
|
||||
import_mc_alias "$MC_ALIAS" "$endpoint" "$ROOT_USER" "$ROOT_PASSWORD"
|
||||
unset ROOT_USER ROOT_PASSWORD
|
||||
}
|
||||
|
||||
ensure_bucket() {
|
||||
log "MinIO bucket 보장 (${DOCKER_REGISTRY_BUCKET})"
|
||||
mc_cmd mb --ignore-existing "${MC_ALIAS}/${DOCKER_REGISTRY_BUCKET}" >/dev/null
|
||||
}
|
||||
|
||||
write_inline_policy() {
|
||||
POLICY_FILE="$MC_CONFIG_DIR/docker-registry-policy.json"
|
||||
jq -nc --arg bucket "$DOCKER_REGISTRY_BUCKET" '{
|
||||
Version: "2012-10-17",
|
||||
Statement: [
|
||||
{
|
||||
Effect: "Allow",
|
||||
Action: [
|
||||
"s3:ListBucket",
|
||||
"s3:ListBucketMultipartUploads",
|
||||
"s3:GetBucketLocation"
|
||||
],
|
||||
Resource: ["arn:aws:s3:::\($bucket)"]
|
||||
},
|
||||
{
|
||||
Effect: "Allow",
|
||||
Action: [
|
||||
"s3:PutObject",
|
||||
"s3:GetObject",
|
||||
"s3:DeleteObject",
|
||||
"s3:ListMultipartUploadParts",
|
||||
"s3:AbortMultipartUpload"
|
||||
],
|
||||
Resource: ["arn:aws:s3:::\($bucket)/*"]
|
||||
}
|
||||
]
|
||||
}' >"$POLICY_FILE"
|
||||
chmod 600 "$POLICY_FILE"
|
||||
}
|
||||
|
||||
read_vault_registry_field() {
|
||||
local field="$1"
|
||||
vault_exec kv get -format=json secret/docker-registry/minio \
|
||||
| jq -er --arg field "$field" '.data.data[$field]'
|
||||
}
|
||||
|
||||
verify_registry_credentials() {
|
||||
local access_key="$1"
|
||||
local secret_key="$2"
|
||||
local endpoint="${MINIO_SCHEME}://127.0.0.1:${PF_LOCAL_PORT}"
|
||||
|
||||
import_mc_alias "$REGISTRY_CHECK_ALIAS" "$endpoint" "$access_key" "$secret_key"
|
||||
mc_cmd stat "${REGISTRY_CHECK_ALIAS}/${DOCKER_REGISTRY_BUCKET}" >/dev/null \
|
||||
|| die "Vault의 docker-registry MinIO credential 검증 실패"
|
||||
}
|
||||
|
||||
use_existing_access_key() {
|
||||
vault_kv_exists "docker-registry/minio" || return 1
|
||||
|
||||
local access_key secret_key
|
||||
access_key="$(read_vault_registry_field access_key)" \
|
||||
|| die "secret/docker-registry/minio.access_key 읽기 실패"
|
||||
secret_key="$(read_vault_registry_field secret_key)" \
|
||||
|| die "secret/docker-registry/minio.secret_key 읽기 실패"
|
||||
|
||||
if mc_cmd admin accesskey info "$MC_ALIAS" "$access_key" >/dev/null 2>&1; then
|
||||
verify_registry_credentials "$access_key" "$secret_key"
|
||||
unset access_key secret_key
|
||||
log "기존 docker-registry MinIO access key 검증 완료"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if mc_cmd admin user info "$MC_ALIAS" "$access_key" >/dev/null 2>&1; then
|
||||
unset access_key secret_key
|
||||
die "기존 Vault 값은 legacy MinIO user를 가리킵니다. 승인된 credential rotation 절차로 먼저 전환하세요."
|
||||
fi
|
||||
|
||||
unset access_key secret_key
|
||||
die "Vault에는 registry credential이 있지만 대응하는 MinIO access key가 없습니다. 자동 재생성하지 않습니다."
|
||||
}
|
||||
|
||||
persist_generated_access_key() {
|
||||
local access_key="$1"
|
||||
local secret_key="$2"
|
||||
|
||||
if ! printf '%s\0%s\0' "$access_key" "$secret_key" \
|
||||
| jq -Rs '
|
||||
split("\u0000") |
|
||||
{
|
||||
access_key: .[0],
|
||||
secret_key: .[1]
|
||||
}
|
||||
' \
|
||||
| vault_exec kv put secret/docker-registry/minio - >/dev/null; then
|
||||
die "생성된 docker-registry credential의 Vault 기록 실패"
|
||||
fi
|
||||
|
||||
ACCESS_KEY_PERSISTED="yes"
|
||||
}
|
||||
|
||||
create_access_key() {
|
||||
log "bucket-scoped docker-registry MinIO access key 생성"
|
||||
local creation_json access_key secret_key
|
||||
creation_json="$(
|
||||
mc_cmd --json admin accesskey create "$MC_ALIAS" \
|
||||
--name docker-registry \
|
||||
--description "docker-registry bucket access" \
|
||||
--policy "$POLICY_FILE"
|
||||
)" || die "MinIO access key 생성 실패"
|
||||
access_key="$(
|
||||
jq -ser 'map(select(.accessKey? or .access_key?)) | last | .accessKey // .access_key' \
|
||||
<<<"$creation_json"
|
||||
)" || die "생성된 MinIO access key 응답 파싱 실패"
|
||||
secret_key="$(
|
||||
jq -ser 'map(select(.secretKey? or .secret_key?)) | last | .secretKey // .secret_key' \
|
||||
<<<"$creation_json"
|
||||
)" || die "생성된 MinIO secret key 응답 파싱 실패"
|
||||
unset creation_json
|
||||
|
||||
[[ -n "$access_key" && -n "$secret_key" ]] \
|
||||
|| die "MinIO가 생성한 access key 응답이 비어 있습니다."
|
||||
CREATED_ACCESS_KEY="$access_key"
|
||||
|
||||
verify_registry_credentials "$access_key" "$secret_key"
|
||||
persist_generated_access_key "$access_key" "$secret_key"
|
||||
|
||||
unset access_key secret_key CREATED_ACCESS_KEY
|
||||
log "생성된 docker-registry credential을 Vault에 기록"
|
||||
}
|
||||
|
||||
main() {
|
||||
require_cmd kubectl jq mc curl sed
|
||||
require_env REPO_ROOT ENV_NAME
|
||||
resolve_transport_defaults
|
||||
|
||||
local keys_file="${VAULT_KEYS_FILE:-$REPO_ROOT/vault-init-keys.json}"
|
||||
vault_login_root_from_keyfile "$keys_file"
|
||||
|
||||
wait_minio_ready
|
||||
start_port_forward
|
||||
read_root_credentials
|
||||
init_mc_config
|
||||
configure_root_alias
|
||||
trap_cleanup_fn cleanup_created_access_key
|
||||
|
||||
ensure_bucket
|
||||
write_inline_policy
|
||||
use_existing_access_key || create_access_key
|
||||
|
||||
log "minio-provision-registry 태스크 완료"
|
||||
}
|
||||
|
||||
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
||||
main "$@"
|
||||
fi
|
||||
Reference in New Issue
Block a user