nervemq/kms/
mod.rs

1//! Key Management Service (KMS) module for handling encryption operations.
2//!
3//! This module provides traits and types for managing cryptographic keys and performing
4//! encryption/decryption operations in a generic way.
5
6use std::{future::Future, pin::Pin};
7
8pub mod aws;
9pub mod memory;
10pub mod sqlite;
11
12/// Represents an in-progress key rotation operation.
13///
14/// Useful for updating encryption of stored data without downtime or data loss.
15pub struct Rotation {
16    key_id: String,
17    new_key_id: String,
18}
19
20impl Rotation {
21    pub fn new(key_id: String, new_key_id: String) -> Self {
22        Self { key_id, new_key_id }
23    }
24
25    pub fn key_id(&self) -> &str {
26        &self.key_id
27    }
28
29    pub fn new_key_id(&self) -> &str {
30        &self.new_key_id
31    }
32}
33
34/// A trait for types that can be used as key identifiers.
35///
36/// This trait is automatically implemented for any type that implements
37/// the required serialization traits, allowing for flexible key ID types
38/// across different KMS implementations.
39pub trait KeyId
40where
41    Self: Clone + Into<String> + serde::Serialize + for<'de> serde::Deserialize<'de>,
42{
43}
44
45impl<T> KeyId for T where
46    T: Clone + Into<String> + serde::Serialize + for<'de> serde::Deserialize<'de>
47{
48}
49
50/// Core trait for key management operations.
51///
52/// This trait defines the interface for a key management service, providing
53/// methods for:
54/// - Encrypting and decrypting data
55/// - Creating and deleting encryption keys
56/// - Rotating keys safely
57///
58/// Implementations of this trait should handle the underlying cryptographic
59/// operations and key management details for specific KMS providers.
60pub trait KeyManager: Send + Sync + 'static {
61    /// Encrypts the provided data using a key managed by this service.
62    ///
63    /// # Arguments
64    /// * `data` - The data to encrypt, provided as any type implementing `bytes::Buf`
65    ///
66    /// # Returns
67    /// An [`Encrypted`] instance containing the encrypted data and the ID of the key used
68    fn encrypt(
69        &self,
70        key_id: &String,
71        data: Vec<u8>,
72    ) -> Pin<Box<dyn Future<Output = eyre::Result<Vec<u8>>>>>;
73
74    /// Decrypts the provided data using the specified key.
75    ///
76    /// # Arguments
77    /// * `key_id` - The ID of the key to use for decryption
78    /// * `data` - The encrypted data to decrypt
79    ///
80    /// # Returns
81    /// The decrypted data as [`Bytes`]
82    fn decrypt(
83        &self,
84        key_id: &String,
85        data: Vec<u8>,
86    ) -> Pin<Box<dyn Future<Output = eyre::Result<Vec<u8>>>>>;
87
88    /// Creates a new encryption key.
89    ///
90    /// # Returns
91    /// The ID of the newly created key
92    fn create_key(&self) -> Pin<Box<dyn Future<Output = eyre::Result<String>>>>;
93
94    /// Deletes an existing encryption key.
95    ///
96    /// # Warning
97    /// Deleting a key will make it impossible to decrypt any data that was encrypted with it.
98    fn delete_key(&self, key_id: &String) -> Pin<Box<dyn Future<Output = eyre::Result<()>>>>;
99
100    /// Begin a key rotation operation.
101    ///
102    /// This will generate a new key and return a handle to the rotation operation. The handle
103    /// should be stored securely and used to complete the rotation operation. The new key will
104    /// not be used until the rotation is completed.
105    ///
106    /// During the rotation operation, you should decrypt data using the old key and re-encrypt it
107    /// using the new key. Then, call [`KeyManager::complete_rotation`] with the handle to complete the
108    /// rotation and activate the new key.
109    ///
110    /// # Important
111    /// It is recommended to perform the rotation operations in a database transaction to avoid
112    /// attempting to decrypt data requiring the new key before it is activated.
113    fn begin_rotation<'a>(
114        &'a self,
115        key_id: &String,
116    ) -> Pin<Box<dyn Future<Output = eyre::Result<Rotation>> + 'a>> {
117        let key_id = key_id.clone();
118        Box::pin(async move {
119            let new_key = self.create_key().await?;
120
121            Ok(Rotation {
122                key_id: key_id.clone(),
123                new_key_id: new_key,
124            })
125        })
126    }
127
128    /// Complete a key rotation operation.
129    ///
130    /// This method finalizes a key rotation operation that was started with [`KeyManager::begin_rotation`].
131    /// It validates the rotation handle and secret, then activates the new key for use.
132    ///
133    /// # Important
134    /// Before calling this method, ensure that:
135    /// 1. All necessary data has been re-encrypted with the new key
136    /// 2. The rotation handle and secret have been kept secure
137    /// 3. You are ready to permanently switch to using the new key
138    ///
139    /// After successful completion:
140    /// - The old key will be deactivated
141    /// - All future encryption operations will use the new key
142    /// - The rotation handle will no longer be valid
143    fn complete_rotation<'a>(
144        &'a self,
145        handle: Rotation,
146    ) -> Pin<Box<dyn Future<Output = eyre::Result<()>> + 'a>> {
147        Box::pin(async move { self.delete_key(&handle.key_id).await })
148    }
149}