Simple Zanzibar
A simplified Rust implementation of Google's Zanzibar authorization system, featuring a human-readable DSL for policy definition and comprehensive support for relationship-based access control (ReBAC).
๐ What is Zanzibar?
Google's Zanzibar is a global authorization system that provides consistent, scalable authorization decisions across Google's services. It's based on the concept of relationship tuples that express relationships between objects and users.
Key Concepts
- Objects: Resources in your system (e.g.,
doc:readme,folder:photos) - Relations: Types of relationships (e.g.,
owner,viewer,editor) - Users: Subjects that can have relationships (e.g.,
user:alice,group:engineers) - Tuples: Assertions of relationships (e.g.,
doc:readme#owner@user:alice)
๐๏ธ Architecture
graph TB
subgraph "Simple Zanzibar Architecture"
DSL[DSL Parser] --> Config[Namespace Config]
Config --> Service[Zanzibar Service]
Service --> Store[Tuple Store]
Service --> Eval[Evaluation Engine]
Store --> Memory[In-Memory Store]
Store --> Future[Future: Database Store]
Eval --> Check[Check API]
Eval --> Expand[Expand API]
Check --> Decision{Authorization Decision}
Expand --> Userset[Expanded Userset]
end
subgraph "External Interface"
Client[Client Application] --> Service
Policy[Policy Definition] --> DSL
end
style Service fill:#e1f5fe
style DSL fill:#f3e5f5
style Eval fill:#e8f5e8
style Store fill:#fff3e0
๐ Data Flow
sequenceDiagram
participant Client
participant Service as ZanzibarService
participant Parser as DSL Parser
participant Store as Tuple Store
participant Eval as Evaluation Engine
Note over Client,Eval: Policy Setup
Client->>Service: add_dsl(policy)
Service->>Parser: parse_dsl(policy)
Parser-->>Service: NamespaceConfig
Note over Client,Eval: Tuple Management
Client->>Service: write_tuple(tuple)
Service->>Store: write_tuple(tuple)
Store-->>Service: Ok()
Note over Client,Eval: Authorization Check
Client->>Service: check(object, relation, user)
Service->>Eval: check(object, relation, user, config, store)
Eval->>Store: read_tuples(filter)
Store-->>Eval: Vec<RelationTuple>
Eval->>Eval: recursive_evaluation()
Eval-->>Service: bool
Service-->>Client: Authorization Result
๐ Entity Relationship
erDiagram
NAMESPACE {
string name
map relations
}
RELATION_CONFIG {
string name
optional userset_rewrite
}
USERSET_EXPRESSION {
enum type
optional relation
optional expressions
}
OBJECT {
string namespace
string id
}
RELATION {
string name
}
USER {
enum type
string user_id
optional object
optional relation
}
RELATION_TUPLE {
object object
relation relation
user user
}
NAMESPACE ||--o{ RELATION_CONFIG : contains
RELATION_CONFIG ||--o| USERSET_EXPRESSION : has
USERSET_EXPRESSION ||--o{ USERSET_EXPRESSION : composed_of
RELATION_TUPLE ||--|| OBJECT : references
RELATION_TUPLE ||--|| RELATION : has
RELATION_TUPLE ||--|| USER : assigned_to
๐ Quick Start
Add this to your Cargo.toml:
[]
= "0.1.0"
Basic Usage
use ;
๐ DSL Reference
The Simple Zanzibar DSL allows you to define authorization policies in a human-readable format.
Syntax Overview
namespace <namespace_name> {
relation <relation_name> {
rewrite <userset_expression>
}
}
Userset Expressions
1. this
Direct relationship - users explicitly granted this relation.
relation owner {
rewrite this
}
2. computed_userset(relation: "relation_name")
Users who have another relation on the same object.
relation viewer {
rewrite computed_userset(relation: "owner")
}
3. tuple_to_userset(tupleset: "relation1", computed_userset: "relation2")
Users who have relation2 on objects that have relation1 with the current object.
relation viewer {
rewrite tuple_to_userset(tupleset: "parent", computed_userset: "viewer")
}
4. union(expr1, expr2, ...)
Users who satisfy any of the expressions.
relation viewer {
rewrite union(
this,
computed_userset(relation: "owner"),
computed_userset(relation: "editor")
)
}
5. intersection(expr1, expr2, ...)
Users who satisfy all expressions.
relation admin {
rewrite intersection(
computed_userset(relation: "owner"),
computed_userset(relation: "manager")
)
}
6. exclusion(base_expr, exclude_expr)
Users in base_expr but not in exclude_expr.
relation editor {
rewrite exclusion(
computed_userset(relation: "viewer"),
computed_userset(relation: "banned")
)
}
Complete Example
// File system with hierarchical permissions
namespace file {
relation owner {}
relation parent {}
relation viewer {
rewrite union(
this,
computed_userset(relation: "owner"),
computed_userset(relation: "editor"),
tuple_to_userset(tupleset: "parent", computed_userset: "viewer")
)
}
relation editor {
rewrite union(
this,
computed_userset(relation: "owner")
)
}
}
namespace folder {
relation owner {}
relation parent {}
relation viewer {
rewrite union(
this,
computed_userset(relation: "owner"),
tuple_to_userset(tupleset: "parent", computed_userset: "viewer")
)
}
}
๐ง API Reference
ZanzibarService
The main service for handling authorization.
Data Types
// Object represents a resource
// Relation represents a permission type
;
// User can be a direct user ID or a userset
// RelationTuple represents a permission assertion
๐ Examples
File Permissions System
This example demonstrates:
- Hierarchical file and folder permissions
- Dynamic permission granting and revocation
- Permission inheritance through parent relationships
- Real-world usage patterns
Custom Implementation
use ;
// Define your domain objects
let document = Object ;
let user = UserId;
// Set up your service with policies
let mut service = new;
service.add_dsl?;
// Grant permissions
service.write_tuple?;
// Check permissions
let can_view = service.check?;
๐งช Testing
Run the test suite:
# Run all tests
# Run specific test categories
# Run with output
๐ Performance Considerations
- In-Memory Storage: Current implementation uses
HashSetfor fast lookups - Cycle Detection: Prevents infinite recursion in policy evaluation
- Extensible Storage:
TupleStoretrait allows custom storage backends - Zero-Copy Parsing: Efficient DSL parsing with
pest
๐ฃ๏ธ Roadmap
- Persistent storage backends (PostgreSQL, Redis)
- Metrics and observability
- Policy validation and testing tools
- Performance benchmarks
- gRPC API server
- Policy migration tools
๐ค Contributing
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
๐ License
This project is licensed under the MIT License - see the LICENSE file for details.
๐ Acknowledgments
- Google's Zanzibar paper for the foundational concepts
- OpenFGA for inspiration on DSL design
- The Rust community for excellent crates like
pestandthiserror
๐ Support
- ๐ Documentation
- ๐ Issue Tracker
- ๐ฌ Discussions
Simple Zanzibar - Making authorization simple, scalable, and secure. ๐