use crate::schema; use microrm::prelude::*; use ring::signature::Ed25519KeyPair; use sha2::Digest; use std::collections::HashMap; pub struct CertStore<'a> { db: &'a microrm::DB, qi: microrm::QueryInterface<'a>, keys: HashMap, } impl<'a> CertStore<'a> { pub fn new(db: &'a microrm::DB) -> Self { Self { db, qi: db.query_interface(), keys: HashMap::new(), } } fn realm_id(&self, realm_name: &str) -> Option { self.qi .get() .by(schema::Realm::Shortname, realm_name) .one() .expect("couldn't query db") .map(|x| x.id()) } pub fn generate_in(&self, realm_name: &str) -> Result { let mut rng = ring::rand::SystemRandom::new(); let sign_generated = Ed25519KeyPair::generate_pkcs8(&mut rng); let realm_id = self.realm_id(realm_name).ok_or("Failed to find realm")?; if let Err(_) = sign_generated { return Err("Failed to generate key"); } let sign_generated = sign_generated.unwrap(); let keydata = sign_generated.as_ref().to_owned(); let mut key_hasher = sha2::Sha256::new(); key_hasher.update(&keydata); let mut key_id = base64::encode(key_hasher.finalize()); key_id.truncate(16); self.qi .add(&schema::Key { realm: realm_id, key_id: key_id.clone(), keydata, }) .expect("Couldn't add key"); Ok(key_id) } } pub fn inspect(db: µrm::DB, realm_name: &str) { let qi = db.query_interface(); let cs = CertStore::new(db); println!("Certstore loaded."); let realm = qi .get() .by(schema::Realm::Shortname, realm_name) .one() .expect("couldn't query db"); if realm.is_none() { println!("No such realm {}", realm_name); return; } let realm = realm.unwrap(); println!("Retrieving keys for {} realm...", realm_name); let keys = qi .get() .by(schema::Key::Realm, &realm.id()) .all() .expect("Can get keys"); for key in keys { println!("- [{:20}]", key.key_id); } } pub fn generate(db: µrm::DB, realm_name: &str) { let qi = db.query_interface(); let cs = CertStore::new(db); if let Err(e) = cs.generate_in(realm_name) { println!("Failed to generate key: {}", e); } }