@@ -1048,7 +1048,7 @@ configure decryption for Secrets that are a part of the Kustomization.
10481048The only supported encryption provider is [SOPS](https://getsops.io/).
10491049With SOPS you can encrypt your secrets with [age](https://github.com/FiloSottile/age)
10501050or [OpenPGP](https://www.openpgp.org) keys, or with keys from Key Management Services
1051- (KMS), like AWS KMS, Azure Key Vault, GCP KMS or Hashicorp Vault.
1051+ (KMS), like AWS KMS, Azure Key Vault, GCP KMS or OpenBao/ Vault.
10521052
10531053**Note:** You must leave `metadata`, `kind` or `apiVersion` in plain text.
10541054An easy way to do this is limiting the encrypted keys with the flag
@@ -1061,7 +1061,12 @@ The `.spec.decryption` field has the following subfields:
10611061- `.secretRef.name` : The name of the secret that contains the keys or cloud provider
10621062 static credentials for KMS services to be used for decryption.
10631063- `.serviceAccountName` : The name of the service account used for
1064- secret-less authentication with KMS services from cloud providers.
1064+ secret-less authentication with KMS services from cloud providers, and
1065+ with OpenBao/Vault via the
1066+ [Kubernetes auth method](#openbaovault-kubernetes-auth) (object-level workload
1067+ identity). This requires the `ObjectLevelWorkloadIdentity` feature gate to be
1068+ enabled. When unset, the controller falls back to its own ServiceAccount
1069+ ([controller-level workload identity](#controller-global-decryption)).
10651070
10661071To make a Kustomization react immediately to changes in the referenced Secret
10671072see [this](#reacting-immediately-to-configuration-dependencies) section.
@@ -1115,7 +1120,7 @@ metadata:
11151120data:
11161121 # Exemplary age private key
11171122 identity.agekey: <BASE64>
1118- # Exemplary Hashicorp Vault token
1123+ # Exemplary OpenBao/ Vault token
11191124 sops.vault-token: <BASE64>
11201125` ` `
11211126
@@ -1293,9 +1298,9 @@ stringData:
12931298 }
12941299` ` `
12951300
1296- # ### Hashicorp Vault Secret entry
1301+ # ### OpenBao/ Vault Secret entry
12971302
1298- To specify credentials for Hashicorp Vault in a Kubernetes Secret, append a
1303+ To specify credentials for OpenBao/ Vault in a Kubernetes Secret, append a
12991304` .data` entry with a fixed `sops.vault-token` key and the token as value.
13001305
13011306` ` ` yaml
@@ -1306,10 +1311,95 @@ metadata:
13061311 name: sops-keys
13071312 namespace: default
13081313data:
1309- # Exemplary Hashicorp Vault Secret token
1314+ # Exemplary OpenBao/ Vault Secret token
13101315 sops.vault-token: <BASE64>
13111316` ` `
13121317
1318+ # ### OpenBao/Vault Kubernetes auth
1319+
1320+ Instead of a static `sops.vault-token`, the controller can authenticate to
1321+ OpenBao/Vault by exchanging a Kubernetes ServiceAccount token for a short-lived
1322+ Vault token via a JWT-backed auth method (e.g. the
1323+ [Kubernetes auth method](https://openbao.org/docs/auth/kubernetes/) or the
1324+ [JWT auth method](https://openbao.org/docs/auth/jwt/)). This is enabled with the
1325+ ` --sops-vault-configmap` flag, which names a ConfigMap in the controller's
1326+ namespace that maps each Vault address to the login path to authenticate at. The
1327+ ConfigMap also acts as an **allowlist** : only addresses listed in it can be
1328+ authenticated to this way. This does not affect the static token paths — the
1329+ ` sops.vault-token` Secret entry and the `VAULT_TOKEN` environment variable
1330+ continue to work for any address. When the flag is empty, this authentication is
1331+ disabled and decryption falls back to those static token paths.
1332+
1333+ The mapping is stored under the `config.yaml` key as a list of instances, each
1334+ with an `address` and the `loginPath` to authenticate at. The login path is used
1335+ verbatim, so it supports any JWT-backed auth method and namespace-prefixed paths
1336+ (e.g. `ns1/ns2/auth/kubernetes/login`). The ConfigMap must be in the same
1337+ namespace as the kustomize-controller Deployment.
1338+
1339+ ` ` ` yaml
1340+ ---
1341+ apiVersion: v1
1342+ kind: ConfigMap
1343+ metadata:
1344+ name: sops-vault-config
1345+ namespace: flux-system
1346+ data:
1347+ config.yaml: |
1348+ instances:
1349+ - address: https://vault-a.example.com:8200
1350+ loginPath: auth/kubernetes/login
1351+ - address: https://vault-b.example.com:8200
1352+ loginPath: ns1/ns2/auth/kubernetes/login
1353+ ` ` `
1354+
1355+ Then, patch the kustomize-controller Deployment to add the flag :
1356+
1357+ ` ` ` yaml
1358+ ---
1359+ apiVersion: apps/v1
1360+ kind: Deployment
1361+ metadata:
1362+ name: kustomize-controller
1363+ namespace: flux-system
1364+ spec:
1365+ template:
1366+ spec:
1367+ containers:
1368+ - name: manager
1369+ args:
1370+ - --sops-vault-configmap=sops-vault-config
1371+ ` ` `
1372+
1373+ When enabled, a Kustomization whose decryption Secret does **not** contain a
1374+ ` sops.vault-token` authenticates to the Vault address found in the SOPS metadata
1375+ of each encrypted data key as follows :
1376+
1377+ - The Kubernetes ServiceAccount token is issued for
1378+ [`.spec.decryption.serviceAccountName`](#decryption) when set (object-level
1379+ workload identity, which requires the `ObjectLevelWorkloadIdentity` feature
1380+ gate to be enabled), otherwise for the controller's own ServiceAccount
1381+ ([controller-level workload identity](#controller-global-decryption)).
1382+ - The token audience is set to the Vault address.
1383+ - The Vault role is derived from the ServiceAccount as `{namespace}_{name}`
1384+ (e.g. a ServiceAccount `sops` in namespace `apps` maps to the role `apps_sops`).
1385+
1386+ On the Vault server, the operator must enable and configure the auth method
1387+ behind the configured login path (for the Kubernetes auth method, with the
1388+ cluster's API server address, CA certificate and a token reviewer JWT), and
1389+ create a role `{namespace}_{name}` bound to the ServiceAccount and namespace,
1390+ with its audience set to the Vault address and a policy granting `update` on the
1391+ relevant `transit/decrypt/<key>` paths. See the
1392+ [OpenBao Kubernetes auth docs](https://openbao.org/docs/auth/kubernetes/) for the
1393+ auth method and role configuration. When several clusters share one Vault, enable
1394+ a separate auth mount per cluster (each configured with that cluster's API
1395+ server, CA and reviewer JWT) and set each cluster's login path in its own
1396+ ConfigMap.
1397+
1398+ The authentication methods are tried in order of precedence : a static
1399+ ` sops.vault-token` in the Secret referenced by
1400+ [`.spec.decryption.secretRef`](#decryption) takes priority over Kubernetes auth,
1401+ which in turn takes priority over the global `VAULT_TOKEN` environment variable.
1402+
13131403# ### Controlling the decryption behavior of resources
13141404
13151405To change the decryption behaviour for specific Kubernetes resources, you can annotate them with :
@@ -1671,10 +1761,15 @@ Controller-level configuration:
16711761These guides provide detailed instructions for setting up authentication,
16721762permissions, and controller configuration for each cloud provider.
16731763
1674- # ### Hashicorp Vault
1764+ # ### OpenBao/Vault
1765+
1766+ There are two ways to configure controller-level authentication to OpenBao/Vault
1767+ for SOPS decryption : a static token, or the Kubernetes auth method.
1768+
1769+ # #### Static token
16751770
1676- To configure a global default for Hashicorp Vault , patch the controller's
1677- Deployment with a `VAULT_TOKEN` environment variable.
1771+ To configure a global default token , patch the controller's Deployment with a
1772+ ` VAULT_TOKEN` environment variable.
16781773
16791774` ` ` yaml
16801775---
@@ -1693,6 +1788,22 @@ spec:
16931788 value: <token>
16941789` ` `
16951790
1791+ # #### Kubernetes auth
1792+
1793+ When SOPS decryption uses OpenBao/Vault with the
1794+ [Kubernetes auth method](#openbaovault-kubernetes-auth), the controller-global
1795+ identity is simply kustomize-controller's own ServiceAccount : a Kustomization
1796+ that sets no [`.spec.decryption.serviceAccountName`](#decryption) authenticates
1797+ to Vault as the controller's ServiceAccount (controller-level workload identity).
1798+
1799+ Setting `.spec.decryption.serviceAccountName` makes the authentication
1800+ object-level rather than global, and requires the `ObjectLevelWorkloadIdentity`
1801+ feature gate to be enabled.
1802+
1803+ See [OpenBao/Vault Kubernetes auth](#openbaovault-kubernetes-auth) for enabling
1804+ the method (the `--sops-vault-configmap` flag and ConfigMap) and the Vault server
1805+ configuration.
1806+
16961807# ### SOPS Age Keys
16971808
16981809To configure global decryption for SOPS Age keys, use the `--sops-age-secret`
0 commit comments