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}