use crate::{EvaluationSession, FactProvenance, PolicyEvalResult, SecurityRuleMetadata};
use async_trait::async_trait;
use std::borrow::Cow;
pub struct PolicyBatchItem<'a, Resource, Context> {
pub resource: &'a Resource,
pub context: &'a Context,
}
pub struct EvalCtx<'a, Subject, Resource, Action, Context> {
pub session: &'a EvaluationSession,
pub subject: &'a Subject,
pub action: &'a Action,
pub resource: &'a Resource,
pub context: &'a Context,
pub policy_type: Cow<'static, str>,
}
impl<'a, S, R, A, C> EvalCtx<'a, S, R, A, C> {
pub fn grant(&self, reason: impl Into<String>) -> PolicyEvalResult {
PolicyEvalResult::granted(self.policy_type.clone(), Some(reason.into()))
}
pub fn deny(&self, reason: impl Into<String>) -> PolicyEvalResult {
PolicyEvalResult::denied(self.policy_type.clone(), reason)
}
pub fn grant_with_facts(
&self,
reason: impl Into<String>,
provenance: Vec<FactProvenance>,
) -> PolicyEvalResult {
PolicyEvalResult::granted_with_facts(
self.policy_type.clone(),
Some(reason.into()),
provenance,
)
}
pub fn deny_with_facts(
&self,
reason: impl Into<String>,
provenance: Vec<FactProvenance>,
) -> PolicyEvalResult {
PolicyEvalResult::denied_with_facts(self.policy_type.clone(), reason, provenance)
}
}
pub struct BatchEvalCtx<'a, Subject, Resource, Action, Context> {
pub session: &'a EvaluationSession,
pub subject: &'a Subject,
pub action: &'a Action,
pub items: &'a [PolicyBatchItem<'a, Resource, Context>],
pub policy_type: Cow<'static, str>,
}
#[async_trait]
pub trait Policy<Subject, Resource, Action, Context>: Send + Sync
where
Subject: Sync,
Resource: Sync,
Action: Sync,
Context: Sync,
{
async fn evaluate(
&self,
ctx: &EvalCtx<'_, Subject, Resource, Action, Context>,
) -> PolicyEvalResult;
async fn evaluate_batch<'item>(
&self,
ctx: &BatchEvalCtx<'item, Subject, Resource, Action, Context>,
) -> Vec<PolicyEvalResult> {
let mut results = Vec::with_capacity(ctx.items.len());
for item in ctx.items {
let item_ctx = EvalCtx {
session: ctx.session,
subject: ctx.subject,
action: ctx.action,
resource: item.resource,
context: item.context,
policy_type: ctx.policy_type.clone(),
};
results.push(self.evaluate(&item_ctx).await);
}
results
}
fn policy_type(&self) -> Cow<'static, str>;
fn security_rule(&self) -> SecurityRuleMetadata {
SecurityRuleMetadata::default()
}
}
#[async_trait]
impl<S, R, A, C> Policy<S, R, A, C> for Box<dyn Policy<S, R, A, C>>
where
S: Sync,
R: Sync,
A: Sync,
C: Sync,
{
async fn evaluate(&self, ctx: &EvalCtx<'_, S, R, A, C>) -> PolicyEvalResult {
(**self).evaluate(ctx).await
}
async fn evaluate_batch<'item>(
&self,
ctx: &BatchEvalCtx<'item, S, R, A, C>,
) -> Vec<PolicyEvalResult> {
(**self).evaluate_batch(ctx).await
}
fn policy_type(&self) -> Cow<'static, str> {
(**self).policy_type()
}
fn security_rule(&self) -> SecurityRuleMetadata {
(**self).security_rule()
}
}