Skip to content
34 changes: 26 additions & 8 deletions crates/common_utils/src/keymanager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,19 +235,37 @@ impl ConvertRaw for TransientBatchDecryptDataRequest {
pub async fn create_key_in_key_manager(
state: &KeyManagerState,
request_body: EncryptionCreateRequest,
) -> errors::CustomResult<DataKeyCreateResponse, errors::KeyManagerError> {
call_encryption_service(state, Method::POST, "key/create", request_body)
.await
.change_context(errors::KeyManagerError::KeyAddFailed)
) -> errors::CustomResult<Option<DataKeyCreateResponse>, errors::KeyManagerError> {
if !state.is_encryption_service_enabled() {
logger::info!(
"Encryption service is disabled, skipping key creation for identifier: {:?}",
request_body.identifier
);
Ok(None)
} else {
call_encryption_service(state, Method::POST, "key/create", request_body)
.await
.map(Some)
.change_context(errors::KeyManagerError::KeyAddFailed)
}
}

/// A function to transfer the key in keymanager
#[instrument(skip_all)]
pub async fn transfer_key_to_key_manager(
state: &KeyManagerState,
request_body: EncryptionTransferRequest,
) -> errors::CustomResult<DataKeyCreateResponse, errors::KeyManagerError> {
call_encryption_service(state, Method::POST, "key/transfer", request_body)
.await
.change_context(errors::KeyManagerError::KeyTransferFailed)
) -> errors::CustomResult<Option<DataKeyCreateResponse>, errors::KeyManagerError> {
if !state.is_encryption_service_enabled() {
logger::info!(
"Encryption service is disabled, skipping key transfer for identifier: {:?}",
request_body.identifier
);
Ok(None)
} else {
call_encryption_service(state, Method::POST, "key/transfer", request_body)
.await
.map(Some)
.change_context(errors::KeyManagerError::KeyTransferFailed)
}
}
12 changes: 12 additions & 0 deletions crates/common_utils/src/types/keymanager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ impl KeyManagerState {
infra_values: Default::default(),
}
}

pub fn add_confirm_value_in_infra_values(
&self,
is_confirm_operation: bool,
Expand All @@ -91,6 +92,17 @@ impl KeyManagerState {
infra_values
})
}

pub fn is_encryption_service_enabled(&self) -> bool {
#[cfg(feature = "encryption_service")]
{
self.enabled
}
#[cfg(not(feature = "encryption_service"))]
{
false
}
}
}

pub trait GetKeymanagerTenant {
Expand Down
4 changes: 2 additions & 2 deletions crates/hyperswitch_domain_models/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ license.workspace = true

[features]
default = ["olap", "frm"]
encryption_service = []
encryption_service = ["common_utils/encryption_service"]
olap = []
payouts = ["api_models/payouts"]
frm = ["api_models/frm"]
Expand All @@ -24,7 +24,7 @@ revenue_recovery= []
api_models = { version = "0.1.0", path = "../api_models", features = ["errors"] }
cards = { version = "0.1.0", path = "../cards" }
common_enums = { version = "0.1.0", path = "../common_enums" }
common_utils = { version = "0.1.0", path = "../common_utils", features = ["async_ext", "metrics", "encryption_service", "keymanager"] }
common_utils = { version = "0.1.0", path = "../common_utils", features = ["async_ext", "metrics", "keymanager"] }
common_types = { version = "0.1.0", path = "../common_types" }
diesel_models = { version = "0.1.0", path = "../diesel_models", features = ["kv_store"], default-features = false }
masking = { version = "0.1.0", path = "../masking" }
Expand Down
35 changes: 12 additions & 23 deletions crates/hyperswitch_domain_models/src/type_encryption.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,17 +99,6 @@ mod encrypt {
) -> CustomResult<FxHashMap<String, Self>, errors::CryptoError>;
}

fn is_encryption_service_enabled(_state: &KeyManagerState) -> bool {
#[cfg(feature = "encryption_service")]
{
_state.enabled
}
#[cfg(not(feature = "encryption_service"))]
{
false
}
}

#[async_trait]
impl<
V: crypto::DecodeMessage + crypto::EncodeMessage + Send + 'static,
Expand All @@ -126,7 +115,7 @@ mod encrypt {
crypt_algo: V,
) -> CustomResult<Self, errors::CryptoError> {
// If encryption service is not enabled, fall back to application encryption or else call encryption service
if !is_encryption_service_enabled(state) {
if !state.is_encryption_service_enabled() {
Self::encrypt(masked_data, key, crypt_algo).await
} else {
let result: Result<
Expand Down Expand Up @@ -161,7 +150,7 @@ mod encrypt {
crypt_algo: V,
) -> CustomResult<Self, errors::CryptoError> {
// If encryption service is not enabled, fall back to application encryption or else call encryption service
if !is_encryption_service_enabled(state) {
if !state.is_encryption_service_enabled() {
Self::decrypt(encrypted_data, key, crypt_algo).await
} else {
let result: Result<
Expand Down Expand Up @@ -235,7 +224,7 @@ mod encrypt {
crypt_algo: V,
) -> CustomResult<FxHashMap<String, Self>, errors::CryptoError> {
// If encryption service is not enabled, fall back to application encryption or else call encryption service
if !is_encryption_service_enabled(state) {
if !state.is_encryption_service_enabled() {
Self::batch_encrypt(masked_data, key, crypt_algo).await
} else {
let result: Result<
Expand Down Expand Up @@ -270,7 +259,7 @@ mod encrypt {
crypt_algo: V,
) -> CustomResult<FxHashMap<String, Self>, errors::CryptoError> {
// If encryption service is not enabled, fall back to application encryption or else call encryption service
if !is_encryption_service_enabled(state) {
if !state.is_encryption_service_enabled() {
Self::batch_decrypt(encrypted_data, key, crypt_algo).await
} else {
let result: Result<
Expand Down Expand Up @@ -364,7 +353,7 @@ mod encrypt {
crypt_algo: V,
) -> CustomResult<Self, errors::CryptoError> {
// If encryption service is not enabled, fall back to application encryption or else call encryption service
if !is_encryption_service_enabled(state) {
if !state.is_encryption_service_enabled() {
Self::encrypt(masked_data, key, crypt_algo).await
} else {
let result: Result<
Expand Down Expand Up @@ -399,7 +388,7 @@ mod encrypt {
crypt_algo: V,
) -> CustomResult<Self, errors::CryptoError> {
// If encryption service is not enabled, fall back to application encryption or else call encryption service
if !is_encryption_service_enabled(state) {
if !state.is_encryption_service_enabled() {
Self::decrypt(encrypted_data, key, crypt_algo).await
} else {
let result: Result<
Expand Down Expand Up @@ -472,7 +461,7 @@ mod encrypt {
crypt_algo: V,
) -> CustomResult<FxHashMap<String, Self>, errors::CryptoError> {
// If encryption service is not enabled, fall back to application encryption or else call encryption service
if !is_encryption_service_enabled(state) {
if !state.is_encryption_service_enabled() {
Self::batch_encrypt(masked_data, key, crypt_algo).await
} else {
let result: Result<
Expand Down Expand Up @@ -507,7 +496,7 @@ mod encrypt {
crypt_algo: V,
) -> CustomResult<FxHashMap<String, Self>, errors::CryptoError> {
// If encryption service is not enabled, fall back to application encryption or else call encryption service
if !is_encryption_service_enabled(state) {
if !state.is_encryption_service_enabled() {
Self::batch_decrypt(encrypted_data, key, crypt_algo).await
} else {
let result: Result<
Expand Down Expand Up @@ -836,7 +825,7 @@ mod encrypt {
crypt_algo: V,
) -> CustomResult<Self, errors::CryptoError> {
// If encryption service is not enabled, fall back to application encryption or else call encryption service
if !is_encryption_service_enabled(state) {
if !state.is_encryption_service_enabled() {
Self::encrypt(masked_data, key, crypt_algo).await
} else {
let result: Result<
Expand Down Expand Up @@ -871,7 +860,7 @@ mod encrypt {
crypt_algo: V,
) -> CustomResult<Self, errors::CryptoError> {
// If encryption service is not enabled, fall back to application encryption or else call encryption service
if !is_encryption_service_enabled(state) {
if !state.is_encryption_service_enabled() {
Self::decrypt(encrypted_data, key, crypt_algo).await
} else {
let result: Result<
Expand Down Expand Up @@ -939,7 +928,7 @@ mod encrypt {
crypt_algo: V,
) -> CustomResult<FxHashMap<String, Self>, errors::CryptoError> {
// If encryption service is not enabled, fall back to application encryption or else call encryption service
if !is_encryption_service_enabled(state) {
if !state.is_encryption_service_enabled() {
Self::batch_encrypt(masked_data, key, crypt_algo).await
} else {
let result: Result<
Expand Down Expand Up @@ -974,7 +963,7 @@ mod encrypt {
crypt_algo: V,
) -> CustomResult<FxHashMap<String, Self>, errors::CryptoError> {
// If encryption service is not enabled, fall back to application encryption or else call encryption service
if !is_encryption_service_enabled(state) {
if !state.is_encryption_service_enabled() {
Self::batch_decrypt(encrypted_data, key, crypt_algo).await
} else {
let result: Result<
Expand Down
3 changes: 2 additions & 1 deletion crates/payment_methods/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ api_models = { version = "0.1.0", path = "../api_models", features = ["errors",
cards = { version = "0.1.0", path = "../cards" }
common_types = { version = "0.1.0", path = "../common_types" }
common_enums = { version = "0.1.0", path = "../common_enums" }
common_utils = { version = "0.1.0", path = "../common_utils", features = ["signals", "async_ext", "logs", "metrics", "keymanager", "encryption_service"] }
common_utils = { version = "0.1.0", path = "../common_utils", features = ["signals", "async_ext", "logs", "metrics", "keymanager"] }
hyperswitch_domain_models = { version = "0.1.0", path = "../hyperswitch_domain_models", default-features = false }
router_env = { version = "0.1.0", path = "../router_env", features = ["log_extra_implicit_fields", "log_custom_entries_to_extra"] }
scheduler = { version = "0.1.0", path = "../scheduler", default-features = false }
Expand All @@ -35,6 +35,7 @@ workspace = true

[features]
default = ["dummy_connector", "payouts"]
encryption_service = ["common_utils/encryption_service"]
v1 = ["hyperswitch_domain_models/v1", "storage_impl/v1", "common_utils/v1", "scheduler/v1", "common_types/v1"]
v2 = ["common_utils/v2", "scheduler/v2", "common_types/v2"]
dummy_connector = ["api_models/dummy_connector", "hyperswitch_interfaces/dummy_connector"]
Expand Down
4 changes: 2 additions & 2 deletions crates/router/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ 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 = ["keymanager_create", "hyperswitch_domain_models/encryption_service", "common_utils/encryption_service"]
encryption_service = ["keymanager_create", "hyperswitch_domain_models/encryption_service", "common_utils/encryption_service", "subscriptions/encryption_service", "payment_methods/encryption_service"]
km_forward_x_request_id = ["common_utils/km_forward_x_request_id"]
frm = ["api_models/frm", "hyperswitch_domain_models/frm", "hyperswitch_connectors/frm", "hyperswitch_interfaces/frm"]
stripe = []
Expand Down Expand Up @@ -121,7 +121,7 @@ analytics = { version = "0.1.0", path = "../analytics", optional = true, default
api_models = { version = "0.1.0", path = "../api_models", features = ["errors", "control_center_theme"] }
cards = { version = "0.1.0", path = "../cards" }
common_enums = { version = "0.1.0", path = "../common_enums" }
common_utils = { version = "0.1.0", path = "../common_utils", features = ["signals", "async_ext", "logs", "metrics", "keymanager", "encryption_service"] }
common_utils = { version = "0.1.0", path = "../common_utils", features = ["signals", "async_ext", "logs", "metrics", "keymanager"] }
common_types = { version = "0.1.0", path = "../common_types" }
currency_conversion = { version = "0.1.0", path = "../currency_conversion" }
diesel_models = { version = "0.1.0", path = "../diesel_models", features = ["kv_store", "tokenization_v2"], default-features = false }
Expand Down
37 changes: 15 additions & 22 deletions crates/router/src/core/admin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ use hyperswitch_domain_models::merchant_connector_account::{
use masking::{ExposeInterface, PeekInterface, Secret};
use pm_auth::types as pm_auth_types;
use uuid::Uuid;
#[cfg(feature = "olap")]
use {
base64::Engine,
common_utils::{keymanager, types::keymanager::EncryptionTransferRequest},
};

use super::routing::helpers::redact_cgraph_cache;
#[cfg(any(feature = "v1", feature = "v2"))]
Expand Down Expand Up @@ -189,9 +194,6 @@ pub async fn create_merchant_account(
req: api::MerchantAccountCreate,
org_data_from_auth: Option<authentication::AuthenticationDataWithOrg>,
) -> RouterResponse<api::MerchantAccountResponse> {
#[cfg(feature = "keymanager_create")]
use common_utils::{keymanager, types::keymanager::EncryptionTransferRequest};

let db = state.store.as_ref();
let key = services::generate_aes256_key()
.change_context(errors::ApiErrorResponse::InternalServerError)
Expand All @@ -202,25 +204,16 @@ pub async fn create_merchant_account(
let key_manager_state: &KeyManagerState = &(&state).into();
let merchant_id = req.get_merchant_reference_id();
let identifier = km_types::Identifier::Merchant(merchant_id.clone());
#[cfg(feature = "keymanager_create")]
{
use base64::Engine;

use crate::consts::BASE64_ENGINE;

if key_manager_state.enabled {
keymanager::transfer_key_to_key_manager(
key_manager_state,
EncryptionTransferRequest {
identifier: identifier.clone(),
key: masking::StrongSecret::new(BASE64_ENGINE.encode(key)),
},
)
.await
.change_context(errors::ApiErrorResponse::DuplicateMerchantAccount)
.attach_printable("Failed to insert key to KeyManager")?;
}
}
keymanager::transfer_key_to_key_manager(
key_manager_state,
EncryptionTransferRequest {
identifier: identifier.clone(),
key: masking::StrongSecret::new(consts::BASE64_ENGINE.encode(key)),
},
)
.await
.change_context(errors::ApiErrorResponse::DuplicateMerchantAccount)
.attach_printable("Failed to insert key to KeyManager")?;

let key_store = domain::MerchantKeyStore {
merchant_id: merchant_id.clone(),
Expand Down
31 changes: 15 additions & 16 deletions crates/router/src/types/domain/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,14 @@ use std::{
use api_models::{
admin as admin_api, organization as api_org, user as user_api, user_role as user_role_api,
};
use base64::Engine;
use common_enums::EntityType;
use common_utils::{
crypto::Encryptable, id_type, new_type::MerchantName, pii, type_name,
types::keymanager::Identifier,
crypto::Encryptable,
id_type,
new_type::MerchantName,
pii, type_name,
types::keymanager::{EncryptionTransferRequest, Identifier},
};
use diesel_models::{
enums::{TotpStatus, UserRoleVersion, UserStatus},
Expand All @@ -25,8 +29,6 @@ use masking::{ExposeInterface, PeekInterface, Secret};
use rand::distributions::{Alphanumeric, DistString};
use time::PrimitiveDateTime;
use unicode_segmentation::UnicodeSegmentation;
#[cfg(feature = "keymanager_create")]
use {base64::Engine, common_utils::types::keymanager::EncryptionTransferRequest};

use crate::{
consts,
Expand Down Expand Up @@ -1213,18 +1215,15 @@ impl UserFromStorage {
.change_context(UserErrors::InternalServerError)
.attach_printable("Unable to generate aes 256 key")?;

#[cfg(feature = "keymanager_create")]
{
common_utils::keymanager::transfer_key_to_key_manager(
key_manager_state,
EncryptionTransferRequest {
identifier: Identifier::User(self.get_user_id().to_string()),
key: masking::StrongSecret::new(consts::BASE64_ENGINE.encode(key)),
},
)
.await
.change_context(UserErrors::InternalServerError)?;
}
common_utils::keymanager::transfer_key_to_key_manager(
key_manager_state,
EncryptionTransferRequest {
identifier: Identifier::User(self.get_user_id().to_string()),
key: masking::StrongSecret::new(consts::BASE64_ENGINE.encode(key)),
},
)
.await
.change_context(UserErrors::InternalServerError)?;

let key_store = UserKeyStore {
user_id: self.get_user_id().to_string(),
Expand Down
3 changes: 2 additions & 1 deletion crates/subscriptions/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ time = { version = "0.3.41", features = ["serde", "std"] }
api_models = { version = "0.1.0", path = "../api_models", features = ["errors", "control_center_theme"] }
common_types = { version = "0.1.0", path = "../common_types" }
common_enums = { version = "0.1.0", path = "../common_enums" }
common_utils = { version = "0.1.0", path = "../common_utils", features = ["signals", "async_ext", "logs", "metrics", "keymanager", "encryption_service"] }
common_utils = { version = "0.1.0", path = "../common_utils", features = ["signals", "async_ext", "logs", "metrics", "keymanager"] }
hyperswitch_domain_models = { version = "0.1.0", path = "../hyperswitch_domain_models", default-features = false }
router_env = { version = "0.1.0", path = "../router_env", features = ["log_extra_implicit_fields", "log_custom_entries_to_extra"] }
scheduler = { version = "0.1.0", path = "../scheduler", default-features = false }
Expand All @@ -29,5 +29,6 @@ workspace = true

[features]
default = ["v1"]
encryption_service = ["common_utils/encryption_service"]
v1 = ["hyperswitch_domain_models/v1", "storage_impl/v1", "common_utils/v1", "scheduler/v1", "common_types/v1"]
v2 = ["common_utils/v2", "scheduler/v2", "common_types/v2"]
Loading