refactor: make this a reusable deployment, not ours
Every environment value is a ${VAR} for the caller to substitute: hostname,
images, storage, ingress class, TLS issuer, Vault server and path, timezone,
retention. Nothing in k8s/ names a host, a realm, an agent or an estate.
Removed: the Flux plumbing under dev/, which described one deployment, and the
ExternalSecret pulling a specific agent's Keycloak client secret. Both belong to
whoever deploys this. The lab CA ConfigMap goes with them — the mount stays,
parameterised and marked optional, because 'trust a private CA' is a property of
an environment and not of n8n.
The README is now the template's: how to consume it, what every variable means,
and the three things it deliberately does not do.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,24 +0,0 @@
|
||||
# The agents' Keycloak client secrets, for the workflows that act as those
|
||||
# agents. Read from the realm's own Vault entry through the keycloak store, not
|
||||
# copied into `n8n/*`: there is one source for a client secret, and rotating it
|
||||
# in Vault rotates it everywhere rather than leaving a stale twin behind.
|
||||
#
|
||||
# It is a narrow grant — this ExternalSecret names the properties it wants, so
|
||||
# the n8n namespace receives those and nothing else of the realm.
|
||||
apiVersion: external-secrets.io/v1
|
||||
kind: ExternalSecret
|
||||
metadata:
|
||||
name: n8n-agent-secrets
|
||||
namespace: n8n
|
||||
spec:
|
||||
refreshInterval: 1h
|
||||
secretStoreRef:
|
||||
kind: ClusterSecretStore
|
||||
name: vault-keycloak
|
||||
target:
|
||||
name: n8n-agent-secrets
|
||||
data:
|
||||
- secretKey: APPROVISIONNEMENT_CLIENT_SECRET
|
||||
remoteRef:
|
||||
key: keycloak/classic-models-realm
|
||||
property: KC_SECRET_CLASSIC_MODELS_AGENT_APPROVISIONNEMENT
|
||||
@@ -1,37 +1,36 @@
|
||||
# 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.
|
||||
# Reads this deployment's secrets from Vault. Scope the AppRole's policy to the
|
||||
# path this store reads and nothing more, so a workload here cannot reach
|
||||
# another estate's secrets.
|
||||
#
|
||||
# Its Vault side is created by hand, once:
|
||||
# The Vault side is created once, outside this repo:
|
||||
#
|
||||
# vault policy write n8n-readonly - <<'HCL'
|
||||
# path "secrets/data/n8n/*" { capabilities = ["read"] }
|
||||
# path "secrets/metadata/n8n/*" { capabilities = ["list", "read"] }
|
||||
# vault policy write <policy> - <<'HCL'
|
||||
# path "<mount>/data/<path>/*" { capabilities = ["read"] }
|
||||
# path "<mount>/metadata/<path>/*" { capabilities = ["list", "read"] }
|
||||
# HCL
|
||||
# vault write auth/approle/role/n8n-eso token_policies=n8n-readonly \
|
||||
# vault write auth/approle/role/<role> token_policies=<policy> \
|
||||
# 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)
|
||||
# kubectl -n external-secrets create secret generic ${VAULT_APPROLE_SECRET} \
|
||||
# --from-literal=roleId=$(vault read -field=role_id auth/approle/role/<role>/role-id) \
|
||||
# --from-literal=secretId=$(vault write -f -field=secret_id auth/approle/role/<role>/secret-id)
|
||||
apiVersion: external-secrets.io/v1
|
||||
kind: ClusterSecretStore
|
||||
metadata:
|
||||
name: vault-n8n
|
||||
name: ${VAULT_STORE_NAME}
|
||||
spec:
|
||||
provider:
|
||||
vault:
|
||||
server: https://vault.sttlab.eu
|
||||
path: secrets
|
||||
server: ${VAULT_SERVER}
|
||||
path: ${VAULT_MOUNT}
|
||||
version: v2
|
||||
auth:
|
||||
appRole:
|
||||
path: approle
|
||||
roleRef:
|
||||
name: vault-approle-n8n
|
||||
name: ${VAULT_APPROLE_SECRET}
|
||||
namespace: external-secrets
|
||||
key: roleId
|
||||
secretRef:
|
||||
name: vault-approle-n8n
|
||||
name: ${VAULT_APPROLE_SECRET}
|
||||
namespace: external-secrets
|
||||
key: secretId
|
||||
|
||||
@@ -8,15 +8,15 @@ apiVersion: external-secrets.io/v1
|
||||
kind: ExternalSecret
|
||||
metadata:
|
||||
name: n8n-secrets
|
||||
namespace: n8n
|
||||
namespace: ${NAMESPACE}
|
||||
spec:
|
||||
refreshInterval: 1h
|
||||
secretStoreRef:
|
||||
kind: ClusterSecretStore
|
||||
name: vault-n8n
|
||||
name: ${VAULT_STORE_NAME}
|
||||
target:
|
||||
name: n8n-secrets
|
||||
creationPolicy: Owner
|
||||
dataFrom:
|
||||
- extract:
|
||||
key: n8n/instance
|
||||
key: ${VAULT_SECRET_PATH}
|
||||
|
||||
Reference in New Issue
Block a user