diff --git a/docs/spec/v1/kustomizations.md b/docs/spec/v1/kustomizations.md index 294dcf2a..79a2041d 100644 --- a/docs/spec/v1/kustomizations.md +++ b/docs/spec/v1/kustomizations.md @@ -1264,6 +1264,18 @@ data: sops.vault-token: ``` +#### Controlling the decryption behavior of resources + +To change the decryption behaviour for specific Kubernetes resources, you can annotate them with: + +| Annotation | Default | Values | Role | +|-------------------------------------|------------|----------------------------------------------------------------|-----------------| +| `kustomize.toolkit.fluxcd.io/decrypt` | `Enabled` | - `Enabled`
- `Disabled` | Decryption policy | + +##### Disabled + +The `Disabled` policy instructs the controller to not decrypt Kubernetes resources. This might be useful if there is another entity that is going to decrpyt the resource later. + ## Working with Kustomizations ### Recommended settings diff --git a/internal/controller/kustomization_controller.go b/internal/controller/kustomization_controller.go index c9c568d0..47939745 100644 --- a/internal/controller/kustomization_controller.go +++ b/internal/controller/kustomization_controller.go @@ -890,7 +890,7 @@ func (r *KustomizationReconciler) apply(ctx context.Context, } for _, u := range objects { - if decryptor.IsEncryptedSecret(u) { + if decryptor.IsEncryptedSecret(u) && !decryptor.IsDecryptionDisabled(u.GetAnnotations()) { return false, nil, fmt.Errorf("%s is SOPS encrypted, configuring decryption is required for this secret to be reconciled", ssautil.FmtUnstructured(u)) diff --git a/internal/decryptor/decryptor.go b/internal/decryptor/decryptor.go index d2bcde94..b44f0524 100644 --- a/internal/decryptor/decryptor.go +++ b/internal/decryptor/decryptor.go @@ -187,6 +187,12 @@ func New(client client.Client, kustomization *kustomizev1.Kustomization, opts .. return d, cleanup, nil } +// IsDecryptionDisabled checks if the given object has the decrypt: disabled annotation set +func IsDecryptionDisabled(annotations map[string]string) bool { + return annotations != nil && + strings.EqualFold(annotations[fmt.Sprintf("%s/decrypt", kustomizev1.GroupVersion.Group)], kustomizev1.DisabledValue) +} + // IsEncryptedSecret checks if the given object is a Kubernetes Secret encrypted // with Mozilla SOPS. func IsEncryptedSecret(object *unstructured.Unstructured) bool { @@ -436,7 +442,10 @@ func (d *Decryptor) SopsDecryptWithFormat(data []byte, inputFormat, outputFormat // while decrypting with DecryptionProviderSOPS, to allow individual data entries // injected by e.g. a Kustomize secret generator to be decrypted func (d *Decryptor) DecryptResource(res *resource.Resource) (*resource.Resource, error) { - if res == nil || d.kustomization.Spec.Decryption == nil || d.kustomization.Spec.Decryption.Provider == "" { + if res == nil || + d.kustomization.Spec.Decryption == nil || + d.kustomization.Spec.Decryption.Provider == "" || + IsDecryptionDisabled(res.GetAnnotations()) { return nil, nil } diff --git a/internal/decryptor/decryptor_test.go b/internal/decryptor/decryptor_test.go index 9fa82206..f72f7865 100644 --- a/internal/decryptor/decryptor_test.go +++ b/internal/decryptor/decryptor_test.go @@ -632,8 +632,18 @@ func TestDecryptor_DecryptResource(t *testing.T) { g.Expect(secret.UnmarshalJSON(encData)).To(Succeed()) g.Expect(isSOPSEncryptedResource(secret)).To(BeTrue()) + secret.SetAnnotations(map[string]string{ + "kustomize.toolkit.fluxcd.io/decrypt": "disabled", + }) + got, err := d.DecryptResource(secret) g.Expect(err).ToNot(HaveOccurred()) + g.Expect(got).To(BeNil()) + + secret.SetAnnotations(map[string]string{}) + + got, err = d.DecryptResource(secret) + g.Expect(err).ToNot(HaveOccurred()) g.Expect(got).ToNot(BeNil()) g.Expect(got.MarshalJSON()).To(Equal(secretData)) })