From 8638f906cf95ec0667493d1c041fdef59f805f4d Mon Sep 17 00:00:00 2001 From: Astra Logical Date: Tue, 7 Apr 2026 13:14:18 -0400 Subject: [PATCH] Stand up vault --- .../vault/keykeeper/keykeeper-deployment.yaml | 8 +-- .../vault/keykeeper/keykeeper-service.yaml | 4 +- services/vault/vault-configmap.yaml | 15 ++++-- services/vault/vault-namespace.yaml | 24 +++++++++ services/vault/vault-statefulset.yaml | 54 +++++++++++++++++-- 5 files changed, 91 insertions(+), 14 deletions(-) diff --git a/services/vault/keykeeper/keykeeper-deployment.yaml b/services/vault/keykeeper/keykeeper-deployment.yaml index 41e0fef..d2d0c28 100644 --- a/services/vault/keykeeper/keykeeper-deployment.yaml +++ b/services/vault/keykeeper/keykeeper-deployment.yaml @@ -13,6 +13,7 @@ spec: labels: app: vault-keykeeper spec: + serviceAccountName: vault # Allows k8s auth for autounsealing nodeSelector: app: keykeeper # Should be Robin/some non-server node with a /keykeeper local dir containers: @@ -22,6 +23,7 @@ spec: env: - name: VAULT_LOCAL_CONFIG value: | + ui = true storage "file" { path = "/vault/file" } @@ -31,13 +33,11 @@ spec: } disable_mlock = true - name: VAULT_API_ADDR - value: "http://$(HOSTNAME).vault-internal:8200" + value: "http://vault-keykeeper.vault.svc.cluster.local:8200" - name: SKIP_SETCAP value: "true" - name: VAULT_ADDR value: "http://127.0.0.1:8200" - - name: VAULT_CLUSTER_ADDR - value: "http://$(HOSTNAME).vault-internal:8201" - name: VAULT_K8S_NAMESPACE valueFrom: fieldRef: @@ -48,7 +48,7 @@ spec: fieldPath: metadata.name ports: - containerPort: 8200 - name: vault-ui + name: web-ui volumeMounts: - name: vault-data mountPath: /vault/file diff --git a/services/vault/keykeeper/keykeeper-service.yaml b/services/vault/keykeeper/keykeeper-service.yaml index ccfc102..9b6924d 100644 --- a/services/vault/keykeeper/keykeeper-service.yaml +++ b/services/vault/keykeeper/keykeeper-service.yaml @@ -7,7 +7,7 @@ spec: type: ClusterIP ports: - name: http-web - port: 8200 - targetPort: vault-ui + port: 80 + targetPort: web-ui selector: app: vault-keykeeper diff --git a/services/vault/vault-configmap.yaml b/services/vault/vault-configmap.yaml index de660fc..0147de4 100644 --- a/services/vault/vault-configmap.yaml +++ b/services/vault/vault-configmap.yaml @@ -17,14 +17,23 @@ data: storage "raft" { path = "/vault/data" retry_join { - leader_api_addr = "http://vault-0.vault-internal:8200" + leader_api_addr = "http://vault-0.vault-internal.vault.svc.cluster.local:8200" } retry_join { - leader_api_addr = "http://vault-1.vault-internal:8200" + leader_api_addr = "http://vault-1.vault-internal.vault.svc.cluster.local:8200" } retry_join { - leader_api_addr = "http://vault-2.vault-internal:8200" + leader_api_addr = "http://vault-2.vault-internal.vault.svc.cluster.local:8200" } } service_registration "kubernetes" {} + + seal "transit" { + # Use the internal K8s service name for the Keykeeper + address = "http://vault-keykeeper.vault.svc.cluster.local:80" + disable_renewal = false + key_name = "nest-unseal-key" + mount_path = "transit/" + token = "REPLACE_WITH_TOKEN" + } diff --git a/services/vault/vault-namespace.yaml b/services/vault/vault-namespace.yaml index 9d5750e..9f39287 100644 --- a/services/vault/vault-namespace.yaml +++ b/services/vault/vault-namespace.yaml @@ -21,3 +21,27 @@ subjects: - kind: ServiceAccount name: vault namespace: vault +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: vault-service-registration + namespace: vault +rules: +- apiGroups: [""] + resources: ["pods"] + verbs: ["get", "update", "patch"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: vault-service-registration-binding + namespace: vault +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: vault-service-registration +subjects: +- kind: ServiceAccount + name: vault + namespace: vault diff --git a/services/vault/vault-statefulset.yaml b/services/vault/vault-statefulset.yaml index 2bc76ee..93825f4 100644 --- a/services/vault/vault-statefulset.yaml +++ b/services/vault/vault-statefulset.yaml @@ -14,7 +14,7 @@ spec: labels: app.kubernetes.io/name: vault spec: - serviceAccountName: vault + serviceAccountName: vault # Allows k8s auth for autounsealing terminationGracePeriodSeconds: 10 # Force pods onto different physical server nodes affinity: @@ -40,21 +40,46 @@ spec: securityContext: runAsUser: 0 privileged: true + + - name: fetch-transit-token + image: hashicorp/vault:latest + command: ["sh", "-c"] + args: + - | + K8S_TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token) + TRANSIT_TOKEN=$(vault write -field=token auth/kubernetes/login \ + role=vault-unsealer \ + jwt=$K8S_TOKEN \ + address=http://vault-keykeeper.vault.svc.cluster.local:80) + + sed "s/REPLACE_WITH_TOKEN/$TRANSIT_TOKEN/" /etc/vault/extraconfig-from-values.hcl > /vault/runtime/vault.hcl + env: + - name: VAULT_ADDR + value: "http://vault-keykeeper.vault.svc.cluster.local:80" + volumeMounts: + - name: config + mountPath: /etc/vault + - name: config-runtime + mountPath: /vault/runtime containers: - name: vault image: hashicorp/vault:latest - args: ["server", "-config=/etc/vault/extraconfig-from-values.hcl"] + args: ["server", "-config=/vault/runtime/vault.hcl"] securityContext: allowPrivilegeEscalation: false env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name - name: VAULT_API_ADDR - value: "http://$(HOSTNAME).vault-internal:8200" + value: "http://$(POD_NAME).vault-internal.vault.svc.cluster.local:8200" + - name: VAULT_CLUSTER_ADDR + value: "https://$(POD_NAME).vault-internal.vault.svc.cluster.local:8201" - name: SKIP_SETCAP value: "true" - name: VAULT_ADDR value: "http://127.0.0.1:8200" - - name: VAULT_CLUSTER_ADDR - value: "http://$(HOSTNAME).vault-internal:8201" - name: VAULT_K8S_NAMESPACE valueFrom: fieldRef: @@ -73,10 +98,29 @@ spec: mountPath: /etc/vault - name: data mountPath: /vault/data + - name: config-runtime + mountPath: /vault/runtime + livenessProbe: + httpGet: + path: /v1/sys/health?standbyok=true&sealedok=true + port: 8200 + scheme: HTTP + initialDelaySeconds: 30 + periodSeconds: 10 + failureThreshold: 3 + timeoutSeconds: 5 + readinessProbe: + httpGet: + path: /v1/sys/health?standbyok=true + port: 8200 + initialDelaySeconds: 10 + periodSeconds: 5 volumes: - name: config configMap: name: vault-config + - name: config-runtime + emptyDir: {} volumeClaimTemplates: - metadata: name: data