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/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 } 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