From 70258e3021f13135fbab50ca2ea17d7df0a1af76 Mon Sep 17 00:00:00 2001 From: Arjun Karthik Date: Mon, 29 Jul 2024 16:53:54 +0530 Subject: [PATCH] feat: add env variable for enable key manager service (#5465) Co-authored-by: dracarys18 --- crates/common_utils/src/types/keymanager.rs | 1 + .../src/type_encryption.rs | 135 ++++++++---------- crates/router/Cargo.toml | 5 +- crates/router/src/configs/defaults.rs | 1 + crates/router/src/configs/settings.rs | 1 + crates/router/src/routes/admin.rs | 4 +- crates/router/src/types/domain/types.rs | 1 + 7 files changed, 65 insertions(+), 83 deletions(-) diff --git a/crates/common_utils/src/types/keymanager.rs b/crates/common_utils/src/types/keymanager.rs index f4b671abcd72..e263f3d57899 100644 --- a/crates/common_utils/src/types/keymanager.rs +++ b/crates/common_utils/src/types/keymanager.rs @@ -23,6 +23,7 @@ use crate::{ #[derive(Debug)] pub struct KeyManagerState { + pub enabled: Option, pub url: String, pub client_idle_timeout: Option, #[cfg(feature = "keymanager_mtls")] diff --git a/crates/hyperswitch_domain_models/src/type_encryption.rs b/crates/hyperswitch_domain_models/src/type_encryption.rs index ba739079169d..a36969478d1f 100644 --- a/crates/hyperswitch_domain_models/src/type_encryption.rs +++ b/crates/hyperswitch_domain_models/src/type_encryption.rs @@ -17,26 +17,19 @@ mod encrypt { crypto, encryption::Encryption, errors::{self, CustomResult}, - types::keymanager::{Identifier, KeyManagerState}, + keymanager::call_encryption_service, + transformers::{ForeignFrom, ForeignTryFrom}, + types::keymanager::{ + BatchDecryptDataResponse, BatchEncryptDataRequest, BatchEncryptDataResponse, + DecryptDataResponse, EncryptDataRequest, EncryptDataResponse, Identifier, + KeyManagerState, TransientBatchDecryptDataRequest, TransientDecryptDataRequest, + }, }; use error_stack::ResultExt; + use http::Method; use masking::{PeekInterface, Secret}; - use router_env::{instrument, tracing}; + use router_env::{instrument, logger, tracing}; use rustc_hash::FxHashMap; - #[cfg(feature = "encryption_service")] - use { - common_utils::{ - keymanager::call_encryption_service, - transformers::{ForeignFrom, ForeignTryFrom}, - types::keymanager::{ - BatchDecryptDataResponse, BatchEncryptDataRequest, BatchEncryptDataResponse, - DecryptDataResponse, EncryptDataRequest, EncryptDataResponse, - TransientBatchDecryptDataRequest, TransientDecryptDataRequest, - }, - }, - http::Method, - router_env::logger, - }; use super::metrics; @@ -104,6 +97,17 @@ mod encrypt { ) -> CustomResult, errors::CryptoError>; } + fn is_encryption_service_enabled(_state: &KeyManagerState) -> bool { + #[cfg(feature = "encryption_service")] + { + _state.enabled.unwrap_or_default() + } + #[cfg(not(feature = "encryption_service"))] + { + false + } + } + #[async_trait] impl< V: crypto::DecodeMessage + crypto::EncodeMessage + Send + 'static, @@ -119,12 +123,10 @@ mod encrypt { key: &[u8], crypt_algo: V, ) -> CustomResult { - #[cfg(not(feature = "encryption_service"))] - { + // If encryption service is not enabled, fall back to application encryption or else call encryption service + if !is_encryption_service_enabled(state) { Self::encrypt(masked_data, key, crypt_algo).await - } - #[cfg(feature = "encryption_service")] - { + } else { let result: Result< EncryptDataResponse, error_stack::Report, @@ -156,12 +158,10 @@ mod encrypt { key: &[u8], crypt_algo: V, ) -> CustomResult { - #[cfg(not(feature = "encryption_service"))] - { + // If encryption service is not enabled, fall back to application encryption or else call encryption service + if !is_encryption_service_enabled(state) { Self::decrypt(encrypted_data, key, crypt_algo).await - } - #[cfg(feature = "encryption_service")] - { + } else { let result: Result< DecryptDataResponse, error_stack::Report, @@ -227,13 +227,10 @@ mod encrypt { key: &[u8], crypt_algo: V, ) -> CustomResult, errors::CryptoError> { - #[cfg(not(feature = "encryption_service"))] - { + // If encryption service is not enabled, fall back to application encryption or else call encryption service + if !is_encryption_service_enabled(state) { Self::batch_encrypt(masked_data, key, crypt_algo).await - } - - #[cfg(feature = "encryption_service")] - { + } else { let result: Result< BatchEncryptDataResponse, error_stack::Report, @@ -264,13 +261,10 @@ mod encrypt { key: &[u8], crypt_algo: V, ) -> CustomResult, errors::CryptoError> { - #[cfg(not(feature = "encryption_service"))] - { + // If encryption service is not enabled, fall back to application encryption or else call encryption service + if !is_encryption_service_enabled(state) { Self::batch_decrypt(encrypted_data, key, crypt_algo).await - } - - #[cfg(feature = "encryption_service")] - { + } else { let result: Result< BatchDecryptDataResponse, error_stack::Report, @@ -356,12 +350,10 @@ mod encrypt { key: &[u8], crypt_algo: V, ) -> CustomResult { - #[cfg(not(feature = "encryption_service"))] - { + // If encryption service is not enabled, fall back to application encryption or else call encryption service + if !is_encryption_service_enabled(state) { Self::encrypt(masked_data, key, crypt_algo).await - } - #[cfg(feature = "encryption_service")] - { + } else { let result: Result< EncryptDataResponse, error_stack::Report, @@ -393,12 +385,10 @@ mod encrypt { key: &[u8], crypt_algo: V, ) -> CustomResult { - #[cfg(not(feature = "encryption_service"))] - { + // If encryption service is not enabled, fall back to application encryption or else call encryption service + if !is_encryption_service_enabled(state) { Self::decrypt(encrypted_data, key, crypt_algo).await - } - #[cfg(feature = "encryption_service")] - { + } else { let result: Result< DecryptDataResponse, error_stack::Report, @@ -465,12 +455,10 @@ mod encrypt { key: &[u8], crypt_algo: V, ) -> CustomResult, errors::CryptoError> { - #[cfg(not(feature = "encryption_service"))] - { + // If encryption service is not enabled, fall back to application encryption or else call encryption service + if !is_encryption_service_enabled(state) { Self::batch_encrypt(masked_data, key, crypt_algo).await - } - #[cfg(feature = "encryption_service")] - { + } else { let result: Result< BatchEncryptDataResponse, error_stack::Report, @@ -501,12 +489,10 @@ mod encrypt { key: &[u8], crypt_algo: V, ) -> CustomResult, errors::CryptoError> { - #[cfg(not(feature = "encryption_service"))] - { + // If encryption service is not enabled, fall back to application encryption or else call encryption service + if !is_encryption_service_enabled(state) { Self::batch_decrypt(encrypted_data, key, crypt_algo).await - } - #[cfg(feature = "encryption_service")] - { + } else { let result: Result< BatchDecryptDataResponse, error_stack::Report, @@ -590,12 +576,10 @@ mod encrypt { key: &[u8], crypt_algo: V, ) -> CustomResult { - #[cfg(not(feature = "encryption_service"))] - { + // If encryption service is not enabled, fall back to application encryption or else call encryption service + if !is_encryption_service_enabled(state) { Self::encrypt(masked_data, key, crypt_algo).await - } - #[cfg(feature = "encryption_service")] - { + } else { let result: Result< EncryptDataResponse, error_stack::Report, @@ -627,12 +611,10 @@ mod encrypt { key: &[u8], crypt_algo: V, ) -> CustomResult { - #[cfg(not(feature = "encryption_service"))] - { + // If encryption service is not enabled, fall back to application encryption or else call encryption service + if !is_encryption_service_enabled(state) { Self::decrypt(encrypted_data, key, crypt_algo).await - } - #[cfg(feature = "encryption_service")] - { + } else { let result: Result< DecryptDataResponse, error_stack::Report, @@ -694,13 +676,10 @@ mod encrypt { key: &[u8], crypt_algo: V, ) -> CustomResult, errors::CryptoError> { - #[cfg(not(feature = "encryption_service"))] - { + // If encryption service is not enabled, fall back to application encryption or else call encryption service + if !is_encryption_service_enabled(state) { Self::batch_encrypt(masked_data, key, crypt_algo).await - } - - #[cfg(feature = "encryption_service")] - { + } else { let result: Result< BatchEncryptDataResponse, error_stack::Report, @@ -731,12 +710,10 @@ mod encrypt { key: &[u8], crypt_algo: V, ) -> CustomResult, errors::CryptoError> { - #[cfg(not(feature = "encryption_service"))] - { + // If encryption service is not enabled, fall back to application encryption or else call encryption service + if !is_encryption_service_enabled(state) { Self::batch_decrypt(encrypted_data, key, crypt_algo).await - } - #[cfg(feature = "encryption_service")] - { + } else { let result: Result< BatchDecryptDataResponse, error_stack::Report, diff --git a/crates/router/Cargo.toml b/crates/router/Cargo.toml index 90774ed0df3b..e01be51a68c1 100644 --- a/crates/router/Cargo.toml +++ b/crates/router/Cargo.toml @@ -12,10 +12,11 @@ license.workspace = true default = ["kv_store", "stripe", "oltp", "olap", "accounts_cache", "dummy_connector", "payouts", "payout_retry", "retry", "frm", "tls", "v1"] olap = ["hyperswitch_domain_models/olap", "storage_impl/olap", "scheduler/olap", "api_models/olap", "dep:analytics"] tls = ["actix-web/rustls-0_22"] -keymanager_mtls = ["reqwest/rustls-tls", "common_utils/keymanager_mtls"] -encryption_service = ["hyperswitch_domain_models/encryption_service", "common_utils/encryption_service"] email = ["external_services/email", "scheduler/email", "olap"] +# keymanager_create, keymanager_mtls, encryption_service should not be removed or added to default feature. Once this features were enabled it can't be disabled as these are breaking changes. keymanager_create = [] +keymanager_mtls = ["reqwest/rustls-tls", "common_utils/keymanager_mtls"] +encryption_service = ["hyperswitch_domain_models/encryption_service", "common_utils/encryption_service"] frm = ["api_models/frm", "hyperswitch_domain_models/frm", "hyperswitch_connectors/frm", "hyperswitch_interfaces/frm"] stripe = ["dep:serde_qs"] release = ["stripe", "email", "accounts_cache", "kv_store", "vergen", "recon", "external_services/aws_kms", "external_services/aws_s3", "keymanager_mtls", "keymanager_create", "encryption_service"] diff --git a/crates/router/src/configs/defaults.rs b/crates/router/src/configs/defaults.rs index ffa3d81edea6..c7125770fffc 100644 --- a/crates/router/src/configs/defaults.rs +++ b/crates/router/src/configs/defaults.rs @@ -8936,6 +8936,7 @@ impl Default for super::settings::ApiKeys { impl Default for super::settings::KeyManagerConfig { fn default() -> Self { Self { + enabled: None, url: String::from("localhost:5000"), #[cfg(feature = "keymanager_mtls")] ca: String::default().into(), diff --git a/crates/router/src/configs/settings.rs b/crates/router/src/configs/settings.rs index 8ccc97c73f46..e920e9b7f105 100644 --- a/crates/router/src/configs/settings.rs +++ b/crates/router/src/configs/settings.rs @@ -220,6 +220,7 @@ pub struct KvConfig { #[derive(Debug, Deserialize, Clone)] pub struct KeyManagerConfig { + pub enabled: Option, pub url: String, #[cfg(feature = "keymanager_mtls")] pub cert: Secret, diff --git a/crates/router/src/routes/admin.rs b/crates/router/src/routes/admin.rs index 5044070037f3..c9cb9dac908a 100644 --- a/crates/router/src/routes/admin.rs +++ b/crates/router/src/routes/admin.rs @@ -772,7 +772,7 @@ pub async fn merchant_account_transfer_keys( payload: web::Json, ) -> HttpResponse { let flow = Flow::ConfigKeyFetch; - api::server_wrap( + Box::pin(api::server_wrap( flow, state, &req, @@ -780,7 +780,7 @@ pub async fn merchant_account_transfer_keys( |state, _, req, _| transfer_key_store_to_key_manager(state, req), &auth::AdminApiAuth, api_locking::LockAction::NotApplicable, - ) + )) .await } diff --git a/crates/router/src/types/domain/types.rs b/crates/router/src/types/domain/types.rs index fa9053a096f5..e105b2eba09f 100644 --- a/crates/router/src/types/domain/types.rs +++ b/crates/router/src/types/domain/types.rs @@ -8,6 +8,7 @@ impl From<&crate::SessionState> for KeyManagerState { fn from(state: &crate::SessionState) -> Self { let conf = state.conf.key_manager.get_inner(); Self { + enabled: conf.enabled, url: conf.url.clone(), client_idle_timeout: state.conf.proxy.idle_pool_connection_timeout, #[cfg(feature = "keymanager_mtls")]