1use std::{future::Future, pin::Pin};
8
9use aws_sdk_kms::operation::encrypt::EncryptOutput;
10
11pub struct AwsKeyManager {
16 client: aws_sdk_kms::Client,
17}
18
19impl AwsKeyManager {
20 pub fn new(client: aws_sdk_kms::Client) -> Self {
22 Self { client }
23 }
24}
25
26impl super::KeyManager for AwsKeyManager {
27 fn encrypt(
31 &self,
32 key_id: &String,
33 data: Vec<u8>,
34 ) -> Pin<Box<dyn Future<Output = eyre::Result<Vec<u8>>>>> {
35 let client = self.client.clone();
36 let key_id = key_id.clone();
37
38 Box::pin(async move {
39 let EncryptOutput {
40 ciphertext_blob, ..
41 } = client
42 .encrypt()
43 .key_id(&key_id)
44 .plaintext(aws_sdk_kms::primitives::Blob::new(data))
45 .encryption_algorithm(aws_sdk_kms::types::EncryptionAlgorithmSpec::SymmetricDefault)
46 .send()
47 .await?;
48
49 let encrypted = match ciphertext_blob {
50 Some(blob) => blob.into_inner(),
51 None => {
52 return Err(eyre::eyre!("No ciphertext blob in response"));
53 }
54 };
55
56 Ok(encrypted)
57 })
58 }
59
60 fn decrypt(
62 &self,
63 key_id: &String,
64 data: Vec<u8>,
65 ) -> Pin<Box<dyn Future<Output = eyre::Result<Vec<u8>>>>> {
66 let client = self.client.clone();
67 let key_id = key_id.clone();
68 Box::pin(async move {
69 let decrypted = client
70 .decrypt()
71 .key_id(key_id)
72 .ciphertext_blob(aws_sdk_kms::primitives::Blob::new(data))
73 .send()
74 .await?
75 .plaintext
76 .ok_or_else(|| eyre::eyre!("No plaintext in response"))?;
77
78 Ok(decrypted.into_inner())
79 })
80 }
81
82 fn create_key(&self) -> Pin<Box<dyn Future<Output = eyre::Result<String>>>> {
84 let client = self.client.clone();
85 Box::pin(async move {
86 let res = client
87 .create_key()
88 .key_usage(aws_sdk_kms::types::KeyUsageType::EncryptDecrypt)
89 .send()
90 .await?;
91
92 let Some(key_meta) = res.key_metadata else {
93 return Err(eyre::eyre!("No key ID in response"));
94 };
95
96 Ok(key_meta.key_id)
97 })
98 }
99
100 fn delete_key(&self, key_id: &String) -> Pin<Box<dyn Future<Output = eyre::Result<()>>>> {
105 let client = self.client.clone();
106 let key_id = key_id.clone();
107 Box::pin(async move {
108 client.schedule_key_deletion().key_id(key_id).send().await?;
109 Ok(())
110 })
111 }
112}