Skip to main content

Sync Attributes, Tenants, Roles, and Relationships

Sync the application data your Permit.io policies evaluate: user attributes, tenants, role assignments, resource instances, and relationship tuples. This page is for developers who have a policy and a first synced user, and need their real data in Permit. It shows the SDK call for each kind of data and where to edit the same data in the Permit dashboard.

For creating users and the sign-in sync flow, see Sync users. This page covers the data you add around those users.

Prerequisites

Data you can sync to Permit

A permission check can pass some data in its arguments. Most data that a policy evaluates is synced to Permit before the check runs. The policy models are role-based access control (RBAC), attribute-based access control (ABAC), and relationship-based access control (ReBAC).

DataUsed byNode.js SDK callPython SDK call
Users and user attributesRBAC, ABAC, ReBACpermit.api.users.sync()permit.api.users.sync()
Tenants and tenant attributesRBAC, ABAC, ReBACpermit.api.tenants.create()permit.api.tenants.create()
Role assignmentsRBAC, ReBACpermit.api.roleAssignments.assign()permit.api.role_assignments.assign()
Resource instances and their attributesABAC, ReBACpermit.api.resourceInstances.create()permit.api.resource_instances.create()
Relationship tuplesReBACpermit.api.relationshipTuples.create()permit.api.relationship_tuples.create()

In the Python SDK, each call is async, so await it. The code samples on this page show Node.js and the equivalent REST API request.

The samples use these placeholders and example values:

ValueMeaning
PERMIT_API_KEY environment variable, YOUR_API_KEYYour environment API key.
{proj_id}, {env_id}The key or ID of your project and environment.
john@permit.ioThe user key.
acme-corpThe tenant key.
dashboard, repository, organizationResource keys. Replace them with resources from your policy.

The first Node.js sample creates the permit client. The other Node.js samples on this page reuse that client.

Event-driven data sync

To load data from your own service as it changes, instead of calling the SDK, use Open Policy Administration Layer (OPAL) data sources. See Use an external data source.

1

Sync user attributes (ABAC)

User attributes describe a user, for example a subscription tier or a department. ABAC policies use them in user set conditions.

For example, a SaaS platform has Free, Pro, and Enterprise tiers. When a user upgrades, your backend syncs the new attribute value, for example tier: "pro", to Permit. The next permission check for that user evaluates the new value, so the user gets the Pro features without a manual step.

To set attributes, pass an attributes object to users.sync. The call creates the user if the key doesn't exist, and replaces the user if it does. The REST equivalent is PUT on the user's URL.

import { Permit } from "permitio";

const permit = new Permit({
token: process.env.PERMIT_API_KEY,
pdp: "https://cloudpdp.api.permit.io",
});

const { user, created } = await permit.api.users.sync({
key: "john@permit.io",
email: "john@permit.io",
first_name: "John",
last_name: "Smith",
attributes: {
department: "marketing",
age: 30,
subscription: {
tier: "pro",
expired: false,
},
},
});
console.log(user.key, created);

The Node.js sample prints john@permit.io true when users.sync creates the user, and john@permit.io false when the user already exists. The REST API returns HTTP 201 for a created user and 200 for a replaced one.

Edit user attributes in the dashboard

Go to Directory, find the user, click the three-dot menu, and select Edit Attributes.

User row menu in the Permit Directory with the Edit Attributes option
2

Sync tenants and tenant attributes

A tenant usually represents one customer organization or account in a multi-tenant application. Tenant attributes describe that organization, so policies can treat tenants differently.

For example, in a multi-tenant e-commerce application, each merchant is a tenant. When a merchant signs up and picks an industry and a region, your backend syncs those values as tenant attributes. Policies then show the merchant's users only the features allowed for that region and industry.

Common tenant attributes:

AttributeExample values
RegionNorth America, Europe, Asia
Subscription levelBasic, Pro, Enterprise
IndustryHealthcare, Finance, Retail

A policy on tenant attributes can say: "Allow access to advanced analytics only for tenants with a Pro or Enterprise subscription."

To create a tenant with attributes, call tenants.create with the tenant key, name, and attributes:

await permit.api.tenants.create({
key: "acme-corp",
name: "Acme Corp",
attributes: {
allowed_locations: ["US", "CA"],
},
});
Edit tenant attributes in the dashboard

Go to Directory, click Settings, and select Manage Tenants. Find the tenant, click the three-dot menu, and select Edit Attributes. Enter the attributes as a JSON object of names and values.

Manage Tenants screen in the Permit dashboard with the Edit Attributes option for a tenant
3

Sync role assignments (RBAC and ReBAC)

A role assignment gives a user a role. A top-level role applies across one tenant (RBAC). An instance role applies to one resource instance (ReBAC).

For example, a project management tool has Admin, Manager, and Contributor roles. When a user becomes Manager of one project, your backend syncs that instance role assignment. The user can assign tasks and view reports in that project, and the user's roles in other projects don't change.

To assign a role, call roleAssignments.assign with the user, role, and tenant. Add resource_instance, in the format resource_key:instance_key, to assign an instance role. You can also assign roles when you create the user, with the role_assignments field of users.sync. A user can have several roles, in several tenants.

await permit.api.roleAssignments.assign({
user: "john@permit.io",
role: "admin",
tenant: "acme-corp",
});

With instance roles, one user can have different roles on different instances of the same resource. For example, with a dashboard resource that has admin and viewer instance roles, john@permit.io can be admin of dashboard:dashboard-a and viewer of dashboard:dashboard-b. The following Node.js sample makes both assignments. The cURL sample shows the first one. To create the dashboard instances with their own keys and attributes, see Sync resource instances and their attributes.

// admin of dashboard-a
await permit.api.roleAssignments.assign({
user: "john@permit.io",
role: "admin",
tenant: "acme-corp",
resource_instance: "dashboard:dashboard-a",
});

// viewer of dashboard-b
await permit.api.roleAssignments.assign({
user: "john@permit.io",
role: "viewer",
tenant: "acme-corp",
resource_instance: "dashboard:dashboard-b",
});
4

Sync resource instances and their attributes

A resource instance is one object of a resource type, for example one repository of the repository resource. You define attributes on the resource type in the Policy Editor. Each instance then stores its own values for those attributes, and policies use the values.

For example, a learning management system has a course resource with a difficulty_level attribute (Beginner, Intermediate, Advanced) and a category attribute (Math, Science). When a course is created, your backend syncs the course instance with its attribute values. A policy can then give some users access only to Advanced Math courses.

To create a resource instance, call resourceInstances.create with the instance key, the resource type, the tenant, and the attributes:

await permit.api.resourceInstances.create({
key: "react",
resource: "repository",
tenant: "acme-corp",
attributes: {
private: "false",
owner: "acme-corp",
},
});
Edit resource instance attributes in the dashboard

Go to Directory and open the Instances tab. Find the resource instance, click the three-dot menu, and select Edit Attributes.

Instances tab of the Permit Directory with the Edit Attributes option for a resource instance
5

Sync relationship tuples (ReBAC)

A relationship tuple says how two resource instances relate, for example that a document belongs to a project. Users get instance roles through role assignments. Relationship tuples, with the role derivations in your policy, extend those roles to related instances.

For example, a collaboration platform has projects and documents. A tuple says that a document belongs to a project. When a user becomes Project Manager of that project, the user gets access to every document in the project. You sync one tuple per document, instead of assigning roles on every document.

Each tuple has the format subject : relation : object. To create one, call relationshipTuples.create with these fields:

FieldRequiredDescription
subjectYesThe resource instance that gets the relation, as resource_key:instance_key.
relationYesThe relation between the subject and the object, as defined on the resource in the Policy Editor.
objectYesThe resource instance the relation points to, as resource_key:instance_key.
tenantWhen neither instance existsThe tenant of both instances. Permit creates missing instances in this tenant. When both instances exist, Permit uses their stored tenant.
await permit.api.relationshipTuples.create({
subject: "organization:acme-corp",
relation: "owner",
object: "repository:react",
tenant: "acme-corp",
});
Create relationship tuples in the dashboard

Go to Directory and open the Instances tab. Find the resource instance, click the three-dot menu, and select Edit Resource Instance. Under Relationships, choose the relation and the related instance, then save.

Verify the synced data

List the role assignments of john@permit.io with the same permit client:

const assignments = await permit.api.roleAssignments.list({ user: "john@permit.io" });
for (const a of assignments) {
console.log(a.role, a.tenant, a.resource_instance ?? "(top-level)");
}

After you run the role assignment samples on this page, the output lists the admin role in acme-corp as top-level, and the admin and viewer instance roles with their dashboard instances.

You can also check the data in Directory in the Permit dashboard:

  • The Users tab lists each user with its top-level roles and instance roles.
  • The Instances tab lists each resource instance with its tenant and the number of relationships.
  • Settings > Manage Tenants lists each tenant.

Then run a permit.check() that depends on the synced data, for example a check on a resource instance, and confirm the result matches your policy.