diff --git a/ci-operator/step-registry/etcd-encryption/vault-configure/etcd-encryption-vault-configure-commands.sh b/ci-operator/step-registry/etcd-encryption/vault-configure/etcd-encryption-vault-configure-commands.sh index f58471757abc0..e561c9405762b 100644 --- a/ci-operator/step-registry/etcd-encryption/vault-configure/etcd-encryption-vault-configure-commands.sh +++ b/ci-operator/step-registry/etcd-encryption/vault-configure/etcd-encryption-vault-configure-commands.sh @@ -3,52 +3,61 @@ set -o nounset set -o errexit set -o pipefail -echo "=========================================" -echo "Vault Configuration for KMS" -echo "=========================================" -echo "Namespace: ${VAULT_NAMESPACE}" -echo "Vault Enterprise NS: ${VAULT_ENTERPRISE_NS}" -echo "" - export KUBECONFIG="${SHARED_DIR}/kubeconfig" # In dev mode, Vault is already initialized and unsealed with root token "root" ROOT_TOKEN="root" -echo "Configuring Vault for KMS..." -echo "" - -# Create the Vault Enterprise namespace used by the KMS plugin -echo "Creating Vault Enterprise namespace '${VAULT_ENTERPRISE_NS}'..." -oc exec vault-0 -n "${VAULT_NAMESPACE}" -- \ - env VAULT_TOKEN="${ROOT_TOKEN}" vault namespace create "${VAULT_ENTERPRISE_NS}" - -# Enable transit secret engine -echo "Enabling transit secret engine..." -oc exec vault-0 -n "${VAULT_NAMESPACE}" -- \ - env VAULT_TOKEN="${ROOT_TOKEN}" vault secrets enable -namespace="${VAULT_ENTERPRISE_NS}" -path=transit transit - -# Create encryption key -echo "Creating transit encryption key..." -oc exec vault-0 -n "${VAULT_NAMESPACE}" -- \ - env VAULT_TOKEN="${ROOT_TOKEN}" vault write -namespace="${VAULT_ENTERPRISE_NS}" -f transit/keys/${VAULT_KMS_KEY_NAME} - -# Enable AppRole auth -echo "Enabling AppRole authentication..." -oc exec vault-0 -n "${VAULT_NAMESPACE}" -- \ - env VAULT_TOKEN="${ROOT_TOKEN}" vault auth enable -namespace="${VAULT_ENTERPRISE_NS}" approle - -# Create KMS policy -echo "Creating KMS policy..." -oc exec vault-0 -n "${VAULT_NAMESPACE}" -- \ - sh -c "VAULT_TOKEN=${ROOT_TOKEN} vault policy write -namespace=${VAULT_ENTERPRISE_NS} kms-policy - < /dev/null; then - echo "Installing Helm..." - HELM_VERSION="3.14.0" - curl -fsSL "https://get.helm.sh/helm-v${HELM_VERSION}-linux-amd64.tar.gz" -o /tmp/helm.tar.gz - tar -xzf /tmp/helm.tar.gz -C /tmp - mkdir -p /tmp/bin - mv /tmp/linux-amd64/helm /tmp/bin/helm - chmod +x /tmp/bin/helm - export PATH="/tmp/bin:$PATH" - rm -rf /tmp/helm.tar.gz /tmp/linux-amd64 - echo "Helm installed: $(helm version --short)" -else - echo "Helm already installed: $(helm version --short)" -fi - -echo "" - -# Create namespace -echo "Creating namespace ${VAULT_NAMESPACE}..." -oc create namespace "${VAULT_NAMESPACE}" - -# Add restricted SCC for Vault service account -echo "Adding restricted SCC for Vault service account..." -oc adm policy add-scc-to-user restricted -z vault -n "${VAULT_NAMESPACE}" - -# Create Vault license secret from mounted credential -echo "Creating Vault license secret from mounted credential..." -oc create secret generic "${VAULT_LICENSE_SECRET_NAME}" \ - --from-file=license=/var/run/vault/tests-private-account/kms-vault-license \ - -n "${VAULT_NAMESPACE}" - -# Add HashiCorp Helm repository -echo "Adding HashiCorp Helm repository..." -helm repo add hashicorp https://helm.releases.hashicorp.com -helm repo update - -echo "" - -# Install Vault via Helm with dev mode and TLS enabled -echo "Installing Vault Enterprise v${VAULT_VERSION} in dev mode with TLS..." -helm upgrade --install vault hashicorp/vault \ - --namespace "${VAULT_NAMESPACE}" \ - --version "${VAULT_CHART_VERSION}" \ - --set global.enabled=true \ - --set global.openshift=true \ - --set global.tlsDisable=false \ - --set server.dev.enabled=true \ - --set server.image.repository="${VAULT_IMAGE_REPOSITORY}" \ - --set server.image.tag="${VAULT_VERSION}" \ - --set injector.enabled=false \ - --set 'server.extraEnvironmentVars.VAULT_DISABLE_USER_LOCKOUT=true' \ - --set 'server.extraEnvironmentVars.VAULT_CACERT=/var/run/tls/vault-ca.pem' \ - --set "server.enterpriseLicense.secretName=${VAULT_LICENSE_SECRET_NAME}" \ - --set "server.enterpriseLicense.secretKey=license" \ - --set "server.extraArgs=-dev-tls -dev-tls-cert-dir=/var/run/tls -dev-tls-san=vault -dev-tls-san=vault.${VAULT_NAMESPACE}.svc" \ - --set 'server.volumes[0].name=tls' \ - --set-json 'server.volumes[0].emptyDir={}' \ - --set 'server.volumeMounts[0].name=tls' \ - --set 'server.volumeMounts[0].mountPath=/var/run/tls' \ - --wait \ - --timeout 10m - -# Helm wait passes even when vault pod is 0/1 Running, so wait for ready condition -echo "Waiting for Vault pod to be ready..." -oc wait --for=condition=ready pod/vault-0 -n "${VAULT_NAMESPACE}" --timeout=5m - -# Extract CA certificate from Vault pod -echo "" -echo "Extracting CA certificate from Vault pod..." -CA_CERT_TMP="/tmp/vault-ca-${VAULT_NAMESPACE}.pem" -oc exec vault-0 -n "${VAULT_NAMESPACE}" -- cat /var/run/tls/vault-ca.pem > "${CA_CERT_TMP}" -echo " ✓ CA certificate extracted" - -# Create or update ConfigMap with CA certificate in openshift-config -echo "" -echo "Creating ConfigMap vault-ca-bundle in openshift-config..." -oc create configmap vault-ca-bundle \ - --from-file=ca-bundle.crt="${CA_CERT_TMP}" \ - -n openshift-config \ - --dry-run=client -o yaml | oc apply -f - -echo " ✓ ConfigMap vault-ca-bundle created/updated" - -# Clean up temporary CA file -rm -f "${CA_CERT_TMP}" - -echo "" -echo "=========================================" -echo "Vault Enterprise Installation Complete" -echo "=========================================" -echo "" -echo "Summary:" -echo " - Namespace: ${VAULT_NAMESPACE}" -echo " - Version: ${VAULT_VERSION}" -echo " - Service: https://vault.${VAULT_NAMESPACE}.svc:8200" -echo " - Pod: vault-0 (Ready)" -echo " - TLS: Enabled (dev mode with auto-generated certificates)" -echo " - TLS CA: /var/run/tls/vault-ca.pem (inside pod)" -echo " - Enterprise License: Configured" -echo " - CA ConfigMap: vault-ca-bundle (openshift-config namespace)" -echo "" -echo "Next step: Run etcd-encryption-vault-configure to configure Vault for KMS" -echo "" +install_helm() { + if ! command -v helm &> /dev/null; then + echo "Installing Helm..." + HELM_VERSION="3.14.0" + curl -fsSL "https://get.helm.sh/helm-v${HELM_VERSION}-linux-amd64.tar.gz" -o /tmp/helm.tar.gz + tar -xzf /tmp/helm.tar.gz -C /tmp + mkdir -p /tmp/bin + mv /tmp/linux-amd64/helm /tmp/bin/helm + chmod +x /tmp/bin/helm + export PATH="/tmp/bin:$PATH" + rm -rf /tmp/helm.tar.gz /tmp/linux-amd64 + echo "Helm installed: $(helm version --short)" + else + echo "Helm already installed: $(helm version --short)" + fi + + echo "Adding HashiCorp Helm repository..." + helm repo add hashicorp https://helm.releases.hashicorp.com + helm repo update +} + +# Install a Vault Enterprise instance in the given namespace. +# Args: $1 = namespace, $2 = CA ConfigMap name, $3 = Helm release name +install_vault() { + local ns="$1" + local ca_configmap="$2" + local release_name="$3" + local pod_name="${release_name}-0" + + echo "" + echo "=========================================" + echo "Vault Enterprise Installation via Helm" + echo "=========================================" + echo "Version: ${VAULT_VERSION}" + echo "Namespace: ${ns}" + echo "" + + echo "Creating namespace ${ns}..." + oc create namespace "${ns}" + + echo "Adding restricted SCC for Vault service account..." + oc adm policy add-scc-to-user restricted -z vault -n "${ns}" + + echo "Creating Vault license secret from mounted credential..." + oc create secret generic "${VAULT_LICENSE_SECRET_NAME}" \ + --from-file=license=/var/run/vault/tests-private-account/kms-vault-license \ + -n "${ns}" + + echo "" + echo "Installing Vault Enterprise v${VAULT_VERSION} in dev mode with TLS..." + helm upgrade --install "${release_name}" hashicorp/vault \ + --namespace "${ns}" \ + --version "${VAULT_CHART_VERSION}" \ + --set global.enabled=true \ + --set global.openshift=true \ + --set global.tlsDisable=false \ + --set server.dev.enabled=true \ + --set server.image.repository="${VAULT_IMAGE_REPOSITORY}" \ + --set server.image.tag="${VAULT_VERSION}" \ + --set injector.enabled=false \ + --set 'server.extraEnvironmentVars.VAULT_DISABLE_USER_LOCKOUT=true' \ + --set 'server.extraEnvironmentVars.VAULT_CACERT=/var/run/tls/vault-ca.pem' \ + --set "server.enterpriseLicense.secretName=${VAULT_LICENSE_SECRET_NAME}" \ + --set "server.enterpriseLicense.secretKey=license" \ + --set "server.extraArgs=-dev-tls -dev-tls-cert-dir=/var/run/tls -dev-tls-san=vault -dev-tls-san=vault.${ns}.svc" \ + --set 'server.volumes[0].name=tls' \ + --set-json 'server.volumes[0].emptyDir={}' \ + --set 'server.volumeMounts[0].name=tls' \ + --set 'server.volumeMounts[0].mountPath=/var/run/tls' \ + --wait \ + --timeout 10m + + # Helm wait passes even when vault pod is 0/1 Running, so wait for ready condition + echo "Waiting for Vault pod to be ready..." + oc wait --for=condition=ready "pod/${pod_name}" -n "${ns}" --timeout=5m + + # Extract CA certificate from Vault pod + echo "" + echo "Extracting CA certificate from Vault pod..." + local ca_cert_tmp="/tmp/vault-ca-${ns}.pem" + oc exec "${pod_name}" -n "${ns}" -- cat /var/run/tls/vault-ca.pem > "${ca_cert_tmp}" + echo " ✓ CA certificate extracted" + + # Create or update ConfigMap with CA certificate in openshift-config + echo "" + echo "Creating ConfigMap ${ca_configmap} in openshift-config..." + oc create configmap "${ca_configmap}" \ + --from-file=ca-bundle.crt="${ca_cert_tmp}" \ + -n openshift-config \ + --dry-run=client -o yaml | oc apply -f - + echo " ✓ ConfigMap ${ca_configmap} created/updated" + + # Clean up temporary CA file + rm -f "${ca_cert_tmp}" + + echo "" + echo "=========================================" + echo "Vault Enterprise Installation Complete" + echo "=========================================" + echo "" + echo "Summary:" + echo " - Namespace: ${ns}" + echo " - Version: ${VAULT_VERSION}" + echo " - Service: https://vault.${ns}.svc:8200" + echo " - Pod: vault-0 (Ready)" + echo " - TLS: Enabled (dev mode with auto-generated certificates)" + echo " - TLS CA: /var/run/tls/vault-ca.pem (inside pod)" + echo " - Enterprise License: Configured" + echo " - CA ConfigMap: ${ca_configmap} (openshift-config namespace)" + echo "" + echo "Next step: Run etcd-encryption-vault-configure to configure Vault for KMS" + echo "" +} + +install_helm + +install_vault "${VAULT_NAMESPACE}" "vault-ca-bundle" "vault" +install_vault "${VAULT_SECONDARY_NAMESPACE}" "vault-ca-bundle-2" "vault-2" diff --git a/ci-operator/step-registry/etcd-encryption/vault-install/etcd-encryption-vault-install-ref.yaml b/ci-operator/step-registry/etcd-encryption/vault-install/etcd-encryption-vault-install-ref.yaml index f7c32d70bed1d..957a25445a56f 100644 --- a/ci-operator/step-registry/etcd-encryption/vault-install/etcd-encryption-vault-install-ref.yaml +++ b/ci-operator/step-registry/etcd-encryption/vault-install/etcd-encryption-vault-install-ref.yaml @@ -31,6 +31,12 @@ ref: Container image repository for Vault Enterprise. Mirrored from docker.io/hashicorp/vault-enterprise (docker.io is blocked in CI due to rate limiting and CI is not accessible in disconnected environments.) + - name: VAULT_SECONDARY_NAMESPACE + default: "vault-kms-2" + documentation: |- + Namespace for a second Vault Enterprise instance. + A second Vault instance is installed in this namespace + with a separate CA ConfigMap (vault-ca-bundle-2 in openshift-config). documentation: |- Installs HashiCorp Vault Enterprise via Helm. @@ -41,6 +47,7 @@ ref: - Creates vault-license secret from mounted credential (if available) - Installs Vault Enterprise using Helm chart - Waits for Vault pod to be ready + - Installs a second instance in VAULT_SECONDARY_NAMESPACE Prerequisites: - OpenShift cluster with adequate resources @@ -50,6 +57,9 @@ ref: Outputs: - Vault service available at: vault.${VAULT_NAMESPACE}.svc:8200 - Vault pod: vault-0 (Ready state) + - CA ConfigMap: vault-ca-bundle (openshift-config namespace) + - Second Vault service at: vault.${VAULT_SECONDARY_NAMESPACE}.svc:8200 + - CA ConfigMap: vault-ca-bundle-2 (openshift-config namespace) Next step: - Run etcd-encryption-vault-configure to initialize and configure Vault for KMS diff --git a/ci-operator/step-registry/etcd-encryption/vault-setup/etcd-encryption-vault-setup-chain.yaml b/ci-operator/step-registry/etcd-encryption/vault-setup/etcd-encryption-vault-setup-chain.yaml index 2b4cd484b174e..64937d2b6fafe 100644 --- a/ci-operator/step-registry/etcd-encryption/vault-setup/etcd-encryption-vault-setup-chain.yaml +++ b/ci-operator/step-registry/etcd-encryption/vault-setup/etcd-encryption-vault-setup-chain.yaml @@ -10,35 +10,41 @@ chain: reusable component that can be used across different platform workflows. What this chain does: - 1. Installs HashiCorp Vault Enterprise via Helm (vault-install step) - - Deploys Vault in dev mode to vault-kms namespace + 1. Installs two HashiCorp Vault Enterprise instances via Helm (vault-install step) + - Deploys Vault in dev mode to vault-kms and vault-kms-2 namespaces - Creates vault-license secret from mounted credentials - - Waits for Vault pod to be ready + - Waits for Vault pods to be ready + - Creates CA ConfigMaps (vault-ca-bundle and vault-ca-bundle-2) in openshift-config - 2. Configures Vault for KMS encryption (vault-configure step) + 2. Configures both Vault instances for KMS encryption (vault-configure step) - Creates Vault Enterprise namespace (default: admin) - Enables transit secret engine in the Enterprise namespace - Creates KMS encryption key in the Enterprise namespace - Configures AppRole authentication in the Enterprise namespace - - Stores credentials in vault-credentials secret + - Stores credentials in vault-credentials secret in each namespace Prerequisites: - OpenShift cluster with adequate resources - Vault Enterprise license secret named 'tests-private-account' in test-credentials namespace containing the license file at key 'kms-vault-license' - Outputs: + Outputs (primary instance): - Vault service: vault.vault-kms.svc:8200 - - Vault pod: vault-0 (Ready state) + - Vault pod: vault-0 (Ready state) in vault-kms namespace + - CA ConfigMap: vault-ca-bundle in openshift-config namespace - Credentials secret: vault-credentials in vault-kms namespace - * role-id: AppRole role ID for KMS plugin - * secret-id: AppRole secret ID for KMS plugin - * root-token: Vault root token (dev mode) + + Outputs (secondary instance): + - Vault service: vault.vault-kms-2.svc:8200 + - Vault pod: vault-0 (Ready state) in vault-kms-2 namespace + - CA ConfigMap: vault-ca-bundle-2 in openshift-config namespace + - Credentials secret: vault-credentials in vault-kms-2 namespace Environment variables (inherited from vault-install step): - VAULT_VERSION: Vault Enterprise version (default: 2.0.0-ent) - VAULT_CHART_VERSION: Helm chart version (default: 0.28.1) - - VAULT_NAMESPACE: Vault namespace (default: vault-kms) + - VAULT_NAMESPACE: Primary Vault namespace (default: vault-kms) + - VAULT_SECONDARY_NAMESPACE: Secondary Vault namespace (default: vault-kms-2) - VAULT_IMAGE_REPOSITORY: Container image repo (default: quay.io/openshifttest/vault-enterprise) Environment variables (inherited from vault-configure step):