From 2d99077aa9c98aee7394e5d08882b3cac851563c Mon Sep 17 00:00:00 2001 From: dvirlabs Date: Mon, 11 Aug 2025 03:23:14 +0300 Subject: [PATCH] Auth vault with kubernetes --- .../cluster-secret-store/vault-cicd.yaml | 14 +-- .../vault-general-secrets.yaml | 14 +-- .../vault-internal-users.yaml | 14 +-- .../vault-oidc-secrets.yaml | 14 +-- manifests/vault/bootstrap-config.yaml | 24 +++++ manifests/vault/policy-cm.yaml | 28 ++++++ manifests/vault/rbac-tokenreview.yaml | 29 ++++++ manifests/vault/vault-bootstrap.job.yaml | 88 +++++++++++++++++++ 8 files changed, 201 insertions(+), 24 deletions(-) create mode 100644 manifests/vault/bootstrap-config.yaml create mode 100644 manifests/vault/policy-cm.yaml create mode 100644 manifests/vault/rbac-tokenreview.yaml create mode 100644 manifests/vault/vault-bootstrap.job.yaml diff --git a/manifests/cluster-secret-store/vault-cicd.yaml b/manifests/cluster-secret-store/vault-cicd.yaml index 08ded04..9f4e58e 100644 --- a/manifests/cluster-secret-store/vault-cicd.yaml +++ b/manifests/cluster-secret-store/vault-cicd.yaml @@ -5,11 +5,13 @@ metadata: spec: provider: vault: - auth: - tokenSecretRef: - key: token - name: vault-eso-token - namespace: dev-tools - path: cicd server: http://vault.dev-tools.svc.cluster.local:8200 + path: cicd version: v2 + auth: + kubernetes: + mountPath: kubernetes # חייב להתאים ל-bootstrap (auth/kubernetes) + role: eso-cicd # כפי שהגדרנו ב-bootstrap-config.yaml + serviceAccountRef: + name: external-secrets # ה-SA של ה-ESO + namespace: dev-tools diff --git a/manifests/cluster-secret-store/vault-general-secrets.yaml b/manifests/cluster-secret-store/vault-general-secrets.yaml index b461bc5..894c20d 100644 --- a/manifests/cluster-secret-store/vault-general-secrets.yaml +++ b/manifests/cluster-secret-store/vault-general-secrets.yaml @@ -5,11 +5,13 @@ metadata: spec: provider: vault: - auth: - tokenSecretRef: - key: token - name: vault-eso-token - namespace: dev-tools - path: general-secrets server: http://vault.dev-tools.svc.cluster.local:8200 + path: general-secrets version: v2 + auth: + kubernetes: + mountPath: kubernetes + role: eso-general + serviceAccountRef: + name: external-secrets + namespace: dev-tools diff --git a/manifests/cluster-secret-store/vault-internal-users.yaml b/manifests/cluster-secret-store/vault-internal-users.yaml index a08b1d3..8e56ca0 100644 --- a/manifests/cluster-secret-store/vault-internal-users.yaml +++ b/manifests/cluster-secret-store/vault-internal-users.yaml @@ -5,11 +5,13 @@ metadata: spec: provider: vault: - auth: - tokenSecretRef: - key: token - name: vault-eso-token - namespace: dev-tools - path: internal-users server: http://vault.dev-tools.svc.cluster.local:8200 + path: internal-users version: v2 + auth: + kubernetes: + mountPath: kubernetes + role: eso-internal-users + serviceAccountRef: + name: external-secrets + namespace: dev-tools diff --git a/manifests/cluster-secret-store/vault-oidc-secrets.yaml b/manifests/cluster-secret-store/vault-oidc-secrets.yaml index d8f3d24..6f997d2 100644 --- a/manifests/cluster-secret-store/vault-oidc-secrets.yaml +++ b/manifests/cluster-secret-store/vault-oidc-secrets.yaml @@ -5,11 +5,13 @@ metadata: spec: provider: vault: - auth: - tokenSecretRef: - key: token - name: vault-eso-token - namespace: dev-tools - path: oidc-secrets server: http://vault.dev-tools.svc.cluster.local:8200 + path: oidc-secrets version: v2 + auth: + kubernetes: + mountPath: kubernetes + role: eso-oidc + serviceAccountRef: + name: external-secrets + namespace: dev-tools diff --git a/manifests/vault/bootstrap-config.yaml b/manifests/vault/bootstrap-config.yaml new file mode 100644 index 0000000..33f7355 --- /dev/null +++ b/manifests/vault/bootstrap-config.yaml @@ -0,0 +1,24 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: vault-bootstrap-config + namespace: dev-tools + annotations: + argocd.argoproj.io/sync-wave: "0" +data: + # mounts: שורה לכל mount בפורמט : + # כאן כולם KV v2 + mounts: | + general-secrets:kv2 + cicd:kv2 + internal-users:kv2 + oidc-secrets:kv2 + + # roles: שורה לכל רול בפורמט + # roleName:serviceAccount:namespace:comma-separated-policies:ttl + # שים לב: אנחנו משתמשים ב-policy הבסיסי client-self + ה-policy הספציפי לכל mount + roles: | + eso-general:external-secrets:dev-tools:client-self,eso-read-general:24h + eso-cicd:external-secrets:dev-tools:client-self,eso-read-cicd:24h + eso-internal-users:external-secrets:dev-tools:client-self,eso-read-internal-users:24h + eso-oidc:external-secrets:dev-tools:client-self,eso-read-oidc:24h diff --git a/manifests/vault/policy-cm.yaml b/manifests/vault/policy-cm.yaml new file mode 100644 index 0000000..deb49dd --- /dev/null +++ b/manifests/vault/policy-cm.yaml @@ -0,0 +1,28 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: vault-policies + namespace: dev-tools + annotations: + argocd.argoproj.io/sync-wave: "0" +data: + client-self.hcl: | + path "auth/token/lookup-self" { capabilities = ["read"] } + path "auth/token/renew-self" { capabilities = ["update"] } + + eso-read-general.hcl: | + path "general-secrets/data/*" { capabilities = ["read"] } + path "general-secrets/metadata/*" { capabilities = ["list"] } + + eso-read-cicd.hcl: | + path "cicd/data/*" { capabilities = ["read"] } + path "cicd/metadata/*" { capabilities = ["list"] } + + eso-read-internal-users.hcl: | + path "internal-users/data/*" { capabilities = ["read"] } + path "internal-users/metadata/*" { capabilities = ["list"] } + + eso-read-oidc.hcl: | + path "oidc-secrets/data/*" { capabilities = ["read"] } + path "oidc-secrets/metadata/*" { capabilities = ["list"] } + diff --git a/manifests/vault/rbac-tokenreview.yaml b/manifests/vault/rbac-tokenreview.yaml new file mode 100644 index 0000000..b47cb1a --- /dev/null +++ b/manifests/vault/rbac-tokenreview.yaml @@ -0,0 +1,29 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: vault-auth + namespace: dev-tools + annotations: + argocd.argoproj.io/sync-wave: "0" +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: vault-tokenreviewer +rules: +- apiGroups: ["authentication.k8s.io"] + resources: ["tokenreviews"] + verbs: ["create"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: vault-auth-tokenreviewer +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: vault-tokenreviewer +subjects: +- kind: ServiceAccount + name: vault-auth + namespace: dev-tools diff --git a/manifests/vault/vault-bootstrap.job.yaml b/manifests/vault/vault-bootstrap.job.yaml new file mode 100644 index 0000000..18ca6a4 --- /dev/null +++ b/manifests/vault/vault-bootstrap.job.yaml @@ -0,0 +1,88 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: vault-bootstrap + namespace: dev-tools + annotations: + argocd.argoproj.io/hook: PostSync + argocd.argoproj.io/hook-delete-policy: BeforeHookCreation + argocd.argoproj.io/sync-wave: "1" +spec: + template: + spec: + serviceAccountName: vault-auth + restartPolicy: OnFailure + containers: + - name: bootstrap + image: hashicorp/vault:1.15 + envFrom: + - secretRef: + name: vault-admin # מספק VAULT_ADDR + VAULT_TOKEN (אדמין) + volumeMounts: + - name: bootstrap-config + mountPath: /config # מכיל mounts + roles + - name: policies + mountPath: /policies # כל *.hcl יהפוך ל-policy + command: ["/bin/sh","-c"] + args: + - | + set -eu + + echo "== Ensure mounts ==" + while IFS= read -r line; do + [ -z "$line" ] && continue + PATH_NAME="${line%%:*}" + TYPE="${line##*:}" + if vault secrets list -format=json | grep -q "\"${PATH_NAME}/\""; then + echo "Mount exists: ${PATH_NAME}/" + continue + fi + case "$TYPE" in + kv2) vault secrets enable -path="${PATH_NAME}" -version=2 kv ;; + kv1) vault secrets enable -path="${PATH_NAME}" kv ;; + *) echo "Unknown type '$TYPE' for ${PATH_NAME}"; exit 1 ;; + esac + done < /config/mounts + + echo "== Write/Update policies ==" + for f in /policies/*.hcl; do + [ -f "$f" ] || continue + NAME="$(basename "$f" .hcl)" + vault policy write "$NAME" "$f" + done + + echo "== Enable & configure kubernetes auth ==" + if ! vault auth list -format=json | grep -q '"kubernetes/"'; then + vault auth enable -path=kubernetes kubernetes + fi + TOKEN_REVIEWER_JWT=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token) + KUBE_HOST="https://${KUBERNETES_PORT_443_TCP_ADDR}:443" + CA_CERT="/var/run/secrets/kubernetes.io/serviceaccount/ca.crt" + vault write auth/kubernetes/config \ + token_reviewer_jwt="$TOKEN_REVIEWER_JWT" \ + kubernetes_host="$KUBE_HOST" \ + kubernetes_ca_cert=@"$CA_CERT" + + echo "== Create/Update roles ==" + while IFS= read -r line; do + [ -z "$line" ] && continue + ROLENAME="${line%%:*}"; REST="${line#*:}" + SA="${REST%%:*}"; REST="${REST#*:}" + NS="${REST%%:*}"; REST="${REST#*:}" + POLICIES="${REST%%:*}"; TTL="${REST#*:}" + vault write "auth/kubernetes/role/${ROLENAME}" \ + bound_service_account_names="$SA" \ + bound_service_account_namespaces="$NS" \ + policies="$POLICIES" \ + ttl="$TTL" + done < /config/roles + securityContext: + runAsNonRoot: true + runAsUser: 100 + volumes: + - name: bootstrap-config + configMap: + name: vault-bootstrap-config + - name: policies + configMap: + name: vault-policies