Skip to content

RBAC Conditions: Attribute-Based Access Control

Vì Sao Quantum Trọng

Standard RBAC — verb + resource matching — không support fine-grained policies:

  • Cannot restrict by resource labels — "grant get pods, nhưng chỉ pods có label tier=prod"
  • Cannot restrict by request IP — "allow deploy từ CI system IP, deny từ personal laptop"
  • Cannot restrict by time — "allow deployment only 9-5 business hours"
  • Cannot restrict by custom attributes — "allow create secrets, nhưng chỉ nếu secret name match pattern"

RBAC Conditions extend RBAC với attribute-based access control (ABAC) capabilities via CEL (Common Expression Language) expressions.

Understanding conditions crucial để:

  • Fine-grained authorization beyond binary verb+resource match
  • Compliance policies (time-based restrictions, geolocation checks)
  • Security policies (resource label restrictions, network source checks)

RBAC Conditions Mechanism

Conditions in ClusterRole Rules

ClusterRole rules có thể include conditions field:

yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: pod-reader-restricted
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list"]
  conditions:
    resourceRules:
    - apiGroups: [""]
      resources: ["pods"]
      resourceNames: []
    evaluationRules:
    - rule: "resource.labels['tier'] == 'prod'"
    - rule: "request.time.getHours('UTC') >= 9 && request.time.getHours('UTC') <= 17"

Semantics:

  • Rule match permission — user có thể GET pods
  • Conditions further restrict — nhưng chỉ nếu conditions all evaluate true
  • Nếu condition false → authorization DENIED (even nếu rule matched)

CEL Expression Evaluation

CEL (Common Expression Language) là language để writing conditions:

# Simple comparisons
resource.labels['tier'] == 'prod'

# Arithmetic
resource.metadata.generation < 10

# String operations
resource.metadata.name.startsWith('test-')

# Logical operators
(resource.labels['tier'] == 'prod' && request.time.hour >= 9)

Kubernetes API server evaluates expressions; nếu true → ALLOW, nếu false → DENY.

Available Request Attributes

Conditions có thể access request attributes:

AttributeTypeExample
request.user.usernameString"alice@example.com"
request.user.groupsString list["engineers", "system:authenticated"]
request.timeTimestampcó thể call .getHours(), .getDate(), etc.
request.pathStringAPI path /api/v1/namespaces/default/pods
request.verbString"get", "create", etc.
request.sourceIPString"192.168.1.100"
resource.nameStringPod name
resource.namespaceStringNamespace
resource.labels['key']String hoặc nullLabel value

Resource Attributes for Conditions

For resource-level conditions:

AttributeAvailable ForExample
resource.metadata.nameAll resourcesPod name
resource.metadata.labelsAll resourcesLabels map
resource.metadata.ownerReferencesAll resourcesOwner info
resource.spec.selectorSelect resourcesLabel selector

CEL Expression Examples

Example 1: Production Pods Only

Restrict access đến pods với label tier=prod:

yaml
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list", "delete"]
  conditions:
    evaluationRules:
    - rule: "resource.labels['tier'] == 'prod'"

User có thể delete pods, nhưng chỉ nếu pod labeled tier=prod.

Example 2: Time-Bounded Access

Allow deployments chỉ during business hours:

yaml
rules:
- apiGroups: ["apps"]
  resources: ["deployments"]
  verbs: ["create", "update"]
  conditions:
    evaluationRules:
    - rule: |
        request.time.getHours('UTC') >= 9 
        && request.time.getHours('UTC') <= 17
        && request.time.getDayOfWeek('UTC') >= 1
        && request.time.getDayOfWeek('UTC') <= 5

Deployments có thể được tạo/updated chỉ Monday-Friday, 9am-5pm UTC.

Example 3: IP-Based Restrictions

Allow kubelet và CI system chỉ:

yaml
rules:
- apiGroups: [""]
  resources: ["nodes"]
  verbs: ["update"]
  conditions:
    evaluationRules:
    - rule: |
        request.sourceIP.startsWith('10.0.1.')
        || request.sourceIP == '192.168.100.5'

Node updates từ request IP di range 10.0.1.0/24 hoặc CI IP.

Example 4: Resource Name Patterns

Restrict đến resources matching pattern:

yaml
rules:
- apiGroups: [""]
  resources: ["configmaps"]
  verbs: ["create", "update"]
  conditions:
    evaluationRules:
    - rule: "resource.metadata.name.startsWith('team-specific-')"

Can create/update ConfigMaps chỉ nếu name start với "team-specific-".

Example 5: Complex: Org-Wide Policy

Only SREs có thể scale deployments với memory > 2Gi:

yaml
rules:
- apiGroups: ["apps"]
  resources: ["deployments"]
  verbs: ["update", "patch"]
  conditions:
    evaluationRules:
    - rule: |
        (request.user.groups.contains('sre-team') 
         || request.user.groups.contains('platform-team'))
        && has(resource.spec.template.spec.containers[0].resources.requests.memory)

Multiple conditions combined: role-based (group check) + resource-based (memory check).

Feature Status & Enablement

Alpha Status

RBAC Conditions masih Alpha di Kubernetes 1.30+. Enablement:

bash
kube-apiserver --feature-gates=AuthorizeWithConditions=true

Enable để API server và authorization webhooks.

Limitations of Current Implementation

  1. Performance — CEL evaluation adds latency đến mỗi authorization decision

    • Estimated 1-5ms per condition evaluation
    • Saat scale (10K requests/sec), significant overhead
  2. Expression language — CEL punya limitations:

    • Cannot call external services
    • Cannot access etcd directly
    • Cannot modify resources (only read)
  3. Debugging — CEL error messages không selalu clear:

    Error evaluating condition: undefined reference to 'foo'

    Debugging require careful inspection expression.

  4. No condition on verb — Cannot write:

    yaml
    rule: "request.verb == 'delete' && request.time.hour >= 22"
    # Won't work; conditions evaluate after verb match

Conditions vs. Webhooks

When to Use Conditions

RequirementConditionsWebhook
Simple attribute checks
Performance critical
No external calls
Complex business logic
Offline availability

Conditions ideal để:

  • Label-based restrictions
  • Time/IP-based policies
  • Simple attribute checks
  • Policies mà không thay đổi frequently

Webhooks ideal để:

  • Complex business logic
  • Integration với external systems (policy engine)
  • Dynamic policies
  • Policies maintained externally

Example: Conditions vs. Webhook

Scenario: Allow delete pods chỉ nếu pod trong grace-period bởi policy engine.

Conditions approach:

yaml
# Can't query external policy engine trong condition
# Not possible

Webhook approach:

Authorization → Webhook call → Policy engine → decision

Practical Patterns

Pattern 1: Environment-Specific Permissions

Different permissions để dev vs. prod:

yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: developer
rules:
- apiGroups: ["apps"]
  resources: ["deployments"]
  verbs: ["create", "update", "delete"]
  conditions:
    evaluationRules:
    - rule: "resource.metadata.namespace.startsWith('dev-')"
      
- apiGroups: ["apps"]
  resources: ["deployments"]
  verbs: ["get", "list"]
  conditions:
    evaluationRules:
    - rule: "resource.metadata.namespace.startsWith('prod-')"
    # Get/list only, no create/update/delete

Developers full access dev namespaces, read-only prod.

Pattern 2: Scheduled Maintenance Windows

Allow cluster changes trong maintenance window:

yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: maintenance-operator
rules:
- apiGroups: ["apps", ""]
  resources: ["deployments", "pods"]
  verbs: ["update", "delete"]
  conditions:
    evaluationRules:
    - rule: |
        request.time.getDayOfWeek('UTC') == 6
        && request.time.getHours('UTC') >= 23

Changes allowed chỉ Saturday nights (23:00 UTC).

Anti-Patterns & Gotchas

Anti-Pattern 1: Over-Complex Conditions

yaml
# Awful: CEL becomes hard to read
rule: |
  (request.user.groups.contains('sre') || request.user.groups.contains('platform')) 
  && (resource.labels['env'] == 'prod' || resource.labels['env'] == 'staging')
  && (request.time.getHours('UTC') >= 9 && request.time.getHours('UTC') <= 17)
  && (request.sourceIP.startsWith('10.0.') || request.sourceIP.startsWith('192.168.'))

Better: split đến multiple rules hoặc use webhook.

Anti-Pattern 2: Time-Based Restrictions as Security

yaml
rule: "request.time.getHours('UTC') >= 22"  # "After hours only"

Problem: Attackers có thể set system clock forward. Time conditions không phải security boundary, chỉ audit/compliance tool.

Anti-Pattern 3: Assuming Conditions Cache

# Không true: conditions evaluated mỗi request
# Jangan expect caching hoặc optimization

CEL evaluates fresh per request. No assumptions về caching.

Troubleshooting Conditions

Issue 1: Condition Syntax Error

Error: invalid condition: undefined reference to 'xyz'

Debug:

bash
# Test condition expression với kubebuilder hoặc standalone CEL
# Check attribute names và types available

Issue 2: Condition Evaluates Wrong

bash
# Enable audit logging để see actual attribute values
kubectl patch clusterrole some-role -p '{"metadata":{"labels":{"debug":"true"}}}'

# Check audit log với full resource object

Issue 3: Performance Degradation

Authorization latency increased after enabling conditions

Causes:

  • Too many conditions per rule
  • Conditions evaluating large resource objects

Mitigation:

  • Limit conditions per rule
  • Use resourceRules filter để reduce evaluations
  • Consider webhook nếu conditions too complex

Summary

RBAC Conditions enable fine-grained authorization:

  • Extend RBAC với attribute checks (labels, time, IP, request attributes)
  • CEL expressions để writing conditions
  • Per-rule scoping — conditions apply đến specific rule, not role
  • Alpha feature — performance/stability implications

Use conditions để:

  • Environmental (label-based) access control
  • Time-based policies
  • IP restrictions
  • Simple attribute checks

Use webhooks để:

  • Complex business logic
  • External policy integration
  • Dynamic policies

Tham Khảo