diff --git a/charts/simplyblock-operator/crds/storage.simplyblock.io_storageclusters.yaml b/charts/simplyblock-operator/crds/storage.simplyblock.io_storageclusters.yaml index 9ca512f..b1db97a 100644 --- a/charts/simplyblock-operator/crds/storage.simplyblock.io_storageclusters.yaml +++ b/charts/simplyblock-operator/crds/storage.simplyblock.io_storageclusters.yaml @@ -129,6 +129,14 @@ spec: haType: description: HAType defines the backend high-availability mode. type: string + hashicorpVaultSettings: + description: HashicorpVaultSettings configures the Vault endpoint + used by the cluster for key storage. + properties: + baseURL: + description: BaseURL is the HashiCorp Vault endpoint (e.g. https://vault.example.com:8200). + type: string + type: object inflightIOThreshold: description: InflightIOThreshold defines the inflight I/O threshold. format: int32 diff --git a/charts/simplyblock-operator/templates/controlplane_svc.yaml b/charts/simplyblock-operator/templates/controlplane_svc.yaml index a8f7b21..96df969 100644 --- a/charts/simplyblock-operator/templates/controlplane_svc.yaml +++ b/charts/simplyblock-operator/templates/controlplane_svc.yaml @@ -24,6 +24,7 @@ metadata: name: simplyblock-webappapi namespace: {{ .Release.Namespace }} spec: + commonName: simplyblock-webappapi secretName: simplyblock-webappapi-tls issuerRef: kind: ClusterIssuer diff --git a/scripts/openbao-values.yaml b/scripts/openbao-values.yaml new file mode 100644 index 0000000..004754a --- /dev/null +++ b/scripts/openbao-values.yaml @@ -0,0 +1,66 @@ +global: + openshift: true + tlsDisable: false + +server: + dataStorage: + storageClass: ssd-csi + + extraEnvironmentVars: + BAO_CACERT: /openbao/tls/ca.crt + + volumes: + - name: tls-cert + secret: + secretName: openbao-server-tls + + volumeMounts: + - name: tls-cert + mountPath: /openbao/tls + readOnly: true + + standalone: + enabled: true + config: | + ui = true + + listener "tcp" { + tls_disable = 0 + address = "[::]:8200" + cluster_address = "[::]:8201" + tls_cert_file = "/openbao/tls/tls.crt" + tls_key_file = "/openbao/tls/tls.key" + tls_min_version = "tls12" + } + + storage "file" { + path = "/openbao/data" + } + +injector: + enabled: false + +extraObjects: + - apiVersion: cert-manager.io/v1 + kind: Certificate + metadata: + name: openbao-server-tls + spec: + secretName: openbao-server-tls + duration: 8760h + renewBefore: 720h + privateKey: + algorithm: ECDSA + size: 256 + dnsNames: + - openbao + - openbao.{{ .Release.Namespace }} + - openbao.{{ .Release.Namespace }}.svc + - openbao.{{ .Release.Namespace }}.svc.cluster.local + - openbao-internal + - openbao-internal.{{ .Release.Namespace }} + - openbao-internal.{{ .Release.Namespace }}.svc + - openbao-internal.{{ .Release.Namespace }}.svc.cluster.local + issuerRef: + name: simplyblock-certificate-authority-issuer + kind: ClusterIssuer diff --git a/scripts/setup-kms.sh b/scripts/setup-kms.sh new file mode 100755 index 0000000..e9fd5b8 --- /dev/null +++ b/scripts/setup-kms.sh @@ -0,0 +1,131 @@ +#!/usr/bin/env bash +# Installs, initializes, unseals, and configures OpenBao for Simplyblock KMS. +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +NAMESPACE="${NAMESPACE:-vault}" +STORAGE_CLASS="${STORAGE_CLASS:-local-path}" +UNSEAL_KEYS_FILE="${UNSEAL_KEYS_FILE:-}" +ROOT_TOKEN="${BAO_TOKEN:-}" + +POD="openbao-0" +BAO_ADDR="https://openbao.vault:8200/" + +info() { echo "[INFO] $*"; } +warn() { echo "[WARN] $*" >&2; } +die() { echo "[ERROR] $*" >&2; exit 1; } + +bao() { + kubectl -n "$NAMESPACE" exec -i "$POD" -- \ + env BAO_ADDR="$BAO_ADDR" BAO_TOKEN="$ROOT_TOKEN" bao "$@" +} + +if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then + cat </dev/null || die "kubectl not found" +command -v helm &>/dev/null || die "helm not found" + +# ── Install ──────────────────────────────────────────────────────────────────── +info "Installing OpenBao..." +helm repo add openbao https://openbao.github.io/openbao-helm +helm repo update +helm upgrade --install openbao openbao/openbao \ + -n "$NAMESPACE" --create-namespace \ + -f "$SCRIPT_DIR/openbao-values.yaml" \ + --set server.dataStorage.storageClass="$STORAGE_CLASS" + +info "Waiting for $POD to be running..." +kubectl -n "$NAMESPACE" wait pod/"$POD" \ + --for=jsonpath='{.status.phase}'=Running --timeout=120s + +# ── Init + unseal ────────────────────────────────────────────────────────────── +if [[ -z "$ROOT_TOKEN" ]]; then + info "Initializing OpenBao..." + INIT_OUTPUT="$(kubectl -n "$NAMESPACE" exec "$POD" -- \ + env BAO_ADDR="$BAO_ADDR" bao operator init 2>&1)" + + echo "" + echo "==========================================" + echo " INIT OUTPUT — SAVE THIS NOW" + echo "==========================================" + echo "$INIT_OUTPUT" + echo "==========================================" + echo "" + + if [[ -n "$UNSEAL_KEYS_FILE" ]]; then + echo "$INIT_OUTPUT" > "$UNSEAL_KEYS_FILE" + chmod 600 "$UNSEAL_KEYS_FILE" + info "Saved to: $UNSEAL_KEYS_FILE" + fi + + mapfile -t UNSEAL_KEYS < <(echo "$INIT_OUTPUT" | grep -E '^Unseal Key [0-9]+:' | awk '{print $NF}') + ROOT_TOKEN="$(echo "$INIT_OUTPUT" | grep '^Initial Root Token:' | awk '{print $NF}')" + + [[ ${#UNSEAL_KEYS[@]} -ge 3 ]] || die "Could not parse unseal keys" + [[ -n "$ROOT_TOKEN" ]] || die "Could not parse root token" + + info "Unsealing (3 of 5 keys)..." + for i in 0 1 2; do + kubectl -n "$NAMESPACE" exec "$POD" -- \ + env BAO_ADDR="$BAO_ADDR" bao operator unseal "${UNSEAL_KEYS[$i]}" + done + + info "Waiting for $POD to be ready..." + kubectl -n "$NAMESPACE" wait pod/"$POD" --for=condition=Ready --timeout=60s +else + info "Skipping init/unseal — using provided BAO_TOKEN" +fi + +# ── Configure ────────────────────────────────────────────────────────────────── +info "Writing webappapi-policy..." +bao policy write webappapi-policy - <<'EOF' +path "transit/keys/*" { + capabilities = ["create", "update", "read", "delete"] +} +path "transit/datakey/plaintext/*" { + capabilities = ["create", "update"] +} +path "transit/datakey/wrapped/*" { + capabilities = ["create", "update"] +} +path "transit/encrypt/*" { + capabilities = ["create", "update"] +} +path "transit/decrypt/*" { + capabilities = ["create", "update"] +} +path "kv/*" { + capabilities = ["create", "read", "update", "delete"] +} +EOF + +info "Enabling cert auth..." +bao auth enable cert || warn "cert auth already enabled, continuing..." +bao write auth/cert/certs/webappapi \ + certificate=@/openbao/tls/ca.crt \ + allowed_dns_sans="simplyblock-webappapi" \ + token_policies=webappapi-policy \ + token_ttl=10m \ + token_max_ttl=30m + +info "Enabling secrets engines..." +bao secrets enable transit || warn "transit already enabled, continuing..." +bao secrets enable -version=1 kv || warn "kv already enabled, continuing..." + +# ── Done ─────────────────────────────────────────────────────────────────────── +info "Done." +if [[ -z "${BAO_TOKEN:-}" ]]; then + info "Root token: $ROOT_TOKEN (store it securely)" +fi