diff --git a/components/processors/observek8sattributesprocessor/processor_test.go b/components/processors/observek8sattributesprocessor/processor_test.go index 5a7152613..4aec3316a 100644 --- a/components/processors/observek8sattributesprocessor/processor_test.go +++ b/components/processors/observek8sattributesprocessor/processor_test.go @@ -31,10 +31,27 @@ type queryWithResult struct { expResult any } +// Functions that check the body of a logRecord post processor actions +// These "custom" check functions are a powerful way to introspect the body +// of a log record (as a raw JSON string). +// Implementations of these functions most likely start with unmarshalling +// the body string to an API object of choice +type checkBodyFunc func(t *testing.T, body string) + +// Functions that check the attributes of a logRecord post processor actions +// These custom actions take as input the key-value attributes as a +// map[string]any +type checkAttributesFunc func(t *testing.T, attributes map[string]any) //nolint:unused + type k8sEventProcessorTest struct { name string inLogs plog.Logs expectedResults []queryWithResult + // Actions that are only ran when testing the body of a resulting logRecord + checkBodyFunctions []checkBodyFunc + // Actions that are only ran when testing the attributes a resulting + // logRecord + checkAttributesFunctions []checkAttributesFunc //nolint:unused } // LogLocation is the part of the log where to check for matches. At the moment, @@ -62,8 +79,14 @@ func runTest(t *testing.T, test k8sEventProcessorTest, location LogLocation) { // map[string]any to be able to query it with jmespath. body := logRecord.Body().AsString() json.Unmarshal([]byte(body), &out) + for _, fn := range test.checkBodyFunctions { + fn(t, body) + } case LogLocationAttributes: out = logRecord.Attributes().AsRaw() + for _, fn := range test.checkAttributesFunctions { + fn(t, out) + } } for _, query := range test.expectedResults { queryJmes, err := jmespath.Compile(query.path) diff --git a/components/processors/observek8sattributesprocessor/secretactions.go b/components/processors/observek8sattributesprocessor/secretactions.go index 0bc36bb05..25f1246da 100644 --- a/components/processors/observek8sattributesprocessor/secretactions.go +++ b/components/processors/observek8sattributesprocessor/secretactions.go @@ -16,10 +16,21 @@ func NewSecretRedactorBodyAction() SecretRedactorBodyAction { // ---------------------------------- Secret "data" values' redaction ---------------------------------- -// Redacts secrets' values -func (SecretRedactorBodyAction) Modify(secret *corev1.Secret) error { +func redactSecretKeys(secret *corev1.Secret) { for key := range secret.Data { secret.Data[key] = []byte(RedactedSecretValue) } + for key := range secret.StringData { + secret.StringData[key] = RedactedSecretValue + } +} + +// Redacts secrets' values +func (SecretRedactorBodyAction) Modify(secret *corev1.Secret) error { + redactSecretKeys(secret) + + annotations := secret.GetAnnotations() + delete(annotations, corev1.LastAppliedConfigAnnotation) + secret.SetAnnotations(annotations) return nil } diff --git a/components/processors/observek8sattributesprocessor/secretactions_test.go b/components/processors/observek8sattributesprocessor/secretactions_test.go index f03e0aa8f..f9e453a2d 100644 --- a/components/processors/observek8sattributesprocessor/secretactions_test.go +++ b/components/processors/observek8sattributesprocessor/secretactions_test.go @@ -4,6 +4,8 @@ import ( "encoding/base64" "fmt" "testing" + + corev1 "k8s.io/api/core/v1" ) func TestSecretBodyActions(t *testing.T) { @@ -16,6 +18,13 @@ func TestSecretBodyActions(t *testing.T) { {fmt.Sprintf("length(values(data)[?@ != '%s'])", base64.StdEncoding.EncodeToString([]byte(RedactedSecretValue))), float64(0)}, }, }, + { + name: "Redact secrets' last configuration values", + inLogs: resourceLogsFromSingleJsonEvent("./testdata/secretEventPrevConfig.json"), + expectedResults: []queryWithResult{ + {fmt.Sprintf("observe_transform.body.metadata.annotations.\"%s\"", corev1.LastAppliedConfigAnnotation), nil}, + }, + }, } { runTest(t, testCase, LogLocationBody) } diff --git a/components/processors/observek8sattributesprocessor/testdata/secretEventPrevConfig.json b/components/processors/observek8sattributesprocessor/testdata/secretEventPrevConfig.json new file mode 100644 index 000000000..4d6f45b7c --- /dev/null +++ b/components/processors/observek8sattributesprocessor/testdata/secretEventPrevConfig.json @@ -0,0 +1,42 @@ +{ + "apiVersion": "v1", + "data": { + "postgres-url": "Tm90IHNvIGVhc3kgbXIgaGFja2VyCg==", + "postgres-url-proxy": "RGFtbiwgWU9VIFJFQUxMWSBUUklFRCEgQ21vbiBub3cuLi4K" + }, + "kind": "Secret", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"v1\",\"data\":{\"postgres-url\":\"Tm90IHNvIGVhc3kgbXIgaGFja2VyCg==\",\"postgres-url-proxy\":\"RGFtbiwgWU9VIFJFQUxMWSBUUklFRCEgQ21vbiBub3cuLi4K\"},\"kind\":\"Secret\",\"metadata\":{\"annotations\":{},\"creationTimestamp\":\"2021-03-18T20:20:00Z\",\"name\":\"postgres-billing-credentials\",\"namespace\":\"o2\",\"resourceVersion\":\"543685028\",\"uid\":\"619570cd-c3da-43b5-a2a3-f85f68860f30\"},\"type\":\"Opaque\"}\n" + }, + "creationTimestamp": "2024-08-14T20:10:30Z", + "managedFields": [ + { + "apiVersion": "v1", + "fieldsType": "FieldsV1", + "fieldsV1": { + "f:data": { + ".": {}, + "f:postgres-url": {}, + "f:postgres-url-proxy": {} + }, + "f:metadata": { + "f:annotations": { + ".": {}, + "f:kubectl.kubernetes.io/last-applied-configuration": {} + } + }, + "f:type": {} + }, + "manager": "kubectl-client-side-apply", + "operation": "Update", + "time": "2024-08-14T20:10:30Z" + } + ], + "name": "postgres-billing-credentials", + "namespace": "o2", + "resourceVersion": "40105", + "uid": "638c64d7-14e0-4551-bc9f-7f8e7644c8b9" + }, + "type": "Opaque" +}