pub use hirn_policy::{
Action, AuthzDecision, AuthzRequest, DEFAULT_OPEN_POLICY, DEFAULT_SCHEMA, EntityKind,
PolicyEngine, PolicyError,
};
use std::sync::Arc;
pub struct PolicyNamespaceResolver {
engine: Arc<PolicyEngine>,
action: Action,
}
impl PolicyNamespaceResolver {
pub fn new(engine: Arc<PolicyEngine>, action: Action) -> Self {
Self { engine, action }
}
pub fn for_recall(engine: Arc<PolicyEngine>) -> Self {
Self::new(engine, Action::Recall)
}
}
#[async_trait::async_trait]
impl hirn_storage::NamespacePolicy for PolicyNamespaceResolver {
async fn allowed_namespaces(&self, principal: &str) -> Option<Vec<String>> {
self.engine.allowed_namespaces_for(principal, self.action)
}
}
#[cfg(test)]
mod tests {
use super::*;
use hirn_storage::NamespacePolicy;
#[tokio::test(flavor = "multi_thread")]
async fn policy_namespace_resolver_open_mode() {
let engine = Arc::new(PolicyEngine::open_mode());
let resolver = PolicyNamespaceResolver::for_recall(engine);
let result = resolver.allowed_namespaces("anyone").await;
assert!(result.is_none());
}
#[tokio::test(flavor = "multi_thread")]
async fn policy_namespace_resolver_filters_namespaces() {
let engine = Arc::new(
PolicyEngine::new(DEFAULT_SCHEMA, &[("default.cedar", DEFAULT_OPEN_POLICY)]).unwrap(),
);
engine.register_realm("production", "prod realm").unwrap();
engine
.register_namespace("ns_a", "public", "production")
.unwrap();
engine
.register_namespace("ns_b", "public", "production")
.unwrap();
engine
.register_agent("agent-1", 50, "2024-01-01", &[])
.unwrap();
let resolver = PolicyNamespaceResolver::for_recall(engine);
let result = resolver.allowed_namespaces("agent-1").await;
assert!(result.is_some());
let mut allowed = result.unwrap();
allowed.sort();
assert_eq!(allowed, vec!["ns_a", "ns_b"]);
}
}