From 536d36c706969a7d9f5cfc84b2582158dd4663a5 Mon Sep 17 00:00:00 2001 From: Craig Jellick Date: Wed, 31 Jan 2018 10:42:59 -0700 Subject: [PATCH 1/2] Fixes for subtypes Change key method (used to find CRD that backs the schema) to use baseType of the schema when it differs from the schema ID. This will allow subtypes to use their base type's CRD store. When creating CRD stores, do not create one for a schema if it is a baseType. --- store/crd/crd_store.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/store/crd/crd_store.go b/store/crd/crd_store.go index dc6f26736..9a2510353 100644 --- a/store/crd/crd_store.go +++ b/store/crd/crd_store.go @@ -2,6 +2,7 @@ package crd import ( "context" + "strings" "github.com/rancher/norman/store/proxy" "github.com/rancher/norman/types" @@ -49,6 +50,10 @@ func NewCRDStoreFromClients(apiExtClientSet apiextclientset.Interface, k8sClient } func key(schema *types.Schema) string { + if !strings.EqualFold(schema.BaseType, schema.ID) { + return schema.Version.Path + "/" + schema.BaseType + } + return schema.Version.Path + "/" + schema.ID } @@ -105,7 +110,7 @@ func (c *Store) AddSchemas(ctx context.Context, schemas ...*types.Schema) error var allSchemas []*types.Schema for _, schema := range schemas { - if schema.Store != nil || !schema.CanList(nil) { + if schema.Store != nil || !schema.CanList(nil) || !strings.EqualFold(schema.BaseType, schema.ID) { continue } From 65807e93724f85a743ad14a4a6c8a22fb7f10f51 Mon Sep 17 00:00:00 2001 From: Craig Jellick Date: Wed, 31 Jan 2018 19:14:35 -0700 Subject: [PATCH 2/2] Distinguish between listing and getting We now have resources (subtypes of authConfig) that can be retrieved by ID but their collections are not viewable. This change is needed to suppport that. --- api/server.go | 16 +++++++++++----- authorization/all.go | 4 ++++ store/schema/schema_store.go | 2 +- types/schema_funcs.go | 7 +++++++ types/server_types.go | 1 + 5 files changed, 24 insertions(+), 6 deletions(-) diff --git a/api/server.go b/api/server.go index 5a2296d20..d473920c5 100644 --- a/api/server.go +++ b/api/server.go @@ -186,26 +186,32 @@ func (s *Server) handle(rw http.ResponseWriter, req *http.Request) (*types.APICo if apiRequest.Link == "" { switch apiRequest.Method { case http.MethodGet: - if !apiRequest.AccessControl.CanList(apiRequest, apiRequest.Schema) { - return apiRequest, httperror.NewAPIError(httperror.PermissionDenied, "Can not list "+apiRequest.Schema.Type) + if apiRequest.ID == "" { + if !apiRequest.AccessControl.CanList(apiRequest, apiRequest.Schema) { + return apiRequest, httperror.NewAPIError(httperror.PermissionDenied, "Can not list "+apiRequest.Schema.ID) + } + } else { + if !apiRequest.AccessControl.CanGet(apiRequest, apiRequest.Schema) { + return apiRequest, httperror.NewAPIError(httperror.PermissionDenied, "Can not get "+apiRequest.Schema.ID) + } } handler = apiRequest.Schema.ListHandler nextHandler = s.Defaults.ListHandler case http.MethodPost: if !apiRequest.AccessControl.CanCreate(apiRequest, apiRequest.Schema) { - return apiRequest, httperror.NewAPIError(httperror.PermissionDenied, "Can not create "+apiRequest.Schema.Type) + return apiRequest, httperror.NewAPIError(httperror.PermissionDenied, "Can not create "+apiRequest.Schema.ID) } handler = apiRequest.Schema.CreateHandler nextHandler = s.Defaults.CreateHandler case http.MethodPut: if !apiRequest.AccessControl.CanUpdate(apiRequest, nil, apiRequest.Schema) { - return apiRequest, httperror.NewAPIError(httperror.PermissionDenied, "Can not update "+apiRequest.Schema.Type) + return apiRequest, httperror.NewAPIError(httperror.PermissionDenied, "Can not update "+apiRequest.Schema.ID) } handler = apiRequest.Schema.UpdateHandler nextHandler = s.Defaults.UpdateHandler case http.MethodDelete: if !apiRequest.AccessControl.CanDelete(apiRequest, nil, apiRequest.Schema) { - return apiRequest, httperror.NewAPIError(httperror.PermissionDenied, "Can not delete "+apiRequest.Schema.Type) + return apiRequest, httperror.NewAPIError(httperror.PermissionDenied, "Can not delete "+apiRequest.Schema.ID) } handler = apiRequest.Schema.DeleteHandler nextHandler = s.Defaults.DeleteHandler diff --git a/authorization/all.go b/authorization/all.go index 2e6e4d48f..fc7821c4f 100644 --- a/authorization/all.go +++ b/authorization/all.go @@ -14,6 +14,10 @@ func (*AllAccess) CanCreate(apiContext *types.APIContext, schema *types.Schema) return slice.ContainsString(schema.CollectionMethods, http.MethodPost) } +func (*AllAccess) CanGet(apiContext *types.APIContext, schema *types.Schema) bool { + return slice.ContainsString(schema.ResourceMethods, http.MethodGet) +} + func (*AllAccess) CanList(apiContext *types.APIContext, schema *types.Schema) bool { return slice.ContainsString(schema.CollectionMethods, http.MethodGet) } diff --git a/store/schema/schema_store.go b/store/schema/schema_store.go index b557510d7..6ba91c5f2 100644 --- a/store/schema/schema_store.go +++ b/store/schema/schema_store.go @@ -74,7 +74,7 @@ func (s *Store) List(apiContext *types.APIContext, schema *types.Schema, opt *ty continue } - if schema.CanList(apiContext) { + if schema.CanList(apiContext) || schema.CanGet(apiContext) { schemas = s.addSchema(apiContext, schema, schemaMap, schemas, included) } } diff --git a/types/schema_funcs.go b/types/schema_funcs.go index 130f0e980..a6f26b9de 100644 --- a/types/schema_funcs.go +++ b/types/schema_funcs.go @@ -28,6 +28,13 @@ func (s *Schema) CanList(context *APIContext) bool { return context.AccessControl.CanList(context, s) } +func (s *Schema) CanGet(context *APIContext) bool { + if context == nil { + return slice.ContainsString(s.ResourceMethods, http.MethodGet) + } + return context.AccessControl.CanGet(context, s) +} + func (s *Schema) CanCreate(context *APIContext) bool { if context == nil { return slice.ContainsString(s.CollectionMethods, http.MethodPost) diff --git a/types/server_types.go b/types/server_types.go index f38d7fda6..14752d142 100644 --- a/types/server_types.go +++ b/types/server_types.go @@ -71,6 +71,7 @@ type ResponseWriter interface { type AccessControl interface { CanCreate(apiContext *APIContext, schema *Schema) bool CanList(apiContext *APIContext, schema *Schema) bool + CanGet(apiContext *APIContext, schema *Schema) bool CanUpdate(apiContext *APIContext, obj map[string]interface{}, schema *Schema) bool CanDelete(apiContext *APIContext, obj map[string]interface{}, schema *Schema) bool