Skip to content

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:

{
  "function": "in_list",
  "attribute": "groups",
  "value": "workspace_administrators"
}

Boolean Check

Verify a boolean attribute:

{
  "function": "boolean_equal",
  "attribute": "is_authenticated",
  "value": true
}

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

  1. Check user groups: Verify the user's group membership
  2. Review policy conditions: Ensure conditions match the request
  3. Test with admin: If admin works but regular user doesn't, it's a policy issue
  4. Check logs: Look for authorization logs in the IAM service

Best Practices

  1. Use groups for role-based access: Assign users to groups rather than creating user-specific policies
  2. Follow least privilege: Grant only the minimum permissions needed
  3. Use descriptive names: Make policy names self-documenting (e.g., reports::readonly_users)
  4. Document custom policies: Keep track of what custom policies are for
  5. Test thoroughly: Test both allow and deny cases
  6. Use priority wisely: Higher priority permissions are evaluated first
  7. Audit regularly: Review and clean up unused policies/permissions