mirror of
https://github.com/rancher/steve.git
synced 2025-08-13 12:05:22 +00:00
Calculate AccessSets once per request instead of per resource (#647)
This commit is contained in:
parent
55a1b940a0
commit
06fe9c3ef4
@ -8,6 +8,8 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const accessSetAttribute = "accessSet"
|
||||||
|
|
||||||
type AccessControl struct {
|
type AccessControl struct {
|
||||||
apiserver.SchemaBasedAccess
|
apiserver.SchemaBasedAccess
|
||||||
}
|
}
|
||||||
@ -25,8 +27,8 @@ func (a *AccessControl) CanDo(apiOp *types.APIRequest, resource, verb, namespace
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
group, resource := kv.Split(resource, "/")
|
group, resource := kv.Split(resource, "/")
|
||||||
accessSet := apiOp.Schemas.Attributes["accessSet"].(*AccessSet)
|
accessSet := AccessSetFromAPIRequest(apiOp)
|
||||||
if accessSet.Grants(verb, schema.GroupResource{
|
if accessSet != nil && accessSet.Grants(verb, schema.GroupResource{
|
||||||
Group: group,
|
Group: group,
|
||||||
Resource: resource,
|
Resource: resource,
|
||||||
}, namespace, name) {
|
}, namespace, name) {
|
||||||
@ -44,3 +46,23 @@ func (a *AccessControl) CanWatch(apiOp *types.APIRequest, schema *types.APISchem
|
|||||||
}
|
}
|
||||||
return a.SchemaBasedAccess.CanWatch(apiOp, schema)
|
return a.SchemaBasedAccess.CanWatch(apiOp, schema)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
@ -181,27 +181,29 @@ func (p *policyRuleIndex) getRoleBindings(subjectName string) []*rbacv1.RoleBind
|
|||||||
|
|
||||||
// getRoleRefs gathers rules from roles granted to a given subject through RoleBindings and ClusterRoleBindings
|
// getRoleRefs gathers rules from roles granted to a given subject through RoleBindings and ClusterRoleBindings
|
||||||
func (p *policyRuleIndex) getRoleRefs(subjectName string) subjectGrants {
|
func (p *policyRuleIndex) getRoleRefs(subjectName string) subjectGrants {
|
||||||
var clusterRoleBindings []roleRef
|
crbs := p.getClusterRoleBindings(subjectName)
|
||||||
for _, crb := range p.getClusterRoleBindings(subjectName) {
|
clusterRoleBindings := make([]roleRef, len(crbs))
|
||||||
|
for x, crb := range crbs {
|
||||||
rules, resourceVersion := p.getRules(All, crb.RoleRef)
|
rules, resourceVersion := p.getRules(All, crb.RoleRef)
|
||||||
clusterRoleBindings = append(clusterRoleBindings, roleRef{
|
clusterRoleBindings[x] = roleRef{
|
||||||
roleName: crb.RoleRef.Name,
|
roleName: crb.RoleRef.Name,
|
||||||
resourceVersion: resourceVersion,
|
resourceVersion: resourceVersion,
|
||||||
rules: rules,
|
rules: rules,
|
||||||
kind: clusterRoleKind,
|
kind: clusterRoleKind,
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var roleBindings []roleRef
|
rbs := p.getRoleBindings(subjectName)
|
||||||
for _, rb := range p.getRoleBindings(subjectName) {
|
roleBindings := make([]roleRef, len(rbs))
|
||||||
|
for x, rb := range rbs {
|
||||||
rules, resourceVersion := p.getRules(rb.Namespace, rb.RoleRef)
|
rules, resourceVersion := p.getRules(rb.Namespace, rb.RoleRef)
|
||||||
roleBindings = append(roleBindings, roleRef{
|
roleBindings[x] = roleRef{
|
||||||
roleName: rb.RoleRef.Name,
|
roleName: rb.RoleRef.Name,
|
||||||
namespace: rb.Namespace,
|
namespace: rb.Namespace,
|
||||||
resourceVersion: resourceVersion,
|
resourceVersion: resourceVersion,
|
||||||
rules: rules,
|
rules: rules,
|
||||||
kind: roleKind,
|
kind: roleKind,
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return subjectGrants{
|
return subjectGrants{
|
||||||
|
@ -102,10 +102,13 @@ func formatter(summarycache common.SummaryCache, asl accesscontrol.AccessSetLook
|
|||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
accessSet := asl.AccessFor(userInfo)
|
accessSet := accesscontrol.AccessSetFromAPIRequest(request)
|
||||||
|
if accessSet == nil {
|
||||||
|
accessSet = asl.AccessFor(userInfo)
|
||||||
if accessSet == nil {
|
if accessSet == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
}
|
||||||
hasUpdate := accessSet.Grants("update", gvr.GroupResource(), resource.APIObject.Namespace(), resource.APIObject.Name())
|
hasUpdate := accessSet.Grants("update", gvr.GroupResource(), resource.APIObject.Namespace(), resource.APIObject.Name())
|
||||||
hasDelete := accessSet.Grants("delete", gvr.GroupResource(), resource.APIObject.Namespace(), resource.APIObject.Name())
|
hasDelete := accessSet.Grants("delete", gvr.GroupResource(), resource.APIObject.Namespace(), resource.APIObject.Name())
|
||||||
hasPatch := accessSet.Grants("patch", gvr.GroupResource(), resource.APIObject.Namespace(), resource.APIObject.Name())
|
hasPatch := accessSet.Grants("patch", gvr.GroupResource(), resource.APIObject.Namespace(), resource.APIObject.Name())
|
||||||
|
@ -171,9 +171,7 @@ func (c *Collection) schemasForSubject(access *accesscontrol.AccessSet) (*types.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result.Attributes = map[string]interface{}{
|
accesscontrol.SetAccessSetAttribute(result, access)
|
||||||
"accessSet": access,
|
|
||||||
}
|
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user