use crate::aws_kms_client::{AwsKmsClient, AwsKmsConfig, KmsClient};
use crate::error::Error;
use ockam_core::compat::sync::{Arc, RwLock};
use ockam_core::{async_trait, Result};
use ockam_vault::{
Signature, SigningKeyType, SigningSecretKeyHandle, VaultError, VaultForSigning,
VerifyingPublicKey,
};
use tracing::error;
struct AwsKeyPair {
key: SigningSecretKeyHandle,
public_key: VerifyingPublicKey,
}
pub struct AwsSigningVault {
client: Arc<dyn KmsClient + Send + Sync>,
keys: Arc<RwLock<Vec<AwsKeyPair>>>,
}
impl AwsSigningVault {
pub async fn create() -> Result<Self> {
Self::create_with_config(AwsKmsConfig::default().await?).await
}
pub async fn create_with_config(config: AwsKmsConfig) -> Result<Self> {
let client = AwsKmsClient::new(config).await?;
let mut key_pairs: Vec<AwsKeyPair> = vec![];
let keys = client.list_keys().await?;
for key in keys {
match client.public_key(&key).await {
Ok(public_key) => key_pairs.push(AwsKeyPair { key, public_key }),
Err(err) => error!("Error exporting public key: {err}"),
}
}
Ok(Self {
client: Arc::new(client),
keys: Arc::new(RwLock::new(key_pairs)),
})
}
pub fn keys(&self) -> Vec<SigningSecretKeyHandle> {
self.keys
.read()
.unwrap()
.iter()
.map(|x| x.key.clone())
.collect()
}
pub async fn number_of_keys(&self) -> Result<usize> {
Ok(self.keys.read().unwrap().len())
}
}
#[async_trait]
impl VaultForSigning for AwsSigningVault {
async fn sign(
&self,
signing_secret_key_handle: &SigningSecretKeyHandle,
data: &[u8],
) -> Result<Signature> {
self.client.sign(signing_secret_key_handle, data).await
}
async fn generate_signing_secret_key(
&self,
signing_key_type: SigningKeyType,
) -> Result<SigningSecretKeyHandle> {
if signing_key_type != SigningKeyType::ECDSASHA256CurveP256 {
return Err(VaultError::InvalidKeyType)?;
}
let key = self.client.create_key().await?;
let public_key = self.client.public_key(&key).await?;
self.keys.write().unwrap().push(AwsKeyPair {
key: key.clone(),
public_key,
});
Ok(key)
}
async fn get_verifying_public_key(
&self,
signing_secret_key_handle: &SigningSecretKeyHandle,
) -> Result<VerifyingPublicKey> {
self.keys
.read()
.unwrap()
.iter()
.find_map(|x| {
if &x.key == signing_secret_key_handle {
Some(x.public_key.clone())
} else {
None
}
})
.ok_or(Error::KeyNotFound.into())
}
async fn get_secret_key_handle(
&self,
verifying_public_key: &VerifyingPublicKey,
) -> Result<SigningSecretKeyHandle> {
self.keys
.read()
.unwrap()
.iter()
.find_map(|x| {
if &x.public_key == verifying_public_key {
Some(x.key.clone())
} else {
None
}
})
.ok_or(Error::KeyNotFound.into())
}
async fn delete_signing_secret_key(
&self,
signing_secret_key_handle: SigningSecretKeyHandle,
) -> Result<bool> {
if self.client.delete_key(&signing_secret_key_handle).await? {
self.keys
.write()
.unwrap()
.retain(|x| x.key != signing_secret_key_handle);
Ok(true)
} else {
Ok(false)
}
}
}