# Role-based access control

## Built-in roles

Union.ai provides three user-assignable roles with progressively broader permissions.

| Role | Capabilities |
|---|---|
| Admin | Full access: manage users, clusters, secrets, projects, all runs |
| Contributor | Create/abort runs, deploy tasks, manage secrets within assigned projects |
| Viewer | Read-only: runs, actions, logs, reports |

Additional internal system roles exist for platform operations but are not user-visible or user-assignable.

## Custom policies

Custom policies bind roles (built-in or custom) to resources scoped at org-wide, domain, or project+domain level using composable YAML bindings via `uctl`. This allows organizations to define fine-grained access policies that match their team structure and security requirements.

## Enforcement

Every API request is authenticated and authorized against the user's role assignments before any data access occurs. Enforcement happens at the service layer. Internal-only services (data plane object store proxy, data plane logs proxy) rely on network-level isolation rather than per-request authorization checks, on the basis that they are reachable only from within the service mesh.

## Least privilege

Union.ai enforces least privilege across all components. IAM roles on the data plane are scoped to minimum required permissions. Each data plane has two IAM roles: an admin role for platform services and a user role for task pods. IAM roles are bound via cloud-native workload identity federation, eliminating static credentials entirely. Presigned URLs grant single-object, operation-specific, time-limited access. Service accounts receive only the permissions needed for their specific function.

## Verification

### RBAC enforcement

**Reviewer focus:** Confirm that each role enforces the expected permissions and that custom policies correctly scope access to specific projects and domains.

**How to verify:**

1. Create three test users with Admin, Contributor, and Viewer roles.

2. Log in as Viewer and confirm restricted operations are denied:

   ```bash
   uctl create run ...    # Expect denied
   uctl create secret ... # Expect denied
   uctl get executions    # Expect success
   ```

3. Log in as Contributor scoped to project A:

   ```bash
   uctl create run --project B ... # Expect denied
   uctl create run --project A ... # Expect success
   ```

4. Create a custom policy scoping a user to project X, development domain only. Attempt to access the production domain. Expect denied.

5. Display all active policy bindings:

   ```bash
   uctl get policy
   ```

6. For Union.ai employee access: the customer creates an RBAC policy for Union.ai support, scoped to viewer only and time-limited.

This verification is fully self-service.

---
**Source**: https://github.com/unionai/unionai-docs/blob/main/content/security/identity-and-access/rbac.md
**HTML**: https://www.union.ai/docs/v2/union/security/identity-and-access/rbac/
