diff --git a/content/en/flux/guides/helmreleases.md b/content/en/flux/guides/helmreleases.md index 28b0c3057..c6208c1d3 100644 --- a/content/en/flux/guides/helmreleases.md +++ b/content/en/flux/guides/helmreleases.md @@ -385,6 +385,133 @@ removed from the cluster by kustomize-controller if [pruning](../components/kustomize/kustomization/#garbage-collection) is enabled. {{% /alert %}} +## Refer to values in Secret generated with Kustomize and SOPS + +It is possible to use Kustomize [Secret generator](https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/secretgenerator/) +to trigger a Helm release upgrade every time the encrypted secret values change. + +A SOPS configuration for your cluster is required first. Follow the [Manage Kubernetes secrets with Mozilla SOPS](../mozilla-sops/) +guide. The details of configuring SOPS are out of scope for this entry. + +Once you have SOPS configured, create a `kustomizeconfig.yaml` for Kustomize to +be able to patch `Secrets` referenced in `HelmRelease` manifests: + +```yaml +nameReference: +- kind: Secret + version: v1 + fieldSpecs: + - path: spec/valuesFrom/name + kind: HelmRelease +``` + +Create a `HelmRelease` definition that references a `Secret`: + +```yaml +apiVersion: helm.toolkit.fluxcd.io/v2beta1 +kind: HelmRelease +metadata: + name: podinfo + namespace: podinfo +spec: + interval: 5m + releaseName: podinfo + chart: + spec: + chart: podinfo + sourceRef: + kind: HelmRepository + name: podinfo + valuesFrom: + - kind: Secret + name: podinfo-values +``` + +Ensure that this HelmRelease will be applied from the same Flux Kustomization +that will decrypt the values secret. The encrypted secret data must be housed +in the same Flux Kustomization path as the `HelmRelease` in order to allow +Kustomize's Secret generator function to compose them together with the +Kustomize configuration. + +Create a `kustomization.yaml` that generates the `Secret`: + +```yaml +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +namespace: podinfo +resources: + - namespace.yaml + - repository.yaml + - release.yaml +secretGenerator: + - name: podinfo-values + files: + - values.yaml=my-values.enc.yaml +configurations: + - kustomizeconfig.yaml +``` + +Now `HelmRelease` values can come from an encrypted secret! Read on below to +prepare the secret file and apply it to the cluster in a Flux Kustomization. + +#### Encrypting a `values.yaml` with the SOPS CLI + +To prepare the encrypted secret, please note there are some divergences from +encrypting a well-formed Kubernetes Secret with metadata and versioning. + +Run this command to encrypt to the output file that was named in +`kustomization.yaml` above: +``` +$ sops -e --input-type=yaml --output-type=yaml my-values.tmp.secret > my-values.enc.yaml +``` + +Commit the `my-values.enc.yaml` file and discard the temp file, being sure not +to accidentally commit secrets to the repository. Read on for more information. + +If users have followed the SOPS guide then we likely added a `creation_rules` +entry telling the `sops` CLI how to handle encrypting all YAML secrets, like: + +```yaml +# ./apps/sensitive/.sops.yaml +creation_rules: + - path_regex: ".*\.yaml" + encrypted_regex: ^(data|stringData)$ + pgp: KEY_ID_ASDF1234 +``` + +This selects only the `data` or `stringData` fields for encryption, leaving all +the metadata unencrypted, which is the proper way to handle normal, well-formed +`Secrets` according to Flux's SOPS guide. + +Since a values file is not a well-formed `Secret` that rule would fail to +encrypt the secret. Instead, here, we add a more specific rule which is listed +first, so that our values.yaml file does not get captured by the `*.yaml` rule. + +```yaml +# ./apps/sensitive/.sops.yaml +creation_rules: + - path_regex: .*values.yaml$ + pgp: KEY_ID_ASDF1234 + - path_regex: ".*\.yaml" + encrypted_regex: ^(data|stringData)$ + pgp: KEY_ID_ASDF1234 +``` + +Alternatively we could rename the input file to avoid matching, or handle the +encryption elsewhere, like in CI where it can be made safer to handle secrets. + +We named our input file `my-values.tmp.secret`, which doesn't end in `.yaml` so +this would work regardless but we may want to conventionally keep `values.yaml` +in a file with the same name; then this rule may be a useful addition as well. + +The filename was also chosen to **not** match with `*.enc` or `*.encrypted` so +that `sops` CLI never infers a binary input type, to avoid that decryption with +`sops my-values.enc.yaml` for editing in-place would also fail. + +Be careful not to mix secrets with other non-sensitive data. A note that Helm +stores its values as Kubernetes Secrets internally; if users can read secrets +in the context then they can recover decrypted values using `helm get values`. + ## Refer to values inside the chart It is possible to replace the `values.yaml` with a different file present inside the Helm chart.