use std::path::PathBuf;
use clap::Parser;
use log::info;
use crate::{
sop::Certificate,
store::{EncryptedStore, EncryptedStoreError, StoreError},
Config, LeafCommand,
};
#[derive(Debug, Parser)]
pub struct ListCerts {}
impl LeafCommand for ListCerts {
type Error = CertError;
fn run(&self, config: &Config) -> Result<(), CertError> {
let store = EncryptedStore::new(config.sop(), config.store()).read_store()?;
info!("loaded store OK");
for name in store.cert_names() {
println!("{name}");
}
Ok(())
}
}
#[derive(Debug, Parser)]
pub struct AddCert {
#[clap(long)]
name: String,
#[clap(long)]
cert: PathBuf,
}
impl LeafCommand for AddCert {
type Error = CertError;
fn run(&self, config: &Config) -> Result<(), CertError> {
let encrypted = EncryptedStore::new(config.sop(), config.store());
let mut store = encrypted.read_store()?;
let cert =
std::fs::read(&self.cert).map_err(|err| CertError::ReadCert(self.cert.clone(), err))?;
let cert = Certificate::new(cert);
store.push_cert(&self.name, &cert);
encrypted.write_store(&store)?;
Ok(())
}
}
#[derive(Debug, Parser)]
pub struct ShowCert {
name: String,
}
impl LeafCommand for ShowCert {
type Error = CertError;
fn run(&self, config: &Config) -> Result<(), CertError> {
let encrypted = EncryptedStore::new(config.sop(), config.store());
let store = encrypted.read_store()?;
info!("get value for {}", self.name);
if let Some(value) = store.get(&self.name) {
println!("{}", String::from_utf8_lossy(value));
} else {
return Err(CertError::NoSuchCert(self.name.clone()));
}
Ok(())
}
}
#[derive(Debug, Parser)]
pub struct RemoveCert {
name: String,
}
impl LeafCommand for RemoveCert {
type Error = CertError;
fn run(&self, config: &Config) -> Result<(), CertError> {
info!("remove certificate {}", self.name);
let encrypted = EncryptedStore::new(config.sop(), config.store());
let mut store = encrypted.read_store()?;
store.remove_cert(&self.name)?;
encrypted.write_store(&store)?;
Ok(())
}
}
#[derive(Debug, Parser)]
pub struct RenameCert {
old: String,
new: String,
}
impl LeafCommand for RenameCert {
type Error = CertError;
fn run(&self, config: &Config) -> Result<(), CertError> {
info!("rename {} to {}", self.old, self.new);
let encrypted = EncryptedStore::new(config.sop(), config.store());
let mut store = encrypted.read_store()?;
info!("rename in memory");
store.rename(&self.old, &self.new)?;
info!("rename in memory OK");
encrypted.write_store(&store)?;
Ok(())
}
}
#[derive(Debug, thiserror::Error)]
pub enum CertError {
#[error("failed to read certificate from file {0}")]
ReadCert(PathBuf, #[source] std::io::Error),
#[error("there is not certificate named {0}")]
NoSuchCert(String),
#[error(transparent)]
Encrypted(#[from] EncryptedStoreError),
#[error(transparent)]
Store(#[from] StoreError),
}