Policies and Permissions Guide¶
Overview¶
Centrali uses Resource-Based Access Control (ReBAC) to manage authorization. This guide explains how policies and permissions work, and how to create custom access rules for your workspace.
Key Concepts¶
Resources¶
Resources represent entities that can be protected. Each resource has: - Name: Unique identifier (e.g., records, structures, files) - Category: Grouping for resources (workspace, billing, high_risk) - Actions: Operations that can be performed (e.g., create, retrieve, update, delete)
Policies¶
Policies define the rules for granting access. They contain: - Conditions: Logic that determines when access is granted - Effect: Either Allow or Deny - Variables: Dynamic values evaluated at runtime
Permissions¶
Permissions connect resources to policies: - Link a Resource with a Policy - Specify which Actions are allowed - Define the Priority when multiple permissions apply
Authorization Flow¶
Request → Resource Lookup → Policy Evaluation → Allow/Deny
↓
Conditions Checked:
- User groups/roles
- Path parameters
- Request metadata
System Resources¶
Centrali provides pre-configured system resources for each workspace:
Core Resources¶
| Resource | Actions | Description |
|---|---|---|
workspace | create, delete, update, retrieve, list, validate, manage | Workspace management |
workspace::users | create, delete, update, retrieve, list, validate, manage, security | User management |
workspace::groups | create, delete, update, retrieve, list, validate, manage | Group management |
workspace::roles | create, delete, update, retrieve, list, validate, manage | Role management |
billing | create, delete, update, retrieve, list, validate, manage | Billing access |
Data Service Resources¶
| Resource | Actions | Description |
|---|---|---|
structures | create, retrieve, update, list, delete, manage, validate | Schema management |
records | create, retrieve, update, list, delete, manage, validate, backup | Record operations |
smart-queries | create, retrieve, update, list, delete, manage, validate, execute | Saved queries |
compute-functions | create, retrieve, update, list, delete, manage, validate, execute | Function management |
function-triggers | create, retrieve, update, list, delete, manage, validate, execute | Trigger configuration |
drafts | retrieve, list, delete, update, validate, manage, create | Draft resources |
Storage Resources¶
| Resource | Actions | Description |
|---|---|---|
files | retrieve, list, create, delete, update, manage | File operations |
folders | retrieve, list, create, delete, update, manage | Folder management |
Notification Resources¶
| Resource | Actions | Description |
|---|---|---|
notifications | create, retrieve, list, delete | User notifications |
notification-preferences | create, retrieve, update, list, delete | Notification settings |
Other Resources¶
| Resource | Actions | Description |
|---|---|---|
search-entries | create, delete, update, retrieve, list | Search index |
analytics | create, retrieve, list | Analytics data |
scheduled-jobs | create, delete, update, retrieve, list, pause, resume, retry | Job scheduling |
realtime | subscribe, list, manage | Real-time events |
Policy Specification¶
Policies are defined using a specification format that supports complex conditions:
Basic Structure¶
{
"rules": [
{
"rule_id": "Allow-Rule",
"effect": "Allow",
"conditions": [
// Condition definitions
]
}
],
"default": {
"rule_id": "Deny-Rule",
"effect": "Deny"
}
}
Condition Functions¶
Group/Role Membership¶
Check if user belongs to a group or has a role:
Boolean Check¶
Verify a boolean attribute:
String Comparison¶
Compare string values:
{
"function": "string_equal",
"attribute": "user_id",
"value": "{{@pathParamsId}}",
"metadata_key": "id",
"fromRequest": true,
"source": "path_params",
"valueKey": "id"
}
Path Matching¶
Check if a path starts with a prefix:
{
"function": "string_starts_with",
"attribute": "request_metadata",
"value": "/root/users/{{$user_id}}",
"metadata_key": "path"
}
Compound Conditions¶
Use operation to combine conditions:
{
"operation": "or",
"conditions": [
{ "function": "in_list", "attribute": "groups", "value": "workspace_administrators" },
{ "function": "in_list", "attribute": "groups", "value": "workspace_owners" }
]
}
Variables¶
Define dynamic values using variables:
{
"rule_id": "Allow-Rule",
"effect": "Allow",
"variables": {
"userPath": {
"operation": "concat",
"parameters": {
"strings": ["/root/users/", "{{$user_id}}"]
}
}
},
"conditions": [
{
"function": "string_starts_with",
"attribute": "request_metadata",
"value": "{{@userPath}}",
"metadata_key": "path"
}
]
}
Common Policy Patterns¶
1. Administrators Only¶
Allow only workspace administrators:
{
"rules": [
{
"rule_id": "Allow-Rule",
"effect": "Allow",
"conditions": [
{ "function": "in_list", "attribute": "groups", "value": "workspace_administrators" }
]
}
],
"default": { "rule_id": "Deny-Rule", "effect": "Deny" }
}
2. Any Authenticated User¶
Allow any authenticated user:
{
"rules": [
{
"rule_id": "Allow-Rule",
"effect": "Allow",
"conditions": [
{ "function": "boolean_equal", "attribute": "is_authenticated", "value": true }
]
}
],
"default": { "rule_id": "Deny-Rule", "effect": "Deny" }
}
3. User's Own Resources¶
Allow users to access only their own resources (e.g., their profile, their files):
{
"rules": [
{
"rule_id": "Allow-Rule",
"effect": "Allow",
"conditions": [
{
"function": "string_equal",
"attribute": "user_id",
"value": "{{@pathParamsId}}",
"metadata_key": "id",
"fromRequest": true,
"source": "path_params",
"valueKey": "id"
}
]
}
],
"default": { "rule_id": "Deny-Rule", "effect": "Deny" }
}
4. Path-Based Access¶
Allow access to files in a specific path:
{
"rules": [
{
"rule_id": "Allow-Rule",
"effect": "Allow",
"variables": {
"userPath": {
"operation": "concat",
"parameters": { "strings": ["/root/users/", "{{$user_id}}"] }
}
},
"conditions": [
{
"function": "string_starts_with",
"attribute": "request_metadata",
"value": "{{@userPath}}",
"metadata_key": "path"
}
]
}
],
"default": { "rule_id": "Deny-Rule", "effect": "Deny" }
}
5. Admin OR Owner¶
Allow if user is either an admin or owner:
{
"rules": [
{
"rule_id": "Allow-Rule",
"effect": "Allow",
"conditions": [
{
"operation": "or",
"conditions": [
{ "function": "in_list", "attribute": "groups", "value": "workspace_administrators" },
{ "function": "in_list", "attribute": "roles", "value": "workspace_owners" }
]
}
]
}
],
"default": { "rule_id": "Deny-Rule", "effect": "Deny" }
}
Creating Custom Resources¶
To add a custom resource via the API:
curl -X POST "https://api.centrali.io/workspace/{workspaceSlug}/api/v1/resources" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "custom-reports",
"category": "workspace",
"description": "Custom reporting resources",
"actions": ["create", "retrieve", "update", "delete", "list", "export"],
"labels": ["type=custom"]
}'
Creating Custom Policies¶
Create a policy to define access rules:
curl -X POST "https://api.centrali.io/workspace/{workspaceSlug}/api/v1/policies" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "reports::managers",
"description": "Allow managers to access reports",
"specification": {
"rules": [
{
"rule_id": "Allow-Rule",
"effect": "Allow",
"conditions": [
{ "function": "in_list", "attribute": "groups", "value": "managers" }
]
}
],
"default": { "rule_id": "Deny-Rule", "effect": "Deny" }
},
"labels": ["type=custom"]
}'
Creating Permissions¶
Link a resource to a policy with specific actions:
curl -X POST "https://api.centrali.io/workspace/{workspaceSlug}/api/v1/permissions" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "custom-reports::managers",
"description": "Allow managers to manage custom reports",
"resourceName": "custom-reports",
"policyName": "reports::managers",
"actions": ["create", "retrieve", "update", "delete", "list"],
"priority": 100,
"labels": ["type=custom"]
}'
Using Authorization in Your Code¶
Backend Authorization Check¶
import { authorize } from '../utils/route_helpers';
router.get('/reports/:reportId', async (req, res) => {
const { workspaceSlug, reportId } = req.params;
// Check authorization
const auth = await authorize(
req,
res,
'retrieve', // action
workspaceSlug, // workspace
'custom-reports', // resource name
'workspace' // resource category
);
if (!auth) return; // 401 or 403 already sent
// Proceed with business logic
const report = await ReportService.get(workspaceSlug, reportId);
res.json({ success: true, data: report });
});
Passing Request Data¶
For policies that need request metadata (like path-based access):
const auth = await authorize(
req,
res,
'create',
workspaceSlug,
'files',
'workspace',
{ path: req.body.path } // Pass path for policy evaluation
);
Default Permissions¶
When a workspace is created, these permissions are automatically configured:
Administrator Permissions¶
- Full access to all workspace resources
- Manage users, groups, and roles
- Configure billing and high-risk operations
Authenticated User Permissions¶
- Read access to users list
- Manage own profile
- Access their own files
- Subscribe to real-time events
- Manage their own notification preferences
Public Permissions¶
- Retrieve avatar images
- Access support files
Troubleshooting¶
Common Issues¶
403 Forbidden - Permission Denied - Verify the user has the correct group/role membership - Check if the policy conditions match the request - Ensure the permission links the correct resource and policy
401 Unauthorized - Not Authenticated - Verify the JWT token is valid and not expired - Check the Authorization header format: Bearer {token}
Policy Not Evaluated - Ensure the resource exists in the workspace - Verify the policy is properly linked via a permission - Check for typos in resource/policy names
Debugging Authorization¶
- Check user groups: Verify the user's group membership
- Review policy conditions: Ensure conditions match the request
- Test with admin: If admin works but regular user doesn't, it's a policy issue
- Check logs: Look for authorization logs in the IAM service
Best Practices¶
- Use groups for role-based access: Assign users to groups rather than creating user-specific policies
- Follow least privilege: Grant only the minimum permissions needed
- Use descriptive names: Make policy names self-documenting (e.g.,
reports::readonly_users) - Document custom policies: Keep track of what custom policies are for
- Test thoroughly: Test both allow and deny cases
- Use priority wisely: Higher priority permissions are evaluated first
- Audit regularly: Review and clean up unused policies/permissions
Related Documentation¶
- Access Control Guide - Authentication overview
- Service Account Authentication - API access
- Workspace Context - Understanding workspaces