use std::fmt;
use std::time::Duration;
use zeroize::Zeroizing;
pub type Key = Zeroizing<String>;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum KeyStoreErrorKind {
Denied,
Unavailable,
Corrupt,
Unsettled,
Other,
}
#[derive(Clone, Debug, thiserror::Error)]
#[error("{kind:?}: {message}")]
pub struct KeyStoreError {
pub kind: KeyStoreErrorKind,
pub message: String,
}
impl KeyStoreError {
pub fn new(kind: KeyStoreErrorKind, message: impl Into<String>) -> Self {
Self {
kind,
message: message.into(),
}
}
pub fn denied(message: impl Into<String>) -> Self {
Self::new(KeyStoreErrorKind::Denied, message)
}
pub fn unavailable(message: impl Into<String>) -> Self {
Self::new(KeyStoreErrorKind::Unavailable, message)
}
pub fn other(message: impl Into<String>) -> Self {
Self::new(KeyStoreErrorKind::Other, message)
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PendingRevision(pub String);
#[derive(Clone)]
pub struct PendingKey {
pub key: Key,
pub revision: PendingRevision,
}
impl fmt::Debug for PendingKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("PendingKey")
.field("key", &"<redacted>")
.field("revision", &self.revision)
.finish()
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum KeySource {
Primary,
Pending,
LegacyStaging(String),
Recovery,
}
pub trait ProtectedKeyStore: Send + Sync {
fn lock_rotation(
&self,
timeout: Duration,
) -> Result<Box<dyn ProtectedKeySession + Send + 'static>, KeyStoreError>;
}
pub trait ProtectedKeySession: Send {
fn read_primary(&mut self) -> Result<Option<Key>, KeyStoreError>;
fn read_pending(&mut self) -> Result<Option<PendingKey>, KeyStoreError>;
fn write_pending(&mut self, key: &Key) -> Result<PendingRevision, KeyStoreError>;
fn promote_pending(&mut self, revision: &PendingRevision) -> Result<(), KeyStoreError>;
fn discard_pending(&mut self, revision: &PendingRevision) -> Result<(), KeyStoreError>;
fn read_legacy_staging(&mut self, alias: &str) -> Result<Option<Key>, KeyStoreError>;
fn delete_legacy_staging(&mut self, alias: &str) -> Result<(), KeyStoreError>;
fn read_recovery(&mut self) -> Result<Option<Key>, KeyStoreError>;
fn write_recovery(&mut self, key: &Key) -> Result<(), KeyStoreError>;
fn clear_recovery(&mut self) -> Result<(), KeyStoreError>;
}