Back to Guides
Advanced
60 minutes

Custom RBAC Policies

Master TigerAccess role-based access control. Create sophisticated policies with label selectors, time-based access, and approval workflows.

Overview

TigerAccess RBAC provides fine-grained access control with:

  • Label-Based Access: Dynamic resource selection using labels
  • Allow/Deny Rules: Explicit permission and restriction policies
  • Time Constraints: Temporary access and business hours restrictions
  • Approval Workflows: Just-in-time access with peer approval

Prerequisites

  • TigerAccess cluster running with auth service
  • Admin access (editor role) to create roles
  • Resources (nodes, databases, clusters) labeled appropriately
  • Understanding of your organization's access requirements

Role Basics

Basic Role Structure

kind: role
version: v7
metadata:
  name: example-role
  description: "Description of what this role provides"
spec:
  # Allow rules - what is permitted
  allow:
    logins: ["ubuntu", "ec2-user"]
    node_labels:
      env: ["development", "staging"]

  # Deny rules - explicit restrictions (takes precedence)
  deny:
    node_labels:
      team: ["finance"]

  # Role options
  options:
    max_session_ttl: "8h"
    require_session_mfa: false

Create a Role

# Create from spec
tac roles create developer --spec - <<EOF
# ... role spec ...
EOF

# Or from file
tac roles create developer --spec=developer-role.yaml

# Assign to user
tac users update alice --add-role=developer

Label Selectors

SSH Node Labels

allow:
  logins: ["ubuntu", "admin"]
  # Match multiple label values
  node_labels:
    env: ["development", "staging"]
    region: ["us-east-1", "us-west-2"]
    team: ["backend"]

  # Wildcard matching
  node_labels:
    env: "*"  # All environments
    hostname: "web-*"  # Hosts starting with web-

  # Regular expressions
  node_labels:
    env: "^(dev|test).*$"

Database Labels

allow:
  db_labels:
    env: ["development"]
    type: ["postgres", "mysql"]
  db_names: ["*"]  # All databases
  db_users: ["readonly", "readwrite"]

deny:
  # Explicitly deny production databases
  db_labels:
    env: ["production"]
  # Deny specific databases
  db_names: ["sensitive_data", "financial_records"]

Kubernetes Labels

allow:
  kubernetes_labels:
    env: ["staging"]
    region: ["us-east-1"]

  kubernetes_resources:
    # Allow read-only access to all pods
    - kind: pod
      namespace: "*"
      name: "*"
      verbs: ["get", "list", "watch"]

    # Allow full access to specific namespace
    - kind: "*"
      namespace: "team-backend"
      name: "*"
      verbs: ["*"]

  kubernetes_groups:
    - "view"
    - "edit"

Time-Based Access

Business Hours Restriction

kind: role
version: v7
metadata:
  name: business-hours-access
spec:
  allow:
    node_labels:
      env: ["production"]

  options:
    # Only allow access during business hours
    access_schedule:
      timezone: "America/New_York"
      windows:
        - days: ["monday", "tuesday", "wednesday", "thursday", "friday"]
          start_time: "09:00"
          end_time: "17:00"

On-Call Access

kind: role
version: v7
metadata:
  name: on-call-engineer
spec:
  allow:
    node_labels:
      env: ["production"]

  options:
    # 24/7 access for on-call
    max_session_ttl: "4h"
    # But requires MFA
    require_session_mfa: true
    # Auto-revoke after 7 days
    max_connections: 100
    cert_ttl: "168h"

Temporary Access

# Grant temporary access to user
tac users update alice --add-role=prod-access --ttl=8h

# Or create a temporary role assignment
tac access-list create contractor-access --spec - <<EOF
kind: access_list
version: v1
metadata:
  name: contractor-access
spec:
  members:
    - "contractor@example.com"
  grants:
    roles: ["developer"]
  expires: "2024-12-31T23:59:59Z"
EOF

Access Request Workflow

Requestable Role

kind: role
version: v7
metadata:
  name: prod-access-request
spec:
  allow:
    node_labels:
      env: ["production"]
    logins: ["ubuntu"]
    request:
      # Users can request this role
      roles: ["prod-access"]
      # Require specific reason
      claims_to_roles:
        - claim: "reason"
          value: "*incident*"

  options:
    # Require approval
    require_session_mfa: true
    # Max request duration
    max_session_ttl: "2h"

Approval Plugin

kind: role
version: v7
metadata:
  name: approver
spec:
  allow:
    # Can approve requests for prod-access
    review_requests:
      roles: ["prod-access"]
    # Slack integration for approvals
    plugins:
      - name: slack
        settings:
          webhook_url: "https://hooks.slack.com/..."
          channel: "#access-requests"

Request Access

# User requests access
tac request create --roles=prod-access \
  --reason="Incident INC-123: investigating database performance" \
  --duration=2h

# Approver reviews
tac requests ls
tac requests approve REQUEST_ID

# Or deny
tac requests deny REQUEST_ID --reason="Need more details"

Advanced Patterns

Trait-Based Access

# Use user traits for dynamic access
allow:
  node_labels:
    # Access based on user's team trait
    team: "{{internal.user_traits.team}}"
    # Access based on user's department
    department: "{{external.department}}"

  logins:
    # Username derived from email
    - "{{internal.user_traits.username}}"
    - "{{external.preferred_username}}"

Multi-Tier Access

# Junior Developer - Limited access
kind: role
metadata:
  name: junior-dev
spec:
  allow:
    node_labels:
      env: ["development"]
    logins: ["deploy"]
  deny:
    node_labels:
      critical: ["true"]

---
# Senior Developer - More access
kind: role
metadata:
  name: senior-dev
spec:
  allow:
    node_labels:
      env: ["development", "staging"]
    logins: ["deploy", "admin"]
  options:
    # Can request production access
    request:
      roles: ["prod-access"]

---
# Principal Engineer - Full access
kind: role
metadata:
  name: principal-engineer
spec:
  allow:
    node_labels:
      env: "*"
    logins: ["root", "admin"]
  options:
    max_session_ttl: "12h"

Break-Glass Access

kind: role
metadata:
  name: emergency-access
spec:
  allow:
    node_labels:
      "*": "*"  # All resources
    logins: ["root"]

  options:
    # Very short TTL
    max_session_ttl: "1h"
    # Always requires MFA
    require_session_mfa: true
    # Record everything
    record_session:
      desktop: true
      default: "yes"
    # Send alerts
    notify:
      - type: "slack"
        webhook: "https://hooks.slack.com/..."
      - type: "email"
        recipients: ["security@example.com"]

Best Practices

Do's

  • ✓ Use label-based selectors instead of hardcoded resource names
  • ✓ Apply principle of least privilege - start restrictive, expand as needed
  • ✓ Require MFA for production and sensitive resource access
  • ✓ Set appropriate session TTLs (shorter for production)
  • ✓ Use deny rules to explicitly block sensitive resources
  • ✓ Document role purpose in metadata description
  • ✓ Use access requests for elevated/temporary access
  • ✓ Regular audit of role assignments and usage

Don'ts

  • ✗ Grant wildcard access ("*") unless absolutely necessary
  • ✗ Create per-user roles - use label selectors instead
  • ✗ Skip MFA requirements for production access
  • ✗ Set overly long session TTLs (max 12h recommended)
  • ✗ Mix development and production access in same role
  • ✗ Create roles without deny rules for sensitive resources
  • ✗ Grant root/admin logins without clear justification

Real-World Policy Examples

DevOps Engineer

kind: role
version: v7
metadata:
  name: devops-engineer
  description: "Full access to dev/staging, read-only prod"
spec:
  allow:
    # Full SSH access to non-prod
    node_labels:
      env: ["development", "staging"]
    logins: ["ubuntu", "deploy", "admin"]

    # Database access
    db_labels:
      env: ["development", "staging"]
    db_users: ["admin"]

    # Kubernetes access
    kubernetes_labels:
      env: ["development", "staging"]
    kubernetes_groups: ["edit"]

  # Read-only production
  allow:
    node_labels:
      env: ["production"]
    logins: ["readonly"]

  deny:
    # Block PCI databases
    db_labels:
      compliance: ["pci"]

  options:
    max_session_ttl: "8h"
    record_session:
      default: "yes"

Database Administrator

kind: role
version: v7
metadata:
  name: dba
  description: "Database administrator with full DB access"
spec:
  allow:
    # All database access
    db_labels:
      "*": "*"
    db_users: ["admin", "root", "postgres"]

    # SSH to database servers only
    node_labels:
      role: ["database"]
    logins: ["postgres", "mysql"]

  deny:
    # No access to application servers
    node_labels:
      role: ["web", "api"]

  options:
    # Require MFA for production
    require_session_mfa: true
    max_session_ttl: "4h"
    # Audit all queries
    record_session:
      default: "yes"

Security Auditor

kind: role
version: v7
metadata:
  name: security-auditor
  description: "Read-only access for security audits"
spec:
  allow:
    # Read-only SSH access
    node_labels:
      "*": "*"
    logins: ["auditor", "readonly"]

    # View all sessions and audit logs
    rules:
      - resources: ["session", "event", "audit_log"]
        verbs: ["list", "read"]

    # Kubernetes read-only
    kubernetes_labels:
      "*": "*"
    kubernetes_groups: ["view"]

  deny:
    # No write access anywhere
    logins: ["root", "admin", "postgres"]

  options:
    # Long sessions for investigations
    max_session_ttl: "12h"
    # No MFA required for read-only
    require_session_mfa: false

Ready to Secure Your Infrastructure?

Join thousands of security-conscious teams using TigerAccess to protect their critical infrastructure and AI agents.

No credit card required • 14-day free trial • Enterprise support available