2019-08-04 17:41:32 +00:00
|
|
|
package accesscontrol
|
|
|
|
|
|
|
|
import (
|
2022-10-10 18:49:05 +00:00
|
|
|
apiserver "github.com/rancher/apiserver/pkg/server"
|
2020-06-12 04:50:59 +00:00
|
|
|
"github.com/rancher/apiserver/pkg/types"
|
|
|
|
"github.com/rancher/steve/pkg/attributes"
|
2024-06-04 18:52:48 +00:00
|
|
|
"github.com/rancher/wrangler/v3/pkg/kv"
|
2021-05-19 05:34:46 +00:00
|
|
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
2019-08-04 17:41:32 +00:00
|
|
|
)
|
|
|
|
|
2025-06-03 10:46:37 +00:00
|
|
|
const accessSetAttribute = "accessSet"
|
|
|
|
|
2019-08-04 17:41:32 +00:00
|
|
|
type AccessControl struct {
|
2022-10-10 18:49:05 +00:00
|
|
|
apiserver.SchemaBasedAccess
|
2019-08-04 17:41:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func NewAccessControl() *AccessControl {
|
|
|
|
return &AccessControl{}
|
|
|
|
}
|
|
|
|
|
2021-05-19 05:34:46 +00:00
|
|
|
func (a *AccessControl) CanDo(apiOp *types.APIRequest, resource, verb, namespace, name string) error {
|
|
|
|
apiSchema := apiOp.Schemas.LookupSchema(resource)
|
|
|
|
if apiSchema != nil && attributes.GVK(apiSchema).Kind != "" {
|
|
|
|
access := GetAccessListMap(apiSchema)
|
|
|
|
if access[verb].Grants(namespace, name) {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
group, resource := kv.Split(resource, "/")
|
2025-06-03 10:46:37 +00:00
|
|
|
accessSet := AccessSetFromAPIRequest(apiOp)
|
|
|
|
if accessSet != nil && accessSet.Grants(verb, schema.GroupResource{
|
2021-05-19 05:34:46 +00:00
|
|
|
Group: group,
|
|
|
|
Resource: resource,
|
|
|
|
}, namespace, name) {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return a.SchemaBasedAccess.CanDo(apiOp, resource, verb, namespace, name)
|
|
|
|
}
|
|
|
|
|
2020-01-31 05:37:59 +00:00
|
|
|
func (a *AccessControl) CanWatch(apiOp *types.APIRequest, schema *types.APISchema) error {
|
2020-06-12 04:50:59 +00:00
|
|
|
if attributes.GVK(schema).Kind != "" {
|
|
|
|
access := GetAccessListMap(schema)
|
|
|
|
if _, ok := access["watch"]; ok {
|
|
|
|
return nil
|
|
|
|
}
|
2019-08-04 17:41:32 +00:00
|
|
|
}
|
2020-06-12 04:50:59 +00:00
|
|
|
return a.SchemaBasedAccess.CanWatch(apiOp, schema)
|
2019-08-04 17:41:32 +00:00
|
|
|
}
|
2025-06-03 10:46:37 +00:00
|
|
|
|
|
|
|
// SetAccessSetAttribute stores the provided accessSet using a predefined attribute
|
|
|
|
func SetAccessSetAttribute(schemas *types.APISchemas, accessSet *AccessSet) {
|
|
|
|
if schemas.Attributes == nil {
|
|
|
|
schemas.Attributes = map[string]interface{}{}
|
|
|
|
}
|
|
|
|
schemas.Attributes[accessSetAttribute] = accessSet
|
|
|
|
}
|
|
|
|
|
|
|
|
// AccessSetFromAPIRequest retrieves an AccessSet from the APIRequest Schemas attributes, if defined.
|
|
|
|
// This attribute must have been previously set by using SetAccessSetAttribute
|
|
|
|
func AccessSetFromAPIRequest(req *types.APIRequest) *AccessSet {
|
|
|
|
if req == nil || req.Schemas == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
if v, ok := req.Schemas.Attributes[accessSetAttribute]; ok {
|
|
|
|
return v.(*AccessSet)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|