Skip to content

Cedarling PostgreSQL Extension

Haileyesus Ayanaw edited this page Aug 26, 2025 · 4 revisions

Cedarling PostgreSQL Extension

A PostgreSQL extension that provides fine-grained row-level access control using Cedarling policy engine and JWT tokens, designed for easy adoption with ORMs and modern application stacks.

Overview

The extension integrates Cedarling authorization with PostgreSQL's Row-Level Security (RLS) to automatically filter database rows based on JWT token claims and Cedar policies. It's designed to work seamlessly with existing ORMs and application architectures.

Flow: SQL Query → RLS Policy → Cedarling Extension → Cedar Policy Engine → Allow/Deny Row

Installation

# Install dependencies (Rust, pgrx, PostgreSQL dev libraries)
cargo pgrx new cedarling_pg
cd cedarling_pg

# Add dependency to Cargo.toml
[dependencies]
cedarling = { path = "../path/to/cedarling" }

# Build and install
cargo pgrx install

# Enable in PostgreSQL
CREATE EXTENSION cedarling_pg;

Usage

Developer-Friendly Setup (Recommended)

Use typed helpers to avoid manual JSON construction:

-- 1. Enable RLS on table
ALTER TABLE students ENABLE ROW LEVEL SECURITY;

-- 2. Create policy using typed helper (no JSON needed)
CREATE POLICY student_access ON students
    USING (cedarling_authorized_row(students, 'Read'));

-- 3. ORM-friendly token management
SELECT cedarling_set_tokens('{"access_token": "...", "id_token": "..."}');
SELECT * FROM students;  -- Automatically filtered
SELECT cedarling_clear_tokens();

ORM Integration Examples

Django/SQLAlchemy (Python)

# Middleware approach - works with any ORM
class CedarlingMiddleware:
    def __call__(self, request):
        with connection.cursor() as cursor:
            cursor.execute("SELECT cedarling_set_tokens(%s)", [request.user.jwt_tokens])

        response = self.get_response(request)

        with connection.cursor() as cursor:
            cursor.execute("SELECT cedarling_clear_tokens()")
        return response

# Now ORM queries work automatically
students = Student.objects.all()  # Filtered by RLS

Spring Boot/Hibernate (Java)

@Component
public class CedarlingInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, ...) {
        String tokens = extractTokens(request);
        jdbcTemplate.execute("SELECT cedarling_set_tokens('" + tokens + "')");
        return true;
    }

    @Override
    public void afterCompletion(...) {
        jdbcTemplate.execute("SELECT cedarling_clear_tokens()");
    }
}

// Repository methods work automatically
@Repository
public class StudentRepository {
    public List<Student> findAll() {
        return studentRepo.findAll(); // Filtered by RLS
    }
}

Performance Optimization

For high-performance scenarios, use predicate pushdown:

-- Generate optimized WHERE clause from policies
SELECT cedarling_where('students', 'Read', current_tokens());
-- Returns: "department = 'engineering' AND grad_year < 2026"

-- Use in queries for better performance
SELECT * FROM students
WHERE (cedarling_where('students', 'Read', current_tokens()))::boolean;

Example

Sample Data

CREATE TABLE students (
    id SERIAL PRIMARY KEY,
    name VARCHAR(100),
    grad_year INTEGER,
    department VARCHAR(50)
);

INSERT INTO students (name, grad_year, department) VALUES
('Jim', 2022, 'engineering'),
('Joe', 2023, 'marketing'),
('Jude', 2026, 'engineering');

Cedar Policy

@id("allow_student_access")
permit(
    principal,
    action == Jans::Action::"Read",
    resource is Jans::Student
) when {
    principal.role == "AdmissionsCounselor" ||
    (resource.department == principal.department && resource.grad_year < 2026)
};

Function Reference

Core Authorization Functions

-- Typed helper (recommended) - auto-maps row to Cedar entity
cedarling_authorized_row(record, action TEXT DEFAULT 'Read') RETURNS BOOLEAN

-- Manual resource construction (for complex cases)
cedarling_authorized(resource_data TEXT, token_bundle TEXT) RETURNS BOOLEAN

-- Build Cedar resource from row
cedarling_build_resource(record) RETURNS TEXT

-- Performance optimization
cedarling_where(table_name TEXT, action TEXT, tokens TEXT) RETURNS TEXT

Token Management Functions

-- Set tokens for current session/transaction
cedarling_set_tokens(tokens JSONB) RETURNS VOID

-- Clear tokens
cedarling_clear_tokens() RETURNS VOID

-- Get current tokens
cedarling_current_tokens() RETURNS JSONB

Debugging and Observability Functions

-- Explain authorization decision
cedarling_explain(resource_data TEXT, action TEXT) RETURNS JSONB

-- Get last authorization trace
cedarling_last_trace() RETURNS JSONB

-- Health check
cedarling_status() RETURNS JSONB

Configuration

-- Token management (ORM-friendly)
SELECT cedarling_set_tokens('{"access_token": "...", "id_token": "..."}');

-- Operational modes
SET cedarling.mode = 'enforcement';          -- 'enforcement' | 'instrumentation' | 'shadow'
SET cedarling.fail_mode = 'closed';          -- 'closed' | 'open' (for non-critical reads)
SET cedarling.cache_ttl = 300;               -- Cache TTL in seconds
SET cedarling.log_level = 'info';            -- Logging level

Operational Features

Health Monitoring

-- Check extension health
SELECT * FROM cedarling_status();
-- Returns: {"status": "healthy", "policy_version": "v1.0", "cache_hit_rate": 0.85}

-- Policy version management
SELECT cedarling_use_policy('v2025-08-19.1');
SELECT cedarling_rollback_policy();

Error Handling Modes

-- Fail-safe (default): deny on errors
SET cedarling.fail_mode = 'closed';

-- Fail-open for read-only, low-risk operations (with audit logging)
SET cedarling.fail_mode = 'open';
SET cedarling.audit_fail_open = true;

Debugging Support

-- Debug a specific authorization decision
SELECT cedarling_explain(
    cedarling_build_resource(students),
    'Read'
) FROM students WHERE id = 1;

-- Returns detailed trace:
{
  "decision": "Deny",
  "policy_id": "allow_student_access",
  "reason": "principal.department != resource.department",
  "principal_claims": {"department": "marketing"},
  "resource_attrs": {"department": "engineering"}
}

Migration and Schema Sync

Generate Cedar Schema from PostgreSQL

# CLI tool to keep schemas in sync
cedarling-pg-codegen --table students --output student.cedarschema
cedarling-pg-codegen --all-tables --output entities/

CI/CD Integration

-- Validate schema compatibility
SELECT cedarling_validate_schema('students', 'path/to/student.cedarschema');

-- Policy diff for safe rollouts
SELECT cedarling_diff_policies('v1.0', 'v1.1');

Security Best Practices

  • Use Typed Helpers: Avoid manual JSON construction with cedarling_authorized_row()
  • Transaction Scope: Use cedarling_set_tokens() / cedarling_clear_tokens() pairs
  • Connection Pooling: Token functions work safely with pgBouncer and connection pools
  • Fail-Safe Default: Extension denies access by default on errors
  • Audit Logging: All decisions are logged with correlation IDs for debugging

Performance

  • Instance Caching: Cedarling instance cached across function calls
  • Result Caching: Authorization decisions cached with configurable TTL
  • Predicate Pushdown: cedarling_where() generates optimized SQL predicates
  • Batch Evaluation: Processes multiple rows efficiently
Clone this wiki locally