| Crates.io | cedrus-core |
| lib.rs | cedrus-core |
| version | 0.1.0 |
| created_at | 2025-11-01 15:00:37.494245+00 |
| updated_at | 2025-11-01 15:00:37.494245+00 |
| description | Business logic and authorization engine for Cedrus. |
| homepage | https://github.com/stratusmedia/cedrus |
| repository | https://github.com/stratusmedia/cedrus |
| max_upload_size | |
| id | 1912073 |
| size | 322,105 |
Business logic and authorization engine for Cedrus.
cedrus-core is the core library that implements the Cedar Policy authorization engine with multi-tenant support. It provides:
┌─────────────────────────────────────────────────────────┐
│ Cedrus Core │
├─────────────────────────────────────────────────────────┤
│ Authorization Engine (Cedar Policy Evaluation) │
├─────────────────────────────────────────────────────────┤
│ Cache Layer (DashMap / Valkey) │
├─────────────────────────────────────────────────────────┤
│ Database Layer (DynamoDB / CouchDB) │
├─────────────────────────────────────────────────────────┤
│ PubSub Layer (Valkey / Dummy) │
└─────────────────────────────────────────────────────────┘
The library defines three main traits for pluggable backends:
Persists Cedar policies, entities, and schemas:
Provides fast in-memory access to authorization data:
Enables cluster synchronization across multiple Cedrus instances:
Cedrus uses Cedar policies to control access to itself:
00000000-0000-0000-0000-000000000000 (nil UUID)Cedrus::User: Represents usersCedrus::Project: Represents tenant projectsCedrus::Group: User groups (e.g., "Admins")Each project is an isolated tenant with:
Cedrus::User entity// Check if user can perform action on resource
let response = cedrus.is_authorized(
&project_id,
principal, // EntityUid
action, // EntityUid
resource, // EntityUid
context, // Optional<Context>
)?;
match response.decision {
Decision::Allow => { /* authorized */ },
Decision::Deny => { /* forbidden */ },
}
// Check multiple requests at once
let requests = vec![
Request { principal, action, resource, context },
// ... more requests
];
let responses = cedrus.is_authorized_batch(&project_id, requests)?;
Entities support parent relationships for group membership:
let entity = Entity::new(
EntityUid::new("MyApp::User".to_string(), "alice".to_string()),
attrs,
parents, // HashSet<EntityUid> - e.g., groups
);
Reusable policy patterns with slots:
// Template with ?principal and ?resource slots
let template = Template { /* ... */ };
// Link template to specific entities
let link = TemplateLink {
template_id: "AdminRole".into(),
new_id: "alice-admin".into(),
values: HashMap::from([
(SlotId::Principal, EntityValue::EntityUid(alice)),
(SlotId::Resource, EntityValue::EntityUid(project)),
]),
};
use cedrus_core::{
core::cedrus::Cedrus,
db::database_factory,
cache::cache_factory,
pubsub::pubsub_factory,
};
// Create backends
let db = database_factory(&config.db).await;
let cache = cache_factory(&config.cache).await;
let pubsub = pubsub_factory(&config.pubsub).await;
// Initialize Cedrus
let cedrus = Arc::new(Cedrus::new(db, cache, pubsub).await);
// Initialize admin project (first run only)
Cedrus::init_project(&cedrus, &config).await?;
// Load data from database to cache
Cedrus::init_cache(&cedrus).await?;
// Load cache data to memory
Cedrus::load_cache(&cedrus).await?;
For multi-instance deployments:
init_project() and init_cache()load_cache() to load from shared cache// Subscribe to cluster events
let ops = [subscribe_closure(&cedrus)];
tokio::spawn(async move {
cedrus.pubsub.subscribe(&ops).await;
});
CouchDB:
DbConfig::CouchDbConfig(CouchDbConfig {
uri: "http://localhost:5984".to_string(),
username: "admin".to_string(),
password: "password".to_string(),
db_name: "cedrus".to_string(),
})
DynamoDB:
DbConfig::DynamoDbConfig(DynamoDBConfig {
table_name: "cedrus-table".to_string(),
region: Some("us-east-1".to_string()),
endpoint_url: None,
})
In-Memory (Development):
CacheConfig::DashMapConfig(DashMapCacheConfig {})
Distributed (Production):
CacheConfig::ValKeyConfig(ValKeyCacheConfig {
urls: vec!["redis://localhost:6379".to_string()],
cluster: false,
..Default::default()
})
Single Instance:
PubSubConfig::DummyConfig(DummyPubSubConfig {})
Cluster:
PubSubConfig::ValKeyConfig(ValKeyPubSubConfig {
urls: vec!["redis://localhost:6379/?protocol=resp3".to_string()],
channel_name: "cedrus".to_string(),
cluster: false,
..Default::default()
})
Cedrus uses an event-driven architecture for cache synchronization:
ProjectCreate: New project createdProjectUpdate: Project metadata updatedProjectRemove: Project deletedProjectPutSchema: Schema updatedProjectAddEntities: Entities addedProjectRemoveEntities: Entities deletedProjectAddPolicies: Policies addedProjectRemovePolicies: Policies deletedProjectAddTemplates: Templates addedProjectAddTemplateLinks: Template links addedThe authorization engine automatically resolves entity hierarchies:
// Fetches entity and all parent entities recursively
let entities = cedrus.get_cedar_entities(&project_id, &entity_uids)?;
Use batch operations for better performance:
project_entities_add(): Add multiple entities at onceproject_policies_add(): Add multiple policies at onceis_authorized_batch(): Evaluate multiple requests at onceThis library is used by:
cedrus-cedar: Type definitions and serializationcedar-policy: Official Cedar policy enginedashmap: Concurrent hash mapaws-sdk-dynamodb: DynamoDB clientcouch_rs: CouchDB clientredis: Valkey/Redis clientjwt-authorizer: JWT validation