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
Documentresource with areadaction, and anEmployeerole (Configure your first RBAC policy). Step 5 sets the role'sreadpermission, so the role can start with no permissions onDocument. - 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.
| Who | Public documents | High-priority classified documents |
|---|---|---|
Employee (role, granted read on the Public Document resource set) | read | No access |
R&D Certified Employee (user set: department is Engineering and training_status is certified) | read | read |
| A user with no roles who doesn't match the user set | No access | No 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.
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. 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.
| Attribute | Type | Example values |
|---|---|---|
department | String | Engineering, Sales |
training_status | String | certified, pending |
- Open Directory and click Settings.
- Select User Attributes and click Add Attribute.
- Enter the Attribute Name
department, select the Value Type String, and save. - Repeat for
training_status.
2. Create resource attributes
Resource attributes describe the resources you control access to. Here, they record each document's priority and classification.
| Attribute | Type | Example values |
|---|---|---|
priority_level | String | high, medium, low |
document_type | String | classified, public |
- Open Policy and select the Resources tab.
- Open the three-dot menu of the Document resource and select Edit.
- Under ABAC Options > Attributes, click Add attribute. Add
priority_levelanddocument_type, both of type String. - Click Save.
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.
- Open Policy > Policy Editor, click Create, and select User Set.
- In the name field, enter
R&D Certified Employee. Permit fills in the keyRD_Certified_Employee. - Add two conditions, joined with and:
user.departmentequalsEngineeringuser.training_statusequalscertified
- Click Save.
The R&D Certified Employee user set appears as a row in the Policy Editor.
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:
- In Policy Editor, click Create and select Resource Set.
- In the name field, enter
High Priority Classified Document. Permit fills in the keyHigh_Priority_Classified_Document. - In Resource Type, select Document.
- Add two conditions, joined with and:
resource.document_typeequalsclassifiedresource.priority_levelequalshigh
- 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_typeequalspublic
Both resource sets appear as columns next to Document in the Policy Editor.
5. Grant permissions on the user set and resource sets
Policy rules connect roles and user sets to resources and resource sets through actions.
- In Policy Editor, find the Employee role. Check
readunder Public Document. Leavereadunder Document and under High Priority Classified Document cleared, so the role can't reach classified documents. - Find the R&D Certified Employee user set. Check
readunder Public Document andreadunder High Priority Classified Document. - 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:
| User | User attributes | Resource attributes | permit.check(user, "read", resource) |
|---|---|---|---|
| Matches the user set | department: "Engineering", training_status: "certified" | priority_level: "high", document_type: "classified" | true |
| Matches the user set | department: "Engineering", training_status: "certified" | document_type: "public" | true |
Holds the Employee role only | none | document_type: "public" | true |
Holds the Employee role only | none | priority_level: "high", document_type: "classified" | false |
| No role, doesn't match the user set | department: "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.
What's next?
Next: model access through relationships between resources.