Skip to content

Roles and Permissions

Overview

Authorization for endpoint uses the built-in can() middleware guard built into Laravel in conjunction with the spatie/laravel-permission package for roles and permissions.

For documentation details, see the Authentication > Roles and Permissions page.

For development, see the database/seeders/Version0001_00_00/AuthPermissionSeeder.php file to learn more about the configuration.

As a user, you can see all of the roles that exist and that you have access to at the {url}/user/permissions endpoint.

There are some complex database query limitations with showing the permissions for each role, so we have deferred that UI visibility for the time being.

Permission Schema

{namespace}.{entity}.{action}

Here is an example of the permissions for the DirectoryAttribute actions.

  • directory.attribute.view (applies to list and describe)
  • directory.attribute.export
  • directory.attribute.create
  • directory.attribute.update
  • directory.attribute.activate
  • directory.attribute.deprecate
  • directory.attribute.deactivate
  • directory.attribute.destroy
  • directory.attribute.sync

For models with sensitive data in child relationships (usually many-to-many relationships), we occasionally use an addition level of permissions.

  • directory.attribute.user.view

If the child relationship data is not sensitive, then we either defer to the related model’s permission or use the parent model’s permission, depending on the use case.

  • directory.attribute.view
  • directory.user.view

Role Schema

We were inspired by Google Cloud Platform (GCP) IAM roles and have created a standardized schema for role-based access control (RBAC) that has pre-defined the permissions that users need.

We only assign users to roles that have predefined permissions, not to permissions directly.

Role Personas

  • Admin: An admin user can perform all actions and is a change management practicitioner or system administrator.
  • Ops: An ops user can perform day-to-day changes and get things up and running. They cannot deprecate or deactivate records.
  • Auditor: A read-only user with export permissions for CSV, JSON, YML, and Google Sheets.
  • Viewer: A read-only user for exploring what is configured. Some companies may restrict this to specific users, while others may expose it to all employees to self service information.

Role and Permission Mapping

PermissionAdminOpsAuditorViewer
{namespace}.{entity}.view
{namespace}.{entity}.export
{namespace}.{entity}.sync
{namespace}.{entity}.create
{namespace}.{entity}.update
{namespace}.{entity}.activate
{namespace}.{entity}.deprecate
{namespace}.{entity}.deactivate
{namespace}.{entity}.destroy

Entity Roles

We have 4 role levels for each entity.

Entity Role SchemaExample
{namespace}.{entity}.admindirectory.attribute.admin
{namespace}.{entity}.opsdirectory.attribute.ops
{namespace}.{entity}.auditordirectory.attribute.auditor
{namespace}.{entity}.viewerdirectory.attribute.viewer

Namespace Roles

For convenience, we also have 4 role levels for each namespace that includes all entities in that namespace.

Namespace Role SchemaExample
{namespace}.namespace.admindirectory.namespace.admin
{namespace}.namespace.opsdirectory.namespace.ops
{namespace}.namespace.auditordirectory.namespace.auditor
{namespace}.namespace.viewerdirectory.namespace.viewer

Global Roles

We have 4 roles that provide global access across all namespaces.

Global Role
global.super.admin
global.super.ops
global.super.auditor
global.super.viewer

Lite Metadata

Many API responses include related models that provide valuable metadata including id, name, slug, created_at, state, etc.

Not all users will have permissions to view those related models, and a lot of the deeper metadata for those models is not relevant to the relationship.

To solve this, we have created Lite JSON resources in app/Http/Resources/ that allow us to provide high level metadata without revealing sensitive data.

We’ve made the conscious decision that we should only include “lite” metadata for parent and child relationships. Since the ID is included, additional metadata can be fetched by calling that entity’s respective endpoint.

Example

Let’s look at the Directory Dimension Resource and the parent Directory Source relationship.

app/Http/Resources/DirectoryDimensionResource.php
return [
'id' => $this->id,
'attribute_key' => $this->attribute_key,
'name' => $this->name,
'slug' => $this->slug,
'attributes_enabled' => $this->attributes_enabled,
'rulesets_enabled' => $this->rulesets_enabled,
'expires_after_days' => $this->expires_after_days,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
'expires_at' => $this->expires_at,
'deleted_at' => $this->whenNotNull($this->deleted_at),
'state' => $this->state,
'source' => $this->whenLoaded(
relationship: 'directorySource',
value: fn() => new DirectorySourceLiteResource($this->directorySource),
default: ['id' => $this->source_id]
),
'count' => [
'attributes' => $this->whenCounted('directoryAttributes'),
'rules' => $this->whenCounted('directoryRulesets'),
'conditions' => $this->whenCounted('directoryConditions')
],
'relationships' => [
'attributes' => DirectoryAttributeLiteResource::collection($this->whenLoaded('directoryAttributes')),
'rules' => DirectoryRulesetLiteResource::collection($this->whenLoaded('directoryRulesets')),
'conditions' => DirectoryConditionLiteResource::collection($this->whenLoaded('directoryConditions')),
],
];

If we include the DirectorySourceLiteResource, it will show this data.

return [
'id' => $this->id,
'is_primary' => $this->is_primary,
'vendor' => $this->vendor,
'name' => DirectorySource::vendors()[$this->vendor],
'slug' => $this->slug,
'domain' => $this->domain
];

If we included the DirectorySourceResource, it would provide too much information and could introduce recursive queries to it’s own relationships if we are not careful.

The Lite resources are intentional not to include any additional relationships, and also supports caching since it’s just string data for the most part.

You can see how our permission model makes sense to provide a high level of metadata without worrying much about sensitive data.

return [
'id' => $this->id,
'is_primary' => $this->is_primary,
'vendor' => $this->vendor,
'name' => DirectorySource::vendors()[$this->vendor],
'slug' => $this->slug,
'domain' => $this->domain,
'manager_id_field' => $this->manager_id_field,
'retention_days' => $this->retention_days,
'sync_cron_schedule' => $this->sync_cron_schedule,
'sync_cron_human' => $this->sync_cron_human,
'sync_enabled' => $this->sync_enabled,
'credentials' => !empty($this->credentials), // This provides a true/false if set, it does not expose credentials
'metadata' => $this->metadata,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
'deleted_at' => $this->whenNotNull($this->deleted_at),
'count' => [
'attributes' => $this->whenCounted('directoryAttributes'),
'dimensions' => $this->whenCounted('directoryDimensions'),
'identities' => $this->whenCounted('directoryIdentities'),
// 'user_attributes' => $this->whenCounted('directoryAttributeUsers'),
'rulesets' => $this->whenCounted('directoryRulesets'),
'users' => $this->whenCounted('directoryUsers'),
],
'relationships' => [
'attributes' => DirectoryAttributeResource::collection($this->whenLoaded('directoryAttributes')),
'dimensions' => DirectoryDimensionResource::collection($this->whenLoaded('directoryDimensions')),
'identities' => DirectoryIdentityResource::collection($this->whenLoaded('directoryIdentities')),
// 'user_attributes' => DirectoryAttributeUserResource::collection($this->whenLoaded('directoryAttributeUsers')),
'rulesets' => DirectoryRulesetResource::collection($this->whenLoaded('directoryRulesets')),
'users' => DirectoryUserResource::collection($this->whenLoaded('directoryUsers')),
],
];

Global Roles

global.super.admin

Insane Risk
  • *.*.view
  • *.*.create
  • *.*.update
  • *.*.deactivate
  • *.*.reactivate
  • *.*.destroy
  • *.*.import
  • *.*.export
  • This role has unrestricted ability to administer everything in Access Control with read-write-destroy permissions.
  • This role should be considered the equivalent of a break-glass root account.
  • This role should be assigned to less than 5 people in your IT or Security team.
  • This role should only be assigned to a secondary admin/elevated account that is not the user's primary account (if available).

global.super.ops

Extreme Risk
  • *.*.view
  • *.*.create
  • *.*.update
  • *.*.deactivate
  • This role has unrestricted ability to administer everything in Access Control with read-write permissions.
  • This role should be considered the equivalent of a break-glass power user account that allows users to perform global day-to-day operations but does not allow any permanent destruction of database records or data import/export.
  • This role should be assigned to less than 25 people in your IT or Security team, usually your Identity team, IT System Administrators and/or IT helpdesk.
  • This is a widely permissive role, and you should consider namespace or model resource roles instead if your organization security policies have stricter least privilege or "need to know" requirements.
  • This should ideally should be assigned to a secondary admin/elevated account that is not the user's primary account.

global.super.auditor

Moderate Risk
  • *.*.view
  • *.*.export
  • This role has unrestricted ability to view everything in Access Control with the following read-only and export permissions
  • This read-only role should be assigned to a limited number of audit, compliance, and security assurance engineers that need to have a global read-only view of everything in Access Control (except credentials and sensitive values) and perform exports to CSV, JSON, YAML, and Google Sheet documents for evidence gathering.
  • This is a widely permissive role, and you should consider namespace or model resource roles instead if your organization security policies have stricter least privilege or "need to know" requirements.
  • This should ideally should be assigned to a secondary admin/elevated account that is not the user's primary account.

global.super.viewer

Moderate Risk
  • *.*.view
  • This role has unrestricted ability to view everything in Access Control with read-only permissions
  • This read-only role is similar to an auditor account but does not allow data export.
  • This role can be assigned at your discretion to identity and access management stakeholders who should have visibility into all of the aspects of how Access Control is configured and the data contained within.
  • This is a widely permissive role, and you should consider namespace or model resource roles instead if your organization security policies have stricter least privilege or "need to know" requirements.
  • This should ideally should be assigned to a secondary admin/elevated account that is not the user's primary account.

Architectural Access Roles

access.cli

Low Risk

access.doc

No Risk

access.pat

Moderate Risk

access.svc

Moderate Risk

access.ui

No Risk

Namespace Roles

auth.namespace.admin

Extreme Risk

auth.namespace.ops

High Risk

auth.namespace.auditor

Moderate Risk

auth.namespace.viewer

Low Risk

directory.namespace.admin

Extreme Risk

directory.namespace.ops

High Risk

directory.namespace.auditor

Low Risk

directory.namespace.viewer

Low Risk

Model Resource Roles

auth.device.admin

High Risk

auth.device.ops

High Risk

auth.device.auditor

Low Risk

auth.device.viewer

Low Risk

auth.role.admin

Extreme Risk

auth.role.auditor

Moderate Risk

auth.role.ops

Extreme Risk

auth.role.viewer

Moderate Risk - Exposure of permissions assigned to users that can be used for social engineering.

auth.user.admin

High Risk

auth.user.ops

High Risk

auth.user.auditor

Moderate Risk - Exposure to personally identifyable information and export of users. Should only be assigned to users performing user access reviews. For sanitized list of organization users, use directory.user.auditor or directory.user.viewer.

auth.user.viewer

Moderate Risk - Exposure to personally identifyable information beyond normal directory metadata. For sanitized list of organization users, use directory.user.auditor or directory.user.viewer.

directory.attribute.admin

Extreme Risk

directory.attribute.ops

High Risk

directory.attribute.auditor

Low Risk

directory.attribute.viewer

Low Risk

directory.condition.admin

High Risk

directory.condition.ops

Moderate Risk

directory.condition.auditor

Low Risk

directory.condition.viewer

Low Risk

directory.dimension.admin

Extreme Risk

directory.dimension.ops

High Risk

directory.dimension.auditor

Low Risk

directory.dimension.viewer

Low Risk

directory.rule.admin

High Risk

directory.rule.ops

Moderate Risk

directory.rule.auditor

Low Risk

directory.rule.viewer

Low Risk

directory.source.admin

Extreme Risk

directory.source.ops

Extreme Risk

directory.source.auditor

Low Risk

directory.source.viewer

Low Risk

directory.source.user.admin

High Risk

directory.source.user.ops

Moderate Risk

directory.source.user.auditor

Low Risk

directory.source.user.viewer

Low Risk

directory.user.admin

High Risk

directory.user.ops

Moderate Risk

directory.user.auditor

Low Risk

directory.user.viewer

Low Risk

directory.user.attribute.admin

High Risk

directory.user.attribute.ops

Moderate Risk

directory.user.attribute.auditor

Low Risk

directory.user.attribute.viewer

Low Risk

Permissions

Permission Name
access.cli
access.doc
access.pat
access.svc
access.ui
auth.device.view
auth.device.create
auth.device.update
auth.device.deactivate
auth.device.reactivate
auth.device.destroy
auth.device.import
auth.device.export
auth.role.view
auth.role.create
auth.role.update
auth.role.deactivate
auth.role.reactivate
auth.role.destroy
auth.role.import
auth.role.export
auth.user.view
auth.user.create
auth.user.update
auth.user.deactivate
auth.user.reactivate
auth.user.destroy
auth.user.import
auth.user.export
directory.source.view
directory.source.create
directory.source.update
directory.source.deactivate
directory.source.reactivate
directory.source.destroy
directory.source.import
directory.source.export
directory.dimension.view
directory.dimension.create
directory.dimension.update
directory.dimension.deactivate
directory.dimension.reactivate
directory.dimension.destroy
directory.dimension.import
directory.dimension.export
directory.attribute.view
directory.attribute.create
directory.attribute.update
directory.attribute.deactivate
directory.attribute.reactivate
directory.attribute.destroy
directory.attribute.import
directory.attribute.export
directory.rule.view
directory.rule.create
directory.rule.update
directory.rule.deactivate
directory.rule.reactivate
directory.rule.destroy
directory.rule.import
directory.rule.export
directory.condition.view
directory.condition.create
directory.condition.update
directory.condition.deactivate
directory.condition.reactivate
directory.condition.destroy
directory.condition.import
directory.condition.export
directory.user.attribute.view
directory.user.attribute.create
directory.user.attribute.update
directory.user.attribute.deactivate
directory.user.attribute.reactivate
directory.user.attribute.destroy
directory.user.attribute.import
directory.user.attribute.export
directory.source.user.view
directory.source.user.create
directory.source.user.update
directory.source.user.deactivate
directory.source.user.reactivate
directory.source.user.destroy
directory.source.user.import
directory.source.user.export
directory.user.view
directory.user.create
directory.user.update
directory.user.deactivate
directory.user.reactivate
directory.user.destroy
directory.user.import
directory.user.export