diff options
-rw-r--r-- | api/server/middleware/debug.go | 40 | ||||
-rw-r--r-- | api/server/middleware/debug_test.go | 52 |
2 files changed, 52 insertions, 40 deletions
diff --git a/api/server/middleware/debug.go b/api/server/middleware/debug.go index 2cef1d46c3..a02c1bc7de 100644 --- a/api/server/middleware/debug.go +++ b/api/server/middleware/debug.go @@ -41,7 +41,7 @@ func DebugRequestMiddleware(handler func(ctx context.Context, w http.ResponseWri var postForm map[string]interface{} if err := json.Unmarshal(b, &postForm); err == nil { - maskSecretKeys(postForm, r.RequestURI) + maskSecretKeys(postForm) formStr, errMarshal := json.Marshal(postForm) if errMarshal == nil { logrus.Debugf("form data: %s", string(formStr)) @@ -54,41 +54,37 @@ func DebugRequestMiddleware(handler func(ctx context.Context, w http.ResponseWri } } -func maskSecretKeys(inp interface{}, path string) { - // Remove any query string from the path - idx := strings.Index(path, "?") - if idx != -1 { - path = path[:idx] - } - // Remove trailing / characters - path = strings.TrimRight(path, "/") - +func maskSecretKeys(inp interface{}) { if arr, ok := inp.([]interface{}); ok { for _, f := range arr { - maskSecretKeys(f, path) + maskSecretKeys(f) } return } if form, ok := inp.(map[string]interface{}); ok { + scrub := []string{ + // Note: The Data field contains the base64-encoded secret in 'secret' + // and 'config' create and update requests. Currently, no other POST + // API endpoints use a data field, so we scrub this field unconditionally. + // Change this handling to be conditional if a new endpoint is added + // in future where this field should not be scrubbed. + "data", + "jointoken", + "password", + "secret", + "signingcakey", + "unlockkey", + } loop0: for k, v := range form { - for _, m := range []string{"password", "secret", "jointoken", "unlockkey", "signingcakey"} { + for _, m := range scrub { if strings.EqualFold(m, k) { form[k] = "*****" continue loop0 } } - maskSecretKeys(v, path) - } - - // Route-specific redactions - if strings.HasSuffix(path, "/secrets/create") { - for k := range form { - if k == "Data" { - form[k] = "*****" - } - } + maskSecretKeys(v) } } } diff --git a/api/server/middleware/debug_test.go b/api/server/middleware/debug_test.go index a64b73e0d7..fb1740d54a 100644 --- a/api/server/middleware/debug_test.go +++ b/api/server/middleware/debug_test.go @@ -9,31 +9,25 @@ import ( func TestMaskSecretKeys(t *testing.T) { tests := []struct { - path string + doc string input map[string]interface{} expected map[string]interface{} }{ { - path: "/v1.30/secrets/create", + doc: "secret/config create and update requests", input: map[string]interface{}{"Data": "foo", "Name": "name", "Labels": map[string]interface{}{}}, expected: map[string]interface{}{"Data": "*****", "Name": "name", "Labels": map[string]interface{}{}}, }, { - path: "/v1.30/secrets/create//", - input: map[string]interface{}{"Data": "foo", "Name": "name", "Labels": map[string]interface{}{}}, - expected: map[string]interface{}{"Data": "*****", "Name": "name", "Labels": map[string]interface{}{}}, - }, - - { - path: "/secrets/create?key=val", - input: map[string]interface{}{"Data": "foo", "Name": "name", "Labels": map[string]interface{}{}}, - expected: map[string]interface{}{"Data": "*****", "Name": "name", "Labels": map[string]interface{}{}}, - }, - { - path: "/v1.30/some/other/path", + doc: "masking other fields (recursively)", input: map[string]interface{}{ - "password": "pass", + "password": "pass", + "secret": "secret", + "jointoken": "jointoken", + "unlockkey": "unlockkey", + "signingcakey": "signingcakey", "other": map[string]interface{}{ + "password": "pass", "secret": "secret", "jointoken": "jointoken", "unlockkey": "unlockkey", @@ -41,8 +35,13 @@ func TestMaskSecretKeys(t *testing.T) { }, }, expected: map[string]interface{}{ - "password": "*****", + "password": "*****", + "secret": "*****", + "jointoken": "*****", + "unlockkey": "*****", + "signingcakey": "*****", "other": map[string]interface{}{ + "password": "*****", "secret": "*****", "jointoken": "*****", "unlockkey": "*****", @@ -50,10 +49,27 @@ func TestMaskSecretKeys(t *testing.T) { }, }, }, + { + doc: "case insensitive field matching", + input: map[string]interface{}{ + "PASSWORD": "pass", + "other": map[string]interface{}{ + "PASSWORD": "pass", + }, + }, + expected: map[string]interface{}{ + "PASSWORD": "*****", + "other": map[string]interface{}{ + "PASSWORD": "*****", + }, + }, + }, } for _, testcase := range tests { - maskSecretKeys(testcase.input, testcase.path) - assert.Check(t, is.DeepEqual(testcase.expected, testcase.input)) + t.Run(testcase.doc, func(t *testing.T) { + maskSecretKeys(testcase.input) + assert.Check(t, is.DeepEqual(testcase.expected, testcase.input)) + }) } } |