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 "$@"
+131
View File
@@ -0,0 +1,131 @@
#!/usr/bin/env bash
set -euo pipefail
resolve_inputs() {
local service=""
local target_env=""
local image_tag=""
local image_name=""
local kustomization=""
if [[ "${GITHUB_EVENT_NAME:-}" == "workflow_dispatch" ]]; then
service="${INPUT_SERVICE:-}"
target_env="${INPUT_TARGET_ENV:-}"
image_tag="${INPUT_IMAGE_TAG:-}"
else
service="${EVENT_SERVICE:-}"
target_env="${EVENT_TARGET_ENV:-}"
image_tag="${EVENT_IMAGE_TAG:-}"
fi
if [[ -z "$service" || -z "$target_env" || -z "$image_tag" ]]; then
echo "Missing service/target_env/image_tag input" >&2
exit 1
fi
case "$service" in
auth-server)
image_name="ghcr.io/donghyeonka/project-auth-server"
;;
api-server)
image_name="ghcr.io/donghyeonka/project-api-server"
;;
*)
echo "Unsupported service: $service" >&2
exit 1
;;
esac
case "$target_env" in
dev|prod)
;;
*)
echo "Unsupported environment: $target_env" >&2
exit 1
;;
esac
if [[ ! "$image_tag" =~ ^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$ ]]; then
echo "Unsupported image tag format: $image_tag" >&2
exit 1
fi
kustomization="apps/${service}/overlays/${target_env}/kustomization.yaml"
{
echo "SERVICE=$service"
echo "TARGET_ENV=$target_env"
echo "IMAGE_TAG=$image_tag"
echo "IMAGE_NAME=$image_name"
echo "KUSTOMIZATION=$kustomization"
} >> "$GITHUB_ENV"
}
update_kustomization() {
if ! command -v kustomize >/dev/null 2>&1; then
echo "kustomize is required to update the image tag" >&2
exit 1
fi
if [[ ! -f "${KUSTOMIZATION:-}" ]]; then
echo "Kustomization not found: ${KUSTOMIZATION:-}" >&2
exit 1
fi
cd "$(dirname "$KUSTOMIZATION")"
kustomize edit set image "${IMAGE_NAME}=${IMAGE_NAME}:${IMAGE_TAG}"
}
validate_overlay() {
if ! command -v kubectl >/dev/null 2>&1; then
echo "kubectl is required to validate the overlay" >&2
exit 1
fi
kubectl kustomize "$(dirname "$KUSTOMIZATION")" >/dev/null
}
check_changes() {
if git diff --quiet -- "$KUSTOMIZATION"; then
echo "changed=false" >> "$GITHUB_OUTPUT"
echo "No changes to commit"
else
echo "changed=true" >> "$GITHUB_OUTPUT"
git diff -- "$KUSTOMIZATION"
fi
}
commit_dev() {
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add "$KUSTOMIZATION"
git commit -m "chore(gitops): update ${SERVICE} ${TARGET_ENV} image to ${IMAGE_TAG}"
git push origin "HEAD:${DEFAULT_BRANCH}"
}
main() {
case "${1:-}" in
resolve-inputs)
resolve_inputs
;;
update-kustomization)
update_kustomization
;;
validate-overlay)
validate_overlay
;;
check-changes)
check_changes
;;
commit-dev)
commit_dev
;;
*)
echo "Usage: scripts/ci/update-image-tag.sh <resolve-inputs|update-kustomization|validate-overlay|check-changes|commit-dev>" >&2
exit 1
;;
esac
}
main "$@"
+55
View File
@@ -0,0 +1,55 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "${SCRIPT_DIR}/../../.." && pwd)"
source "${SCRIPT_DIR}/../../vault/dev/provider-lib.sh"
if ! command -v terraform >/dev/null 2>&1; then
echo "terraform CLI is required" >&2
exit 1
fi
export VAULT_TRANSIT_ADDR="${VAULT_TRANSIT_ADDR:-${VAULT_ADDR:-http://127.0.0.1:18200}}"
export TF_VAR_vault_addr="$VAULT_TRANSIT_ADDR"
export TF_VAR_vault_token="$(provider_vault_token)"
if [[ -n "${SEAL_KEY_NAME:-}" ]]; then
export TF_VAR_seal_key_name="$SEAL_KEY_NAME"
fi
if [[ -n "${SEAL_TOKEN_PERIOD:-}" ]]; then
export TF_VAR_seal_token_period="$SEAL_TOKEN_PERIOD"
fi
if [[ -n "${TARGET_NAMESPACE:-}" ]]; then
export TF_VAR_target_namespace="$TARGET_NAMESPACE"
fi
if [[ -n "${TARGET_SECRET_NAME:-}" ]]; then
export TF_VAR_target_secret_name="$TARGET_SECRET_NAME"
fi
if [[ -n "${WORKFLOW_POLICY_NAME:-}" ]]; then
export TF_VAR_workflow_policy_name="$WORKFLOW_POLICY_NAME"
fi
if [[ -n "${WORKFLOW_ROLE_NAME:-}" ]]; then
export TF_VAR_workflow_role_name="$WORKFLOW_ROLE_NAME"
fi
mkdir -p "${REPO_ROOT}/.terraform-state"
if [[ -n "${TF_STATE_DIR:-}" ]]; then
mkdir -p "${TF_STATE_DIR}"
terraform -chdir="${REPO_ROOT}/terraform/vault-transit/dev" init \
-input=false \
-reconfigure \
-backend-config="path=${TF_STATE_DIR}/vault-transit-dev.tfstate"
else
terraform -chdir="${REPO_ROOT}/terraform/vault-transit/dev" init -input=false
fi
terraform -chdir="${REPO_ROOT}/terraform/vault-transit/dev" apply -input=false -auto-approve
+41
View File
@@ -0,0 +1,41 @@
#!/usr/bin/env bash
set -euo pipefail
VAULT_ADDR="${VAULT_ADDR:-http://127.0.0.1:18200}"
export VAULT_ADDR
if ! command -v vault >/dev/null 2>&1; then
echo "vault CLI is required" >&2
exit 1
fi
status_json="$(mktemp)"
trap 'rm -f "$status_json"' EXIT
if vault status -format=json >"$status_json" 2>/dev/null; then
:
else
if [[ ! -s "$status_json" ]]; then
echo "Vault transit provider is unreachable at ${VAULT_ADDR}" >&2
exit 1
fi
fi
initialized="$(jq -r '.initialized' "$status_json")"
sealed="$(jq -r '.sealed' "$status_json")"
if [[ "$initialized" != "true" ]]; then
echo "Transit provider Vault is not initialized." >&2
exit 1
fi
if [[ "$sealed" == "true" ]]; then
cat >&2 <<'EOF'
Transit provider Vault is sealed.
Manual unseal is required before the CI reconcile workflow can continue.
Run the provider Vault runbook from runbooks/vault-transit/dev/README.md and unseal the vault-transit instance first.
EOF
exit 1
fi
+90
View File
@@ -0,0 +1,90 @@
#!/usr/bin/env bash
set -euo pipefail
if ! command -v vault >/dev/null 2>&1; then
echo "vault CLI is required" >&2
exit 1
fi
prompt_secret() {
local var_name="$1"
local label="$2"
local value=""
local confirm=""
while true; do
read -r -s -p "${label}: " value
echo
read -r -s -p "${label} (confirm): " confirm
echo
if [[ "$value" != "$confirm" ]]; then
echo "Values did not match. Try again." >&2
continue
fi
if [[ -z "$value" ]]; then
echo "Value must not be empty." >&2
continue
fi
printf -v "$var_name" '%s' "$value"
break
done
}
prompt_value() {
local var_name="$1"
local label="$2"
local default_value="${3:-}"
local value=""
if [[ -n "$default_value" ]]; then
read -r -p "${label} [${default_value}]: " value
value="${value:-$default_value}"
else
read -r -p "${label}: " value
fi
if [[ -z "$value" ]]; then
echo "Value must not be empty." >&2
exit 1
fi
printf -v "$var_name" '%s' "$value"
}
echo "Populate provider Vault workload seeds"
echo "VAULT_ADDR=${VAULT_ADDR:-unset}"
echo "This script prompts securely so values are not exposed in shell history."
echo "The workload workflow AppRole bootstrap path is managed by Terraform."
echo
prompt_secret PLATFORM_POSTGRES_SUPERUSER_PASSWORD "Platform Postgres superuser password"
prompt_value AUTH_SERVER_DATASOURCE_USERNAME "Postgres auth-server username" "project_auth"
prompt_secret AUTH_SERVER_DATASOURCE_PASSWORD "Postgres auth-server password"
prompt_secret PLATFORM_KEYCLOAK_DB_PASSWORD "Postgres keycloak password"
prompt_secret PLATFORM_KEYCLOAK_BOOTSTRAP_ADMIN_PASSWORD "Platform Keycloak bootstrap admin password"
prompt_secret AUTH_SERVER_KEYCLOAK_CLIENT_SECRET "Keycloak auth-server client secret"
vault kv put kv/dev/workload/platform/postgres/superuser \
POSTGRES_SUPERUSER_PASSWORD="$PLATFORM_POSTGRES_SUPERUSER_PASSWORD" >/dev/null
vault kv put kv/dev/workload/platform/postgres/auth-server \
APP_DATASOURCE_USERNAME="$AUTH_SERVER_DATASOURCE_USERNAME" \
APP_DATASOURCE_PASSWORD="$AUTH_SERVER_DATASOURCE_PASSWORD" \
AUTH_DB_PASSWORD="$AUTH_SERVER_DATASOURCE_PASSWORD" >/dev/null
vault kv put kv/dev/workload/platform/postgres/keycloak \
KEYCLOAK_DB_PASSWORD="$PLATFORM_KEYCLOAK_DB_PASSWORD" >/dev/null
vault kv put kv/dev/workload/platform/keycloak/bootstrap-admin \
KC_BOOTSTRAP_ADMIN_PASSWORD="$PLATFORM_KEYCLOAK_BOOTSTRAP_ADMIN_PASSWORD" >/dev/null
vault kv put kv/dev/workload/platform/keycloak/client-auth-server \
APP_SECURITY_OAUTH2_KEYCLOAK_CLIENT_SECRET="$AUTH_SERVER_KEYCLOAK_CLIENT_SECRET" \
KEYCLOAK_CLIENT_SECRET="$AUTH_SERVER_KEYCLOAK_CLIENT_SECRET" >/dev/null
echo
echo "Provider Vault workload seed values updated."
+14
View File
@@ -0,0 +1,14 @@
#!/usr/bin/env bash
set -euo pipefail
for cmd in kubectl; do
if ! command -v "$cmd" >/dev/null 2>&1; then
echo "$cmd is required" >&2
exit 1
fi
done
kubectl apply -f argocd/projects/dev
kubectl apply -f argocd/applications/dev/infra/platform.yaml
kubectl apply -f argocd/applications/dev/apps
+16
View File
@@ -0,0 +1,16 @@
#!/usr/bin/env bash
set -euo pipefail
for cmd in kubectl; do
if ! command -v "$cmd" >/dev/null 2>&1; then
echo "$cmd is required" >&2
exit 1
fi
done
kubectl apply -f argocd/projects/dev
kubectl apply -f argocd/applications/dev/infra/sealed-secrets.yaml
kubectl apply -f argocd/applications/dev/infra/vault-transit.yaml
kubectl apply -f argocd/applications/dev/infra/vault.yaml
kubectl apply -f argocd/applications/dev/infra/vault-agent-injector.yaml
+35
View File
@@ -0,0 +1,35 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "${SCRIPT_DIR}/../../.." && pwd)"
source "${SCRIPT_DIR}/provider-lib.sh"
source "${SCRIPT_DIR}/workload-auth-lib.sh"
if ! command -v terraform >/dev/null 2>&1; then
echo "terraform CLI is required" >&2
exit 1
fi
export VAULT_WORKLOAD_ADDR="${VAULT_WORKLOAD_ADDR:-${VAULT_ADDR:-http://127.0.0.1:8200}}"
export VAULT_TRANSIT_ADDR="${VAULT_TRANSIT_ADDR:-http://127.0.0.1:18200}"
export TF_VAR_workload_vault_addr="$VAULT_WORKLOAD_ADDR"
export TF_VAR_workload_vault_token="$(workload_vault_token)"
export TF_VAR_transit_vault_addr="$VAULT_TRANSIT_ADDR"
export TF_VAR_transit_vault_token="$(provider_vault_token)"
mkdir -p "${REPO_ROOT}/.terraform-state"
if [[ -n "${TF_STATE_DIR:-}" ]]; then
mkdir -p "${TF_STATE_DIR}"
terraform -chdir="${REPO_ROOT}/terraform/vault/dev" init \
-input=false \
-reconfigure \
-backend-config="path=${TF_STATE_DIR}/vault-dev.tfstate"
else
terraform -chdir="${REPO_ROOT}/terraform/vault/dev" init -input=false
fi
terraform -chdir="${REPO_ROOT}/terraform/vault/dev" apply -input=false -auto-approve
+37
View File
@@ -0,0 +1,37 @@
#!/usr/bin/env bash
set -euo pipefail
VAULT_ADDR="${VAULT_ADDR:-http://127.0.0.1:8200}"
export VAULT_ADDR
if ! command -v vault >/dev/null 2>&1; then
echo "vault CLI is required" >&2
exit 1
fi
status_json="$(mktemp)"
trap 'rm -f "$status_json"' EXIT
if vault status -format=json >"$status_json" 2>/dev/null; then
:
else
if [[ ! -s "$status_json" ]]; then
echo "Vault is unreachable at ${VAULT_ADDR}" >&2
exit 1
fi
fi
initialized="$(jq -r '.initialized' "$status_json")"
sealed="$(jq -r '.sealed' "$status_json")"
if [[ "$initialized" != "true" ]]; then
echo "Workload Vault is not initialized." >&2
exit 1
fi
if [[ "$sealed" == "true" ]]; then
echo "Workload Vault is still sealed. Check the transit unseal provider and vault-transit-seal secret." >&2
exit 1
fi
+38
View File
@@ -0,0 +1,38 @@
#!/usr/bin/env bash
set -euo pipefail
VAULT_ADDR="${VAULT_ADDR:-http://127.0.0.1:8200}"
VAULT_TOKEN="${VAULT_TOKEN:-}"
TOKEN_TTL="${TOKEN_TTL:-1h}"
if [[ -z "$VAULT_TOKEN" ]]; then
echo "VAULT_TOKEN must be set to a platform-admin-dev token." >&2
exit 1
fi
for cmd in vault; do
if ! command -v "$cmd" >/dev/null 2>&1; then
echo "$cmd is required" >&2
exit 1
fi
done
export VAULT_ADDR
export VAULT_TOKEN
postgres_token="$(
vault token create -orphan -policy=postgres-operator-dev -ttl="$TOKEN_TTL" -field=token
)"
keycloak_token="$(
vault token create -orphan -policy=keycloak-operator-dev -ttl="$TOKEN_TTL" -field=token
)"
echo ""
echo "postgres-operator-dev token:"
echo "$postgres_token"
echo ""
echo "keycloak-operator-dev token:"
echo "$keycloak_token"
echo ""
+67
View File
@@ -0,0 +1,67 @@
#!/usr/bin/env bash
__provider_vault_token_cache="${__provider_vault_token_cache:-}"
provider_vault_addr() {
printf '%s\n' "${VAULT_TRANSIT_ADDR:-http://127.0.0.1:18200}"
}
provider_vault_login_with_approle() {
local role_id="$1"
local secret_id="$2"
if [[ -n "$__provider_vault_token_cache" ]]; then
printf '%s\n' "$__provider_vault_token_cache"
return 0
fi
__provider_vault_token_cache="$(
VAULT_ADDR="$(provider_vault_addr)" \
vault write -field=token auth/approle/login \
role_id="$role_id" \
secret_id="$secret_id"
)"
printf '%s\n' "$__provider_vault_token_cache"
}
provider_vault_token() {
if [[ -n "${VAULT_TRANSIT_DEV_ROLE_ID:-}" && -n "${VAULT_TRANSIT_DEV_SECRET_ID:-}" ]]; then
provider_vault_login_with_approle \
"$VAULT_TRANSIT_DEV_ROLE_ID" \
"$VAULT_TRANSIT_DEV_SECRET_ID"
return 0
fi
if [[ -n "${VAULT_TRANSIT_DEV_BOOTSTRAP_TOKEN:-}" ]]; then
printf '%s\n' "$VAULT_TRANSIT_DEV_BOOTSTRAP_TOKEN"
return 0
fi
if [[ -n "${VAULT_TOKEN:-}" ]]; then
printf '%s\n' "$VAULT_TOKEN"
return 0
fi
echo "VAULT_TRANSIT_DEV_BOOTSTRAP_TOKEN or VAULT_TRANSIT_DEV_ROLE_ID/VAULT_TRANSIT_DEV_SECRET_ID or VAULT_TOKEN must be set." >&2
return 1
}
provider_kv_get_json() {
local path="$1"
VAULT_ADDR="$(provider_vault_addr)" \
VAULT_TOKEN="$(provider_vault_token)" \
vault kv get -format=json "$path"
}
provider_read_workload_bootstrap_token() {
provider_kv_get_json "kv/dev/workload/bootstrap" | jq -r '.data.data.VAULT_WORKLOAD_DEV_BOOTSTRAP_TOKEN // empty'
}
provider_read_workload_role_id() {
provider_kv_get_json "kv/dev/workload/bootstrap" | jq -r '.data.data.VAULT_WORKLOAD_DEV_ROLE_ID // empty'
}
provider_read_workload_secret_id() {
provider_kv_get_json "kv/dev/workload/bootstrap" | jq -r '.data.data.VAULT_WORKLOAD_DEV_SECRET_ID // empty'
}
+61
View File
@@ -0,0 +1,61 @@
#!/usr/bin/env bash
__workload_vault_token_cache="${__workload_vault_token_cache:-}"
workload_vault_login_with_approle() {
local role_id="$1"
local secret_id="$2"
if [[ -n "$__workload_vault_token_cache" ]]; then
printf '%s\n' "$__workload_vault_token_cache"
return 0
fi
__workload_vault_token_cache="$(
VAULT_ADDR="${VAULT_WORKLOAD_ADDR:-${VAULT_ADDR:-http://127.0.0.1:8200}}" \
vault write -field=token auth/approle/login \
role_id="$role_id" \
secret_id="$secret_id"
)"
printf '%s\n' "$__workload_vault_token_cache"
}
workload_vault_token() {
local role_id=""
local secret_id=""
local token=""
if [[ -n "${VAULT_WORKLOAD_DEV_BOOTSTRAP_TOKEN:-}" ]]; then
printf '%s\n' "$VAULT_WORKLOAD_DEV_BOOTSTRAP_TOKEN"
return 0
fi
if [[ -n "${VAULT_WORKLOAD_DEV_ROLE_ID:-}" && -n "${VAULT_WORKLOAD_DEV_SECRET_ID:-}" ]]; then
workload_vault_login_with_approle \
"$VAULT_WORKLOAD_DEV_ROLE_ID" \
"$VAULT_WORKLOAD_DEV_SECRET_ID"
return 0
fi
role_id="$(provider_read_workload_role_id 2>/dev/null || true)"
secret_id="$(provider_read_workload_secret_id 2>/dev/null || true)"
if [[ -n "$role_id" && -n "$secret_id" ]]; then
workload_vault_login_with_approle "$role_id" "$secret_id"
return 0
fi
token="$(provider_read_workload_bootstrap_token 2>/dev/null || true)"
if [[ -n "$token" ]]; then
printf '%s\n' "$token"
return 0
fi
if [[ -n "${VAULT_TOKEN:-}" ]]; then
printf '%s\n' "$VAULT_TOKEN"
return 0
fi
echo "VAULT_WORKLOAD_DEV_ROLE_ID/VAULT_WORKLOAD_DEV_SECRET_ID or VAULT_WORKLOAD_DEV_BOOTSTRAP_TOKEN or VAULT_TOKEN must be set." >&2
return 1
}