diff --git a/deploy/agent-secrets.yaml b/deploy/agent-secrets.yaml index 7d1b846..0609104 100644 --- a/deploy/agent-secrets.yaml +++ b/deploy/agent-secrets.yaml @@ -22,3 +22,9 @@ spec: remoteRef: key: keycloak/classic-models-realm property: KC_SECRET_CLASSIC_MODELS_AGENT_APPROVISIONNEMENT + # Redeems a mandate. Held by the workflow rather than by the adapter because + # it is the workflow that acts as the agent. + - secretKey: MANDATE_CLIENT_SECRET + remoteRef: + key: keycloak/classic-models-realm + property: KC_SECRET_MANDATE diff --git a/deploy/flux-kustomization.yaml b/deploy/flux-kustomization.yaml index 38a47d1..ccf05ae 100644 --- a/deploy/flux-kustomization.yaml +++ b/deploy/flux-kustomization.yaml @@ -37,6 +37,7 @@ spec: # The agents' Keycloak client secrets, so a workflow can exchange tokens # as the agent it represents. Created by agent-secrets.yaml beside this. EXTRA_ENV_SECRET: n8n-agent-secrets + EXTRA_ENV_SECRET_2: n8n-mandate-secrets EXTRA_CA_CONFIGMAP: sttlab-ca # "false" so a workflow can read $env._CLIENT_SECRET. It means any # workflow on this instance can read any variable in the pod — acceptable diff --git a/deploy/mandate-secrets.yaml b/deploy/mandate-secrets.yaml new file mode 100644 index 0000000..4179b71 --- /dev/null +++ b/deploy/mandate-secrets.yaml @@ -0,0 +1,25 @@ +# The standing authority the autonomous runs act under. +# +# A mandate is an `offline_access` refresh token, issued by the +# classic-models-mandate client for the user who authorised the agent. It does +# not expire, which is exactly why it is here and not in a workflow: it is +# revoked by that user's session being revoked in Keycloak, and by nothing else. +# +# Two ExternalSecrets rather than one, because they answer to different owners: +# the mandate is the agent estate's, the client secret that redeems it is the +# realm's. +apiVersion: external-secrets.io/v1 +kind: ExternalSecret +metadata: + name: n8n-mandate-secrets + namespace: n8n +spec: + refreshInterval: 1h + secretStoreRef: + kind: ClusterSecretStore + name: vault-n8n + target: + name: n8n-mandate-secrets + dataFrom: + - extract: + key: n8n/mandates