Skip to main content

chio_kernel/
authority.rs

1use chio_core::capability::{
2    CapabilityToken, CapabilityTokenBody, ChioScope, RuntimeAttestationEvidence,
3};
4use chio_core::crypto::{Keypair, PublicKey};
5use uuid::Uuid;
6
7use crate::KernelError;
8
9pub trait CapabilityAuthority: Send + Sync {
10    fn authority_public_key(&self) -> PublicKey;
11
12    fn trusted_public_keys(&self) -> Vec<PublicKey> {
13        vec![self.authority_public_key()]
14    }
15
16    fn issue_capability(
17        &self,
18        subject: &PublicKey,
19        scope: ChioScope,
20        ttl_seconds: u64,
21    ) -> Result<CapabilityToken, KernelError>;
22
23    fn issue_capability_with_attestation(
24        &self,
25        subject: &PublicKey,
26        scope: ChioScope,
27        ttl_seconds: u64,
28        _runtime_attestation: Option<RuntimeAttestationEvidence>,
29    ) -> Result<CapabilityToken, KernelError> {
30        self.issue_capability(subject, scope, ttl_seconds)
31    }
32}
33
34pub struct LocalCapabilityAuthority {
35    keypair: Keypair,
36}
37
38impl LocalCapabilityAuthority {
39    pub fn new(keypair: Keypair) -> Self {
40        Self { keypair }
41    }
42}
43
44impl CapabilityAuthority for LocalCapabilityAuthority {
45    fn authority_public_key(&self) -> PublicKey {
46        self.keypair.public_key()
47    }
48
49    fn issue_capability(
50        &self,
51        subject: &PublicKey,
52        scope: ChioScope,
53        ttl_seconds: u64,
54    ) -> Result<CapabilityToken, KernelError> {
55        let now = std::time::SystemTime::now()
56            .duration_since(std::time::UNIX_EPOCH)
57            .map(|duration| duration.as_secs())
58            .unwrap_or(0);
59        let body = CapabilityTokenBody {
60            id: format!("cap-{}", Uuid::now_v7()),
61            issuer: self.keypair.public_key(),
62            subject: subject.clone(),
63            scope,
64            issued_at: now,
65            expires_at: now.saturating_add(ttl_seconds),
66            delegation_chain: vec![],
67        };
68
69        CapabilityToken::sign(body, &self.keypair)
70            .map_err(|error| KernelError::CapabilityIssuanceFailed(error.to_string()))
71    }
72}
73
74#[derive(Debug, Clone, PartialEq, Eq)]
75pub struct AuthorityStatus {
76    pub public_key: PublicKey,
77    pub generation: u64,
78    pub rotated_at: u64,
79    pub trusted_public_keys: Vec<PublicKey>,
80}
81
82#[derive(Debug, Clone, PartialEq, Eq)]
83pub struct AuthorityTrustedKeySnapshot {
84    pub public_key_hex: String,
85    pub generation: u64,
86    pub activated_at: u64,
87}
88
89#[derive(Debug, Clone, PartialEq, Eq)]
90pub struct AuthoritySnapshot {
91    pub public_key_hex: String,
92    pub generation: u64,
93    pub rotated_at: u64,
94    pub trusted_keys: Vec<AuthorityTrustedKeySnapshot>,
95}
96
97#[derive(Debug, thiserror::Error)]
98pub enum AuthorityStoreError {
99    #[error("sqlite error: {0}")]
100    Sqlite(#[from] rusqlite::Error),
101
102    #[error("failed to prepare authority store directory: {0}")]
103    Io(#[from] std::io::Error),
104
105    #[error("invalid authority seed: {0}")]
106    Core(#[from] chio_core::error::Error),
107
108    #[error("authority fence rejected mutation: {0}")]
109    Fence(String),
110}