6 min read
On this page

Access Control

Access control determines what actions an authenticated entity is permitted to perform on a resource. It answers: "Are you allowed to do this?" -- distinct from authentication ("Who are you?").

Fundamental Concepts

Subject: The entity requesting access (user, process, service).

Object: The resource being accessed (file, API endpoint, database row).

Action/Permission: The operation (read, write, execute, delete, approve).

Policy: The rules that govern access decisions.

Reference monitor: The component that mediates every access request. Must be tamper-proof, always invoked, and small enough to verify (complete mediation).

Access Control Matrix

The theoretical foundation. A matrix with subjects as rows, objects as columns, and permissions as entries:

              File_A      File_B      Printer
Alice       {read,write}  {read}      {print}
Bob         {read}        {read,write} {}
Process_X   {read}        {}          {print}

Impractical to store directly (sparse, large). Implemented as ACLs or capability lists.

ACL (column view): Each object stores a list of (subject, permissions) pairs. File_A: [(Alice, rw), (Bob, r), (Process_X, r)].

Capability list (row view): Each subject holds unforgeable tokens granting access to objects. Alice: [(File_A, rw), (File_B, r), (Printer, print)].

Discretionary Access Control (DAC)

The resource owner decides who can access their resources. The dominant model in Unix/Linux and Windows.

Unix Permission Model

-rwxr-x--- 1 alice developers 4096 Jan 15 10:00 report.sh
 ^^^       owner
    ^^^    group
       ^^^ others

r=4, w=2, x=1
chmod 750 report.sh  → owner:rwx, group:r-x, others:---

POSIX ACLs extend this with fine-grained per-user and per-group entries:

setfacl -m u:bob:rx report.sh    # Grant bob read+execute
getfacl report.sh                # View ACL

Weakness of DAC: Users can pass access to others (copy a file, change permissions). A compromised user account inherits all that user's permissions. Malware running as a user has full access to that user's files.

Mandatory Access Control (MAC)

The system (not the resource owner) enforces access policies. Subjects and objects have security labels assigned by an administrator. Users cannot change labels or override policy.

Used in: Military/government systems, SELinux, AppArmor, macOS sandboxing.

Bell-LaPadula Model (Confidentiality)

Focuses on preventing information leakage upward to downward.

Security levels: Top Secret > Secret > Confidential > Unclassified.

Two rules:

Simple Security Property (no read up): A subject at level L can only read objects at level L or below.

Star Property (no write down): A subject at level L can only write to objects at level L or above.

Subject at SECRET level:
  Can READ:  Unclassified ✓, Confidential ✓, Secret ✓, Top Secret ✗
  Can WRITE: Unclassified ✗, Confidential ✗, Secret ✓, Top Secret ✓

This prevents a Secret-cleared process from writing sensitive data to an Unclassified file (information leakage).

Biba Model (Integrity)

The dual of Bell-LaPadula. Focuses on preventing corruption of high-integrity data.

Integrity levels: High > Medium > Low.

Simple Integrity Property (no read down): A subject can only read objects at its integrity level or above (don't trust low-integrity data).

Star Integrity Property (no write up): A subject can only write to objects at its integrity level or below (don't corrupt high-integrity data).

Prevents untrusted code from modifying critical system files. Used conceptually in Windows (Mandatory Integrity Control) and web browser sandboxes.

Clark-Wilson Model (Commercial Integrity)

Designed for business environments. Enforces well-formed transactions and separation of duties.

Components:

  • Constrained Data Items (CDIs): Data that must maintain integrity (e.g., financial records).
  • Unconstrained Data Items (UDIs): External inputs not yet validated.
  • Transformation Procedures (TPs): The only way to modify CDIs. Each TP enforces business rules.
  • Integrity Verification Procedures (IVPs): Validate that CDIs are in a consistent state.

Rules:

  1. Only certified TPs can modify CDIs.
  2. Users can only execute TPs they are authorized for.
  3. Separation of duties: The person who certifies a TP is different from the person who executes it.

Example: A bank transfer TP validates that debit and credit amounts match, both accounts exist, and the initiator is authorized. No user can directly edit account balances.

Role-Based Access Control (RBAC)

Permissions are assigned to roles, and users are assigned to roles. Simplifies administration -- manage roles instead of individual user permissions.

Roles:
  viewer:  [read_reports, view_dashboard]
  editor:  [read_reports, view_dashboard, edit_reports]
  admin:   [read_reports, view_dashboard, edit_reports, manage_users, configure_system]

Users → Roles:
  alice → [admin]
  bob   → [editor]
  carol → [viewer, editor]  (multiple roles)

RBAC Levels (NIST)

  • RBAC0 (Core): Users, roles, permissions, sessions. Users activate roles in sessions.
  • RBAC1 (Hierarchical): Role inheritance. Senior roles inherit permissions of junior roles (admin inherits editor inherits viewer).
  • RBAC2 (Constrained): Separation of duty constraints. Static: a user cannot hold both "requester" and "approver" roles. Dynamic: a user cannot activate both roles in the same session.
  • RBAC3: Combines RBAC1 and RBAC2.
STRUCTURE RbacSystem
    user_roles: map of string → set of strings
    role_permissions: map of string → set of strings
    role_hierarchy: map of string → set of strings   // parent → children

PROCEDURE GET_EFFECTIVE_PERMISSIONS(system, user) → set of strings
    permissions ← empty set
    IF user IN system.user_roles THEN
        FOR EACH role IN system.user_roles[user] DO
            COLLECT_PERMISSIONS(system, role, permissions)
    RETURN permissions

PROCEDURE COLLECT_PERMISSIONS(system, role, perms)
    IF role IN system.role_permissions THEN
        ADD ALL system.role_permissions[role] TO perms
    // Inherit from child roles in hierarchy
    IF role IN system.role_hierarchy THEN
        FOR EACH child IN system.role_hierarchy[role] DO
            COLLECT_PERMISSIONS(system, child, perms)

PROCEDURE CHECK_ACCESS(system, user, permission) → boolean
    RETURN permission IN GET_EFFECTIVE_PERMISSIONS(system, user)

Widely used in: AWS IAM, Kubernetes RBAC, database systems, enterprise applications.

Attribute-Based Access Control (ABAC)

Access decisions based on attributes of the subject, resource, action, and environment. More flexible than RBAC.

Attributes:

  • Subject: role, department, clearance, location, device_type.
  • Resource: classification, owner, creation_date, sensitivity.
  • Action: read, write, approve, delete.
  • Environment: time_of_day, ip_address, threat_level.

Policy example (natural language):

"Allow doctors to read patient records in their own department during business hours from hospital network."

subject.role == "doctor"
AND resource.type == "patient_record"
AND subject.department == resource.department
AND environment.time IN 08:00..18:00
AND environment.network == "hospital_internal"
→ PERMIT read

XACML (eXtensible Access Control Markup Language)

OASIS standard for expressing ABAC policies. Architecture:

  • PEP (Policy Enforcement Point): Intercepts requests, sends to PDP.
  • PDP (Policy Decision Point): Evaluates policies, returns Permit/Deny.
  • PAP (Policy Administration Point): Where policies are authored.
  • PIP (Policy Information Point): Provides attribute values to PDP.

Policies combine with algorithms: deny-overrides, permit-overrides, first-applicable, only-one-applicable.

Relationship-Based Access Control (ReBAC)

Access decisions based on relationships between subjects and resources in a graph.

// Google Zanzibar-style relation tuples
document:readme#viewer@user:alice        // Alice is a viewer of readme
document:readme#owner@user:bob           // Bob is the owner of readme
folder:root#viewer@group:engineering     // Engineering group can view root folder
group:engineering#member@user:alice      // Alice is in engineering

// Permission check: can alice view readme?
// Direct: alice is viewer of readme ✓
// Inherited: alice is member of engineering, which is viewer of root,
//            and readme is in root → check parent relationship

Google Zanzibar: The system behind Google Drive, YouTube, and Cloud IAM permissions. Stores relation tuples and evaluates access by graph traversal. Handles billions of ACL checks per second.

Open-source implementations: OpenFGA (CNCF), SpiceDB, Ory Keto.

Capability-Based Security

Instead of checking "is subject S allowed to access object O?", the subject holds an unforgeable token (capability) that grants access.

Properties:

  • Capabilities are transferable (can be delegated).
  • No ambient authority -- a process can only access what it has capabilities for.
  • Follows the principle of least privilege naturally.

Examples:

  • File descriptors in Unix: A process with an open file descriptor can read/write the file regardless of file permissions. The descriptor is the capability.
  • Object-capability model: In languages like E and Wasm, object references are capabilities. You can only call methods on objects you have a reference to.
  • Capsicum (FreeBSD): Capability mode restricts processes to using only pre-opened file descriptors.
  • Cloud IAM pre-signed URLs: An S3 pre-signed URL is a capability -- anyone with the URL can access the object, no identity required.
// Capability-based design: the handle IS the permission
STRUCTURE FileHandle
    fd: file descriptor
    // Holding this structure = having permission to read/write
    // No additional access check needed

PROCEDURE PROCESS_DATA(input: FileHandle, output: FileHandle)
    // This procedure can ONLY access the files it was given handles to
    // It cannot open arbitrary files -- that capability was not granted

Access Control in Practice

Combining Models

Real systems combine multiple models:

  • Kubernetes: RBAC for API access + namespace isolation (MAC-like) + NetworkPolicy (ABAC-like).
  • AWS IAM: RBAC (managed policies attached to roles) + ABAC (policy conditions on tags) + resource-based policies (capability-like).
  • Linux: DAC (file permissions) + MAC (SELinux/AppArmor) + capabilities (POSIX capabilities replacing monolithic root).

Design Principles

  1. Default deny: If no policy matches, deny access.
  2. Least privilege: Grant minimum necessary permissions.
  3. Separation of duties: Critical actions require multiple actors.
  4. Audit logging: Log all access decisions for forensics and compliance.
  5. Regular review: Periodically audit permissions and remove stale grants.
  6. Prefer allow-lists: Explicitly grant access rather than denying specific cases.