Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of having feature flag based branching in a fn, we can have two definitions for v1 and v2 right

#[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