init: 아르고cd, vault 기반 인프라 설계

This commit is contained in:
DongHyeonka
2026-07-24 14:31:09 +09:00
parent 8879d0a3fe
commit d507ac6ee9
137 changed files with 11431 additions and 1 deletions
+292
View File
@@ -0,0 +1,292 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"
source "${REPO_ROOT}/scripts/vault/dev/provider-lib.sh"
usage() {
cat <<'EOF'
Usage: scripts/ci/reconcile-vault-dev.sh <command>
Commands:
prepare-infra
reconcile-transit
reconcile-workload
apply-apps
EOF
}
log() {
printf '[reconcile-vault-dev] %s\n' "$*"
}
require_cmd() {
local cmd="$1"
if ! command -v "$cmd" >/dev/null 2>&1; then
echo "$cmd is required" >&2
exit 1
fi
}
require_env() {
local name="$1"
if [[ -z "${!name:-}" ]]; then
echo "$name must be set" >&2
exit 1
fi
}
wait_http_ready() {
local url="$1"
local label="$2"
if ! curl -fsS --retry 30 --retry-delay 2 --retry-connrefused "$url" >/dev/null 2>&1; then
echo "${label} is not reachable at ${url}" >&2
return 1
fi
}
start_port_forward() {
local namespace="$1"
local service="$2"
local local_port="$3"
local remote_port="$4"
local log_file="$5"
kubectl -n "$namespace" port-forward "svc/${service}" "${local_port}:${remote_port}" >"$log_file" 2>&1 &
local pf_pid=$!
trap 'kill "$pf_pid" >/dev/null 2>&1 || true' EXIT
printf '%s\n' "$pf_pid"
}
use_port_forward() {
[[ "${RECONCILE_USE_PORT_FORWARD:-true}" == "true" ]]
}
transit_login() {
VAULT_ADDR="${TRANSIT_VAULT_ADDR}" \
vault write -field=token auth/approle/login \
role_id="${VAULT_TRANSIT_DEV_ROLE_ID}" \
secret_id="${VAULT_TRANSIT_DEV_SECRET_ID}"
}
ensure_transit_state_resource() {
local address="$1"
local import_id="$2"
if ! terraform -chdir="${REPO_ROOT}/terraform/vault-transit/reconcile" state show "$address" >/dev/null 2>&1; then
log "Importing missing vault-transit state for ${address}"
terraform -chdir="${REPO_ROOT}/terraform/vault-transit/reconcile" import "$address" "$import_id"
fi
}
ensure_workload_state_resource() {
local address="$1"
local import_id="$2"
if ! terraform -chdir="${REPO_ROOT}/terraform/vault/reconcile" state show "$address" >/dev/null 2>&1; then
log "Importing missing workload-vault state for ${address}"
terraform -chdir="${REPO_ROOT}/terraform/vault/reconcile" import "$address" "$import_id"
fi
}
prepare_infra() {
require_cmd kubectl
require_env TF_STATE_DIR
mkdir -p "${TF_STATE_DIR}"
"${REPO_ROOT}/scripts/vault/dev/apply-argocd-dev-infra.sh"
kubectl -n vault-transit wait --for=create deployment/vault-transit --timeout=300s
kubectl -n vault-transit wait --for=condition=available deployment/vault-transit --timeout=300s
kubectl -n vault wait --for=create deployment/vault --timeout=300s
kubectl -n vault wait --for=condition=available deployment/vault --timeout=300s
}
reconcile_transit() {
require_cmd kubectl
require_cmd vault
require_cmd terraform
require_cmd curl
require_cmd jq
require_env TF_STATE_DIR
require_env TRANSIT_VAULT_ADDR
require_env VAULT_TRANSIT_DEV_ROLE_ID
require_env VAULT_TRANSIT_DEV_SECRET_ID
if use_port_forward; then
start_port_forward vault-transit vault-transit 18200 8200 /tmp/vault-transit-port-forward.log >/dev/null
fi
wait_http_ready "${TRANSIT_VAULT_ADDR}/v1/sys/health" "Transit provider Vault API"
VAULT_ADDR="${TRANSIT_VAULT_ADDR}" "${REPO_ROOT}/scripts/vault-transit/dev/ensure-unsealed.sh"
local transit_tf_token
transit_tf_token="$(transit_login)"
VAULT_ADDR="${TRANSIT_VAULT_ADDR}" \
VAULT_TOKEN="${transit_tf_token}" \
vault policy write \
vault-transit-automation-dev \
"${REPO_ROOT}/runbooks/vault-transit/dev/policies/vault-transit-automation-dev.hcl"
transit_tf_token="$(transit_login)"
local transit_state_path="${TF_STATE_DIR}/vault-transit-reconcile.tfstate"
TF_VAR_vault_addr="${TRANSIT_VAULT_ADDR}" \
TF_VAR_vault_token="${transit_tf_token}" \
terraform -chdir="${REPO_ROOT}/terraform/vault-transit/reconcile" init \
-input=false \
-reconfigure \
-backend-config="path=${transit_state_path}"
if ! terraform -chdir="${REPO_ROOT}/terraform/vault-transit/reconcile" state list >/dev/null 2>&1; then
echo "vault-transit Terraform state is unreadable. Re-seed ${transit_state_path}." >&2
exit 1
fi
export TF_VAR_vault_addr="${TRANSIT_VAULT_ADDR}"
export TF_VAR_vault_token="${transit_tf_token}"
ensure_transit_state_resource vault_policy.workload_vault_transit_dev workload-vault-transit-dev
ensure_transit_state_resource vault_policy.vault_transit_admin_dev vault-transit-admin-dev
ensure_transit_state_resource vault_policy.vault_transit_automation_dev vault-transit-automation-dev
ensure_transit_state_resource vault_approle_auth_backend_role.workflow auth/approle/role/vault-transit-dev-workflow
TF_VAR_vault_addr="${TRANSIT_VAULT_ADDR}" \
TF_VAR_vault_token="${transit_tf_token}" \
terraform -chdir="${REPO_ROOT}/terraform/vault-transit/reconcile" apply -input=false -auto-approve
}
reconcile_workload() {
require_cmd kubectl
require_cmd vault
require_cmd terraform
require_cmd curl
require_env TF_STATE_DIR
require_env TRANSIT_VAULT_ADDR
require_env WORKLOAD_VAULT_ADDR
require_env VAULT_TRANSIT_DEV_ROLE_ID
require_env VAULT_TRANSIT_DEV_SECRET_ID
if use_port_forward; then
start_port_forward vault vault 8200 8200 /tmp/vault-workload-port-forward.log >/dev/null
fi
wait_http_ready "${WORKLOAD_VAULT_ADDR}/v1/sys/health" "Workload Vault API"
VAULT_ADDR="${WORKLOAD_VAULT_ADDR}" "${REPO_ROOT}/scripts/vault/dev/ensure-unsealed.sh"
local transit_tf_token
transit_tf_token="$(transit_login)"
local workload_role_id
local workload_secret_id
workload_role_id="$(
VAULT_ADDR="${TRANSIT_VAULT_ADDR}" \
VAULT_TOKEN="${transit_tf_token}" \
vault kv get -field=VAULT_WORKLOAD_DEV_ROLE_ID kv/dev/workload/bootstrap 2>/dev/null || true
)"
workload_secret_id="$(
VAULT_ADDR="${TRANSIT_VAULT_ADDR}" \
VAULT_TOKEN="${transit_tf_token}" \
vault kv get -field=VAULT_WORKLOAD_DEV_SECRET_ID kv/dev/workload/bootstrap 2>/dev/null || true
)"
if [[ -z "${workload_role_id}" || -z "${workload_secret_id}" ]]; then
echo "Workload Vault bootstrap AppRole is missing from provider Vault." >&2
echo "Execute scripts/vault/dev/bootstrap-runbook.sh manually with a privileged workload token to seed kv/dev/workload/bootstrap." >&2
exit 1
fi
local workload_tf_token
workload_tf_token="$(
VAULT_ADDR="${WORKLOAD_VAULT_ADDR}" \
vault write -field=token auth/approle/login \
role_id="${workload_role_id}" \
secret_id="${workload_secret_id}"
)"
local workload_state_path="${TF_STATE_DIR}/vault-reconcile.tfstate"
TF_VAR_workload_vault_addr="${WORKLOAD_VAULT_ADDR}" \
TF_VAR_workload_vault_token="${workload_tf_token}" \
TF_VAR_transit_vault_addr="${TRANSIT_VAULT_ADDR}" \
TF_VAR_transit_vault_token="${transit_tf_token}" \
terraform -chdir="${REPO_ROOT}/terraform/vault/reconcile" init \
-input=false \
-reconfigure \
-backend-config="path=${workload_state_path}"
export TF_VAR_workload_vault_addr="${WORKLOAD_VAULT_ADDR}"
export TF_VAR_workload_vault_token="${workload_tf_token}"
export TF_VAR_transit_vault_addr="${TRANSIT_VAULT_ADDR}"
export TF_VAR_transit_vault_token="${transit_tf_token}"
ensure_workload_state_resource vault_policy.auth_server auth-server-dev
ensure_workload_state_resource vault_policy.auth_db_migration auth-db-migration-dev
ensure_workload_state_resource vault_policy.postgres postgres-dev
ensure_workload_state_resource vault_policy.keycloak keycloak-dev
ensure_workload_state_resource vault_policy.keycloak_client_sync keycloak-client-sync-dev
ensure_workload_state_resource vault_policy.postgres_operator postgres-operator-dev
ensure_workload_state_resource vault_policy.keycloak_operator keycloak-operator-dev
ensure_workload_state_resource vault_policy.platform_admin platform-admin-dev
ensure_workload_state_resource vault_policy.workload_automation workload-automation-dev
ensure_workload_state_resource vault_kubernetes_auth_backend_role.auth_server auth/kubernetes/role/auth-server-dev
ensure_workload_state_resource vault_kubernetes_auth_backend_role.auth_db_migration auth/kubernetes/role/auth-db-migration-dev
ensure_workload_state_resource vault_kubernetes_auth_backend_role.postgres auth/kubernetes/role/postgres-dev
ensure_workload_state_resource vault_kubernetes_auth_backend_role.keycloak auth/kubernetes/role/keycloak-dev
ensure_workload_state_resource vault_kubernetes_auth_backend_role.keycloak_client_sync auth/kubernetes/role/keycloak-client-sync-dev
ensure_workload_state_resource vault_approle_auth_backend_role.workflow auth/approle/role/workload-dev-workflow
ensure_workload_state_resource vault_database_secret_backend_connection.platform_postgres database/config/platform-postgres-dev
ensure_workload_state_resource vault_database_secret_backend_role.auth_db_migration database/roles/auth-db-migration-dev
ensure_workload_state_resource vault_database_secret_backend_role.postgres_operator database/roles/postgres-operator-dev
ensure_workload_state_resource vault_kv_secret_v2.platform_postgres_superuser kv/data/dev/platform/postgres/superuser
ensure_workload_state_resource vault_kv_secret_v2.platform_postgres_auth_server kv/data/dev/platform/postgres/auth-server
ensure_workload_state_resource vault_kv_secret_v2.platform_postgres_keycloak kv/data/dev/platform/postgres/keycloak
ensure_workload_state_resource vault_kv_secret_v2.platform_keycloak_bootstrap_admin kv/data/dev/platform/keycloak/bootstrap-admin
ensure_workload_state_resource vault_kv_secret_v2.platform_keycloak_client_auth_server kv/data/dev/platform/keycloak/client-auth-server
TF_VAR_workload_vault_addr="${WORKLOAD_VAULT_ADDR}" \
TF_VAR_workload_vault_token="${workload_tf_token}" \
TF_VAR_transit_vault_addr="${TRANSIT_VAULT_ADDR}" \
TF_VAR_transit_vault_token="${transit_tf_token}" \
terraform -chdir="${REPO_ROOT}/terraform/vault/reconcile" apply -input=false -auto-approve
if kubectl -n vault get deployment -l app.kubernetes.io/name=vault-agent-injector -o name | grep -q .; then
kubectl -n vault wait --for=condition=available deployment -l app.kubernetes.io/name=vault-agent-injector --timeout=180s
fi
}
apply_apps() {
require_cmd kubectl
"${REPO_ROOT}/scripts/vault/dev/apply-argocd-dev-apps.sh"
}
main() {
require_cmd bash
require_cmd kubectl
case "${1:-}" in
prepare-infra)
prepare_infra
;;
reconcile-transit)
reconcile_transit
;;
reconcile-workload)
reconcile_workload
;;
apply-apps)
apply_apps
;;
*)
usage >&2
exit 1
;;
esac
}
main "$@"