-
Notifications
You must be signed in to change notification settings - Fork 1
feat: Implement permission trie for RBAC authorization optimization #57
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
…g and enhance error logging
…roxy into feat/enhance-rbac
Add test cases for authorizer and permission trie
c8978df
to
e36060a
Compare
type PermissionTrie struct { | ||
subjectNodes map[string]*SubjectNode | ||
mu sync.RWMutex | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not understand how this is a Trie. Can you please explain what happens here? Thanks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The PermissionTrie acts as a high-speed index for RBAC rules. Understood it as a hierarchical lookup tree where each level represents a different dimension of a Kubernetes permission. It uses the core principle of a trie: a path through the structure represents a key. In this case, the "key" is the combination of Subject, Cluster, Namespace, APIGroup, and Resource. This avoids re-evaluating a long list of rules for every single API request.
How It Works
Storing Permissions
When an RBAC rule is loaded, we create a path in the tree to represent it. Let's say we add a permission for user "bob" to "delete" "pods" in the "dev" namespace on cluster "production":
- Subject Level: Find/create the node for User: "bob".
- Cluster Level: Find/create the node for Cluster: "production".
- Namespace Level: Find/create the node for Namespace: "dev".
- API Group Level: Find/create the node for API group "" (the core API).
- Resource Level: Find/create the final node for Resource: "pods".
- Store Verb: At this final node, we update a bitmask to add the delete permission.
Checking Permissions
When checking if user "bob" can "delete" a pod in the "dev" namespace:
- Traversal: The code rapidly traverses the tree following the request's attributes: User: "bob" -> Cluster: "production" -> Namespace: "dev" -> API Group: "" -> Resource: "pods".
- Check: At the final node, it checks if the delete verb is present in the permission bitmask. In this case, it is. ✅ Access Granted.
If no rule were found for the "dev" namespace, the lookup would automatically fall back and check again using the cluster-wide namespace ("") to see if permission was granted or not.
Example Tree Structure
Here is a visual representation with annotations explaining what each path represents.
PermissionTrie
├── User:alice (SubjectNode)
│ └── cluster1 (ClusterNode)
│ ├── "" (NamespaceNode) // Cluster-wide rule
│ │ └── apps (APIGroupNode)
│ │ └── deployments (ResourceNode)
│ │ └── verbs: [get, list]
│ └── default (NamespaceNode) // Namespace-specific rule from a Role
│ └── "" (APIGroupNode - core API)
│ └── pods (ResourceNode)
│ └── verbs: [get, list, watch]
│
└── Group:dev-team (SubjectNode)
└── cluster1 (ClusterNode)
└── * (URLNode) // Non-resource URL rule (e.g., for /healthz)
└── verbs: [get]
This PR implements a permission trie structure to replace the nested loop-based RBAC authorization system, reducing authorization time.
Fixes Issue
Closes #58
Changes proposed
Backward Compatibility
Check List (Check all the applicable boxes)
Screenshots
Note to reviewers