Group Binding Strategies & Semantics
Vì Sao Quantum Trọng
Group-based access control là backbone để scalable RBAC di large organizations:
- Individual user binding scales poorly — mỗi hire/departure membutuhkan manual binding updates
- Team-based access lebih natural — "grant engineering-team access to prod" vs. enumerating individual engineers
- Directory integration (LDAP, OIDC) populates groups từ authoritative source, reducing manual overhead
- Cross-team collaboration easier với groups — "grant site-reliability-engineers access to X" covers current and future engineers
Nhưng group semantics trong Kubernetes punya subtle implications:
- System groups vs. custom groups punya different semantics
- Group membership populated bởi authentication layer, không authorization
- Understanding group extraction từ tokens crucial để debugging
- Over-relying vào groups without explicit binding lead đến privilege creep
System Groups
Built-in System Groups
Kubernetes define special system groups automatically injected để every request:
| Group | Members | Scope |
|---|---|---|
system:authenticated | All authenticated users & SAs | Every request với valid token/cert |
system:unauthenticated | Requests tanpa authentication | Requests tanpa token/cert (rare) |
system:serviceaccounts | All SAs cluster-wide | Kubelet, in-cluster clients |
system:serviceaccounts:<namespace> | SAs trong namespace cụ thể | Pod trong namespace đó |
system:masters | (Not membership; special case) | Bootstrap, apiserver self-auth |
Example: system:authenticated Group
Mỗi authenticated request automatically trong system:authenticated group:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: basic-viewer
rules:
# Accessible để everyone authenticated
- apiGroups: [""]
resources: ["namespaces"]
verbs: ["list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: authenticated-viewers
roleRef:
kind: ClusterRole
name: basic-viewer
subjects:
- kind: Group
name: system:authenticatedTất cả users và SAs (mà authenticated) có thể list namespaces.
Implementation:
Authenticator processes request, sets request.groups = [... user's groups ..., "system:authenticated"]
Authorization checks: "user trong system:authenticated?" → YES
→ Grant permissions trong bindingsystem:serviceaccounts Group
Mỗi service account automatically trong hai groups:
system:serviceaccounts # cluster-wide SAs group
system:serviceaccounts:<namespace> # namespace-specific SAs groupJadi SA prometheus di namespace monitoring:
Username: system:serviceaccount:monitoring:prometheus
Groups:
- system:serviceaccounts
- system:serviceaccounts:monitoring
- system:authenticatedCó thể use để grant permissions đến all SAs hoặc namespace-specific SAs:
# Grant to ALL SAs in cluster
subjects:
- kind: Group
name: system:serviceaccounts
# Grant to ALL SAs in monitoring namespace
subjects:
- kind: Group
name: system:serviceaccounts:monitoringsystem:masters Special Case
system:masters không phải normal group. Members automatically bypass all authorization:
# Subject với system:masters trong groups
subjects:
- kind: Group
name: system:masters→ User trong group này skip authorization checks entirely. Dangerous, chỉ để bootstrap.
Custom Groups from Authentication
OIDC Integration
OIDC provider (Google, Auth0, Keycloak) có thể populate groups trong token claims:
{
"sub": "alice@example.com",
"email": "alice@example.com",
"groups": ["engineering", "platform-team", "oncall"],
"org": "acme-corp"
}OIDC authenticator trong API server:
kube-apiserver \
--oidc-issuer-url=https://accounts.google.com \
--oidc-client-id=xxx \
--oidc-groups-claim=groupsAuthenticator extracts groups claim từ token, sets request.groups:
Token claims: groups = ["engineering", "platform-team", "oncall"]
Authenticator sets: request.groups = ["engineering", "platform-team", "oncall", "system:authenticated"]Authorization có thể match terhadap custom groups:
subjects:
- kind: Group
name: engineering
---
# Hoặc
subjects:
- kind: Group
name: platform-teamLDAP Integration via External Authenticator
LDAP authenticator có thể query LDAP directory để group membership:
User: alice@example.com
LDAP query: what groups does alice belong to?
LDAP response: ["engineering", "sre", "deployment-approvers"]
Authenticator sets: request.groups = ["engineering", "sre", "deployment-approvers", "system:authenticated"]RBAC binding có thể target LDAP groups:
subjects:
- kind: Group
name: deployment-approvers # From LDAPGroup Extraction & Debugging
How Groups Are Populated
Request Flow:
↓
Authenticator (OIDC, LDAP, x509, etc.)
↓
Extracts groups claim/attribute
↓
Sets request.groups = [user's groups, "system:authenticated", ...]
↓
Authorization checks group membershipKey insight: Groups extracted bởi authenticator, not authorization. Authorization only consumes groups; doesn't generate.
Debugging Missing Groups
Nếu user không punya expected group access:
1. Check token/credentials:
Nếu OIDC:
# Decode token, check groups claim
jq '.groups' <(echo $TOKEN | cut -d. -f2 | base64 -d)Nếu LDAP:
# Query LDAP directly
ldapsearch -x "uid=alice" memberOf2. Check authenticator configuration:
# Verify API server OIDC config
kubectl describe pod kube-apiserver-xxx -n kube-system | grep oidc-
# Verify OIDC provider returning groups3. Check audit log để actual groups:
# Search audit log
grep "alice" /var/log/audit.log | jq '.user.groups'Audit log cho thấy exactly apa groups diset bởi authenticator.
4. Check RBAC bindings:
# Find all bindings để group
kubectl get rolebindings,clusterrolebindings -A -o wide | grep engineering
# Verify binding's role punya necessary permissions
kubectl get rolebinding engineering-deployers -n production -o yamlGroup Binding Patterns
Pattern 1: Org-Wide Permissions via Group
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: engineers-read-all
roleRef:
kind: ClusterRole
name: view # read-only access
subjects:
- kind: Group
name: engineering # All engineers, from OIDC/LDAPMỗi engineer (member từ engineering group trong OIDC) automatically có thể read all resources.
Pattern 2: Team-Specific Access
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
namespace: platform-team
name: platform-admins
roleRef:
kind: ClusterRole
name: admin
subjects:
- kind: Group
name: platform-team # Custom group from LDAP/OIDC
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
namespace: data-team
name: data-admins
roleRef:
kind: ClusterRole
name: admin
subjects:
- kind: Group
name: data-teamTeams có thể self-manage own namespace.
Pattern 3: Role-Based Access Control (RBAC + Groups)
# Deployment approvers (manually curated list trong LDAP)
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: deployment-approver
namespace: production
rules:
- resources: ["deployments"]
verbs: ["update", "patch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: deployment-approvers-binding
namespace: production
roleRef:
kind: Role
name: deployment-approver
subjects:
- kind: Group
name: deployment-approvers # Curated LDAP groupOnly members từ deployment-approvers group có thể approve deployments.
Constraints & Limitations
Limitation 1: Groups Are Strings
Group names arbitrary strings, no validation:
subjects:
- kind: Group
name: "typo-in-grpup" # Misspelled! Won't match anyoneNo warning, silently no match. Debugging requires checking audit log.
Limitation 2: Case Sensitivity
Group names case-sensitive:
- kind: Group
name: "Engineering" # Capital E
---
- kind: Group
name: "engineering" # Lowercase eHai bindings terpisah. Nếu OIDC returns lowercase "engineering" nhưng binding punya "Engineering", no match.
Limitation 3: Group Membership Opaque to Authorization
Authorization layer chỉ checks nếu group trong request.groups list. Không có thể:
- Query nested group membership ("if alice trong group X and X nested trong Y, grant Y permissions")
- Dynamic group membership checks ("grant permissions nếu group size > 10")
- Conditional group checks ("grant nếu alice trong engineering AND trong tier-1")
Tất cả group logic phải di authenticator layer.
Limitation 4: No Negative Constraints
Không có thể say "grant access EXCEPT group X":
# NOT POSSIBLE
subjects:
- kind: Group
name: "NOT contractors"Must use explicit include list hoặc separate RBAC layer.
Multi-Directory Integration
Scenario: Multiple OIDC Providers
Nếu organization punya multiple identity providers (Google workspace, GitHub SAML):
# API server support multiple OIDC issuers via webhook
kube-apiserver \
--authentication-token-webhook-config=/etc/auth/webhook-config.yamlWebhook có thể:
- Validate token từ multiple issuers
- Extract groups từ different claim paths
- Map external groups đến internal Kubernetes groups
Example: Bridging External & Internal Groups
# Webhook logic
if issuer == "google.com":
groups = token.groups
add_group("google-employees")
if issuer == "github.com":
groups = token.organizations
add_group("github-community")
# Result: user trong google.com AND github.com punya:
# request.groups = [
# "engineering" (từ google),
# "kubernetes-sigs" (từ github),
# "google-employees",
# "github-community",
# "system:authenticated"
# ]RBAC có thể target mana saja từ extracted groups.
Group Size & Scalability
Performance: Large Groups
Nếu group punya ribuan members:
Per-request authorization latency ~ O(num_bindings × num_group_members)Không directly — authorization chỉ checks "is user trong group X", not iterating members.
Nhưng nếu cluster punya nhiều groups (thousands):
Number of bindings × number of groups → slower matchingMitigation:
- Keep number of bindings reasonable (< 1000 per cluster)
- Use hierarchical groups (nested trong LDAP) at identity provider level, not Kubernetes
Storage: Group Names in Audit
Audit log stores every user's groups per request:
{
"user": {
"username": "alice",
"groups": ["engineering", "platform-team", "deployment-approvers", "system:authenticated"]
}
}10,000 requests/sec × 4 groups = 40K group entries/sec trong audit log. Có thể cause audit log bloat.
Mitigation:
- Limit group count per user (< 10)
- Compress audit logs, hoặc use audit backend mà support grouping
Best Practices
Best Practice 1: Minimize Group Count per User
Each group increases:
- Token size (OIDC claims)
- Audit log size
- Authorization decision latency (slightly)
Keep to ~5-10 groups per user.
Best Practice 2: Consistent Naming Convention
✓ engineering
✓ platform-team
✓ data-sre
✗ Engineering (inconsistent case)
✗ eng (ambiguous)
✗ "group-123" (opaque)Clear naming để easier debugging và audit.
Best Practice 3: Document Group-to-Role Mappings
# In Kubernetes namespace README hoặc ConfigMap
# RBAC Group Mappings
# - engineering → view (all namespaces), admin (dev/staging)
# - platform-team → admin (platform namespaces)
# - deployment-approvers → approver role (production)Makes source-of-truth explicit.
Best Practice 4: Regular Group Membership Audits
# Extract all groups từ audit log
grep -o '"groups":\[[^]]*\]' /var/log/audit.log | sort -u
# Check nếu orphaned groups (no matching bindings)Detect stale group references.
Summary
Groups trong Kubernetes RBAC:
- System groups automatically included (system:authenticated, system:serviceaccounts:*)
- Custom groups extracted từ authentication provider (OIDC, LDAP)
- Group matching opaque string comparison — no hierarchy or nesting
- Scoping via RoleBinding/ClusterRoleBinding, same as users/SAs
Smart group usage:
- Use groups để team-based access, not individual binding
- Extract từ authoritative identity provider
- Keep group count per user minimal
- Document mappings clearly