diff --git a/pkg/datagatherer/k8sdynamic/fieldfilter.go b/pkg/datagatherer/k8sdynamic/fieldfilter.go index 392c75fd..38a3649e 100644 --- a/pkg/datagatherer/k8sdynamic/fieldfilter.go +++ b/pkg/datagatherer/k8sdynamic/fieldfilter.go @@ -69,10 +69,16 @@ var RouteSelectedFields = []FieldPath{ {"status"}, } -// RedactFields are removed from all objects +// RedactFields are removed from all objects. +// Includes known GitOps tool annotations that store a full copy of the original +// manifest (including Secret .data) to prevent private key material leaking via +// the annotation channel. var RedactFields = []FieldPath{ {"metadata", "managedFields"}, {"metadata", "annotations", "kubectl.kubernetes.io/last-applied-configuration"}, + {"metadata", "annotations", "kapp.k14s.io/original"}, + {"metadata", "annotations", "objectset.rio.cattle.io/applied"}, + {"metadata", "annotations", "banzaicloud.com/last-applied"}, } type FieldPath []string diff --git a/pkg/datagatherer/k8sdynamic/fieldfilter_test.go b/pkg/datagatherer/k8sdynamic/fieldfilter_test.go index 097e735f..7e35717f 100644 --- a/pkg/datagatherer/k8sdynamic/fieldfilter_test.go +++ b/pkg/datagatherer/k8sdynamic/fieldfilter_test.go @@ -329,6 +329,35 @@ func TestRedactPod(t *testing.T) { assert.Equal(t, expectedJSON, string(bytes)) } +func TestRedactGitOpsAnnotations(t *testing.T) { + resource := &unstructured.Unstructured{ + Object: map[string]any{ + "apiVersion": "v1", + "kind": "Secret", + "metadata": map[string]any{ + "name": "example", + "namespace": "example", + "annotations": map[string]any{ + "kapp.k14s.io/original": `{"data":{"tls.key":"c2VjcmV0"}}`, + "objectset.rio.cattle.io/applied": `{"data":{"tls.key":"c2VjcmV0"}}`, + "banzaicloud.com/last-applied": `{"data":{"tls.key":"c2VjcmV0"}}`, + "kubectl.kubernetes.io/last-applied-configuration": `{"data":{"tls.key":"c2VjcmV0"}}`, + "safe-annotation": "keep-me", + }, + }, + }, + } + + Redact(RedactFields, resource) + + annotations := resource.GetAnnotations() + assert.NotContains(t, annotations, "kapp.k14s.io/original") + assert.NotContains(t, annotations, "objectset.rio.cattle.io/applied") + assert.NotContains(t, annotations, "banzaicloud.com/last-applied") + assert.NotContains(t, annotations, "kubectl.kubernetes.io/last-applied-configuration") + assert.Equal(t, "keep-me", annotations["safe-annotation"]) +} + func TestRedactMissingField(t *testing.T) { resource := &unstructured.Unstructured{ Object: map[string]any{