Roles and Permissions
Overview
- 📖 Related Docs - Authentication > Roles and Permissions
- 📖 Laravel Framework - Authorization via Middleware
- 📖 Package - spatie/laravel-permission
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
Permission | Admin | Ops | Auditor | Viewer |
---|---|---|---|---|
{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 Schema | Example |
---|---|
{namespace}.{entity}.admin | directory.attribute.admin |
{namespace}.{entity}.ops | directory.attribute.ops |
{namespace}.{entity}.auditor | directory.attribute.auditor |
{namespace}.{entity}.viewer | directory.attribute.viewer |
Namespace Roles
For convenience, we also have 4 role levels for each namespace that includes all entities in that namespace.
Namespace Role Schema | Example |
---|---|
{namespace}.namespace.admin | directory.namespace.admin |
{namespace}.namespace.ops | directory.namespace.ops |
{namespace}.namespace.auditor | directory.namespace.auditor |
{namespace}.namespace.viewer | directory.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.
If we include the DirectorySourceLiteResource
, it will show this data.
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.
Global Roles
global.super.admin
Insane Risk
|
|
global.super.ops
Extreme Risk
|
|
global.super.auditor
Moderate Risk
|
|
global.super.viewer
Moderate Risk
|
|
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 |