relationships
Relationships record that a person or group stands in a named relation, such as owner or viewer, to one resource.
Relationships record that a person or group stands in a named relation, such as owner or viewer, to one resource.
Alice is an owner of folder/plans; the design group are viewers of folder/plans. They express per-resource
sharing and ownership (relationship-based access control) without writing resource ids into policies: one role says
"viewers may read", and sharing a folder is a single tuple instead of a policy edit. The
relationships guide shows the full pattern.
How policies read relations
A tuple is {type}/{id}#{relation}@{subjectType}:{subjectId}. The relation must be declared on the resource type
(relations in permissions.resourceTypes, or on a
tenant-defined type). The subject is an identity or a group; a
group's tuples apply to its current members.
When a decision is made, the caller's live relations on the evaluated resource appear as resource.relations (a
sorted array of names) and those on its registered parent as resource.parentRelations. Test them with
ArrayContains:
{ effect: 'allow', actions: ['files:read'], resources: ['file/*'],
conditions: { ArrayContains: { 'resource.parentRelations': ['viewer', 'editor', 'owner'] } } }Administrative calls on iam/{type}/{id} see the relations on the named resource too, which is how an owner can share
their own folder without a tenant-wide administrator role: grant iam:relationships:create on iam/folder/* under the
condition ArrayContains: { 'resource.relations': ['owner'] }. Role sessions hold no relations. Expired tuples stop
counting at once and are removed later by iam.sweepExpired(). Tuples are also removed with their identity, their
group, or their managed resource. listAccessible takes relations into account.
| Method | What it does | Access |
|---|---|---|
create | Gives an identity or group a declared relation on one resource, optionally until a given time. | Credential |
delete | Removes one relationship tuple, ending the access it gave. | Credential |
list | Lists relationship tuples of one resource, one subject, one type, or the whole tenant, newest first. | Credential |
create
Gives an identity or group a declared relation on one resource, optionally until a given time.
Used inRelationships,Sharing and access questions
- Permission:
iam:relationships:createoniam/{type}/{id}. - Audited as:
iam:relationships:create, on{type}/{id}. - Errors:
INVALID_RESOURCE_TYPEwhen the type is not declared;INVALID_INPUTwhen the relation is not declared for the type, the subject type is notidentityorgroup, orexpiresAtis not in the future (at most ten years out);NOT_FOUNDwhen a managed resource is not registered, the identity is not in this tenant or was deleted, or the group is not in this tenant;INVARIANT_VIOLATIONwhen an enforced access invariant would newly fail.
Resources of managed types must be registered first; resources of application-owned types are accepted as named.
Creating a tuple that already exists replaces it instead of failing: its expiresAt becomes the one you pass (none
makes it permanent) and the caller is recorded as createdBy. Use expiresAt for time-boxed sharing, such as giving
an auditor viewer on a folder for a week.
await iam.api.relationships.create(credential, {
tenantId,
type: 'folder',
id: 'plans',
relation: 'viewer',
subjectType: 'group',
subjectId: designGroupId,
expiresAt: Date.now() + 7 * 24 * 60 * 60 * 1000,
});Prop
Type
A Relationship object:
Prop
Type
Example HTTP request
Only the required fields are shown; replace each <placeholder>. The response is { "data": … } on success or { "error": { "code", "message" } }.
curl -X POST "$IAM_URL/api/iam/relationships/create" \
-H "Authorization: Bearer $BETTER_IAM_TOKEN" \
-H "Content-Type: application/json" \
-H "X-Better-IAM: 1" \
-d '{
"tenantId": "<tenantId>",
"type": "<type>",
"id": "<id>",
"relation": "<relation>",
"subjectType": "identity",
"subjectId": "<subjectId>"
}'iam.api.relationships.create(
credential: CredentialInput,
input: {
tenantId: string;
type: string;
id: string;
relation: string;
subjectType: 'identity' | 'group';
subjectId: string;
expiresAt?: number;
},
): Promise<Relationship>delete
Removes one relationship tuple, ending the access it gave.
- Permission:
iam:relationships:deleteon the tuple's resource,iam/{type}/{id}. - Audited as:
iam:relationships:delete, on{type}/{id}. - Errors:
NOT_FOUNDwhen the tuple is not in this tenant;INVARIANT_VIOLATIONwhen an enforced access invariant would newly fail.
Pass the tuple's id, as returned by create or list. The change applies to the next
decision.
Prop
Type
Prop
Type
Example HTTP request
Only the required fields are shown; replace each <placeholder>. The response is { "data": … } on success or { "error": { "code", "message" } }.
curl -X POST "$IAM_URL/api/iam/relationships/delete" \
-H "Authorization: Bearer $BETTER_IAM_TOKEN" \
-H "Content-Type: application/json" \
-H "X-Better-IAM: 1" \
-d '{
"tenantId": "<tenantId>",
"relationshipId": "<relationshipId>"
}'iam.api.relationships.delete(
credential: CredentialInput,
input: { tenantId: string; relationshipId: string },
): Promise<{ deleted: boolean }>list
Lists relationship tuples of one resource, one subject, one type, or the whole tenant, newest first.
- Permission:
iam:relationships:readoniam/{type}/{id}whentypeandidare given, oniam/{type}/*when onlytypeis, otherwise oniam/*. - Audited as:
iam:relationships:read. - Errors:
INVALID_INPUTfor a subject type other thanidentityorgroup.
Filter by type, id, relation, subjectType, and subjectId in any combination: "who can see this folder" is
{ type, id }, and "what has been shared with this group" is { subjectType: 'group', subjectId }. Expired tuples
are left out unless includeExpired is true. Because the permission is checked on the resource, an owner allowed to
read relationships on their own folder can review who it is shared with.
Prop
Type
An array of Relationship.
Prop
Type
Example HTTP request
Only the required fields are shown; replace each <placeholder>. The response is { "data": … } on success or { "error": { "code", "message" } }.
curl -X POST "$IAM_URL/api/iam/relationships/list" \
-H "Authorization: Bearer $BETTER_IAM_TOKEN" \
-H "Content-Type: application/json" \
-H "X-Better-IAM: 1" \
-d '{
"tenantId": "<tenantId>"
}'iam.api.relationships.list(
credential: CredentialInput,
input: {
tenantId: string;
type?: string;
id?: string;
relation?: string;
subjectType?: 'identity' | 'group';
subjectId?: string;
includeExpired?: boolean;
},
): Promise<Relationship[]>Better IAM is created by Sean Filimon
Last updated