Skip to main content

Create an ABAC Policy

Build an attribute-based access control (ABAC) policy in the Permit.io dashboard. This walkthrough is for developers who have built a role-based access control (RBAC) policy and need rules that roles alone can't express. You define attributes, group users and documents by those attributes, and grant permissions on the groups.

ABAC decides access from attributes of the user, the resource, and the environment. Use ABAC when access depends on values such as a department, a training status, or a document's classification.

Prerequisites

  • A Document resource with a read action, and an Employee role (Configure your first RBAC policy). Step 5 sets the role's read permission, so the role can start with no permissions on Document.
  • To test the policy from code: a container policy decision point (PDP). The Cloud PDP doesn't evaluate ABAC policies. See Cloud PDP capabilities.

The scenario

A company stores project documents. Only employees in the Engineering department who completed cybersecurity training can read high-priority classified documents. Every other employee can read public documents only.

WhoPublic documentsHigh-priority classified documents
Employee (role, granted read on the Public Document resource set)readNo access
R&D Certified Employee (user set: department is Engineering and training_status is certified)readread
A user with no roles who doesn't match the user setNo accessNo access

A role can't tell certified Engineering employees apart from other employees. ABAC conditions on user and resource attributes can.

To build this policy you create two resource sets, Public Document and High Priority Classified Document, and grant the Employee role read on the Public Document set only.

Granting an action on a resource also grants it on every resource set of that resource

Permit allows an action when any of the user's roles or user sets grants it. A role with read on Document can read every document, including the documents in the High Priority Classified Document resource set, which defeats the goal of this scenario. Grant the Employee role read on the Public Document resource set instead of on Document. If Configure your first RBAC policy already gave the Employee role read on Document, clear that checkbox in step 5.

1

1. Create user attributes

User attributes describe the user. User set conditions test them. In production, the values usually come from your identity provider (for example Okta, Auth0, or Clerk) when the user signs in, and your application syncs them to Permit.

AttributeTypeExample values
departmentStringEngineering, Sales
training_statusStringcertified, pending
  1. Open Directory and click Settings.
  2. Select User Attributes and click Add Attribute.
  3. Enter the Attribute Name department, select the Value Type String, and save.
  4. Repeat for training_status.
2

2. Create resource attributes

Resource attributes describe the resources you control access to. Here, they record each document's priority and classification.

AttributeTypeExample values
priority_levelStringhigh, medium, low
document_typeStringclassified, public
  1. Open Policy and select the Resources tab.
  2. Open the three-dot menu of the Document resource and select Edit.
  3. Under ABAC Options > Attributes, click Add attribute. Add priority_level and document_type, both of type String.
  4. Click Save.
3

3. Create a user set

A user set, also called a dynamic role, groups users by their attributes. A policy on the user set applies to every user who matches its conditions.

  1. Open Policy > Policy Editor, click Create, and select User Set.
  2. In the name field, enter R&D Certified Employee. Permit fills in the key RD_Certified_Employee.
  3. Add two conditions, joined with and:
    • user.department equals Engineering
    • user.training_status equals certified
  4. Click Save.

The R&D Certified Employee user set appears as a row in the Policy Editor.

4

4. Create two resource sets

A resource set, also called a dynamic resource, groups resources by their attributes. This scenario needs two sets of documents: the classified ones that only certified Engineering employees read, and the public ones that every employee reads.

Create the first resource set:

  1. In Policy Editor, click Create and select Resource Set.
  2. In the name field, enter High Priority Classified Document. Permit fills in the key High_Priority_Classified_Document.
  3. In Resource Type, select Document.
  4. Add two conditions, joined with and:
    • resource.document_type equals classified
    • resource.priority_level equals high
  5. Click Save.

Repeat the same steps for the second resource set, with the name Public Document (key Public_Document), the resource type Document, and one condition:

  • resource.document_type equals public

Both resource sets appear as columns next to Document in the Policy Editor.

5

5. Grant permissions on the user set and resource sets

Policy rules connect roles and user sets to resources and resource sets through actions.

  1. In Policy Editor, find the Employee role. Check read under Public Document. Leave read under Document and under High Priority Classified Document cleared, so the role can't reach classified documents.
  2. Find the R&D Certified Employee user set. Check read under Public Document and read under High Priority Classified Document.
  3. Click Save Changes.

Verify the policy

Run permission checks against a container PDP. The Cloud PDP doesn't evaluate ABAC policies. Pass the user and resource attributes in the check, as shown in Check permissions with attributes.

The following checks use a test user, alice@permit.io, who matches the user set and holds no role. Run them against your container PDP:

const classifiedDocument = {
type: "document",
attributes: { priority_level: "high", document_type: "classified" },
};

// Certified Engineering employee, classified document: allowed by the user set
const certified = await permit.check(
{ key: "alice@permit.io", attributes: { department: "Engineering", training_status: "certified" } },
"read",
classifiedDocument,
);
console.log("certified engineer reads classified:", certified);

// Same user, training not completed: no rule grants read
const pending = await permit.check(
{ key: "alice@permit.io", attributes: { department: "Engineering", training_status: "pending" } },
"read",
classifiedDocument,
);
console.log("pending engineer reads classified:", pending);

The example prints:

certified engineer reads classified: true
pending engineer reads classified: false

The expected decisions for the whole scenario:

UserUser attributesResource attributespermit.check(user, "read", resource)
Matches the user setdepartment: "Engineering", training_status: "certified"priority_level: "high", document_type: "classified"true
Matches the user setdepartment: "Engineering", training_status: "certified"document_type: "public"true
Holds the Employee role onlynonedocument_type: "public"true
Holds the Employee role onlynonepriority_level: "high", document_type: "classified"false
No role, doesn't match the user setdepartment: "Sales", training_status: "pending"document_type: "public"false

If the fourth row returns true, the Employee role still has read on Document or on the High Priority Classified Document resource set. Clear those checkboxes in the Policy Editor and run the check again. Each decision also appears on the Audit Log screen of the Permit dashboard.

What you built

You created an ABAC policy from attributes, a user set, two resource sets, and the permissions that connect them. Certified Engineering employees read high-priority classified documents, and every other employee reads public documents only. When a user's or a document's attributes change, access changes with them, without new role assignments.