use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use std::error::Error;
use std::fmt::{Display, Formatter};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Violation {
pub stage: &'static str,
pub reason: String,
}
impl Violation {
pub fn new(stage: &'static str, reason: impl Into<String>) -> Self {
Self {
stage,
reason: reason.into(),
}
}
}
impl Display for Violation {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}: {}", self.stage, self.reason)
}
}
impl Error for Violation {}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct DelegationToken {
pub spec_version: String,
pub kind: String,
pub token_id: String,
pub issuer: String,
pub agent_id: String,
pub delegator_id: String,
pub audience: Vec<String>,
pub allowed_actions: Vec<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub allowed_resources: Option<Vec<String>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub max_delegation_depth: Option<u16>,
pub issued_at: DateTime<Utc>,
pub expires_at: DateTime<Utc>,
pub nonce: String,
pub key_id: String,
pub signature_alg: String,
pub signature: String,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct RequestEnvelope {
pub spec_version: String,
pub kind: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub request_id: Option<String>,
pub delegation_token: DelegationToken,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct OperationContext {
pub audience: String,
pub action: String,
pub resource: Option<String>,
pub delegation_depth: Option<u16>,
}
impl OperationContext {
pub fn new(audience: impl Into<String>, action: impl Into<String>) -> Self {
Self {
audience: audience.into(),
action: action.into(),
resource: None,
delegation_depth: None,
}
}
pub fn with_resource(mut self, resource: impl Into<String>) -> Self {
self.resource = Some(resource.into());
self
}
pub fn with_delegation_depth(mut self, depth: u16) -> Self {
self.delegation_depth = Some(depth);
self
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Decision {
pub allowed: bool,
pub stage: String,
pub reason: String,
}
impl Decision {
pub fn allow(stage: impl Into<String>, reason: impl Into<String>) -> Self {
Self {
allowed: true,
stage: stage.into(),
reason: reason.into(),
}
}
pub fn deny(stage: impl Into<String>, reason: impl Into<String>) -> Self {
Self {
allowed: false,
stage: stage.into(),
reason: reason.into(),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct AuditEvent {
pub occurred_at: DateTime<Utc>,
pub allowed: bool,
pub stage: String,
pub reason: String,
pub claims_verified: bool,
pub request_id: Option<String>,
pub token_id: Option<String>,
pub issuer: Option<String>,
pub agent_id: Option<String>,
pub delegator_id: Option<String>,
pub audience: String,
pub action: String,
pub resource: Option<String>,
}