Authorization

Authorization (AuthZ) determines what authenticated users can access and perform in Geode. This guide covers role-based access control (RBAC), attribute-based access control (ABAC), row-level security (RLS), and fine-grained permissions.

Overview

Geode provides layered authorization mechanisms:

LayerMechanismGranularityUse Case
1RBACRole-basedUser groups, job functions
2ABACAttribute-basedDynamic policies, context-aware
3RLSRow-levelMulti-tenancy, data isolation

Authorization Flow:

  1. User authenticates (see Authentication )
  2. System evaluates RBAC permissions
  3. ABAC policies filter accessible resources
  4. RLS policies filter accessible rows
  5. Query executes with filtered scope

Role-Based Access Control (RBAC)

RBAC assigns permissions to roles, then roles to users.

Built-in Roles

Geode includes predefined roles:

RoleDescriptionPermissions
adminFull system accessAll operations
dbaDatabase administrationSchema, users, backup
developerDevelopment accessRead, write, schema (non-prod)
analystRead-only analyticsRead, execute procedures
readerRead-only accessRead only
writerRead and write accessRead, write

Creating Custom Roles

-- Create role
CREATE ROLE data_scientist;

-- Create role with description
CREATE ROLE compliance_officer
COMMENT 'Audit and compliance access';

-- List all roles
SHOW ROLES;

-- Show role details
DESCRIBE ROLE data_scientist;

-- Drop role
DROP ROLE data_scientist;

Granting Permissions

Permission Types:

PermissionDescription
SELECTRead data (MATCH queries)
INSERTCreate nodes/relationships
UPDATEModify existing data
DELETERemove nodes/relationships
EXECUTERun stored procedures
CREATECreate schema objects
ALTERModify schema objects
DROPDelete schema objects
GRANTDelegate permissions
ADMINAdministrative operations

Grant Examples:

-- Grant read access to specific graph
GRANT SELECT ON GRAPH SocialNetwork TO analyst;

-- Grant write access to specific node type
GRANT INSERT, UPDATE ON GRAPH SocialNetwork.Person TO writer;

-- Grant all data operations
GRANT SELECT, INSERT, UPDATE, DELETE ON GRAPH * TO developer;

-- Grant schema modification
GRANT CREATE, ALTER, DROP ON SCHEMA SocialNetwork TO dba;

-- Grant procedure execution
GRANT EXECUTE ON PROCEDURE analytics.* TO data_scientist;

-- Grant with grant option (can delegate)
GRANT SELECT ON GRAPH SocialNetwork TO team_lead WITH GRANT OPTION;

Revoking Permissions

-- Revoke specific permission
REVOKE INSERT ON GRAPH SocialNetwork.Person FROM writer;

-- Revoke all permissions on object
REVOKE ALL ON GRAPH SocialNetwork FROM developer;

-- Revoke role from user
REVOKE ROLE analyst FROM alice;

-- Revoke with cascade (revoke delegated permissions too)
REVOKE SELECT ON GRAPH SocialNetwork FROM team_lead CASCADE;

Assigning Roles to Users

-- Grant role to user
GRANT ROLE analyst TO alice;

-- Grant multiple roles
GRANT ROLE analyst, reader TO bob;

-- Show user roles
SHOW ROLES FOR USER alice;

-- Revoke role from user
REVOKE ROLE analyst FROM alice;

Role Hierarchy

Create role hierarchies for inheritance:

-- Create role hierarchy
CREATE ROLE senior_analyst;
GRANT ROLE analyst TO senior_analyst;  -- Inherits analyst permissions

-- Add additional permissions
GRANT EXECUTE ON PROCEDURE analytics.* TO senior_analyst;

-- Assign hierarchy role
GRANT ROLE senior_analyst TO charlie;
-- charlie now has: analyst permissions + procedure execution

Attribute-Based Access Control (ABAC)

ABAC provides dynamic, context-aware authorization using attributes.

Policy Components

ABAC policies evaluate:

  • Subject attributes: User properties (department, clearance, location)
  • Resource attributes: Data properties (classification, owner, type)
  • Action: Operation being performed (SELECT, INSERT, etc.)
  • Environment: Context (time, IP address, device)

Creating ABAC Policies

-- Policy: Only Data Science department can access ML models
CREATE POLICY ml_model_access
FOR SELECT ON :MLModel
WHEN current_user.department = 'Data Science';

-- Policy: Clearance level requirement
CREATE POLICY classified_data_access
FOR SELECT ON :Document
WHEN current_user.clearance_level >= resource.classification_level;

-- Policy: Time-based access
CREATE POLICY business_hours_only
FOR SELECT ON :FinancialData
WHEN current_time BETWEEN '09:00:00' AND '17:00:00'
  AND current_day NOT IN ('Saturday', 'Sunday');

-- Policy: Geographic restriction
CREATE POLICY us_data_residency
FOR SELECT ON :Customer
WHEN resource.country = 'US'
  AND current_user.location_country = 'US';

Policy Functions

Built-in functions for policy evaluation:

-- User context functions
current_user.username         -- Current username
current_user.roles            -- User's roles (array)
current_user.department       -- User department attribute
current_user.clearance_level  -- User clearance level
has_role('admin')             -- Check if user has role

-- Session context functions
current_session.ip_address    -- Client IP address
current_session.created_at    -- Session start time
current_session.mfa_verified  -- MFA status

-- Time functions
current_time                  -- Current time (HH:MM:SS)
current_date                  -- Current date (YYYY-MM-DD)
current_timestamp             -- Current timestamp
current_day                   -- Day of week name

-- Resource functions
resource.<property>           -- Access resource property

Combining Policies

Multiple policies combine with AND logic:

-- Policy 1: Department check
CREATE POLICY dept_policy
FOR SELECT ON :SensitiveData
WHEN current_user.department = resource.owning_department;

-- Policy 2: Clearance check
CREATE POLICY clearance_policy
FOR SELECT ON :SensitiveData
WHEN current_user.clearance_level >= resource.classification;

-- Both policies must pass for access
-- User must be in correct department AND have sufficient clearance

Policy Management

-- List all policies
SHOW POLICIES;

-- Show policies for specific type
SHOW POLICIES ON :Person;

-- Enable/disable policy
DISABLE POLICY dept_policy;
ENABLE POLICY dept_policy;

-- Drop policy
DROP POLICY ml_model_access;

Row-Level Security (RLS)

RLS provides fine-grained access control at the row (node/relationship) level.

RLS Overview

RLS policies are transparent to applications:

  • Automatically applied to all queries
  • No query rewriting needed
  • Users see only permitted data
  • Violations return empty results (not errors)

Creating RLS Policies

SELECT Policies (control visibility):

-- Multi-tenant isolation
CREATE POLICY tenant_isolation ON Person
FOR SELECT
USING (tenant_id = current_user_tenant_id());

-- Data ownership
CREATE POLICY owner_access ON Document
FOR SELECT
USING (
  owner_id = current_user.id OR
  is_public = true OR
  has_role('admin')
);

-- Classification-based access
CREATE POLICY classification_filter ON Record
FOR SELECT
USING (
  classification IN ('public', 'internal') OR
  (classification = 'confidential' AND has_role('manager')) OR
  (classification = 'secret' AND has_role('executive'))
);

INSERT Policies (control creation):

-- Users can only create in their tenant
CREATE POLICY tenant_insert ON Person
FOR INSERT
USING (tenant_id = current_user_tenant_id());

-- Validate data on insert
CREATE POLICY valid_classification ON Document
FOR INSERT
USING (classification IN ('public', 'internal', 'confidential'));

UPDATE Policies (control modification):

-- Users can only update their own data
CREATE POLICY owner_update ON Profile
FOR UPDATE
USING (owner_id = current_user.id);

-- Prevent modification of archived data
CREATE POLICY no_archive_update ON Document
FOR UPDATE
USING (status != 'archived');

DELETE Policies (control deletion):

-- Only owners or admins can delete
CREATE POLICY owner_delete ON Document
FOR DELETE
USING (
  owner_id = current_user.id OR
  has_role('admin')
);

-- Soft delete only (prevent hard delete)
CREATE POLICY soft_delete_only ON AuditRecord
FOR DELETE
USING (false);  -- Always deny hard delete

RLS for Relationships

-- Relationship visibility based on node access
CREATE POLICY relationship_visibility ON KNOWS
FOR SELECT
USING (
  -- User must be able to see both endpoints
  EXISTS(
    MATCH (a)-[this]->(b)
    WHERE can_access(a) AND can_access(b)
  )
);

-- Tenant isolation for relationships
CREATE POLICY relationship_tenant ON WORKS_AT
FOR SELECT
USING (
  start_node.tenant_id = current_user_tenant_id() AND
  end_node.tenant_id = current_user_tenant_id()
);

RLS Context Variables

Set session context for RLS evaluation:

-- Set session variables
SET session.tenant_id = 'tenant-123';
SET session.user_department = 'Engineering';
SET session.clearance_level = 3;

-- Use in RLS policies
CREATE POLICY tenant_filter ON *
FOR SELECT
USING (tenant_id = session.tenant_id);

Client-Side Context Setting:

// Go client example
ctx := context.WithValue(ctx, "tenant_id", "tenant-123")
client.Query(ctx, "MATCH (n) RETURN n")
# Python client example
async with client.session(tenant_id="tenant-123") as session:
    await session.run("MATCH (n) RETURN n")

RLS Performance

RLS policies are optimized for performance:

-- View query plan with RLS
EXPLAIN MATCH (p:Person) WHERE p.age > 30 RETURN p;

-- Output shows RLS filter integration:
-- IndexScan (Person, age > 30)
--   └── RLS Filter (tenant_id = 'tenant-123')
--       └── Return

Best Practices for RLS Performance:

  1. Index columns used in RLS policies
  2. Use simple equality checks when possible
  3. Avoid complex subqueries in policies
  4. Test with EXPLAIN to verify index usage

Permission Inheritance

Graph-Level Permissions

-- Permission hierarchy:
-- DATABASE > GRAPH > LABEL > PROPERTY

-- Grant on database (all graphs)
GRANT SELECT ON DATABASE geodedb TO analyst;

-- Grant on graph (all labels)
GRANT SELECT ON GRAPH SocialNetwork TO analyst;

-- Grant on label (all properties)
GRANT SELECT ON GRAPH SocialNetwork.Person TO analyst;

-- Grant on property (specific columns)
GRANT SELECT (name, email) ON GRAPH SocialNetwork.Person TO analyst;

Default Permissions

Configure default permissions for new objects:

security:
  authorization:
    default_permissions:
      new_graphs: ["SELECT"]     # Default for new graphs
      new_users: ["reader"]      # Default role for new users
    public_schema:
      enabled: true              # Allow public schema
      permissions: ["SELECT"]    # Public schema permissions

Effective Permissions

Viewing Effective Permissions

-- Show effective permissions for current user
SHOW GRANTS;

-- Show permissions for specific user
SHOW GRANTS FOR USER alice;

-- Show permissions on specific object
SHOW GRANTS ON GRAPH SocialNetwork;

-- Detailed permission check
EXPLAIN SECURITY MATCH (p:Person) RETURN p;

-- Output:
-- Permission Check for: MATCH (p:Person) RETURN p
-- User: alice
-- Roles: analyst, reader
--
-- RBAC:
--   [ALLOW] SELECT on GRAPH SocialNetwork (via role: analyst)
--
-- ABAC:
--   [ALLOW] dept_policy: user.department = 'Analytics'
--
-- RLS:
--   [FILTER] tenant_isolation: tenant_id = 'tenant-123'
--
-- Effective: ALLOW with RLS filter

Permission Precedence

  1. Explicit DENY takes precedence over ALLOW
  2. More specific permissions override general permissions
  3. Multiple ALLOW permissions are combined (OR logic)
  4. RLS policies are always applied after RBAC/ABAC
-- Explicit deny
DENY DELETE ON GRAPH SocialNetwork TO analyst;

-- This overrides any ALLOW from role inheritance
-- analyst cannot delete even if parent role allows it

Audit and Compliance

Authorization Audit Events

security:
  audit:
    authorization_events:
      - permission_granted
      - permission_revoked
      - role_created
      - role_dropped
      - role_assigned
      - role_revoked
      - policy_created
      - policy_dropped
      - access_denied
      - rls_filter_applied

Sample Audit Log:

{
  "timestamp": "2026-01-28T14:30:00.123Z",
  "event_type": "access_denied",
  "user": "bob",
  "action": "DELETE",
  "resource": "SocialNetwork.Person",
  "reason": "insufficient_privileges",
  "required": "DELETE",
  "actual": "SELECT, INSERT",
  "trace_id": "abc123..."
}

Compliance Reports

# Generate access report
geode admin access-report \
  --user alice \
  --output access-report.json

# Generate permission matrix
geode admin permission-matrix \
  --graph SocialNetwork \
  --output permissions.csv

# Audit permission changes
geode admin audit-log \
  --event-type permission_* \
  --since "2026-01-01" \
  --output audit.json

Configuration Reference

Complete Authorization Configuration

security:
  authorization:
    enabled: true

    # Default deny (require explicit grants)
    default_deny: true

    # Cache settings
    cache:
      enabled: true
      ttl_seconds: 300
      max_entries: 10000

    # RBAC settings
    rbac:
      enabled: true
      role_hierarchy: true        # Enable role inheritance
      max_roles_per_user: 20

    # ABAC settings
    abac:
      enabled: true
      policy_evaluation_order: "most_specific_first"
      default_policy: "deny"

    # RLS settings
    rls:
      enabled: true
      bypass_roles:               # Roles that bypass RLS
        - admin
        - dba
      default_policy: "deny"      # Deny if no policy matches

Best Practices

RBAC Best Practices

  1. Use roles, not user-specific permissions: Easier to manage and audit
  2. Create role hierarchy: Inherit common permissions
  3. Principle of least privilege: Grant minimum required permissions
  4. Regular access reviews: Audit permissions quarterly
  5. Document role purposes: Use COMMENT on role creation

ABAC Best Practices

  1. Keep policies simple: Complex policies are hard to debug
  2. Use meaningful attribute names: Clear naming improves maintainability
  3. Test policies thoroughly: Verify behavior with different contexts
  4. Monitor policy performance: Avoid expensive computations
  5. Document policy rationale: Explain why each policy exists

RLS Best Practices

  1. Index RLS columns: Performance critical for large datasets
  2. Use tenant isolation for multi-tenancy: Standard pattern
  3. Test with multiple users: Verify isolation works correctly
  4. Consider performance impact: Simple policies perform better
  5. Combine with RBAC: RLS filters what RBAC allows

Troubleshooting

Permission Denied

# Check effective permissions
geode query "SHOW GRANTS FOR USER alice"

# Explain security check
geode query "EXPLAIN SECURITY MATCH (p:Person) RETURN p" --as alice

# Check role membership
geode query "SHOW ROLES FOR USER alice"

RLS Not Filtering

# Verify RLS is enabled
geode admin show-config | grep rls

# Check policy exists
geode query "SHOW POLICIES ON Person"

# Verify session context
geode query "SELECT session.tenant_id"

Policy Conflicts

# List all policies affecting type
geode query "SHOW POLICIES ON :Person VERBOSE"

# Check policy evaluation order
geode admin policy-debug --type Person --action SELECT