refactor(config): Add new type for kms encrypted values (#1823)

This commit is contained in:
Sampras Lopes
2023-08-02 14:25:23 +05:30
committed by GitHub
parent de875e6935
commit 73ed7ae7e3
21 changed files with 214 additions and 177 deletions

View File

@ -7,7 +7,10 @@ use aws_sdk_kms::{config::Region, primitives::Blob, Client};
use base64::Engine;
use common_utils::errors::CustomResult;
use error_stack::{IntoReport, ResultExt};
use masking::{PeekInterface, Secret};
use router_env::logger;
/// decrypting data using the AWS KMS SDK.
pub mod decrypt;
use crate::{consts, metrics};
@ -15,7 +18,7 @@ static KMS_CLIENT: tokio::sync::OnceCell<KmsClient> = tokio::sync::OnceCell::con
/// Returns a shared KMS client, or initializes a new one if not previously initialized.
#[inline]
pub async fn get_kms_client(config: &KmsConfig) -> &KmsClient {
pub async fn get_kms_client(config: &KmsConfig) -> &'static KmsClient {
KMS_CLIENT.get_or_init(|| KmsClient::new(config)).await
}
@ -113,6 +116,10 @@ pub enum KmsError {
/// An error occurred UTF-8 decoding KMS decrypted output.
#[error("Failed to UTF-8 decode decryption output")]
Utf8DecodingFailed,
/// The KMS client has not been initialized.
#[error("The KMS client has not been initialized")]
KmsClientNotInitialized,
}
impl KmsConfig {
@ -129,3 +136,14 @@ impl KmsConfig {
})
}
}
/// A wrapper around a KMS value that can be decrypted.
#[derive(Clone, Debug, Default, serde::Deserialize, Eq, PartialEq)]
#[serde(transparent)]
pub struct KmsValue(Secret<String>);
impl common_utils::ext_traits::ConfigExt for KmsValue {
fn is_empty_after_trim(&self) -> bool {
self.0.peek().is_empty_after_trim()
}
}

View File

@ -0,0 +1,34 @@
use common_utils::errors::CustomResult;
use super::*;
#[async_trait::async_trait]
/// This trait performs in place decryption of the structure on which this is implemented
pub trait KmsDecrypt {
/// The output type of the decryption
type Output;
/// Decrypts the structure given a KMS client
async fn decrypt_inner(self, kms_client: &KmsClient) -> CustomResult<Self::Output, KmsError>
where
Self: Sized;
/// Tries to use the Singleton client to decrypt the structure
async fn try_decrypt_inner(self) -> CustomResult<Self::Output, KmsError>
where
Self: Sized,
{
let client = KMS_CLIENT.get().ok_or(KmsError::KmsClientNotInitialized)?;
self.decrypt_inner(client).await
}
}
#[async_trait::async_trait]
impl KmsDecrypt for &KmsValue {
type Output = String;
async fn decrypt_inner(self, kms_client: &KmsClient) -> CustomResult<Self::Output, KmsError> {
kms_client
.decrypt(self.0.peek())
.await
.attach_printable("Failed to decrypt KMS value")
}
}