1
0
mirror of https://github.com/rancher/steve.git synced 2025-09-15 14:58:52 +00:00

refactor(accesscontrol): add unit tests for CacheKey (#245)

This is a follow up to 435e220 with a small refactor to make the function easier to test, and adding unit tests for CacheKey.
This commit is contained in:
Alejandro Ruiz
2024-08-28 10:06:21 +02:00
committed by GitHub
parent 01429f8528
commit 32c30149a6
3 changed files with 367 additions and 39 deletions

View File

@@ -4,10 +4,12 @@ import (
"context"
"crypto/sha256"
"encoding/hex"
"hash"
"sort"
"time"
v1 "github.com/rancher/wrangler/v3/pkg/generated/controllers/rbac/v1"
rbacv1 "k8s.io/api/rbac/v1"
"k8s.io/apimachinery/pkg/util/cache"
"k8s.io/apiserver/pkg/authentication/user"
)
@@ -19,10 +21,21 @@ type AccessSetLookup interface {
PurgeUserData(id string)
}
type policyRules interface {
get(string) *AccessSet
getRoleBindings(string) []*rbacv1.RoleBinding
getClusterRoleBindings(string) []*rbacv1.ClusterRoleBinding
}
type roleRevisions interface {
roleRevision(string, string) string
}
type AccessStore struct {
users *policyRuleIndex
groups *policyRuleIndex
cache *cache.LRUExpireCache
usersPolicyRules policyRules
groupsPolicyRules policyRules
roles roleRevisions
cache *cache.LRUExpireCache
}
type roleKey struct {
@@ -31,10 +44,10 @@ type roleKey struct {
}
func NewAccessStore(ctx context.Context, cacheResults bool, rbac v1.Interface) *AccessStore {
revisions := newRoleRevision(ctx, rbac)
as := &AccessStore{
users: newPolicyRuleIndex(true, revisions, rbac),
groups: newPolicyRuleIndex(false, revisions, rbac),
usersPolicyRules: newPolicyRuleIndex(true, rbac),
groupsPolicyRules: newPolicyRuleIndex(false, rbac),
roles: newRoleRevision(ctx, rbac),
}
if cacheResults {
as.cache = cache.NewLRUExpireCache(50)
@@ -53,9 +66,9 @@ func (l *AccessStore) AccessFor(user user.Info) *AccessSet {
}
}
result := l.users.get(user.GetName())
result := l.usersPolicyRules.get(user.GetName())
for _, group := range user.GetGroups() {
result.Merge(l.groups.get(group))
result.Merge(l.groupsPolicyRules.get(group))
}
if l.cache != nil {
@@ -73,16 +86,30 @@ func (l *AccessStore) PurgeUserData(id string) {
func (l *AccessStore) CacheKey(user user.Info) string {
d := sha256.New()
l.users.addRolesToHash(d, user.GetName())
groupBase := user.GetGroups()
groups := make([]string, len(groupBase))
copy(groups, groupBase)
sort.Strings(groups)
l.addRolesToHash(d, user.GetName(), l.usersPolicyRules)
for _, group := range groups {
l.groups.addRolesToHash(d, group)
l.addRolesToHash(d, group, l.groupsPolicyRules)
}
return hex.EncodeToString(d.Sum(nil))
}
func (l *AccessStore) addRolesToHash(digest hash.Hash, subjectName string, rules policyRules) {
for _, crb := range rules.getClusterRoleBindings(subjectName) {
digest.Write([]byte(crb.RoleRef.Name))
digest.Write([]byte(l.roles.roleRevision("", crb.RoleRef.Name)))
}
for _, rb := range rules.getRoleBindings(subjectName) {
digest.Write([]byte(rb.RoleRef.Name))
if rb.Namespace != "" {
digest.Write([]byte(rb.Namespace))
}
digest.Write([]byte(l.roles.roleRevision(rb.Namespace, rb.RoleRef.Name)))
}
}