Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: OB-37389 Obfuscate secrets inside Secret previous configuration #102

Merged
merged 1 commit into from
Oct 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"encoding/base64"
"fmt"
"testing"

corev1 "k8s.io/api/core/v1"
)

func TestSecretBodyActions(t *testing.T) {
Expand All @@ -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)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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"
}
Loading