nervemq/kms/
aws.rs

1//! AWS KMS (Key Management Service) implementation.
2//!
3//! Provides encryption, decryption, and key management operations using
4//! AWS KMS as the backend service. Implements the KeyManager trait for
5//! seamless integration with the rest of the system.
6
7use std::{future::Future, pin::Pin};
8
9use aws_sdk_kms::operation::encrypt::EncryptOutput;
10
11/// AWS KMS implementation of the KeyManager trait.
12///
13/// Manages cryptographic operations using AWS KMS service,
14/// supporting symmetric encryption/decryption and key lifecycle.
15pub struct AwsKeyManager {
16    client: aws_sdk_kms::Client,
17}
18
19impl AwsKeyManager {
20    /// Creates a new AWS KMS manager with the provided client.
21    pub fn new(client: aws_sdk_kms::Client) -> Self {
22        Self { client }
23    }
24}
25
26impl super::KeyManager for AwsKeyManager {
27    /// Encrypts data using AWS KMS with the specified key.
28    ///
29    /// Uses symmetric encryption with the default algorithm.
30    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    /// Decrypts KMS-encrypted data using the specified key.
61    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    /// Creates a new KMS key for encryption/decryption.
83    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    /// Schedules deletion of a KMS key.
101    ///
102    /// Note: This initiates key deletion with AWS KMS's standard
103    /// waiting period before actual deletion.
104    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}