# One AppRole per estate, each with a policy that can read only its own path. # The n8n store cannot read `keycloak/*` and the keycloak store cannot read # `n8n/*` — so a compromised workload in one namespace does not become a way # into the other's secrets. # # Its Vault side is created by hand, once: # # vault policy write n8n-readonly - <<'HCL' # path "secrets/data/n8n/*" { capabilities = ["read"] } # path "secrets/metadata/n8n/*" { capabilities = ["list", "read"] } # HCL # vault write auth/approle/role/n8n-eso token_policies=n8n-readonly \ # token_ttl=1h token_max_ttl=4h # kubectl -n external-secrets create secret generic vault-approle-n8n \ # --from-literal=roleId=$(vault read -field=role_id auth/approle/role/n8n-eso/role-id) \ # --from-literal=secretId=$(vault write -f -field=secret_id auth/approle/role/n8n-eso/secret-id) apiVersion: external-secrets.io/v1 kind: ClusterSecretStore metadata: name: vault-n8n spec: provider: vault: server: https://vault.sttlab.eu path: secrets version: v2 auth: appRole: path: approle roleRef: name: vault-approle-n8n namespace: external-secrets key: roleId secretRef: name: vault-approle-n8n namespace: external-secrets key: secretId