Hide bearer token in logs
This commit is contained in:
		| @@ -409,6 +409,38 @@ func (rt *debuggingRoundTripper) CancelRequest(req *http.Request) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | var knownAuthTypes = map[string]bool{ | ||||||
|  | 	"bearer":    true, | ||||||
|  | 	"basic":     true, | ||||||
|  | 	"negotiate": true, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // maskValue masks credential content from authorization headers | ||||||
|  | // See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Authorization | ||||||
|  | func maskValue(key string, value string) string { | ||||||
|  | 	if !strings.EqualFold(key, "Authorization") { | ||||||
|  | 		return value | ||||||
|  | 	} | ||||||
|  | 	if len(value) == 0 { | ||||||
|  | 		return "" | ||||||
|  | 	} | ||||||
|  | 	var authType string | ||||||
|  | 	if i := strings.Index(value, " "); i > 0 { | ||||||
|  | 		authType = value[0:i] | ||||||
|  | 	} else { | ||||||
|  | 		authType = value | ||||||
|  | 	} | ||||||
|  | 	if !knownAuthTypes[strings.ToLower(authType)] { | ||||||
|  | 		return "<masked>" | ||||||
|  | 	} | ||||||
|  | 	if len(value) > len(authType)+1 { | ||||||
|  | 		value = authType + " <masked>" | ||||||
|  | 	} else { | ||||||
|  | 		value = authType | ||||||
|  | 	} | ||||||
|  | 	return value | ||||||
|  | } | ||||||
|  |  | ||||||
| func (rt *debuggingRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { | func (rt *debuggingRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { | ||||||
| 	reqInfo := newRequestInfo(req) | 	reqInfo := newRequestInfo(req) | ||||||
|  |  | ||||||
| @@ -423,6 +455,7 @@ func (rt *debuggingRoundTripper) RoundTrip(req *http.Request) (*http.Response, e | |||||||
| 		klog.Infof("Request Headers:") | 		klog.Infof("Request Headers:") | ||||||
| 		for key, values := range reqInfo.RequestHeaders { | 		for key, values := range reqInfo.RequestHeaders { | ||||||
| 			for _, value := range values { | 			for _, value := range values { | ||||||
|  | 				value = maskValue(key, value) | ||||||
| 				klog.Infof("    %s: %s", key, value) | 				klog.Infof("    %s: %s", key, value) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|   | |||||||
| @@ -35,6 +35,91 @@ func (rt *testRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) | |||||||
| 	return rt.Response, rt.Err | 	return rt.Response, rt.Err | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func TestMaskValue(t *testing.T) { | ||||||
|  | 	tcs := []struct { | ||||||
|  | 		key      string | ||||||
|  | 		value    string | ||||||
|  | 		expected string | ||||||
|  | 	}{ | ||||||
|  | 		{ | ||||||
|  | 			key:      "Authorization", | ||||||
|  | 			value:    "Basic YWxhZGRpbjpvcGVuc2VzYW1l", | ||||||
|  | 			expected: "Basic <masked>", | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			key:      "Authorization", | ||||||
|  | 			value:    "basic", | ||||||
|  | 			expected: "basic", | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			key:      "Authorization", | ||||||
|  | 			value:    "Basic", | ||||||
|  | 			expected: "Basic", | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			key:      "Authorization", | ||||||
|  | 			value:    "Bearer cn389ncoiwuencr", | ||||||
|  | 			expected: "Bearer <masked>", | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			key:      "Authorization", | ||||||
|  | 			value:    "Bearer", | ||||||
|  | 			expected: "Bearer", | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			key:      "Authorization", | ||||||
|  | 			value:    "bearer", | ||||||
|  | 			expected: "bearer", | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			key:      "Authorization", | ||||||
|  | 			value:    "bearer ", | ||||||
|  | 			expected: "bearer", | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			key:      "Authorization", | ||||||
|  | 			value:    "Negotiate cn389ncoiwuencr", | ||||||
|  | 			expected: "Negotiate <masked>", | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			key:      "ABC", | ||||||
|  | 			value:    "Negotiate cn389ncoiwuencr", | ||||||
|  | 			expected: "Negotiate cn389ncoiwuencr", | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			key:      "Authorization", | ||||||
|  | 			value:    "Negotiate", | ||||||
|  | 			expected: "Negotiate", | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			key:      "Authorization", | ||||||
|  | 			value:    "Negotiate ", | ||||||
|  | 			expected: "Negotiate", | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			key:      "Authorization", | ||||||
|  | 			value:    "negotiate", | ||||||
|  | 			expected: "negotiate", | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			key:      "Authorization", | ||||||
|  | 			value:    "abc cn389ncoiwuencr", | ||||||
|  | 			expected: "<masked>", | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			key:      "Authorization", | ||||||
|  | 			value:    "", | ||||||
|  | 			expected: "", | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 	for _, tc := range tcs { | ||||||
|  | 		maskedValue := maskValue(tc.key, tc.value) | ||||||
|  | 		if tc.expected != maskedValue { | ||||||
|  | 			t.Errorf("unexpected value %s, given %s.", maskedValue, tc.value) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| func TestBearerAuthRoundTripper(t *testing.T) { | func TestBearerAuthRoundTripper(t *testing.T) { | ||||||
| 	rt := &testRoundTripper{} | 	rt := &testRoundTripper{} | ||||||
| 	req := &http.Request{} | 	req := &http.Request{} | ||||||
|   | |||||||
| @@ -722,7 +722,6 @@ metadata: | |||||||
| 			framework.ExpectError(err) | 			framework.ExpectError(err) | ||||||
| 			gomega.Expect(err).To(gomega.ContainSubstring("Using in-cluster namespace")) | 			gomega.Expect(err).To(gomega.ContainSubstring("Using in-cluster namespace")) | ||||||
| 			gomega.Expect(err).To(gomega.ContainSubstring("Using in-cluster configuration")) | 			gomega.Expect(err).To(gomega.ContainSubstring("Using in-cluster configuration")) | ||||||
| 			gomega.Expect(err).To(gomega.ContainSubstring("Authorization: Bearer invalid")) |  | ||||||
| 			gomega.Expect(err).To(gomega.ContainSubstring("Response Status: 401 Unauthorized")) | 			gomega.Expect(err).To(gomega.ContainSubstring("Response Status: 401 Unauthorized")) | ||||||
|  |  | ||||||
| 			ginkgo.By("trying to use kubectl with invalid server") | 			ginkgo.By("trying to use kubectl with invalid server") | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Ted Yu
					Ted Yu