init: 아르고cd, vault 기반 인프라 설계
This commit is contained in:
@@ -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 "$@"
|
||||
@@ -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
@@ -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
|
||||
Executable
+41
@@ -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
@@ -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."
|
||||
Executable
+14
@@ -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
|
||||
Executable
+16
@@ -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
|
||||
Executable
+35
@@ -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
|
||||
Executable
+37
@@ -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
|
||||
Executable
+38
@@ -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 ""
|
||||
@@ -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'
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user