set fallback := true

export K8S_VAULT_NAMESPACE := env("K8S_VAULT_NAMESPACE", "vault")
export VAULT_CHART_VERSION := env("VAULT_CHART_VERSION", "0.31.0")
export VAULT_HOST := env("VAULT_HOST", "")
export VAULT_ADDR := "https://" + VAULT_HOST
export VAULT_DEBUG := env("VAULT_DEBUG", "false")
SECRET_PATH := "secret"


[private]
default:
    @just --list --unsorted --list-submodules

# Add Helm repository
add-helm-repo:
    helm repo add hashicorp https://helm.releases.hashicorp.com
    helm repo update

# Remove Helm repository
remove-helm-repo:
    helm repo remove hashicorp


# Create Vault namespace
create-namespace:
    @kubectl get namespace ${K8S_VAULT_NAMESPACE} > /dev/null || kubectl create namespace ${K8S_VAULT_NAMESPACE}

# Delete Vault namespace
delete-namespace:
    @kubectl delete namespace ${K8S_VAULT_NAMESPACE} --ignore-not-found

install:
    #!/bin/bash
    set -eu
    just create-namespace
    just add-helm-repo
 
    gomplate -f vault-values.gomplate.yaml -o vault-values.yaml

    helm upgrade \
      --cleanup-on-fail \
      --install \
      vault \
      hashicorp/vault \
      --namespace ${K8S_VAULT_NAMESPACE} \
      --wait \
      -f vault-values.yaml

    kubectl wait pod --for=condition=PodReadyToStartContainers \
        -n ${K8S_VAULT_NAMESPACE} vault-0 --timeout=5m

    # Wait for Vault service to be ready to accept connections
    echo "Waiting for Vault service to be ready..."
    for i in {1..30}; do
        if kubectl exec -n ${K8S_VAULT_NAMESPACE} vault-0 -- \
            vault status 2>&1 | grep -qE "(Initialized|Sealed)"; then
            echo "✓ Vault service is ready"
            break
        fi
        if [ $i -eq 30 ]; then
            echo "Error: Timeout waiting for Vault service to be ready"
            exit 1
        fi
        sleep 3
    done

    init_output=$(kubectl exec -n ${K8S_VAULT_NAMESPACE} vault-0 -- \
        vault operator init -key-shares=1 -key-threshold=1 -format=json || true)

    root_token=""
    if echo "${init_output}" | grep -q "Vault is already initialized"; then
        echo "Vault is already initialized"
        while [ -z "${root_token}" ]; do
            root_token=$(gum input --prompt="Vault root token: " --password --width=100)
        done
    else
        unseal_key=$(echo "${init_output}" | jq -r '.unseal_keys_b64[0]')
        root_token=$(echo "${init_output}" | jq -r '.root_token')
        kubectl exec -n ${K8S_VAULT_NAMESPACE} vault-0 -- \
            vault operator unseal "${unseal_key}"
        echo "Vault initialized and unsealed successfully"
        echo "Root Token: ${root_token}"
        echo "Unseal Key: ${unseal_key}"
        echo "Please save these credentials securely!"
    fi

    # Wait for all vault instances to pass readiness checks and be ready to serve requests
    kubectl wait pod --for=condition=ready -n ${K8S_VAULT_NAMESPACE} \
        -l app.kubernetes.io/name=vault --timeout=5m

    just setup-kubernetes-auth "${root_token}"


# Uninstall Vault
uninstall delete-ns='false':
    #!/bin/bash
    set -euo pipefail
    helm uninstall vault -n ${K8S_VAULT_NAMESPACE} --ignore-not-found --wait
    just delete-namespace


# Setup Kubernetes authentication
setup-kubernetes-auth root_token='':
    #!/bin/bash
    set -euo pipefail
    export VAULT_TOKEN="{{ root_token }}"
    while [ -z "${VAULT_TOKEN}" ]; do
        VAULT_TOKEN=$(gum input --prompt="Vault root token: " --password --width=100)
    done

    gomplate -f ./serviceaccount.gomplate.yaml | kubectl apply -n "${K8S_VAULT_NAMESPACE}" -f -
    gomplate -f ./rolebinding.gomplate.yaml | kubectl apply -n "${K8S_VAULT_NAMESPACE}" -f -
    kubectl apply -n "${K8S_VAULT_NAMESPACE}" -f ./auth-token-secret.yaml

    SA_SECRET="vault-auth-token"
    SA_JWT=$(kubectl get secret -n ${K8S_VAULT_NAMESPACE} ${SA_SECRET} -o jsonpath='{.data.token}' | base64 --decode)
    SA_CA=$(kubectl get secret -n ${K8S_VAULT_NAMESPACE} ${SA_SECRET} -o jsonpath='{.data.ca\.crt}' | base64 --decode)

    vault auth list -format=json | jq -e '.["kubernetes/"]' >/dev/null 2>&1 || \
        vault auth enable kubernetes
    
    vault write auth/kubernetes/config \
        token_reviewer_jwt="${SA_JWT}" \
        kubernetes_host="https://kubernetes.default.svc" \
        kubernetes_ca_cert="${SA_CA}"
