mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-28 04:04:55 +08:00
feat: add env variable for enable key manager service (#5442)
Co-authored-by: dracarys18 <karthikey.hegde@juspay.in>
This commit is contained in:
@ -23,6 +23,7 @@ use crate::{
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct KeyManagerState {
|
pub struct KeyManagerState {
|
||||||
|
pub enabled: Option<bool>,
|
||||||
pub url: String,
|
pub url: String,
|
||||||
pub client_idle_timeout: Option<u64>,
|
pub client_idle_timeout: Option<u64>,
|
||||||
#[cfg(feature = "keymanager_mtls")]
|
#[cfg(feature = "keymanager_mtls")]
|
||||||
|
|||||||
@ -17,26 +17,19 @@ mod encrypt {
|
|||||||
crypto,
|
crypto,
|
||||||
encryption::Encryption,
|
encryption::Encryption,
|
||||||
errors::{self, CustomResult},
|
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 error_stack::ResultExt;
|
||||||
|
use http::Method;
|
||||||
use masking::{PeekInterface, Secret};
|
use masking::{PeekInterface, Secret};
|
||||||
use router_env::{instrument, tracing};
|
use router_env::{instrument, logger, tracing};
|
||||||
use rustc_hash::FxHashMap;
|
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;
|
use super::metrics;
|
||||||
|
|
||||||
@ -104,6 +97,17 @@ mod encrypt {
|
|||||||
) -> CustomResult<FxHashMap<String, Self>, errors::CryptoError>;
|
) -> CustomResult<FxHashMap<String, Self>, 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]
|
#[async_trait]
|
||||||
impl<
|
impl<
|
||||||
V: crypto::DecodeMessage + crypto::EncodeMessage + Send + 'static,
|
V: crypto::DecodeMessage + crypto::EncodeMessage + Send + 'static,
|
||||||
@ -119,12 +123,10 @@ mod encrypt {
|
|||||||
key: &[u8],
|
key: &[u8],
|
||||||
crypt_algo: V,
|
crypt_algo: V,
|
||||||
) -> CustomResult<Self, errors::CryptoError> {
|
) -> CustomResult<Self, 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::encrypt(masked_data, key, crypt_algo).await
|
Self::encrypt(masked_data, key, crypt_algo).await
|
||||||
}
|
} else {
|
||||||
#[cfg(feature = "encryption_service")]
|
|
||||||
{
|
|
||||||
let result: Result<
|
let result: Result<
|
||||||
EncryptDataResponse,
|
EncryptDataResponse,
|
||||||
error_stack::Report<errors::KeyManagerClientError>,
|
error_stack::Report<errors::KeyManagerClientError>,
|
||||||
@ -156,12 +158,10 @@ mod encrypt {
|
|||||||
key: &[u8],
|
key: &[u8],
|
||||||
crypt_algo: V,
|
crypt_algo: V,
|
||||||
) -> CustomResult<Self, errors::CryptoError> {
|
) -> CustomResult<Self, 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::decrypt(encrypted_data, key, crypt_algo).await
|
Self::decrypt(encrypted_data, key, crypt_algo).await
|
||||||
}
|
} else {
|
||||||
#[cfg(feature = "encryption_service")]
|
|
||||||
{
|
|
||||||
let result: Result<
|
let result: Result<
|
||||||
DecryptDataResponse,
|
DecryptDataResponse,
|
||||||
error_stack::Report<errors::KeyManagerClientError>,
|
error_stack::Report<errors::KeyManagerClientError>,
|
||||||
@ -227,13 +227,10 @@ mod encrypt {
|
|||||||
key: &[u8],
|
key: &[u8],
|
||||||
crypt_algo: V,
|
crypt_algo: V,
|
||||||
) -> CustomResult<FxHashMap<String, Self>, errors::CryptoError> {
|
) -> CustomResult<FxHashMap<String, Self>, 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
|
Self::batch_encrypt(masked_data, key, crypt_algo).await
|
||||||
}
|
} else {
|
||||||
|
|
||||||
#[cfg(feature = "encryption_service")]
|
|
||||||
{
|
|
||||||
let result: Result<
|
let result: Result<
|
||||||
BatchEncryptDataResponse,
|
BatchEncryptDataResponse,
|
||||||
error_stack::Report<errors::KeyManagerClientError>,
|
error_stack::Report<errors::KeyManagerClientError>,
|
||||||
@ -264,13 +261,10 @@ mod encrypt {
|
|||||||
key: &[u8],
|
key: &[u8],
|
||||||
crypt_algo: V,
|
crypt_algo: V,
|
||||||
) -> CustomResult<FxHashMap<String, Self>, errors::CryptoError> {
|
) -> CustomResult<FxHashMap<String, Self>, 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
|
Self::batch_decrypt(encrypted_data, key, crypt_algo).await
|
||||||
}
|
} else {
|
||||||
|
|
||||||
#[cfg(feature = "encryption_service")]
|
|
||||||
{
|
|
||||||
let result: Result<
|
let result: Result<
|
||||||
BatchDecryptDataResponse,
|
BatchDecryptDataResponse,
|
||||||
error_stack::Report<errors::KeyManagerClientError>,
|
error_stack::Report<errors::KeyManagerClientError>,
|
||||||
@ -356,12 +350,10 @@ mod encrypt {
|
|||||||
key: &[u8],
|
key: &[u8],
|
||||||
crypt_algo: V,
|
crypt_algo: V,
|
||||||
) -> CustomResult<Self, errors::CryptoError> {
|
) -> CustomResult<Self, 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::encrypt(masked_data, key, crypt_algo).await
|
Self::encrypt(masked_data, key, crypt_algo).await
|
||||||
}
|
} else {
|
||||||
#[cfg(feature = "encryption_service")]
|
|
||||||
{
|
|
||||||
let result: Result<
|
let result: Result<
|
||||||
EncryptDataResponse,
|
EncryptDataResponse,
|
||||||
error_stack::Report<errors::KeyManagerClientError>,
|
error_stack::Report<errors::KeyManagerClientError>,
|
||||||
@ -393,12 +385,10 @@ mod encrypt {
|
|||||||
key: &[u8],
|
key: &[u8],
|
||||||
crypt_algo: V,
|
crypt_algo: V,
|
||||||
) -> CustomResult<Self, errors::CryptoError> {
|
) -> CustomResult<Self, 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::decrypt(encrypted_data, key, crypt_algo).await
|
Self::decrypt(encrypted_data, key, crypt_algo).await
|
||||||
}
|
} else {
|
||||||
#[cfg(feature = "encryption_service")]
|
|
||||||
{
|
|
||||||
let result: Result<
|
let result: Result<
|
||||||
DecryptDataResponse,
|
DecryptDataResponse,
|
||||||
error_stack::Report<errors::KeyManagerClientError>,
|
error_stack::Report<errors::KeyManagerClientError>,
|
||||||
@ -465,12 +455,10 @@ mod encrypt {
|
|||||||
key: &[u8],
|
key: &[u8],
|
||||||
crypt_algo: V,
|
crypt_algo: V,
|
||||||
) -> CustomResult<FxHashMap<String, Self>, errors::CryptoError> {
|
) -> CustomResult<FxHashMap<String, Self>, 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
|
Self::batch_encrypt(masked_data, key, crypt_algo).await
|
||||||
}
|
} else {
|
||||||
#[cfg(feature = "encryption_service")]
|
|
||||||
{
|
|
||||||
let result: Result<
|
let result: Result<
|
||||||
BatchEncryptDataResponse,
|
BatchEncryptDataResponse,
|
||||||
error_stack::Report<errors::KeyManagerClientError>,
|
error_stack::Report<errors::KeyManagerClientError>,
|
||||||
@ -501,12 +489,10 @@ mod encrypt {
|
|||||||
key: &[u8],
|
key: &[u8],
|
||||||
crypt_algo: V,
|
crypt_algo: V,
|
||||||
) -> CustomResult<FxHashMap<String, Self>, errors::CryptoError> {
|
) -> CustomResult<FxHashMap<String, Self>, 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
|
Self::batch_decrypt(encrypted_data, key, crypt_algo).await
|
||||||
}
|
} else {
|
||||||
#[cfg(feature = "encryption_service")]
|
|
||||||
{
|
|
||||||
let result: Result<
|
let result: Result<
|
||||||
BatchDecryptDataResponse,
|
BatchDecryptDataResponse,
|
||||||
error_stack::Report<errors::KeyManagerClientError>,
|
error_stack::Report<errors::KeyManagerClientError>,
|
||||||
@ -590,12 +576,10 @@ mod encrypt {
|
|||||||
key: &[u8],
|
key: &[u8],
|
||||||
crypt_algo: V,
|
crypt_algo: V,
|
||||||
) -> CustomResult<Self, errors::CryptoError> {
|
) -> CustomResult<Self, 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::encrypt(masked_data, key, crypt_algo).await
|
Self::encrypt(masked_data, key, crypt_algo).await
|
||||||
}
|
} else {
|
||||||
#[cfg(feature = "encryption_service")]
|
|
||||||
{
|
|
||||||
let result: Result<
|
let result: Result<
|
||||||
EncryptDataResponse,
|
EncryptDataResponse,
|
||||||
error_stack::Report<errors::KeyManagerClientError>,
|
error_stack::Report<errors::KeyManagerClientError>,
|
||||||
@ -627,12 +611,10 @@ mod encrypt {
|
|||||||
key: &[u8],
|
key: &[u8],
|
||||||
crypt_algo: V,
|
crypt_algo: V,
|
||||||
) -> CustomResult<Self, errors::CryptoError> {
|
) -> CustomResult<Self, 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::decrypt(encrypted_data, key, crypt_algo).await
|
Self::decrypt(encrypted_data, key, crypt_algo).await
|
||||||
}
|
} else {
|
||||||
#[cfg(feature = "encryption_service")]
|
|
||||||
{
|
|
||||||
let result: Result<
|
let result: Result<
|
||||||
DecryptDataResponse,
|
DecryptDataResponse,
|
||||||
error_stack::Report<errors::KeyManagerClientError>,
|
error_stack::Report<errors::KeyManagerClientError>,
|
||||||
@ -694,13 +676,10 @@ mod encrypt {
|
|||||||
key: &[u8],
|
key: &[u8],
|
||||||
crypt_algo: V,
|
crypt_algo: V,
|
||||||
) -> CustomResult<FxHashMap<String, Self>, errors::CryptoError> {
|
) -> CustomResult<FxHashMap<String, Self>, 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
|
Self::batch_encrypt(masked_data, key, crypt_algo).await
|
||||||
}
|
} else {
|
||||||
|
|
||||||
#[cfg(feature = "encryption_service")]
|
|
||||||
{
|
|
||||||
let result: Result<
|
let result: Result<
|
||||||
BatchEncryptDataResponse,
|
BatchEncryptDataResponse,
|
||||||
error_stack::Report<errors::KeyManagerClientError>,
|
error_stack::Report<errors::KeyManagerClientError>,
|
||||||
@ -731,12 +710,10 @@ mod encrypt {
|
|||||||
key: &[u8],
|
key: &[u8],
|
||||||
crypt_algo: V,
|
crypt_algo: V,
|
||||||
) -> CustomResult<FxHashMap<String, Self>, errors::CryptoError> {
|
) -> CustomResult<FxHashMap<String, Self>, 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
|
Self::batch_decrypt(encrypted_data, key, crypt_algo).await
|
||||||
}
|
} else {
|
||||||
#[cfg(feature = "encryption_service")]
|
|
||||||
{
|
|
||||||
let result: Result<
|
let result: Result<
|
||||||
BatchDecryptDataResponse,
|
BatchDecryptDataResponse,
|
||||||
error_stack::Report<errors::KeyManagerClientError>,
|
error_stack::Report<errors::KeyManagerClientError>,
|
||||||
|
|||||||
@ -12,10 +12,11 @@ license.workspace = true
|
|||||||
default = ["kv_store", "stripe", "oltp", "olap", "accounts_cache", "dummy_connector", "payouts", "payout_retry", "retry", "frm", "tls", "v1"]
|
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"]
|
olap = ["hyperswitch_domain_models/olap", "storage_impl/olap", "scheduler/olap", "api_models/olap", "dep:analytics"]
|
||||||
tls = ["actix-web/rustls-0_22"]
|
tls = ["actix-web/rustls-0_22"]
|
||||||
|
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"]
|
keymanager_mtls = ["reqwest/rustls-tls", "common_utils/keymanager_mtls"]
|
||||||
encryption_service = ["hyperswitch_domain_models/encryption_service", "common_utils/encryption_service"]
|
encryption_service = ["hyperswitch_domain_models/encryption_service", "common_utils/encryption_service"]
|
||||||
email = ["external_services/email", "scheduler/email", "olap"]
|
|
||||||
keymanager_create = []
|
|
||||||
frm = ["api_models/frm", "hyperswitch_domain_models/frm", "hyperswitch_connectors/frm", "hyperswitch_interfaces/frm"]
|
frm = ["api_models/frm", "hyperswitch_domain_models/frm", "hyperswitch_connectors/frm", "hyperswitch_interfaces/frm"]
|
||||||
stripe = ["dep:serde_qs"]
|
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"]
|
release = ["stripe", "email", "accounts_cache", "kv_store", "vergen", "recon", "external_services/aws_kms", "external_services/aws_s3", "keymanager_mtls", "keymanager_create", "encryption_service"]
|
||||||
|
|||||||
@ -8936,6 +8936,7 @@ impl Default for super::settings::ApiKeys {
|
|||||||
impl Default for super::settings::KeyManagerConfig {
|
impl Default for super::settings::KeyManagerConfig {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
enabled: None,
|
||||||
url: String::from("localhost:5000"),
|
url: String::from("localhost:5000"),
|
||||||
#[cfg(feature = "keymanager_mtls")]
|
#[cfg(feature = "keymanager_mtls")]
|
||||||
ca: String::default().into(),
|
ca: String::default().into(),
|
||||||
|
|||||||
@ -210,6 +210,7 @@ pub struct KvConfig {
|
|||||||
|
|
||||||
#[derive(Debug, Deserialize, Clone)]
|
#[derive(Debug, Deserialize, Clone)]
|
||||||
pub struct KeyManagerConfig {
|
pub struct KeyManagerConfig {
|
||||||
|
pub enabled: Option<bool>,
|
||||||
pub url: String,
|
pub url: String,
|
||||||
#[cfg(feature = "keymanager_mtls")]
|
#[cfg(feature = "keymanager_mtls")]
|
||||||
pub cert: Secret<String>,
|
pub cert: Secret<String>,
|
||||||
|
|||||||
@ -772,7 +772,7 @@ pub async fn merchant_account_transfer_keys(
|
|||||||
payload: web::Json<api_models::admin::MerchantKeyTransferRequest>,
|
payload: web::Json<api_models::admin::MerchantKeyTransferRequest>,
|
||||||
) -> HttpResponse {
|
) -> HttpResponse {
|
||||||
let flow = Flow::ConfigKeyFetch;
|
let flow = Flow::ConfigKeyFetch;
|
||||||
api::server_wrap(
|
Box::pin(api::server_wrap(
|
||||||
flow,
|
flow,
|
||||||
state,
|
state,
|
||||||
&req,
|
&req,
|
||||||
@ -780,7 +780,7 @@ pub async fn merchant_account_transfer_keys(
|
|||||||
|state, _, req, _| transfer_key_store_to_key_manager(state, req),
|
|state, _, req, _| transfer_key_store_to_key_manager(state, req),
|
||||||
&auth::AdminApiAuth,
|
&auth::AdminApiAuth,
|
||||||
api_locking::LockAction::NotApplicable,
|
api_locking::LockAction::NotApplicable,
|
||||||
)
|
))
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -8,6 +8,7 @@ impl From<&crate::SessionState> for KeyManagerState {
|
|||||||
fn from(state: &crate::SessionState) -> Self {
|
fn from(state: &crate::SessionState) -> Self {
|
||||||
let conf = state.conf.key_manager.get_inner();
|
let conf = state.conf.key_manager.get_inner();
|
||||||
Self {
|
Self {
|
||||||
|
enabled: conf.enabled,
|
||||||
url: conf.url.clone(),
|
url: conf.url.clone(),
|
||||||
client_idle_timeout: state.conf.proxy.idle_pool_connection_timeout,
|
client_idle_timeout: state.conf.proxy.idle_pool_connection_timeout,
|
||||||
#[cfg(feature = "keymanager_mtls")]
|
#[cfg(feature = "keymanager_mtls")]
|
||||||
|
|||||||
Reference in New Issue
Block a user