plumb APIGroup to authorization attributes and test
This commit is contained in:
		@@ -367,6 +367,8 @@ func (r *requestAttributeGetter) GetAttribs(req *http.Request) authorizer.Attrib
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	apiRequestInfo, _ := r.apiRequestInfoResolver.GetAPIRequestInfo(req)
 | 
						apiRequestInfo, _ := r.apiRequestInfoResolver.GetAPIRequestInfo(req)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						attribs.APIGroup = apiRequestInfo.APIGroup
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// If a path follows the conventions of the REST object store, then
 | 
						// If a path follows the conventions of the REST object store, then
 | 
				
			||||||
	// we can extract the resource.  Otherwise, not.
 | 
						// we can extract the resource.  Otherwise, not.
 | 
				
			||||||
	attribs.Resource = apiRequestInfo.Resource
 | 
						attribs.Resource = apiRequestInfo.Resource
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -41,6 +41,9 @@ type Attributes interface {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// The kind of object, if a request is for a REST object.
 | 
						// The kind of object, if a request is for a REST object.
 | 
				
			||||||
	GetResource() string
 | 
						GetResource() string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// The group of the resource, if a request is for a REST object.
 | 
				
			||||||
 | 
						GetAPIGroup() string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Authorizer makes an authorization decision based on information gained by making
 | 
					// Authorizer makes an authorization decision based on information gained by making
 | 
				
			||||||
@@ -61,6 +64,7 @@ type AttributesRecord struct {
 | 
				
			|||||||
	User      user.Info
 | 
						User      user.Info
 | 
				
			||||||
	ReadOnly  bool
 | 
						ReadOnly  bool
 | 
				
			||||||
	Namespace string
 | 
						Namespace string
 | 
				
			||||||
 | 
						APIGroup  string
 | 
				
			||||||
	Resource  string
 | 
						Resource  string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -83,3 +87,7 @@ func (a AttributesRecord) GetNamespace() string {
 | 
				
			|||||||
func (a AttributesRecord) GetResource() string {
 | 
					func (a AttributesRecord) GetResource() string {
 | 
				
			||||||
	return a.Resource
 | 
						return a.Resource
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (a AttributesRecord) GetAPIGroup() string {
 | 
				
			||||||
 | 
						return a.APIGroup
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -792,6 +792,94 @@ func newAuthorizerWithContents(t *testing.T, contents string) authorizer.Authori
 | 
				
			|||||||
	return pl
 | 
						return pl
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type trackingAuthorizer struct {
 | 
				
			||||||
 | 
						requestAttributes []authorizer.Attributes
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (a *trackingAuthorizer) Authorize(attributes authorizer.Attributes) error {
 | 
				
			||||||
 | 
						a.requestAttributes = append(a.requestAttributes, attributes)
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TestAuthorizationAttributeDetermination tests that authorization attributes are built correctly
 | 
				
			||||||
 | 
					func TestAuthorizationAttributeDetermination(t *testing.T) {
 | 
				
			||||||
 | 
						framework.DeleteAllEtcdKeys()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						etcdStorage, err := framework.NewEtcdStorage()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatalf("unexpected error: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						trackingAuthorizer := &trackingAuthorizer{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var m *master.Master
 | 
				
			||||||
 | 
						s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
 | 
				
			||||||
 | 
							m.Handler.ServeHTTP(w, req)
 | 
				
			||||||
 | 
						}))
 | 
				
			||||||
 | 
						defer s.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						m = master.New(&master.Config{
 | 
				
			||||||
 | 
							DatabaseStorage:       etcdStorage,
 | 
				
			||||||
 | 
							KubeletClient:         client.FakeKubeletClient{},
 | 
				
			||||||
 | 
							EnableCoreControllers: true,
 | 
				
			||||||
 | 
							EnableLogsSupport:     false,
 | 
				
			||||||
 | 
							EnableUISupport:       false,
 | 
				
			||||||
 | 
							EnableIndex:           true,
 | 
				
			||||||
 | 
							APIPrefix:             "/api",
 | 
				
			||||||
 | 
							Authenticator:         getTestTokenAuth(),
 | 
				
			||||||
 | 
							Authorizer:            trackingAuthorizer,
 | 
				
			||||||
 | 
							AdmissionControl:      admit.NewAlwaysAdmit(),
 | 
				
			||||||
 | 
							StorageVersions:       map[string]string{"": testapi.Default.Version()},
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						transport := http.DefaultTransport
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						requests := map[string]struct {
 | 
				
			||||||
 | 
							verb               string
 | 
				
			||||||
 | 
							URL                string
 | 
				
			||||||
 | 
							expectedAttributes authorizer.Attributes
 | 
				
			||||||
 | 
						}{
 | 
				
			||||||
 | 
							"prefix/version/resource":       {"GET", "/api/v1/pods", authorizer.AttributesRecord{APIGroup: "", Resource: "pods"}},
 | 
				
			||||||
 | 
							"prefix/group/version/resource": {"GET", "/apis/experimental/v1/pods", authorizer.AttributesRecord{APIGroup: "experimental", Resource: "pods"}},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						currentAuthorizationAttributesIndex := 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for testName, r := range requests {
 | 
				
			||||||
 | 
							token := BobToken
 | 
				
			||||||
 | 
							req, err := http.NewRequest(r.verb, s.URL+r.URL, nil)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								t.Logf("case %v", testName)
 | 
				
			||||||
 | 
								t.Fatalf("unexpected error: %v", err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token))
 | 
				
			||||||
 | 
							func() {
 | 
				
			||||||
 | 
								resp, err := transport.RoundTrip(req)
 | 
				
			||||||
 | 
								defer resp.Body.Close()
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									t.Logf("case %v", r)
 | 
				
			||||||
 | 
									t.Fatalf("unexpected error: %v", err)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								found := false
 | 
				
			||||||
 | 
								for i := currentAuthorizationAttributesIndex; i < len(trackingAuthorizer.requestAttributes); i++ {
 | 
				
			||||||
 | 
									if trackingAuthorizer.requestAttributes[i].GetAPIGroup() == r.expectedAttributes.GetAPIGroup() &&
 | 
				
			||||||
 | 
										trackingAuthorizer.requestAttributes[i].GetResource() == r.expectedAttributes.GetResource() {
 | 
				
			||||||
 | 
										found = true
 | 
				
			||||||
 | 
										break
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									t.Logf("%#v did not match %#v", r.expectedAttributes, trackingAuthorizer.requestAttributes[i].(*authorizer.AttributesRecord))
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if !found {
 | 
				
			||||||
 | 
									t.Errorf("did not find %#v in %#v", r.expectedAttributes, trackingAuthorizer.requestAttributes[currentAuthorizationAttributesIndex:])
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								currentAuthorizationAttributesIndex = len(trackingAuthorizer.requestAttributes)
 | 
				
			||||||
 | 
							}()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TestNamespaceAuthorization tests that authorization can be controlled
 | 
					// TestNamespaceAuthorization tests that authorization can be controlled
 | 
				
			||||||
// by namespace.
 | 
					// by namespace.
 | 
				
			||||||
func TestNamespaceAuthorization(t *testing.T) {
 | 
					func TestNamespaceAuthorization(t *testing.T) {
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user