Cerbos is the open-source authorization layer that keeps permission logic out of your codebase. Define policies in YAML, check them via API — no hardcoded if/else chains.
What Is Cerbos?
Cerbos is a stateless, self-hosted authorization engine. Your app sends a check request with the principal, resource, and action — Cerbos returns allow or deny based on your policies.
Quick Start
# Docker
docker run --rm -p 3592:3592 -p 3593:3593 \
-v $(pwd)/policies:/policies \
ghcr.io/cerbos/cerbos:latest server
Define Policies
# policies/resource_document.yaml
apiVersion: api.cerbos.dev/v1
resourcePolicy:
resource: document
version: default
rules:
- actions: ['read']
effect: EFFECT_ALLOW
roles: ['viewer', 'editor', 'admin']
- actions: ['edit', 'update']
effect: EFFECT_ALLOW
roles: ['editor', 'admin']
condition:
match:
expr: request.resource.attr.status != 'archived'
- actions: ['delete', 'archive']
effect: EFFECT_ALLOW
roles: ['admin']
- actions: ['edit']
effect: EFFECT_ALLOW
roles: ['viewer']
condition:
match:
expr: request.resource.attr.ownerId == request.principal.id
Check Permissions
curl -s -X POST 'http://localhost:3592/api/check/resources' \
-H 'Content-Type: application/json' \
-d '{
"principal": {
"id": "user-123",
"roles": ["editor"],
"attr": {"department": "engineering"}
},
"resources": [{
"resource": {
"kind": "document",
"id": "doc-456",
"attr": {"status": "draft", "ownerId": "user-789"}
},
"actions": ["read", "edit", "delete"]
}]
}' | jq '.results["doc-456"].actions'
# {"read": "EFFECT_ALLOW", "edit": "EFFECT_ALLOW", "delete": "EFFECT_DENY"}
TypeScript SDK
import { GRPC } from '@cerbos/grpc'
const cerbos = new GRPC('localhost:3593', { tls: false })
// Check permission
const decision = await cerbos.checkResource({
principal: {
id: userId,
roles: [userRole],
attr: { department: userDept },
},
resource: {
kind: 'document',
id: docId,
attr: { status: doc.status, ownerId: doc.ownerId },
},
actions: ['read', 'edit', 'delete'],
})
if (decision.isAllowed('edit')) {
// User can edit this document
}
Express.js Middleware
const authorize = (action: string, resourceKind: string) => {
return async (req, res, next) => {
const decision = await cerbos.checkResource({
principal: { id: req.user.id, roles: req.user.roles },
resource: { kind: resourceKind, id: req.params.id, attr: req.resourceAttrs },
actions: [action],
})
if (!decision.isAllowed(action)) return res.status(403).json({ error: 'Forbidden' })
next()
}
}
app.put('/documents/:id', authorize('edit', 'document'), updateDocument)
app.delete('/documents/:id', authorize('delete', 'document'), deleteDocument)
Why Cerbos?
- Stateless: no database needed, policies are files
- Fast: sub-millisecond decisions
- Testable: unit test policies without running your app
- GitOps: policies in Git, deploy with CI/CD
- Language agnostic: REST + gRPC SDKs for all languages
Need access control for scraping APIs? Scrapfly provides enterprise web scraping with access management. Email spinov001@gmail.com for secure scraping solutions.
Top comments (0)