package authorizer import ( "net/http" "testing" kapi "k8s.io/kubernetes/pkg/api" kapiserver "k8s.io/kubernetes/pkg/apiserver" "k8s.io/kubernetes/pkg/auth/user" "k8s.io/kubernetes/pkg/util/sets" ) func TestUpstreamInfoResolver(t *testing.T) { subresourceRequest, _ := http.NewRequest("GET", "/api/v1/namespaces/myns/pods/mypod/proxy", nil) proxyRequest, _ := http.NewRequest("GET", "/api/v1/proxy/nodes/mynode", nil) testcases := map[string]struct { Request *http.Request ExpectedVerb string ExpectedSubresource string }{ "unsafe proxy subresource": { Request: subresourceRequest, ExpectedVerb: "get", ExpectedSubresource: "proxy", // should be "unsafeproxy" or similar once check moves upstream }, "unsafe proxy verb": { Request: proxyRequest, ExpectedVerb: "proxy", // should be "unsafeproxy" or similar once check moves upstream }, } for k, tc := range testcases { resolver := &kapiserver.RequestInfoResolver{ APIPrefixes: sets.NewString("api", "osapi", "oapi", "apis"), GrouplessAPIPrefixes: sets.NewString("api", "osapi", "oapi"), } info, err := resolver.GetRequestInfo(tc.Request) if err != nil { t.Errorf("%s: unexpected error: %v", k, err) continue } if info.Verb != tc.ExpectedVerb { t.Errorf("%s: expected verb %s, got %s. If kapiserver.RequestInfoResolver now adjusts attributes for proxy safety, investigate removing the NewBrowserSafeRequestInfoResolver wrapper.", k, tc.ExpectedVerb, info.Verb) } if info.Subresource != tc.ExpectedSubresource { t.Errorf("%s: expected verb %s, got %s. If kapiserver.RequestInfoResolver now adjusts attributes for proxy safety, investigate removing the NewBrowserSafeRequestInfoResolver wrapper.", k, tc.ExpectedSubresource, info.Subresource) } } } func TestBrowserSafeRequestInfoResolver(t *testing.T) { testcases := map[string]struct { RequestInfo kapiserver.RequestInfo Context kapi.Context Host string Headers http.Header ExpectedVerb string ExpectedSubresource string }{ "non-resource": { RequestInfo: kapiserver.RequestInfo{IsResourceRequest: false, Verb: "GET"}, ExpectedVerb: "GET", }, "non-proxy": { RequestInfo: kapiserver.RequestInfo{IsResourceRequest: true, Verb: "get", Resource: "pods", Subresource: "logs"}, ExpectedVerb: "get", ExpectedSubresource: "logs", }, "unsafe proxy subresource": { RequestInfo: kapiserver.RequestInfo{IsResourceRequest: true, Verb: "get", Resource: "pods", Subresource: "proxy"}, ExpectedVerb: "get", ExpectedSubresource: "unsafeproxy", }, "unsafe proxy verb": { RequestInfo: kapiserver.RequestInfo{IsResourceRequest: true, Verb: "proxy", Resource: "nodes"}, ExpectedVerb: "unsafeproxy", }, "unsafe proxy verb anonymous": { Context: kapi.WithUser(kapi.NewContext(), &user.DefaultInfo{Name: "system:anonymous", Groups: []string{"system:unauthenticated"}}), RequestInfo: kapiserver.RequestInfo{IsResourceRequest: true, Verb: "proxy", Resource: "nodes"}, ExpectedVerb: "unsafeproxy", }, "proxy subresource authenticated": { Context: kapi.WithUser(kapi.NewContext(), &user.DefaultInfo{Name: "bob", Groups: []string{"system:authenticated"}}), RequestInfo: kapiserver.RequestInfo{IsResourceRequest: true, Verb: "get", Resource: "pods", Subresource: "proxy"}, ExpectedVerb: "get", ExpectedSubresource: "proxy", }, "proxy subresource custom header": { RequestInfo: kapiserver.RequestInfo{IsResourceRequest: true, Verb: "get", Resource: "pods", Subresource: "proxy"}, Headers: http.Header{"X-Csrf-Token": []string{"1"}}, ExpectedVerb: "get", ExpectedSubresource: "proxy", }, } for k, tc := range testcases { resolver := NewBrowserSafeRequestInfoResolver( &testContextMapper{tc.Context}, sets.NewString("system:authenticated"), &testInfoResolver{tc.RequestInfo}, ) req, _ := http.NewRequest("GET", "/", nil) req.Host = tc.Host req.Header = tc.Headers info, err := resolver.GetRequestInfo(req) if err != nil { t.Errorf("%s: unexpected error: %v", k, err) continue } if info.Verb != tc.ExpectedVerb { t.Errorf("%s: expected verb %s, got %s", k, tc.ExpectedVerb, info.Verb) } if info.Subresource != tc.ExpectedSubresource { t.Errorf("%s: expected verb %s, got %s", k, tc.ExpectedSubresource, info.Subresource) } } } type testContextMapper struct { context kapi.Context } func (t *testContextMapper) Get(req *http.Request) (kapi.Context, bool) { return t.context, t.context != nil } func (t *testContextMapper) Update(req *http.Request, ctx kapi.Context) error { return nil } type testInfoResolver struct { info kapiserver.RequestInfo } func (t *testInfoResolver) GetRequestInfo(req *http.Request) (kapiserver.RequestInfo, error) { return t.info, nil }