Use simpler prefix matching for impersonation headers.

Signed-off-by: Matt Moyer <moyerm@vmware.com>
This commit is contained in:
Matt Moyer 2021-03-08 14:36:29 -06:00
parent 6efbd81f75
commit 8fd6a71312
No known key found for this signature in database
GPG Key ID: EAE88AD172C5AE2D

View File

@ -10,7 +10,6 @@ import (
"net/http"
"net/http/httputil"
"net/url"
"regexp"
"strings"
"time"
@ -28,8 +27,6 @@ import (
"go.pinniped.dev/internal/kubeclient"
)
var impersonateHeaderRegex = regexp.MustCompile("Impersonate-.*")
type proxy struct {
cache *authncache.Cache
jsonDecoder runtime.Decoder
@ -150,11 +147,10 @@ func (e *httpError) Error() string { return e.message }
func ensureNoImpersonationHeaders(r *http.Request) error {
for key := range r.Header {
if impersonateHeaderRegex.MatchString(key) {
if isImpersonationHeader(key) {
return fmt.Errorf("%q header already exists", key)
}
}
return nil
}
@ -163,7 +159,9 @@ type roundTripperFunc func(*http.Request) (*http.Response, error)
func (f roundTripperFunc) RoundTrip(r *http.Request) (*http.Response, error) { return f(r) }
func getProxyHeaders(userInfo user.Info, requestHeaders http.Header) http.Header {
newHeaders := http.Header{}
// Copy over all headers except the Authorization header from the original request to the new request.
newHeaders := requestHeaders.Clone()
newHeaders.Del("Authorization")
// Leverage client-go's impersonation RoundTripper to set impersonation headers for us in the new
// request. The client-go RoundTripper not only sets all of the impersonation headers for us, but
@ -176,12 +174,8 @@ func getProxyHeaders(userInfo user.Info, requestHeaders http.Header) http.Header
Extra: userInfo.GetExtra(),
}
impersonateHeaderSpy := roundTripperFunc(func(r *http.Request) (*http.Response, error) {
newHeaders.Set(transport.ImpersonateUserHeader, r.Header.Get(transport.ImpersonateUserHeader))
for _, groupHeaderValue := range r.Header.Values(transport.ImpersonateGroupHeader) {
newHeaders.Add(transport.ImpersonateGroupHeader, groupHeaderValue)
}
for headerKey, headerValues := range r.Header {
if strings.HasPrefix(headerKey, transport.ImpersonateUserExtraHeaderPrefix) {
if isImpersonationHeader(headerKey) {
for _, headerValue := range headerValues {
newHeaders.Add(headerKey, headerValue)
}
@ -192,19 +186,13 @@ func getProxyHeaders(userInfo user.Info, requestHeaders http.Header) http.Header
fakeReq, _ := http.NewRequestWithContext(context.Background(), "", "", nil)
//nolint:bodyclose // We return a nil http.Response above, so there is nothing to close.
_, _ = transport.NewImpersonatingRoundTripper(impersonateConfig, impersonateHeaderSpy).RoundTrip(fakeReq)
// Copy over all headers except the Authorization header from the original request to the new request.
for key := range requestHeaders {
if key != "Authorization" {
for _, val := range requestHeaders.Values(key) {
newHeaders.Add(key, val)
}
}
}
return newHeaders
}
func isImpersonationHeader(header string) bool {
return strings.HasPrefix(http.CanonicalHeaderKey(header), "Impersonate")
}
func extractToken(token string, jsonDecoder runtime.Decoder) (*login.TokenCredentialRequest, error) {
tokenCredentialRequestJSON, err := base64.StdEncoding.DecodeString(token)
if err != nil {