From 2488ac8206103755b8de05eab796be231dd2236a Mon Sep 17 00:00:00 2001 From: Jonathan Grahl Date: Tue, 10 Sep 2024 18:05:19 +0200 Subject: [PATCH] test: a beginning to dst --- crates/keystore/src/api/server.rs | 14 +- crates/keystore/src/clock.rs | 93 ++++++++++++++ crates/keystore/src/cmd/main.rs | 4 +- crates/keystore/src/lib.rs | 198 ++++++++++++++++++++++++----- crates/keystore/src/rotator.rs | 48 +++++++ crates/keystore/src/storage/fdb.rs | 45 ++++++- crates/keystore/src/tests.rs | 18 +-- crates/valv/src/main.rs | 45 +++---- 8 files changed, 389 insertions(+), 76 deletions(-) create mode 100644 crates/keystore/src/clock.rs create mode 100644 crates/keystore/src/rotator.rs diff --git a/crates/keystore/src/api/server.rs b/crates/keystore/src/api/server.rs index 0746ad0..61008c9 100644 --- a/crates/keystore/src/api/server.rs +++ b/crates/keystore/src/api/server.rs @@ -24,7 +24,7 @@ impl MasterKeyManagementService for API { ) -> Result, tonic::Status> { let key = self .keystore - .create_key(request.get_ref().keyring_name.clone(), request.get_ref().master_key_id.clone()) + .create_key(request.get_ref().keyring_name.as_str(), request.get_ref().master_key_id.as_str()) .await; let reply = CreateMasterKeyResponse { @@ -86,9 +86,9 @@ impl MasterKeyManagementService for API { request: tonic::Request, ) -> Result, tonic::Status> { let encrypted_value = self.keystore.encrypt( - request.get_ref().keyring_name.clone(), - request.get_ref().master_key_id.clone(), - request.get_ref().plaintext.clone().to_vec(), + request.get_ref().keyring_name.as_str(), + request.get_ref().master_key_id.as_str(), + request.get_ref().plaintext.to_vec(), ).await; let reply = crate::valv::keystore::v1::EncryptResponse { @@ -104,9 +104,9 @@ impl MasterKeyManagementService for API { request: tonic::Request, ) -> Result, tonic::Status> { let decrypted_result = self.keystore.decrypt( - request.get_ref().keyring_name.clone(), - request.get_ref().master_key_id.clone(), - request.get_ref().ciphertext.clone().to_vec(), + request.get_ref().keyring_name.as_str(), + request.get_ref().master_key_id.as_str(), + request.get_ref().ciphertext.to_vec(), ).await; match decrypted_result { Ok(decrypted_value) => { diff --git a/crates/keystore/src/clock.rs b/crates/keystore/src/clock.rs new file mode 100644 index 0000000..88c8aa7 --- /dev/null +++ b/crates/keystore/src/clock.rs @@ -0,0 +1,93 @@ +use std::time::{Duration, SystemTime}; +use std::sync::Mutex; + +pub struct MockClock { + current_time: Mutex, +} + +impl MockClock { + pub fn new(initial_time: SystemTime) -> Self { + MockClock { + current_time: Mutex::new(initial_time), + } + } + + fn now(&self) -> SystemTime { + *self.current_time.lock().unwrap() + } + + fn advance(&self, duration: Duration) { + let mut current_time = self.current_time.lock().unwrap(); + *current_time += duration; + } +} + +pub trait Clock: Send + Sync { + fn now(&self) -> SystemTime; +} + +impl Clock for MockClock { + fn now(&self) -> SystemTime { + self.now() + } +} + +impl Clock for SystemTime { + fn now(&self) -> SystemTime { + SystemTime::now() + } +} + +#[cfg(test)] +mod tests { + use super::*; + use std::time::{Duration, SystemTime}; + + #[test] + fn test_mock_clock_new() { + let initial_time = SystemTime::UNIX_EPOCH + Duration::from_secs(1000); + let clock = MockClock::new(initial_time); + assert_eq!(clock.now(), initial_time); + } + + #[test] + fn test_mock_clock_advance() { + let initial_time = SystemTime::UNIX_EPOCH; + let clock = MockClock::new(initial_time); + + clock.advance(Duration::from_secs(60)); + assert_eq!(clock.now(), initial_time + Duration::from_secs(60)); + + clock.advance(Duration::from_secs(30)); + assert_eq!(clock.now(), initial_time + Duration::from_secs(90)); + } + + #[test] + fn test_mock_clock_multiple_advances() { + let initial_time = SystemTime::UNIX_EPOCH; + let clock = MockClock::new(initial_time); + + for i in 1..=5 { + clock.advance(Duration::from_secs(10)); + assert_eq!(clock.now(), initial_time + Duration::from_secs(i * 10)); + } + } + + #[test] + fn test_mock_clock_trait_implementation() { + let initial_time = SystemTime::UNIX_EPOCH + Duration::from_secs(500); + let clock: Box = Box::new(MockClock::new(initial_time)); + + assert_eq!(clock.now(), initial_time); + } + + #[test] + fn test_system_time_clock_trait_implementation() { + let clock: Box = Box::new(SystemTime::UNIX_EPOCH); + + // This test is non-deterministic, but we can check if the time is recent + let now = clock.now(); + let elapsed = now.duration_since(SystemTime::UNIX_EPOCH).unwrap(); + assert!(elapsed.as_secs() > 0); + } +} \ No newline at end of file diff --git a/crates/keystore/src/cmd/main.rs b/crates/keystore/src/cmd/main.rs index 7fe7561..0f44ff5 100644 --- a/crates/keystore/src/cmd/main.rs +++ b/crates/keystore/src/cmd/main.rs @@ -1,4 +1,4 @@ -use std::sync::Arc; +use std::{sync::Arc, time::SystemTime}; use clap::Parser; use keystore::{ @@ -21,7 +21,7 @@ struct Cli { async fn main() { let args = Cli::parse(); - let mut keystore = Keystore::new().await; + let mut keystore = Keystore::new(Arc::new(SystemTime::now())).await; let master_key = args.master_key.clone().expose_secret().clone().into_bytes()[..32] .try_into() diff --git a/crates/keystore/src/lib.rs b/crates/keystore/src/lib.rs index ae1923f..451e168 100644 --- a/crates/keystore/src/lib.rs +++ b/crates/keystore/src/lib.rs @@ -1,5 +1,7 @@ +use std::{sync::Arc, time::UNIX_EPOCH}; use boring::error::ErrorStack; +use clock::Clock; use gen::keystore::internal; use prost::bytes::Buf; use secrecy::{ExposeSecret, Secret}; @@ -7,10 +9,14 @@ use serde::{Deserialize, Serialize}; use storage::{fdb::FoundationDB, interface::KeystoreStorage}; pub mod api; +pub mod clock; pub mod gen; + +//mod rotator; mod storage; mod tests; + pub mod valv { pub mod keystore { pub mod v1 { @@ -39,25 +45,29 @@ pub struct KeyMaterial { #[async_trait::async_trait] pub trait KeystoreAPI: Send + Sync { - async fn create_key(&self, tenant: String, name: String) -> internal::Key; - async fn get_key(&self, tenant: String, name: String) -> Option; - async fn list_keys(&self, tenant: String) -> Option>; - async fn update_key(&self, tenant: String, key: internal::Key) -> internal::Key; + async fn list_tenants(&self) -> Result, anyhow::Error>; - async fn get_key_version(&self, tenant: String, key_name: String, version_id: u32) -> Option; + async fn create_key(&self, tenant: &str, name: &str) -> internal::Key; + async fn get_key(&self, tenant: &str, name: &str) -> Option; + async fn list_keys(&self, tenant: &str) -> Option>; + async fn update_key(&self, tenant: &str, key: internal::Key) -> internal::Key; - async fn encrypt(&self, tenant: String, key_name: String, plaintext: Vec) -> Vec; - async fn decrypt(&self, tenant: String, key_name: String, ciphertext: Vec) -> Result, ErrorStack>; + async fn get_key_version(&self, tenant: &str, key_name: &str, version_id: u32) -> Option; + + async fn encrypt(&self, tenant: &str, key_name: &str, plaintext: Vec) -> Vec; + async fn decrypt(&self, tenant: &str, key_name: &str, ciphertext: Vec) -> Result, ErrorStack>; } pub struct Keystore { + clock: Arc, pub db: FoundationDB, pub master_key: Secret<[u8; 32]>, } impl Keystore { - pub async fn new() -> Keystore { + pub async fn new(clock: Arc) -> Keystore { Keystore { + clock, db: FoundationDB::new("local").await.unwrap(), master_key: [0; 32].into(), } @@ -70,22 +80,26 @@ impl Keystore { #[async_trait::async_trait] impl KeystoreAPI for Keystore { - async fn get_key(&self, tenant: String, name: String) -> Option { + async fn list_tenants(&self) -> Result, anyhow::Error> { + self.db.list_tenants().await + } + + async fn get_key(&self, tenant: &str, name: &str) -> Option { let key = self .db - .get_key_metadata(tenant.as_str(), name.as_str()) + .get_key_metadata(tenant, name) .await .unwrap(); Some(key) } - async fn list_keys(&self, tenant: String) -> Option> { - let keys = self.db.list_key_metadata(tenant.as_str()).await.unwrap(); + async fn list_keys(&self, tenant: &str) -> Option> { + let keys = self.db.list_key_metadata(tenant).await.unwrap(); Some(keys) } - async fn create_key(&self, tenant: String, name: String) -> internal::Key { + async fn create_key(&self, tenant: &str, name: &str) -> internal::Key { let mut iv = [0; 12]; let mut key = [0; 32]; let mut tag = [0; 16]; @@ -114,12 +128,12 @@ impl KeystoreAPI for Keystore { encrypted_result.extend_from_slice(&tag); let key = internal::Key { - key_id: name.clone(), + key_id: name.to_string(), primary_version_id: 1.to_string(), purpose: "ENCRYPT_DECRYPT".to_string(), creation_time: Some(prost_types::Timestamp { - seconds: chrono::Utc::now().timestamp(), - nanos: chrono::Utc::now().timestamp_subsec_nanos() as i32, + seconds: self.clock.now().duration_since(UNIX_EPOCH).unwrap().as_secs() as i64, + nanos: self.clock.now().duration_since(UNIX_EPOCH).unwrap().subsec_nanos() as i32, }), rotation_schedule: Some(prost_types::Duration { seconds: chrono::TimeDelta::days(30).num_seconds() as i64, @@ -129,23 +143,23 @@ impl KeystoreAPI for Keystore { }; self.db - .update_key_metadata(tenant.as_str(), key.clone()).await.unwrap(); + .update_key_metadata(tenant, key.clone()).await.unwrap(); let key_version = internal::KeyVersion { - key_id: name.clone(), + key_id: name.to_string(), key_material: encrypted_result.to_vec().into(), state: internal::KeyVersionState::Enabled as i32, version: 1, creation_time: Some(prost_types::Timestamp { - seconds: chrono::Utc::now().timestamp(), - nanos: chrono::Utc::now().timestamp_subsec_nanos() as i32, + seconds: self.clock.now().duration_since(UNIX_EPOCH).unwrap().as_secs() as i64, + nanos: self.clock.now().duration_since(UNIX_EPOCH).unwrap().subsec_nanos() as i32, }), ..Default::default() }; self.db .append_key_version( - tenant.as_str(), + tenant, key.clone(), key_version, ) @@ -155,20 +169,20 @@ impl KeystoreAPI for Keystore { key } - async fn update_key(&self, tenant: String, key: internal::Key) -> internal::Key { - self.db.update_key_metadata(tenant.as_str(), key.clone()).await.unwrap(); + async fn update_key(&self, tenant: &str, key: internal::Key) -> internal::Key { + self.db.update_key_metadata(tenant, key.clone()).await.unwrap(); key } - async fn get_key_version(&self, tenant: String, key_name: String, version_id: u32) -> Option { - let key_version = self.db.get_key_version(tenant.as_str(), &key_name, version_id).await.unwrap(); + async fn get_key_version(&self, tenant: &str, key_name: &str, version_id: u32) -> Option { + let key_version = self.db.get_key_version(tenant, &key_name, version_id).await.unwrap(); Some(key_version) } - async fn encrypt(&self, tenant: String, key_name: String, plaintext: Vec) -> Vec { - let key = self.db.get_key_metadata(tenant.as_str(), &key_name).await.unwrap(); - let key_version = self.db.get_key_version(tenant.as_str(), &key.key_id, key.primary_version_id.parse().unwrap()).await.unwrap(); + async fn encrypt(&self, tenant: &str, key_name: &str, plaintext: Vec) -> Vec { + let key = self.db.get_key_metadata(tenant, &key_name).await.unwrap(); + let key_version = self.db.get_key_version(tenant, &key.key_id, key.primary_version_id.parse().unwrap()).await.unwrap(); let (iv, remainder) = key_version.key_material.split_at(12); let (cipher, tag) = remainder.split_at(remainder.len() - 16); @@ -214,14 +228,14 @@ impl KeystoreAPI for Keystore { encrypted_result } - async fn decrypt(&self, tenant: String, key_name: String, ciphertext: Vec) -> Result, ErrorStack> { + async fn decrypt(&self, tenant: &str, key_name: &str, ciphertext: Vec) -> Result, ErrorStack> { let (key_version_id, remainder) = ciphertext.split_at(4); let (iv, remainder) = remainder.split_at(12); let (cipher, tag) = remainder.split_at(remainder.len() - 16); - let key = self.db.get_key_metadata(tenant.as_str(), &key_name).await.unwrap(); + let key = self.db.get_key_metadata(tenant, &key_name).await.unwrap(); let key_version_id = std::io::Cursor::new(key_version_id).get_u32(); - let key_version = self.db.get_key_version(tenant.as_str(), &key.key_id, key_version_id).await.unwrap(); + let key_version = self.db.get_key_version(tenant, &key.key_id, key_version_id).await.unwrap(); let (kv_iv, kv_remainder) = key_version.key_material.split_at(12); let (kv_cipher, kv_tag) = kv_remainder.split_at(kv_remainder.len() - 16); @@ -245,3 +259,125 @@ impl KeystoreAPI for Keystore { ) } } + +#[cfg(test)] +mod unittests { + use super::*; + use std::{panic, sync::Arc}; + use foundationdb::api::NetworkAutoStop; + use tokio::sync::Mutex; + + struct MockClock { + now: std::time::SystemTime, + } + + impl Clock for MockClock { + fn now(&self) -> std::time::SystemTime { + self.now + } + } + + async fn setup_keystore() -> Arc> { + let mock_clock = Arc::new(MockClock { + now: std::time::SystemTime::UNIX_EPOCH + std::time::Duration::from_secs(1000), + }); + let mut keystore = Keystore::new(mock_clock).await; + keystore.set_master_key([1; 32]); + Arc::new(Mutex::new(keystore)) + } + + #[tokio::test] + async fn run_all_tests() { + let _guard = unsafe { foundationdb::boot() }; + + let keystore = setup_keystore().await; + + test_create_and_get_key(&keystore).await; + test_list_keys(&keystore).await; + test_update_key(&keystore).await; + test_encrypt_and_decrypt(&keystore).await; + test_list_tenants(&keystore).await; + test_get_key_version(&keystore).await; + + } + + async fn test_create_and_get_key(keystore: &Arc>) { + let tenant = "test_tenant"; + let key_name = "test_key"; + + let created_key = keystore.lock().await.create_key(tenant, key_name).await; + assert_eq!(created_key.key_id, key_name); + + let retrieved_key = keystore.lock().await.get_key(tenant, key_name).await.unwrap(); + assert_eq!(retrieved_key, created_key); + } + + async fn test_list_keys(keystore: &Arc>) { + let tenant = "test_tenant_list"; + let key_names = vec!["key1", "key2", "key3"]; + + for name in &key_names { + keystore.lock().await.create_key(tenant, name).await; + } + + let listed_keys = keystore.lock().await.list_keys(tenant).await.unwrap(); + assert_eq!(listed_keys.len(), key_names.len()); + for key in listed_keys { + assert!(key_names.contains(&key.key_id.as_str())); + } + } + + async fn test_update_key(keystore: &Arc>) { + let tenant = "test_tenant_update"; + let key_name = "test_key_update"; + + let mut created_key = keystore.lock().await.create_key(tenant, key_name).await; + created_key.purpose = "SIGN_VERIFY".to_string(); + + let updated_key = keystore.lock().await.update_key(tenant, created_key.clone()).await; + assert_eq!(updated_key.purpose, "SIGN_VERIFY"); + + let retrieved_key = keystore.lock().await.get_key(tenant, key_name).await.unwrap(); + assert_eq!(retrieved_key, updated_key); + } + + async fn test_encrypt_and_decrypt(keystore: &Arc>) { + let tenant = "test_tenant_encrypt"; + let key_name = "test_key_encrypt"; + let plaintext = b"Hello, World!".to_vec(); + + keystore.lock().await.create_key(tenant, key_name).await; + + let ciphertext = keystore.lock().await.encrypt(tenant, key_name, plaintext.clone()).await; + assert_ne!(ciphertext, plaintext); + + let decrypted = keystore.lock().await.decrypt(tenant, key_name, ciphertext).await.unwrap(); + assert_eq!(decrypted, plaintext); + } + + async fn test_list_tenants(keystore: &Arc>) { + let tenants = vec!["tenant1", "tenant2", "tenant3"]; + + for tenant in &tenants { + keystore.lock().await.create_key(tenant, "dummy_key").await; + } + + let listed_tenants = keystore.lock().await.list_tenants().await.unwrap(); + assert_eq!(listed_tenants.len(), tenants.len()); + for tenant in tenants { + assert!(listed_tenants.contains(&tenant.to_string())); + } + } + + async fn test_get_key_version(keystore: &Arc>) { + let tenant = "test_tenant_version"; + let key_name = "test_key_version"; + + let created_key = keystore.lock().await.create_key(tenant, key_name).await; + let version_id = created_key.primary_version_id.parse::().unwrap(); + + let key_version = keystore.lock().await.get_key_version(tenant, key_name, version_id).await.unwrap(); + assert_eq!(key_version.key_id, key_name); + assert_eq!(key_version.version, version_id); + } +} diff --git a/crates/keystore/src/rotator.rs b/crates/keystore/src/rotator.rs new file mode 100644 index 0000000..e603bb8 --- /dev/null +++ b/crates/keystore/src/rotator.rs @@ -0,0 +1,48 @@ +use std::sync::Arc; + +use crate::{Keystore, KeystoreAPI}; + +pub struct KeyRotator { + keystore: Arc, +} + +impl KeyRotator { + pub fn new(keystore: Arc) -> Self { + KeyRotator { keystore } + } + + pub async fn run_rotation(&self) -> anyhow::Result<()> { + let now = self.keystore.clock.now(); + let keys = self.keystore.list_keys(None).await?; + + for key in keys { + if let Some(rotation_period) = key.rotation_period() { + let last_rotated = key.last_rotated(); + if now.duration_since(last_rotated)? >= rotation_period { + self.rotate_key(&key)?; + } + } + } + + Ok(()) + } + + async fn rotate_key(&self, key: &Key) -> Result<(), Box> { + // Implement key rotation logic here + // This might involve generating a new key, updating the old key, + // and storing the new key in the keystore + println!("Rotating key: {}", key.name()); + // self.keystore.rotate_key(key.name())?; + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::clock::MockClock; + use std::time::Duration; + + // Implement tests for KeyRotator + // You'll need to create a mock KeyStore for testing +} \ No newline at end of file diff --git a/crates/keystore/src/storage/fdb.rs b/crates/keystore/src/storage/fdb.rs index 6281efb..380bf9e 100644 --- a/crates/keystore/src/storage/fdb.rs +++ b/crates/keystore/src/storage/fdb.rs @@ -1,7 +1,7 @@ use anyhow::anyhow; use async_trait::async_trait; use foundationdb::{ - directory::Directory, + directory::{Directory, DirectoryLayer}, tuple::unpack, FdbError, RangeOption, }; @@ -34,7 +34,7 @@ impl FoundationDB { tenant: &str, key_id: &str, ) -> Vec { - let directory = foundationdb::directory::DirectoryLayer::default(); + let directory = DirectoryLayer::default(); let path = vec![ String::from(self.location.as_str()), @@ -68,7 +68,7 @@ impl FoundationDB { key_id: &str, version: u32, ) -> Vec { - let directory = foundationdb::directory::DirectoryLayer::default(); + let directory = DirectoryLayer::default(); let path = vec![ String::from(self.location.as_str()), @@ -99,6 +99,41 @@ impl FoundationDB { } } +impl FoundationDB { + pub async fn list_tenants(&self) -> Result, anyhow::Error> { + let trx = self.database.create_trx()?; + let directory = DirectoryLayer::default(); + + let path = vec![String::from(self.location.as_str())]; + + let location_subspace = directory + .create_or_open(&trx, &path, None, None) + .await + .map_err(|e| anyhow!("Failed to open root directory: {:?}", e))?; + + let range = RangeOption::from(location_subspace.range().unwrap()); + + let key_values = trx + .get_range(&range, 1_024, false) + .await + .map_err(|e| anyhow!("Failed to get range: {:?}", e))?; + + println!("key_value length: {:?}", key_values.len()); + + let tenants: Vec = key_values + .iter() + .filter_map(|kv| { + let unpacked: Result, _> = location_subspace.unpack(&kv.key()).unwrap(); + unpacked.ok().and_then(|u| { + Some(String::from_utf8(u).unwrap()) + }) + }) + .collect(); + + Ok(tenants) + } +} + #[async_trait] impl KeystoreStorage for FoundationDB { async fn get_key_metadata( @@ -121,7 +156,7 @@ impl KeystoreStorage for FoundationDB { async fn list_key_metadata(&self, tenant: &str) -> anyhow::Result> { let trx = self.database.create_trx()?; - let directory = foundationdb::directory::DirectoryLayer::default(); + let directory = DirectoryLayer::default(); let path = vec![ String::from(self.location.as_str()), @@ -200,7 +235,7 @@ impl KeystoreStorage for FoundationDB { async fn get_key_versions(&self, tenant: &str, key_id: &str) -> anyhow::Result> { let trx = self.database.create_trx()?; - let directory = foundationdb::directory::DirectoryLayer::default(); + let directory = DirectoryLayer::default(); let path = vec![ String::from(self.location.as_str()), diff --git a/crates/keystore/src/tests.rs b/crates/keystore/src/tests.rs index 6acf139..2bcfd11 100644 --- a/crates/keystore/src/tests.rs +++ b/crates/keystore/src/tests.rs @@ -1,15 +1,13 @@ #[cfg(test)] mod tests { use crate::{ - api::server::API, - valv::keystore::v1::{ + api::server::API, clock::MockClock, valv::keystore::v1::{ master_key_management_service_server::MasterKeyManagementServiceServer, CreateMasterKeyRequest, DecryptRequest, EncryptRequest, MasterKey, - }, - Keystore, KeystoreAPI, + }, Keystore, KeystoreAPI }; - use std::{sync::Arc, time::Duration}; + use std::{sync::Arc, time::{Duration, SystemTime}}; use tonic::transport::Server; use crate::valv::keystore::v1::master_key_management_service_client::MasterKeyManagementServiceClient; @@ -40,7 +38,8 @@ mod tests { async fn setup_server() -> anyhow::Result>> { let addr = SERVER_ADDR.parse()?; - let mut keystore = Keystore::new().await; + let mock_clock = Arc::new(MockClock::new(SystemTime::UNIX_EPOCH)); + let mut keystore = Keystore::new(mock_clock).await; let master_key_bytes: [u8; 32] = "77aaee825aa561995d7bda258f9b76b0" .as_bytes() .try_into() @@ -73,9 +72,10 @@ mod tests { } async fn test_keystore() -> anyhow::Result<()> { - let keystore = Keystore::new().await; - let key = keystore.create_key("tenant".to_string(), "test".to_string()).await; - let key_metadata = keystore.get_key("tenant".to_string(), key.key_id).await; + let clock = Arc::new(MockClock::new(SystemTime::UNIX_EPOCH)); + let keystore = Keystore::new(clock).await; + let key = keystore.create_key("tenant", "test").await; + let key_metadata = keystore.get_key("tenant", key.key_id.as_str()).await; assert_eq!(key_metadata.unwrap().key_id, "test"); Ok(()) diff --git a/crates/valv/src/main.rs b/crates/valv/src/main.rs index 7a33f22..8580a32 100644 --- a/crates/valv/src/main.rs +++ b/crates/valv/src/main.rs @@ -4,10 +4,11 @@ pub mod google { } } +use std::{sync::Arc, time::SystemTime}; + use crc32c::crc32c; use google::kms::{crypto_key::RotationSchedule, key_management_service_server::KeyManagementService}; -use keystore::{gen::keystore::internal, KeystoreAPI}; -use prost_types::Duration; +use keystore::{gen::keystore::internal, Keystore, KeystoreAPI}; use tokio::sync::Mutex; mod tests; @@ -29,7 +30,7 @@ impl KeyManagementService for ValvAPI { &self, request: tonic::Request, ) -> Result, tonic::Status> { - let keys = self.keystore.lock().await.list_keys(request.into_inner().parent.split('/').last().unwrap().to_string()).await; + let keys = self.keystore.lock().await.list_keys(request.into_inner().parent.split('/').last().unwrap()).await; return Ok(tonic::Response::new(google::kms::ListCryptoKeysResponse { crypto_keys: keys.unwrap_or_default().into_iter().map(|key| { @@ -72,12 +73,12 @@ impl KeyManagementService for ValvAPI { ) -> Result, tonic::Status> { let request = request.into_inner(); - let tenant_name = request.name.split('/').nth(5).unwrap().to_string(); - let key_name = request.name.split('/').last().unwrap().to_string(); + let tenant_name = request.name.split('/').nth(5).unwrap(); + let key_name = request.name.split('/').last().unwrap(); let key = self.keystore.lock().await.get_key( - tenant_name.clone(), - key_name.clone(), + tenant_name, + key_name, ).await; match key { @@ -128,18 +129,18 @@ impl KeyManagementService for ValvAPI { ) -> Result, tonic::Status> { let request = request.into_inner(); - let tenant_name = request.parent.split('/').nth(5).unwrap().to_string(); + let tenant_name = request.parent.split('/').nth(5).unwrap(); let key_name = request.crypto_key_id; let keystore = self.keystore.lock().await; let key = keystore .create_key( - tenant_name.clone(), - key_name.clone(), + tenant_name, + key_name.clone().as_str(), ) .await; - let primary = keystore.get_key_version(tenant_name, key_name, key.primary_version_id.parse().unwrap()).await; + let primary = keystore.get_key_version(tenant_name, key_name.as_str(), key.primary_version_id.parse().unwrap()).await; if primary.is_none() { return Err(tonic::Status::not_found("primary key version not found")); } @@ -180,11 +181,11 @@ impl KeyManagementService for ValvAPI { let crypto_key = request.crypto_key.unwrap(); - let tenant_name = crypto_key.name.split('/').nth(5).unwrap().to_string(); - let key_name = crypto_key.name.split('/').last().unwrap().to_string(); + let tenant_name = crypto_key.name.split('/').nth(5).unwrap(); + let key_name = crypto_key.name.split('/').last().unwrap(); let keystore = self.keystore.lock().await; - let key = keystore.get_key(tenant_name.clone(), key_name.clone()).await; + let key = keystore.get_key(tenant_name, key_name).await; let mut key = if key.is_none() { return Err(tonic::Status::not_found("key not found")); @@ -200,7 +201,7 @@ impl KeyManagementService for ValvAPI { key.rotation_schedule = Some(rotation_period.clone()); - let key = keystore.update_key(tenant_name.clone(), key).await; + let key = keystore.update_key(tenant_name, key).await; let primary = keystore.get_key_version(tenant_name, key_name, key.primary_version_id.parse().unwrap()).await; if primary.is_none() { @@ -223,8 +224,8 @@ impl KeyManagementService for ValvAPI { ) -> Result, tonic::Status> { let request = request.into_inner(); - let tenant_name = request.name.split('/').nth(5).unwrap().to_string(); - let key_name = request.name.split('/').last().unwrap().to_string(); + let tenant_name = request.name.split('/').nth(5).unwrap(); + let key_name = request.name.split('/').last().unwrap(); let ciphertext = self.keystore.lock().await.encrypt(tenant_name, key_name, request.plaintext).await; @@ -242,8 +243,8 @@ impl KeyManagementService for ValvAPI { ) -> Result, tonic::Status> { let request = request.into_inner(); - let tenant_name = request.name.split('/').nth(5).unwrap().to_string(); - let key_name = request.name.split('/').last().unwrap().to_string(); + let tenant_name = request.name.split('/').nth(5).unwrap(); + let key_name = request.name.split('/').last().unwrap(); let result = self.keystore.lock().await.decrypt(tenant_name, key_name, request.ciphertext).await; @@ -368,11 +369,11 @@ async fn main() { let mut key = [0; 32]; boring::rand::rand_bytes(&mut key).unwrap(); - let mut store = keystore::Keystore::new().await; + let mut keystore = Keystore::new(Arc::new(SystemTime::now())).await; - store.set_master_key(key); + keystore.set_master_key(key); let api = ValvAPI { - keystore: Mutex::new(store), + keystore: Mutex::new(keystore), }; tonic::transport::Server::builder()