mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-30 01:27:31 +08:00
feat(kms): reduce redundant kms calls (#1264)
This commit is contained in:
@ -1,3 +1,5 @@
|
|||||||
mod defaults;
|
mod defaults;
|
||||||
|
#[cfg(feature = "kms")]
|
||||||
|
pub(super) mod kms;
|
||||||
pub mod settings;
|
pub mod settings;
|
||||||
mod validations;
|
mod validations;
|
||||||
|
|||||||
60
crates/router/src/configs/kms.rs
Normal file
60
crates/router/src/configs/kms.rs
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
use common_utils::errors::CustomResult;
|
||||||
|
use external_services::kms;
|
||||||
|
use masking::ExposeInterface;
|
||||||
|
|
||||||
|
use crate::configs::settings;
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
// This trait performs inplace decryption of the structure on which this is implemented
|
||||||
|
pub(crate) trait KmsDecrypt {
|
||||||
|
async fn decrypt_inner(self, kms_config: &kms::KmsConfig) -> CustomResult<Self, kms::KmsError>
|
||||||
|
where
|
||||||
|
Self: Sized;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
impl KmsDecrypt for settings::Jwekey {
|
||||||
|
async fn decrypt_inner(self, kms_config: &kms::KmsConfig) -> CustomResult<Self, kms::KmsError> {
|
||||||
|
let client = kms::get_kms_client(kms_config).await;
|
||||||
|
|
||||||
|
// If this pattern required repetition, a macro approach needs to be deviced
|
||||||
|
let (
|
||||||
|
locker_encryption_key1,
|
||||||
|
locker_encryption_key2,
|
||||||
|
locker_decryption_key1,
|
||||||
|
locker_decryption_key2,
|
||||||
|
vault_encryption_key,
|
||||||
|
vault_private_key,
|
||||||
|
tunnel_private_key,
|
||||||
|
) = tokio::try_join!(
|
||||||
|
client.decrypt(self.locker_encryption_key1),
|
||||||
|
client.decrypt(self.locker_encryption_key2),
|
||||||
|
client.decrypt(self.locker_decryption_key1),
|
||||||
|
client.decrypt(self.locker_decryption_key2),
|
||||||
|
client.decrypt(self.vault_encryption_key),
|
||||||
|
client.decrypt(self.vault_private_key),
|
||||||
|
client.decrypt(self.tunnel_private_key),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
locker_key_identifier1: self.locker_key_identifier1,
|
||||||
|
locker_key_identifier2: self.locker_key_identifier2,
|
||||||
|
locker_encryption_key1,
|
||||||
|
locker_encryption_key2,
|
||||||
|
locker_decryption_key1,
|
||||||
|
locker_decryption_key2,
|
||||||
|
vault_encryption_key,
|
||||||
|
vault_private_key,
|
||||||
|
tunnel_private_key,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
impl KmsDecrypt for settings::ActiveKmsSecrets {
|
||||||
|
async fn decrypt_inner(self, kms_config: &kms::KmsConfig) -> CustomResult<Self, kms::KmsError> {
|
||||||
|
Ok(Self {
|
||||||
|
jwekey: self.jwekey.expose().decrypt_inner(kms_config).await?.into(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -39,6 +39,16 @@ pub enum Subcommand {
|
|||||||
GenerateOpenapiSpec,
|
GenerateOpenapiSpec,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "kms")]
|
||||||
|
/// Store the decrypted kms secret values for active use in the application
|
||||||
|
/// Currently using `StrongSecret` won't have any effect as this struct have smart pointers to heap
|
||||||
|
/// allocations.
|
||||||
|
/// note: we can consider adding such behaviour in the future with custom implementation
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct ActiveKmsSecrets {
|
||||||
|
pub jwekey: masking::Secret<Jwekey>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Clone, Default)]
|
#[derive(Debug, Deserialize, Clone, Default)]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub struct Settings {
|
pub struct Settings {
|
||||||
|
|||||||
@ -250,10 +250,10 @@ pub async fn add_card_hs(
|
|||||||
merchant_account: &storage::MerchantAccount,
|
merchant_account: &storage::MerchantAccount,
|
||||||
) -> errors::CustomResult<(api::PaymentMethodResponse, bool), errors::VaultError> {
|
) -> errors::CustomResult<(api::PaymentMethodResponse, bool), errors::VaultError> {
|
||||||
let locker = &state.conf.locker;
|
let locker = &state.conf.locker;
|
||||||
|
#[cfg(not(feature = "kms"))]
|
||||||
let jwekey = &state.conf.jwekey;
|
let jwekey = &state.conf.jwekey;
|
||||||
|
|
||||||
#[cfg(feature = "kms")]
|
#[cfg(feature = "kms")]
|
||||||
let kms_config = &state.conf.kms;
|
let jwekey = &state.kms_secrets;
|
||||||
|
|
||||||
let db = &*state.store;
|
let db = &*state.store;
|
||||||
let merchant_id = &merchant_account.merchant_id;
|
let merchant_id = &merchant_account.merchant_id;
|
||||||
@ -264,16 +264,9 @@ pub async fn add_card_hs(
|
|||||||
.get_required_value("locker_id")
|
.get_required_value("locker_id")
|
||||||
.change_context(errors::VaultError::SaveCardFailed)?;
|
.change_context(errors::VaultError::SaveCardFailed)?;
|
||||||
|
|
||||||
let request = payment_methods::mk_add_card_request_hs(
|
let request =
|
||||||
jwekey,
|
payment_methods::mk_add_card_request_hs(jwekey, locker, &card, &customer_id, merchant_id)
|
||||||
locker,
|
.await?;
|
||||||
&card,
|
|
||||||
&customer_id,
|
|
||||||
merchant_id,
|
|
||||||
#[cfg(feature = "kms")]
|
|
||||||
kms_config,
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
let stored_card_response = if !locker.mock_locker {
|
let stored_card_response = if !locker.mock_locker {
|
||||||
let response = services::call_connector_api(state, request)
|
let response = services::call_connector_api(state, request)
|
||||||
@ -284,15 +277,10 @@ pub async fn add_card_hs(
|
|||||||
.get_response_inner("JweBody")
|
.get_response_inner("JweBody")
|
||||||
.change_context(errors::VaultError::FetchCardFailed)?;
|
.change_context(errors::VaultError::FetchCardFailed)?;
|
||||||
|
|
||||||
let decrypted_payload = payment_methods::get_decrypted_response_payload(
|
let decrypted_payload = payment_methods::get_decrypted_response_payload(jwekey, jwe_body)
|
||||||
jwekey,
|
.await
|
||||||
jwe_body,
|
.change_context(errors::VaultError::SaveCardFailed)
|
||||||
#[cfg(feature = "kms")]
|
.attach_printable("Error getting decrypted response payload")?;
|
||||||
kms_config,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
.change_context(errors::VaultError::SaveCardFailed)
|
|
||||||
.attach_printable("Error getting decrypted response payload")?;
|
|
||||||
let stored_card_resp: payment_methods::StoreCardResp = decrypted_payload
|
let stored_card_resp: payment_methods::StoreCardResp = decrypted_payload
|
||||||
.parse_struct("StoreCardResp")
|
.parse_struct("StoreCardResp")
|
||||||
.change_context(errors::VaultError::ResponseDeserializationFailed)?;
|
.change_context(errors::VaultError::ResponseDeserializationFailed)?;
|
||||||
@ -394,10 +382,10 @@ pub async fn get_card_from_hs_locker<'a>(
|
|||||||
card_reference: &'a str,
|
card_reference: &'a str,
|
||||||
) -> errors::CustomResult<payment_methods::Card, errors::VaultError> {
|
) -> errors::CustomResult<payment_methods::Card, errors::VaultError> {
|
||||||
let locker = &state.conf.locker;
|
let locker = &state.conf.locker;
|
||||||
|
#[cfg(not(feature = "kms"))]
|
||||||
let jwekey = &state.conf.jwekey;
|
let jwekey = &state.conf.jwekey;
|
||||||
|
|
||||||
#[cfg(feature = "kms")]
|
#[cfg(feature = "kms")]
|
||||||
let kms_config = &state.conf.kms;
|
let jwekey = &state.kms_secrets;
|
||||||
|
|
||||||
let request = payment_methods::mk_get_card_request_hs(
|
let request = payment_methods::mk_get_card_request_hs(
|
||||||
jwekey,
|
jwekey,
|
||||||
@ -405,8 +393,6 @@ pub async fn get_card_from_hs_locker<'a>(
|
|||||||
customer_id,
|
customer_id,
|
||||||
merchant_id,
|
merchant_id,
|
||||||
card_reference,
|
card_reference,
|
||||||
#[cfg(feature = "kms")]
|
|
||||||
kms_config,
|
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.change_context(errors::VaultError::FetchCardFailed)
|
.change_context(errors::VaultError::FetchCardFailed)
|
||||||
@ -419,15 +405,10 @@ pub async fn get_card_from_hs_locker<'a>(
|
|||||||
let jwe_body: services::JweBody = response
|
let jwe_body: services::JweBody = response
|
||||||
.get_response_inner("JweBody")
|
.get_response_inner("JweBody")
|
||||||
.change_context(errors::VaultError::FetchCardFailed)?;
|
.change_context(errors::VaultError::FetchCardFailed)?;
|
||||||
let decrypted_payload = payment_methods::get_decrypted_response_payload(
|
let decrypted_payload = payment_methods::get_decrypted_response_payload(jwekey, jwe_body)
|
||||||
jwekey,
|
.await
|
||||||
jwe_body,
|
.change_context(errors::VaultError::FetchCardFailed)
|
||||||
#[cfg(feature = "kms")]
|
.attach_printable("Error getting decrypted response payload for get card")?;
|
||||||
kms_config,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
.change_context(errors::VaultError::FetchCardFailed)
|
|
||||||
.attach_printable("Error getting decrypted response payload for get card")?;
|
|
||||||
let get_card_resp: payment_methods::RetrieveCardResp = decrypted_payload
|
let get_card_resp: payment_methods::RetrieveCardResp = decrypted_payload
|
||||||
.parse_struct("RetrieveCardResp")
|
.parse_struct("RetrieveCardResp")
|
||||||
.change_context(errors::VaultError::FetchCardFailed)?;
|
.change_context(errors::VaultError::FetchCardFailed)?;
|
||||||
@ -483,10 +464,10 @@ pub async fn delete_card_from_hs_locker<'a>(
|
|||||||
card_reference: &'a str,
|
card_reference: &'a str,
|
||||||
) -> errors::RouterResult<payment_methods::DeleteCardResp> {
|
) -> errors::RouterResult<payment_methods::DeleteCardResp> {
|
||||||
let locker = &state.conf.locker;
|
let locker = &state.conf.locker;
|
||||||
|
#[cfg(not(feature = "kms"))]
|
||||||
let jwekey = &state.conf.jwekey;
|
let jwekey = &state.conf.jwekey;
|
||||||
|
|
||||||
#[cfg(feature = "kms")]
|
#[cfg(feature = "kms")]
|
||||||
let kms_config = &state.conf.kms;
|
let jwekey = &state.kms_secrets;
|
||||||
|
|
||||||
let request = payment_methods::mk_delete_card_request_hs(
|
let request = payment_methods::mk_delete_card_request_hs(
|
||||||
jwekey,
|
jwekey,
|
||||||
@ -494,8 +475,6 @@ pub async fn delete_card_from_hs_locker<'a>(
|
|||||||
customer_id,
|
customer_id,
|
||||||
merchant_id,
|
merchant_id,
|
||||||
card_reference,
|
card_reference,
|
||||||
#[cfg(feature = "kms")]
|
|
||||||
kms_config,
|
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||||
@ -507,15 +486,10 @@ pub async fn delete_card_from_hs_locker<'a>(
|
|||||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||||
.attach_printable("Failed while executing call_connector_api for delete card");
|
.attach_printable("Failed while executing call_connector_api for delete card");
|
||||||
let jwe_body: services::JweBody = response.get_response_inner("JweBody")?;
|
let jwe_body: services::JweBody = response.get_response_inner("JweBody")?;
|
||||||
let decrypted_payload = payment_methods::get_decrypted_response_payload(
|
let decrypted_payload = payment_methods::get_decrypted_response_payload(jwekey, jwe_body)
|
||||||
jwekey,
|
.await
|
||||||
jwe_body,
|
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||||
#[cfg(feature = "kms")]
|
.attach_printable("Error getting decrypted response payload for delete card")?;
|
||||||
kms_config,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
|
||||||
.attach_printable("Error getting decrypted response payload for delete card")?;
|
|
||||||
let delete_card_resp: payment_methods::DeleteCardResp = decrypted_payload
|
let delete_card_resp: payment_methods::DeleteCardResp = decrypted_payload
|
||||||
.parse_struct("DeleteCardResp")
|
.parse_struct("DeleteCardResp")
|
||||||
.change_context(errors::ApiErrorResponse::InternalServerError)?;
|
.change_context(errors::ApiErrorResponse::InternalServerError)?;
|
||||||
|
|||||||
@ -2,8 +2,6 @@ use std::str::FromStr;
|
|||||||
|
|
||||||
use common_utils::{ext_traits::StringExt, pii::Email};
|
use common_utils::{ext_traits::StringExt, pii::Email};
|
||||||
use error_stack::ResultExt;
|
use error_stack::ResultExt;
|
||||||
#[cfg(feature = "kms")]
|
|
||||||
use external_services::kms;
|
|
||||||
use josekit::jwe;
|
use josekit::jwe;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
@ -151,24 +149,14 @@ pub fn get_dotted_jws(jws: encryption::JwsBody) -> String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_decrypted_response_payload(
|
pub async fn get_decrypted_response_payload(
|
||||||
jwekey: &settings::Jwekey,
|
#[cfg(not(feature = "kms"))] jwekey: &settings::Jwekey,
|
||||||
|
#[cfg(feature = "kms")] jwekey: &settings::ActiveKmsSecrets,
|
||||||
jwe_body: encryption::JweBody,
|
jwe_body: encryption::JweBody,
|
||||||
#[cfg(feature = "kms")] kms_config: &kms::KmsConfig,
|
|
||||||
) -> CustomResult<String, errors::VaultError> {
|
) -> CustomResult<String, errors::VaultError> {
|
||||||
#[cfg(feature = "kms")]
|
#[cfg(feature = "kms")]
|
||||||
let public_key = kms::get_kms_client(kms_config)
|
let public_key = jwekey.jwekey.peek().vault_encryption_key.clone();
|
||||||
.await
|
|
||||||
.decrypt(&jwekey.vault_encryption_key)
|
|
||||||
.await
|
|
||||||
.change_context(errors::VaultError::SaveCardFailed)
|
|
||||||
.attach_printable("Fails to get public key of vault")?;
|
|
||||||
#[cfg(feature = "kms")]
|
#[cfg(feature = "kms")]
|
||||||
let private_key = kms::get_kms_client(kms_config)
|
let private_key = jwekey.jwekey.peek().vault_private_key.clone();
|
||||||
.await
|
|
||||||
.decrypt(&jwekey.vault_private_key)
|
|
||||||
.await
|
|
||||||
.change_context(errors::VaultError::SaveCardFailed)
|
|
||||||
.attach_printable("Error getting private key for signing jws")?;
|
|
||||||
|
|
||||||
#[cfg(not(feature = "kms"))]
|
#[cfg(not(feature = "kms"))]
|
||||||
let public_key = jwekey.vault_encryption_key.to_owned();
|
let public_key = jwekey.vault_encryption_key.to_owned();
|
||||||
@ -199,9 +187,9 @@ pub async fn get_decrypted_response_payload(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn mk_basilisk_req(
|
pub async fn mk_basilisk_req(
|
||||||
jwekey: &settings::Jwekey,
|
#[cfg(feature = "kms")] jwekey: &settings::ActiveKmsSecrets,
|
||||||
|
#[cfg(not(feature = "kms"))] jwekey: &settings::Jwekey,
|
||||||
jws: &str,
|
jws: &str,
|
||||||
#[cfg(feature = "kms")] kms_config: &kms::KmsConfig,
|
|
||||||
) -> CustomResult<encryption::JweBody, errors::VaultError> {
|
) -> CustomResult<encryption::JweBody, errors::VaultError> {
|
||||||
let jws_payload: Vec<&str> = jws.split('.').collect();
|
let jws_payload: Vec<&str> = jws.split('.').collect();
|
||||||
|
|
||||||
@ -219,12 +207,7 @@ pub async fn mk_basilisk_req(
|
|||||||
.change_context(errors::VaultError::SaveCardFailed)?;
|
.change_context(errors::VaultError::SaveCardFailed)?;
|
||||||
|
|
||||||
#[cfg(feature = "kms")]
|
#[cfg(feature = "kms")]
|
||||||
let public_key = kms::get_kms_client(kms_config)
|
let public_key = jwekey.jwekey.peek().vault_encryption_key.clone();
|
||||||
.await
|
|
||||||
.decrypt(&jwekey.vault_encryption_key)
|
|
||||||
.await
|
|
||||||
.change_context(errors::VaultError::SaveCardFailed)
|
|
||||||
.attach_printable("Fails to get encryption key of vault")?;
|
|
||||||
|
|
||||||
#[cfg(not(feature = "kms"))]
|
#[cfg(not(feature = "kms"))]
|
||||||
let public_key = jwekey.vault_encryption_key.to_owned();
|
let public_key = jwekey.vault_encryption_key.to_owned();
|
||||||
@ -251,12 +234,12 @@ pub async fn mk_basilisk_req(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn mk_add_card_request_hs(
|
pub async fn mk_add_card_request_hs(
|
||||||
jwekey: &settings::Jwekey,
|
#[cfg(not(feature = "kms"))] jwekey: &settings::Jwekey,
|
||||||
|
#[cfg(feature = "kms")] jwekey: &settings::ActiveKmsSecrets,
|
||||||
locker: &settings::Locker,
|
locker: &settings::Locker,
|
||||||
card: &api::CardDetail,
|
card: &api::CardDetail,
|
||||||
customer_id: &str,
|
customer_id: &str,
|
||||||
merchant_id: &str,
|
merchant_id: &str,
|
||||||
#[cfg(feature = "kms")] kms_config: &kms::KmsConfig,
|
|
||||||
) -> CustomResult<services::Request, errors::VaultError> {
|
) -> CustomResult<services::Request, errors::VaultError> {
|
||||||
let merchant_customer_id = if cfg!(feature = "sandbox") {
|
let merchant_customer_id = if cfg!(feature = "sandbox") {
|
||||||
format!("{customer_id}::{merchant_id}")
|
format!("{customer_id}::{merchant_id}")
|
||||||
@ -281,12 +264,7 @@ pub async fn mk_add_card_request_hs(
|
|||||||
.change_context(errors::VaultError::RequestEncodingFailed)?;
|
.change_context(errors::VaultError::RequestEncodingFailed)?;
|
||||||
|
|
||||||
#[cfg(feature = "kms")]
|
#[cfg(feature = "kms")]
|
||||||
let private_key = kms::get_kms_client(kms_config)
|
let private_key = jwekey.jwekey.peek().vault_private_key.clone();
|
||||||
.await
|
|
||||||
.decrypt(&jwekey.vault_private_key)
|
|
||||||
.await
|
|
||||||
.change_context(errors::VaultError::SaveCardFailed)
|
|
||||||
.attach_printable("Error getting private key for signing jws")?;
|
|
||||||
|
|
||||||
#[cfg(not(feature = "kms"))]
|
#[cfg(not(feature = "kms"))]
|
||||||
let private_key = jwekey.vault_private_key.to_owned();
|
let private_key = jwekey.vault_private_key.to_owned();
|
||||||
@ -295,13 +273,7 @@ pub async fn mk_add_card_request_hs(
|
|||||||
.await
|
.await
|
||||||
.change_context(errors::VaultError::RequestEncodingFailed)?;
|
.change_context(errors::VaultError::RequestEncodingFailed)?;
|
||||||
|
|
||||||
let jwe_payload = mk_basilisk_req(
|
let jwe_payload = mk_basilisk_req(jwekey, &jws).await?;
|
||||||
jwekey,
|
|
||||||
&jws,
|
|
||||||
#[cfg(feature = "kms")]
|
|
||||||
kms_config,
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
let body = utils::Encode::<encryption::JweBody>::encode_to_value(&jwe_payload)
|
let body = utils::Encode::<encryption::JweBody>::encode_to_value(&jwe_payload)
|
||||||
.change_context(errors::VaultError::RequestEncodingFailed)?;
|
.change_context(errors::VaultError::RequestEncodingFailed)?;
|
||||||
@ -416,12 +388,12 @@ pub fn mk_add_card_request(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn mk_get_card_request_hs(
|
pub async fn mk_get_card_request_hs(
|
||||||
jwekey: &settings::Jwekey,
|
#[cfg(not(feature = "kms"))] jwekey: &settings::Jwekey,
|
||||||
|
#[cfg(feature = "kms")] jwekey: &settings::ActiveKmsSecrets,
|
||||||
locker: &settings::Locker,
|
locker: &settings::Locker,
|
||||||
customer_id: &str,
|
customer_id: &str,
|
||||||
merchant_id: &str,
|
merchant_id: &str,
|
||||||
card_reference: &str,
|
card_reference: &str,
|
||||||
#[cfg(feature = "kms")] kms_config: &kms::KmsConfig,
|
|
||||||
) -> CustomResult<services::Request, errors::VaultError> {
|
) -> CustomResult<services::Request, errors::VaultError> {
|
||||||
let merchant_customer_id = if cfg!(feature = "sandbox") {
|
let merchant_customer_id = if cfg!(feature = "sandbox") {
|
||||||
format!("{customer_id}::{merchant_id}")
|
format!("{customer_id}::{merchant_id}")
|
||||||
@ -437,12 +409,7 @@ pub async fn mk_get_card_request_hs(
|
|||||||
.change_context(errors::VaultError::RequestEncodingFailed)?;
|
.change_context(errors::VaultError::RequestEncodingFailed)?;
|
||||||
|
|
||||||
#[cfg(feature = "kms")]
|
#[cfg(feature = "kms")]
|
||||||
let private_key = kms::get_kms_client(kms_config)
|
let private_key = jwekey.jwekey.peek().vault_private_key.clone();
|
||||||
.await
|
|
||||||
.decrypt(&jwekey.vault_private_key)
|
|
||||||
.await
|
|
||||||
.change_context(errors::VaultError::SaveCardFailed)
|
|
||||||
.attach_printable("Error getting private key for signing jws")?;
|
|
||||||
|
|
||||||
#[cfg(not(feature = "kms"))]
|
#[cfg(not(feature = "kms"))]
|
||||||
let private_key = jwekey.vault_private_key.to_owned();
|
let private_key = jwekey.vault_private_key.to_owned();
|
||||||
@ -451,13 +418,7 @@ pub async fn mk_get_card_request_hs(
|
|||||||
.await
|
.await
|
||||||
.change_context(errors::VaultError::RequestEncodingFailed)?;
|
.change_context(errors::VaultError::RequestEncodingFailed)?;
|
||||||
|
|
||||||
let jwe_payload = mk_basilisk_req(
|
let jwe_payload = mk_basilisk_req(jwekey, &jws).await?;
|
||||||
jwekey,
|
|
||||||
&jws,
|
|
||||||
#[cfg(feature = "kms")]
|
|
||||||
kms_config,
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
let body = utils::Encode::<encryption::JweBody>::encode_to_value(&jwe_payload)
|
let body = utils::Encode::<encryption::JweBody>::encode_to_value(&jwe_payload)
|
||||||
.change_context(errors::VaultError::RequestEncodingFailed)?;
|
.change_context(errors::VaultError::RequestEncodingFailed)?;
|
||||||
@ -508,12 +469,12 @@ pub fn mk_get_card_response(card: GetCardResponse) -> errors::RouterResult<Card>
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn mk_delete_card_request_hs(
|
pub async fn mk_delete_card_request_hs(
|
||||||
jwekey: &settings::Jwekey,
|
#[cfg(feature = "kms")] jwekey: &settings::ActiveKmsSecrets,
|
||||||
|
#[cfg(not(feature = "kms"))] jwekey: &settings::Jwekey,
|
||||||
locker: &settings::Locker,
|
locker: &settings::Locker,
|
||||||
customer_id: &str,
|
customer_id: &str,
|
||||||
merchant_id: &str,
|
merchant_id: &str,
|
||||||
card_reference: &str,
|
card_reference: &str,
|
||||||
#[cfg(feature = "kms")] kms_config: &kms::KmsConfig,
|
|
||||||
) -> CustomResult<services::Request, errors::VaultError> {
|
) -> CustomResult<services::Request, errors::VaultError> {
|
||||||
let merchant_customer_id = if cfg!(feature = "sandbox") {
|
let merchant_customer_id = if cfg!(feature = "sandbox") {
|
||||||
format!("{customer_id}::{merchant_id}")
|
format!("{customer_id}::{merchant_id}")
|
||||||
@ -529,12 +490,7 @@ pub async fn mk_delete_card_request_hs(
|
|||||||
.change_context(errors::VaultError::RequestEncodingFailed)?;
|
.change_context(errors::VaultError::RequestEncodingFailed)?;
|
||||||
|
|
||||||
#[cfg(feature = "kms")]
|
#[cfg(feature = "kms")]
|
||||||
let private_key = kms::get_kms_client(kms_config)
|
let private_key = jwekey.jwekey.peek().vault_private_key.clone();
|
||||||
.await
|
|
||||||
.decrypt(&jwekey.vault_private_key)
|
|
||||||
.await
|
|
||||||
.change_context(errors::VaultError::SaveCardFailed)
|
|
||||||
.attach_printable("Error getting private key for signing jws")?;
|
|
||||||
|
|
||||||
#[cfg(not(feature = "kms"))]
|
#[cfg(not(feature = "kms"))]
|
||||||
let private_key = jwekey.vault_private_key.to_owned();
|
let private_key = jwekey.vault_private_key.to_owned();
|
||||||
@ -543,13 +499,7 @@ pub async fn mk_delete_card_request_hs(
|
|||||||
.await
|
.await
|
||||||
.change_context(errors::VaultError::RequestEncodingFailed)?;
|
.change_context(errors::VaultError::RequestEncodingFailed)?;
|
||||||
|
|
||||||
let jwe_payload = mk_basilisk_req(
|
let jwe_payload = mk_basilisk_req(jwekey, &jws).await?;
|
||||||
jwekey,
|
|
||||||
&jws,
|
|
||||||
#[cfg(feature = "kms")]
|
|
||||||
kms_config,
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
let body = utils::Encode::<encryption::JweBody>::encode_to_value(&jwe_payload)
|
let body = utils::Encode::<encryption::JweBody>::encode_to_value(&jwe_payload)
|
||||||
.change_context(errors::VaultError::RequestEncodingFailed)?;
|
.change_context(errors::VaultError::RequestEncodingFailed)?;
|
||||||
|
|||||||
@ -3,8 +3,6 @@ use common_utils::generate_id_with_default_len;
|
|||||||
use error_stack::report;
|
use error_stack::report;
|
||||||
use error_stack::{IntoReport, ResultExt};
|
use error_stack::{IntoReport, ResultExt};
|
||||||
#[cfg(feature = "basilisk")]
|
#[cfg(feature = "basilisk")]
|
||||||
use external_services::kms;
|
|
||||||
#[cfg(feature = "basilisk")]
|
|
||||||
use josekit::jwe;
|
use josekit::jwe;
|
||||||
use masking::PeekInterface;
|
use masking::PeekInterface;
|
||||||
use router_env::{instrument, tracing};
|
use router_env::{instrument, tracing};
|
||||||
@ -470,11 +468,11 @@ pub fn get_key_id(keys: &settings::Jwekey) -> &str {
|
|||||||
|
|
||||||
#[cfg(feature = "basilisk")]
|
#[cfg(feature = "basilisk")]
|
||||||
async fn get_locker_jwe_keys(
|
async fn get_locker_jwe_keys(
|
||||||
keys: &settings::Jwekey,
|
keys: &settings::ActiveKmsSecrets,
|
||||||
kms_config: &kms::KmsConfig,
|
|
||||||
) -> CustomResult<(String, String), errors::EncryptionError> {
|
) -> CustomResult<(String, String), errors::EncryptionError> {
|
||||||
|
let keys = keys.jwekey.peek();
|
||||||
let key_id = get_key_id(keys);
|
let key_id = get_key_id(keys);
|
||||||
let (encryption_key, decryption_key) = if key_id == keys.locker_key_identifier1 {
|
let (public_key, private_key) = if key_id == keys.locker_key_identifier1 {
|
||||||
(&keys.locker_encryption_key1, &keys.locker_decryption_key1)
|
(&keys.locker_encryption_key1, &keys.locker_decryption_key1)
|
||||||
} else if key_id == keys.locker_key_identifier2 {
|
} else if key_id == keys.locker_key_identifier2 {
|
||||||
(&keys.locker_encryption_key2, &keys.locker_decryption_key2)
|
(&keys.locker_encryption_key2, &keys.locker_decryption_key2)
|
||||||
@ -482,18 +480,7 @@ async fn get_locker_jwe_keys(
|
|||||||
return Err(errors::EncryptionError.into());
|
return Err(errors::EncryptionError.into());
|
||||||
};
|
};
|
||||||
|
|
||||||
let public_key = kms::get_kms_client(kms_config)
|
Ok((public_key.to_string(), private_key.to_string()))
|
||||||
.await
|
|
||||||
.decrypt(encryption_key)
|
|
||||||
.await
|
|
||||||
.change_context(errors::EncryptionError)?;
|
|
||||||
let private_key = kms::get_kms_client(kms_config)
|
|
||||||
.await
|
|
||||||
.decrypt(decryption_key)
|
|
||||||
.await
|
|
||||||
.change_context(errors::EncryptionError)?;
|
|
||||||
|
|
||||||
Ok((public_key, private_key))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "basilisk")]
|
#[cfg(feature = "basilisk")]
|
||||||
@ -515,7 +502,7 @@ pub async fn create_tokenize(
|
|||||||
)
|
)
|
||||||
.change_context(errors::ApiErrorResponse::InternalServerError)?;
|
.change_context(errors::ApiErrorResponse::InternalServerError)?;
|
||||||
|
|
||||||
let (public_key, private_key) = get_locker_jwe_keys(&state.conf.jwekey, &state.conf.kms)
|
let (public_key, private_key) = get_locker_jwe_keys(&state.kms_secrets)
|
||||||
.await
|
.await
|
||||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||||
.attach_printable("Error getting Encryption key")?;
|
.attach_printable("Error getting Encryption key")?;
|
||||||
@ -592,7 +579,7 @@ pub async fn get_tokenized_data(
|
|||||||
let payload = serde_json::to_string(&payload_to_be_encrypted)
|
let payload = serde_json::to_string(&payload_to_be_encrypted)
|
||||||
.map_err(|_x| errors::ApiErrorResponse::InternalServerError)?;
|
.map_err(|_x| errors::ApiErrorResponse::InternalServerError)?;
|
||||||
|
|
||||||
let (public_key, private_key) = get_locker_jwe_keys(&state.conf.jwekey, &state.conf.kms)
|
let (public_key, private_key) = get_locker_jwe_keys(&state.kms_secrets)
|
||||||
.await
|
.await
|
||||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||||
.attach_printable("Error getting Encryption key")?;
|
.attach_printable("Error getting Encryption key")?;
|
||||||
@ -663,7 +650,7 @@ pub async fn delete_tokenized_data(
|
|||||||
let payload = serde_json::to_string(&payload_to_be_encrypted)
|
let payload = serde_json::to_string(&payload_to_be_encrypted)
|
||||||
.map_err(|_x| errors::ApiErrorResponse::InternalServerError)?;
|
.map_err(|_x| errors::ApiErrorResponse::InternalServerError)?;
|
||||||
|
|
||||||
let (public_key, _private_key) = get_locker_jwe_keys(&state.conf.jwekey, &state.conf.kms)
|
let (public_key, _private_key) = get_locker_jwe_keys(&state.kms_secrets)
|
||||||
.await
|
.await
|
||||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||||
.attach_printable("Error getting Encryption key")?;
|
.attach_printable("Error getting Encryption key")?;
|
||||||
|
|||||||
@ -6,8 +6,6 @@ use common_utils::{
|
|||||||
};
|
};
|
||||||
// TODO : Evaluate all the helper functions ()
|
// TODO : Evaluate all the helper functions ()
|
||||||
use error_stack::{report, IntoReport, ResultExt};
|
use error_stack::{report, IntoReport, ResultExt};
|
||||||
#[cfg(feature = "kms")]
|
|
||||||
use external_services::kms;
|
|
||||||
use josekit::jwe;
|
use josekit::jwe;
|
||||||
use masking::{ExposeOptionInterface, PeekInterface};
|
use masking::{ExposeOptionInterface, PeekInterface};
|
||||||
use router_env::{instrument, tracing};
|
use router_env::{instrument, tracing};
|
||||||
@ -1607,15 +1605,7 @@ pub async fn get_merchant_connector_account(
|
|||||||
)?;
|
)?;
|
||||||
|
|
||||||
#[cfg(feature = "kms")]
|
#[cfg(feature = "kms")]
|
||||||
let kms_config = &state.conf.kms;
|
let private_key = state.kms_secrets.jwekey.peek().tunnel_private_key.clone();
|
||||||
|
|
||||||
#[cfg(feature = "kms")]
|
|
||||||
let private_key = kms::get_kms_client(kms_config)
|
|
||||||
.await
|
|
||||||
.decrypt(state.conf.jwekey.tunnel_private_key.to_owned())
|
|
||||||
.await
|
|
||||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
|
||||||
.attach_printable("Error getting tunnel private key")?;
|
|
||||||
|
|
||||||
#[cfg(not(feature = "kms"))]
|
#[cfg(not(feature = "kms"))]
|
||||||
let private_key = state.conf.jwekey.tunnel_private_key.to_owned();
|
let private_key = state.conf.jwekey.tunnel_private_key.to_owned();
|
||||||
|
|||||||
@ -12,8 +12,10 @@ use super::{admin::*, api_keys::*, disputes::*, files::*};
|
|||||||
use super::{configs::*, customers::*, mandates::*, payments::*, payouts::*, refunds::*};
|
use super::{configs::*, customers::*, mandates::*, payments::*, payouts::*, refunds::*};
|
||||||
#[cfg(feature = "oltp")]
|
#[cfg(feature = "oltp")]
|
||||||
use super::{ephemeral_key::*, payment_methods::*, webhooks::*};
|
use super::{ephemeral_key::*, payment_methods::*, webhooks::*};
|
||||||
|
#[cfg(feature = "kms")]
|
||||||
|
use crate::configs::kms;
|
||||||
use crate::{
|
use crate::{
|
||||||
configs::settings::Settings,
|
configs::settings,
|
||||||
db::{MockDb, StorageImpl, StorageInterface},
|
db::{MockDb, StorageImpl, StorageInterface},
|
||||||
routes::cards_info::card_iin_info,
|
routes::cards_info::card_iin_info,
|
||||||
services::Store,
|
services::Store,
|
||||||
@ -23,13 +25,15 @@ use crate::{
|
|||||||
pub struct AppState {
|
pub struct AppState {
|
||||||
pub flow_name: String,
|
pub flow_name: String,
|
||||||
pub store: Box<dyn StorageInterface>,
|
pub store: Box<dyn StorageInterface>,
|
||||||
pub conf: Settings,
|
pub conf: settings::Settings,
|
||||||
#[cfg(feature = "email")]
|
#[cfg(feature = "email")]
|
||||||
pub email_client: Box<dyn EmailClient>,
|
pub email_client: Box<dyn EmailClient>,
|
||||||
|
#[cfg(feature = "kms")]
|
||||||
|
pub kms_secrets: settings::ActiveKmsSecrets,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait AppStateInfo {
|
pub trait AppStateInfo {
|
||||||
fn conf(&self) -> Settings;
|
fn conf(&self) -> settings::Settings;
|
||||||
fn flow_name(&self) -> String;
|
fn flow_name(&self) -> String;
|
||||||
fn store(&self) -> Box<dyn StorageInterface>;
|
fn store(&self) -> Box<dyn StorageInterface>;
|
||||||
#[cfg(feature = "email")]
|
#[cfg(feature = "email")]
|
||||||
@ -37,7 +41,7 @@ pub trait AppStateInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AppStateInfo for AppState {
|
impl AppStateInfo for AppState {
|
||||||
fn conf(&self) -> Settings {
|
fn conf(&self) -> settings::Settings {
|
||||||
self.conf.to_owned()
|
self.conf.to_owned()
|
||||||
}
|
}
|
||||||
fn flow_name(&self) -> String {
|
fn flow_name(&self) -> String {
|
||||||
@ -54,7 +58,7 @@ impl AppStateInfo for AppState {
|
|||||||
|
|
||||||
impl AppState {
|
impl AppState {
|
||||||
pub async fn with_storage(
|
pub async fn with_storage(
|
||||||
conf: Settings,
|
conf: settings::Settings,
|
||||||
storage_impl: StorageImpl,
|
storage_impl: StorageImpl,
|
||||||
shut_down_signal: oneshot::Sender<()>,
|
shut_down_signal: oneshot::Sender<()>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
@ -66,6 +70,17 @@ impl AppState {
|
|||||||
StorageImpl::Mock => Box::new(MockDb::new(&conf).await),
|
StorageImpl::Mock => Box::new(MockDb::new(&conf).await),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(feature = "kms")]
|
||||||
|
#[allow(clippy::expect_used)]
|
||||||
|
let kms_secrets = kms::KmsDecrypt::decrypt_inner(
|
||||||
|
settings::ActiveKmsSecrets {
|
||||||
|
jwekey: conf.jwekey.clone().into(),
|
||||||
|
},
|
||||||
|
&conf.kms,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.expect("Failed while performing KMS decryption");
|
||||||
|
|
||||||
#[cfg(feature = "email")]
|
#[cfg(feature = "email")]
|
||||||
#[allow(clippy::expect_used)]
|
#[allow(clippy::expect_used)]
|
||||||
let email_client = Box::new(AwsSes::new(&conf.email).await);
|
let email_client = Box::new(AwsSes::new(&conf.email).await);
|
||||||
@ -75,10 +90,12 @@ impl AppState {
|
|||||||
conf,
|
conf,
|
||||||
#[cfg(feature = "email")]
|
#[cfg(feature = "email")]
|
||||||
email_client,
|
email_client,
|
||||||
|
#[cfg(feature = "kms")]
|
||||||
|
kms_secrets,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn new(conf: Settings, shut_down_signal: oneshot::Sender<()>) -> Self {
|
pub async fn new(conf: settings::Settings, shut_down_signal: oneshot::Sender<()>) -> Self {
|
||||||
Self::with_storage(conf, StorageImpl::Postgresql, shut_down_signal).await
|
Self::with_storage(conf, StorageImpl::Postgresql, shut_down_signal).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user