Skip to content

Commit

Permalink
fix: add log sanitization for Secret kind in updateResource
Browse files Browse the repository at this point in the history
- Added a new function `desensitizeLog` to sanitize logs by replacing sensitive data in a Secret with "***".
- Modified the `updateResource` function to use `desensitizeLog` when the kind is "Secret".
- Added a test case for the `desensitizeLog` function to ensure it works as expected.

Signed-off-by: Daniel Hu <tao.hu@merico.dev>
  • Loading branch information
daniel-hutao committed Jul 6, 2023
1 parent 03911ae commit 309cad9
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 1 deletion.
46 changes: 45 additions & 1 deletion pkg/kube/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -687,14 +687,58 @@ func updateResource(c *Client, target *resource.Info, currentObj runtime.Object,
c.Log("Patch %s %q in namespace %s", kind, target.Name, target.Namespace)
obj, err = helper.Patch(target.Namespace, target.Name, patchType, patch, nil)
if err != nil {
return errors.Wrapf(err, "cannot patch %q with kind %s", target.Name, kind)
sanitizeLog := err.Error()
if kind == "Secret" {
sanitizeLog = desensitizeLog(err.Error())
}
return errors.Wrapf(errors.New(sanitizeLog), "cannot patch %q with kind %s", target.Name, kind)
}
}

target.Refresh(obj, true)
return nil
}

// desensitizeLog replaces the data in a Secret with {"key": "***"}.
// e.g. "data": {"username": "admin", "password": "password"} becomes "data": {"username": "***", "password": "***"}
func desensitizeLog(log string) string {
start := strings.Index(log, `{\"apiVersion`)
end := strings.Index(log, `,\"kind\":\"Secret\"`)
if start == -1 || end == -1 {
return log
}

// Extract the JSON string and add a } at the end
jsonStr := log[start:end] + "}"
jsonStr = strings.ReplaceAll(jsonStr, "\\\"", "\"")

// Parse the JSON string into a map
var data map[string]interface{}
err := json.Unmarshal([]byte(jsonStr), &data)
if err != nil {
return log
}

// Desensitize the values in the data map
if dataMap, ok := data["data"].(map[string]interface{}); ok {
for k := range dataMap {
dataMap[k] = "***"
}
}

// Convert the map back to JSON string
newJsonStr, err := json.Marshal(data)
if err != nil {
return log
}

// Replace the original JSON string with the new one in the log
newJsonStr = []byte(strings.ReplaceAll(string(newJsonStr), "\"", "\\\""))
newLog := log[:start] + string(newJsonStr[:len(newJsonStr)-1]) + log[end:]

return newLog
}

func (c *Client) watchUntilReady(timeout time.Duration, info *resource.Info) error {
kind := info.Mapping.GroupVersionKind.Kind
switch kind {
Expand Down
16 changes: 16 additions & 0 deletions pkg/kube/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -558,3 +558,19 @@ spec:
ports:
- containerPort: 80
`

func TestDesensitizeLog(t *testing.T) {
log := `Error: UPGRADE FAILED: cannot patch "mysecret" with kind Secret: "" is invalid: patch: Invalid value: "{\"apiVersion\":\"v1\",\"data\":{\"mykey1\":\"hello\", \"mykey2\":\"world\"},\"kind\":\"Secret\",\"metadata\"……,\"type\":\"Opaque\"}": illegal base64 data at input byte 12`
expected1 := `\"mykey1\":\"***\"`
expected2 := `\"mykey2\":\"***\"`

result := desensitizeLog(log)

if !strings.Contains(result, expected1) {
t.Errorf("Expected %s to contain %s", result, expected1)
}

if !strings.Contains(result, expected2) {
t.Errorf("Expected %s to contain %s", result, expected2)
}
}

0 comments on commit 309cad9

Please sign in to comment.