mirror of
				https://github.com/juspay/hyperswitch.git
				synced 2025-10-31 18:17:13 +08:00 
			
		
		
		
	refactor(router): remove pii-encryption-script feature and use of timestamps for decryption (#1350)
				
					
				
			This commit is contained in:
		| @ -101,7 +101,6 @@ admin_api_key = "test_admin"     # admin API key for admin authentication. Only | ||||
| kms_encrypted_admin_api_key = "" # Base64-encoded (KMS encrypted) ciphertext of the admin_api_key. Only applicable when KMS is enabled. | ||||
| jwt_secret = "secret"            # JWT secret used for user authentication. Only applicable when KMS is disabled. | ||||
| kms_encrypted_jwt_secret = ""    # Base64-encoded (KMS encrypted) ciphertext of the jwt_secret. Only applicable when KMS is enabled. | ||||
| migration_encryption_timestamp = 0  # Timestamp to decide which entries are not encrypted in the database. | ||||
|  | ||||
| # Locker settings contain details for accessing a card locker, a | ||||
| # PCI Compliant storage entity which stores payment method information | ||||
|  | ||||
| @ -32,7 +32,6 @@ connection_timeout = 10 | ||||
|  | ||||
| [secrets] | ||||
| admin_api_key = "test_admin" | ||||
| migration_encryption_timestamp = 1682425530 | ||||
| master_enc_key = "73ad7bbbbc640c845a150f67d058b279849370cd2c1f3c67c4dd6c869213e13a" | ||||
|  | ||||
| [locker] | ||||
|  | ||||
| @ -16,8 +16,8 @@ kms = ["external_services/kms","dep:aws-config"] | ||||
| email = ["external_services/email","dep:aws-config"] | ||||
| basilisk = ["kms"] | ||||
| stripe = ["dep:serde_qs"] | ||||
| sandbox = ["kms", "stripe", "basilisk", "s3","email"] | ||||
| production = ["kms", "stripe", "basilisk", "s3","pii-encryption-script","email"] | ||||
| sandbox = ["kms", "stripe", "basilisk", "s3", "email"] | ||||
| production = ["kms", "stripe", "basilisk", "s3", "email"] | ||||
| olap = [] | ||||
| oltp = [] | ||||
| kv_store = [] | ||||
| @ -25,7 +25,6 @@ accounts_cache = [] | ||||
| openapi = ["olap", "oltp"] | ||||
| vergen = ["router_env/vergen"] | ||||
| multiple_mca = ["api_models/multiple_mca"] | ||||
| pii-encryption-script = [] | ||||
| dummy_connector = ["api_models/dummy_connector"] | ||||
| external_access_dc = ["dummy_connector"] | ||||
| detailed_errors = ["api_models/detailed_errors", "error-stack/serde"] | ||||
|  | ||||
| @ -36,24 +36,6 @@ async fn main() -> ApplicationResult<()> { | ||||
|  | ||||
|     let _guard = logger::setup(&conf.log); | ||||
|  | ||||
|     #[cfg(feature = "pii-encryption-script")] | ||||
|     { | ||||
|         let store = | ||||
|             router::services::Store::new(&conf, false, tokio::sync::oneshot::channel().0).await; | ||||
|  | ||||
|         // ^-------- KMS decryption of the master key is a fallible and the server will panic in | ||||
|         // the above mentioned line | ||||
|  | ||||
|         router::scripts::pii_encryption::test_2_step_encryption(&store).await; | ||||
|  | ||||
|         #[allow(clippy::expect_used)] | ||||
|         router::scripts::pii_encryption::encrypt_merchant_account_fields(&store) | ||||
|             .await | ||||
|             .expect("Failed while encrypting merchant account"); | ||||
|  | ||||
|         crate::logger::error!("Done with everything"); | ||||
|     } | ||||
|  | ||||
|     logger::info!("Application started [{:?}] [{:?}]", conf.server, conf.log); | ||||
|  | ||||
|     #[allow(clippy::expect_used)] | ||||
|  | ||||
| @ -40,7 +40,6 @@ impl Default for super::settings::Secrets { | ||||
|             kms_encrypted_jwt_secret: "".into(), | ||||
|             #[cfg(feature = "kms")] | ||||
|             kms_encrypted_admin_api_key: "".into(), | ||||
|             migration_encryption_timestamp: 0, | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -37,8 +37,6 @@ pub enum Subcommand { | ||||
|     #[cfg(feature = "openapi")] | ||||
|     /// Generate the OpenAPI specification file from code. | ||||
|     GenerateOpenapiSpec, | ||||
|     #[cfg(feature = "pii-encryption-script")] | ||||
|     EncryptDatabase, | ||||
| } | ||||
|  | ||||
| #[cfg(feature = "kms")] | ||||
| @ -288,8 +286,6 @@ pub struct Secrets { | ||||
|     pub kms_encrypted_jwt_secret: String, | ||||
|     #[cfg(feature = "kms")] | ||||
|     pub kms_encrypted_admin_api_key: String, | ||||
|  | ||||
|     pub migration_encryption_timestamp: i64, | ||||
| } | ||||
|  | ||||
| #[derive(Debug, Deserialize, Clone)] | ||||
|  | ||||
| @ -239,7 +239,7 @@ pub async fn delete_customer( | ||||
|         .change_context(errors::ApiErrorResponse::InternalServerError) | ||||
|         .attach_printable("Failed while getting key for encryption")?; | ||||
|     let redacted_encrypted_value: Encryptable<masking::Secret<_>> = | ||||
|         Encryptable::encrypt(REDACTED.to_string().into(), &key, GcmAes256 {}) | ||||
|         Encryptable::encrypt(REDACTED.to_string().into(), &key, GcmAes256) | ||||
|             .await | ||||
|             .change_context(errors::ApiErrorResponse::InternalServerError)?; | ||||
|  | ||||
| @ -278,7 +278,7 @@ pub async fn delete_customer( | ||||
|     let updated_customer = storage::CustomerUpdate::Update { | ||||
|         name: Some(redacted_encrypted_value.clone()), | ||||
|         email: Some( | ||||
|             Encryptable::encrypt(REDACTED.to_string().into(), &key, GcmAes256 {}) | ||||
|             Encryptable::encrypt(REDACTED.to_string().into(), &key, GcmAes256) | ||||
|                 .await | ||||
|                 .change_context(errors::ApiErrorResponse::InternalServerError)?, | ||||
|         ), | ||||
|  | ||||
| @ -74,16 +74,12 @@ pub trait StorageInterface: | ||||
|  | ||||
| pub trait MasterKeyInterface { | ||||
|     fn get_master_key(&self) -> &[u8]; | ||||
|     fn get_migration_timestamp(&self) -> i64; | ||||
| } | ||||
|  | ||||
| impl MasterKeyInterface for Store { | ||||
|     fn get_master_key(&self) -> &[u8] { | ||||
|         &self.master_key | ||||
|     } | ||||
|     fn get_migration_timestamp(&self) -> i64 { | ||||
|         self.migration_timestamp | ||||
|     } | ||||
| } | ||||
|  | ||||
| /// Default dummy key for MockDb | ||||
| @ -94,10 +90,6 @@ impl MasterKeyInterface for MockDb { | ||||
|             25, 26, 27, 28, 29, 30, 31, 32, | ||||
|         ] | ||||
|     } | ||||
|  | ||||
|     fn get_migration_timestamp(&self) -> i64 { | ||||
|         0 | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[async_trait::async_trait] | ||||
|  | ||||
| @ -2,7 +2,7 @@ use common_utils::ext_traits::AsyncExt; | ||||
| use error_stack::{IntoReport, ResultExt}; | ||||
| use storage_models::address::AddressUpdateInternal; | ||||
|  | ||||
| use super::{MasterKeyInterface, MockDb, Store}; | ||||
| use super::{MockDb, Store}; | ||||
| use crate::{ | ||||
|     connection, | ||||
|     core::errors::{self, CustomResult}, | ||||
| @ -58,7 +58,7 @@ impl AddressInterface for Store { | ||||
|             .async_and_then(|address| async { | ||||
|                 let merchant_id = address.merchant_id.clone(); | ||||
|                 address | ||||
|                     .convert(self, &merchant_id, self.get_migration_timestamp()) | ||||
|                     .convert(self, &merchant_id) | ||||
|                     .await | ||||
|                     .change_context(errors::StorageError::DecryptionError) | ||||
|             }) | ||||
| @ -78,7 +78,7 @@ impl AddressInterface for Store { | ||||
|             .async_and_then(|address| async { | ||||
|                 let merchant_id = address.merchant_id.clone(); | ||||
|                 address | ||||
|                     .convert(self, &merchant_id, self.get_migration_timestamp()) | ||||
|                     .convert(self, &merchant_id) | ||||
|                     .await | ||||
|                     .change_context(errors::StorageError::DecryptionError) | ||||
|             }) | ||||
| @ -101,7 +101,7 @@ impl AddressInterface for Store { | ||||
|             .async_and_then(|address| async { | ||||
|                 let merchant_id = address.merchant_id.clone(); | ||||
|                 address | ||||
|                     .convert(self, &merchant_id, self.get_migration_timestamp()) | ||||
|                     .convert(self, &merchant_id) | ||||
|                     .await | ||||
|                     .change_context(errors::StorageError::DecryptionError) | ||||
|             }) | ||||
| @ -130,7 +130,7 @@ impl AddressInterface for Store { | ||||
|                 let merchant_id = address.merchant_id.clone(); | ||||
|                 output.push( | ||||
|                     address | ||||
|                         .convert(self, &merchant_id, self.get_migration_timestamp()) | ||||
|                         .convert(self, &merchant_id) | ||||
|                         .await | ||||
|                         .change_context(errors::StorageError::DecryptionError)?, | ||||
|                 ) | ||||
| @ -158,7 +158,7 @@ impl AddressInterface for MockDb { | ||||
|                 let merchant_id = address.merchant_id.clone(); | ||||
|                 address | ||||
|                     .clone() | ||||
|                     .convert(self, &merchant_id, self.get_migration_timestamp()) | ||||
|                     .convert(self, &merchant_id) | ||||
|                     .await | ||||
|                     .change_context(errors::StorageError::DecryptionError) | ||||
|             } | ||||
| @ -190,7 +190,7 @@ impl AddressInterface for MockDb { | ||||
|             Some(address_updated) => { | ||||
|                 let merchant_id = address_updated.merchant_id.clone(); | ||||
|                 address_updated | ||||
|                     .convert(self, &merchant_id, self.get_migration_timestamp()) | ||||
|                     .convert(self, &merchant_id) | ||||
|                     .await | ||||
|                     .change_context(errors::StorageError::DecryptionError) | ||||
|             } | ||||
| @ -217,7 +217,7 @@ impl AddressInterface for MockDb { | ||||
|         addresses.push(address.clone()); | ||||
|  | ||||
|         address | ||||
|             .convert(self, &merchant_id, self.get_migration_timestamp()) | ||||
|             .convert(self, &merchant_id) | ||||
|             .await | ||||
|             .change_context(errors::StorageError::DecryptionError) | ||||
|     } | ||||
| @ -244,7 +244,7 @@ impl AddressInterface for MockDb { | ||||
|             }) { | ||||
|             Some(address) => { | ||||
|                 let address: domain::Address = address | ||||
|                     .convert(self, merchant_id, self.get_migration_timestamp()) | ||||
|                     .convert(self, merchant_id) | ||||
|                     .await | ||||
|                     .change_context(errors::StorageError::DecryptionError)?; | ||||
|                 Ok(vec![address]) | ||||
|  | ||||
| @ -2,7 +2,7 @@ use common_utils::ext_traits::AsyncExt; | ||||
| use error_stack::{IntoReport, ResultExt}; | ||||
| use masking::PeekInterface; | ||||
|  | ||||
| use super::{MasterKeyInterface, MockDb, Store}; | ||||
| use super::{MockDb, Store}; | ||||
| use crate::{ | ||||
|     connection, | ||||
|     core::{ | ||||
| @ -72,7 +72,7 @@ impl CustomerInterface for Store { | ||||
|             .map_err(Into::into) | ||||
|             .into_report()? | ||||
|             .async_map(|c| async { | ||||
|                 c.convert(self, merchant_id, self.get_migration_timestamp()) | ||||
|                 c.convert(self, merchant_id) | ||||
|                     .await | ||||
|                     .change_context(errors::StorageError::DecryptionError) | ||||
|             }) | ||||
| @ -108,7 +108,7 @@ impl CustomerInterface for Store { | ||||
|         .into_report() | ||||
|         .async_and_then(|c| async { | ||||
|             let merchant_id = c.merchant_id.clone(); | ||||
|             c.convert(self, &merchant_id, self.get_migration_timestamp()) | ||||
|             c.convert(self, &merchant_id) | ||||
|                 .await | ||||
|                 .change_context(errors::StorageError::DecryptionError) | ||||
|         }) | ||||
| @ -128,7 +128,7 @@ impl CustomerInterface for Store { | ||||
|                 .into_report() | ||||
|                 .async_and_then(|c| async { | ||||
|                     let merchant_id = c.merchant_id.clone(); | ||||
|                     c.convert(self, &merchant_id, self.get_migration_timestamp()) | ||||
|                     c.convert(self, &merchant_id) | ||||
|                         .await | ||||
|                         .change_context(errors::StorageError::DecryptionError) | ||||
|                 }) | ||||
| @ -156,7 +156,7 @@ impl CustomerInterface for Store { | ||||
|             .into_report() | ||||
|             .async_and_then(|c| async { | ||||
|                 let merchant_id = c.merchant_id.clone(); | ||||
|                 c.convert(self, &merchant_id, self.get_migration_timestamp()) | ||||
|                 c.convert(self, &merchant_id) | ||||
|                     .await | ||||
|                     .change_context(errors::StorageError::DecryptionError) | ||||
|             }) | ||||
| @ -194,7 +194,7 @@ impl CustomerInterface for MockDb { | ||||
|         customer | ||||
|             .async_map(|c| async { | ||||
|                 let merchant_id = c.merchant_id.clone(); | ||||
|                 c.convert(self, &merchant_id, self.get_migration_timestamp()) | ||||
|                 c.convert(self, &merchant_id) | ||||
|                     .await | ||||
|                     .change_context(errors::StorageError::DecryptionError) | ||||
|             }) | ||||
| @ -236,7 +236,7 @@ impl CustomerInterface for MockDb { | ||||
|         customers.push(customer.clone()); | ||||
|  | ||||
|         customer | ||||
|             .convert(self, &merchant_id, self.get_migration_timestamp()) | ||||
|             .convert(self, &merchant_id) | ||||
|             .await | ||||
|             .change_context(errors::StorageError::DecryptionError) | ||||
|     } | ||||
|  | ||||
| @ -7,7 +7,6 @@ use crate::cache::{self, ACCOUNTS_CACHE}; | ||||
| use crate::{ | ||||
|     connection, | ||||
|     core::errors::{self, CustomResult}, | ||||
|     db::MasterKeyInterface, | ||||
|     types::{ | ||||
|         domain::{ | ||||
|             self, | ||||
| @ -72,7 +71,7 @@ impl MerchantAccountInterface for Store { | ||||
|             .await | ||||
|             .map_err(Into::into) | ||||
|             .into_report()? | ||||
|             .convert(self, &merchant_id, self.get_migration_timestamp()) | ||||
|             .convert(self, &merchant_id) | ||||
|             .await | ||||
|             .change_context(errors::StorageError::DecryptionError) | ||||
|     } | ||||
| @ -93,7 +92,7 @@ impl MerchantAccountInterface for Store { | ||||
|         { | ||||
|             fetch_func() | ||||
|                 .await? | ||||
|                 .convert(self, merchant_id, self.get_migration_timestamp()) | ||||
|                 .convert(self, merchant_id) | ||||
|                 .await | ||||
|                 .change_context(errors::StorageError::DecryptionError) | ||||
|         } | ||||
| @ -102,7 +101,7 @@ impl MerchantAccountInterface for Store { | ||||
|         { | ||||
|             super::cache::get_or_populate_in_memory(self, merchant_id, fetch_func, &ACCOUNTS_CACHE) | ||||
|                 .await? | ||||
|                 .convert(self, merchant_id, self.get_migration_timestamp()) | ||||
|                 .convert(self, merchant_id) | ||||
|                 .await | ||||
|                 .change_context(errors::StorageError::DecryptionError) | ||||
|         } | ||||
| @ -124,7 +123,7 @@ impl MerchantAccountInterface for Store { | ||||
|                 .map_err(Into::into) | ||||
|                 .into_report() | ||||
|                 .async_and_then(|item| async { | ||||
|                     item.convert(self, &_merchant_id, self.get_migration_timestamp()) | ||||
|                     item.convert(self, &_merchant_id) | ||||
|                         .await | ||||
|                         .change_context(errors::StorageError::DecryptionError) | ||||
|                 }) | ||||
| @ -163,7 +162,7 @@ impl MerchantAccountInterface for Store { | ||||
|             .map_err(Into::into) | ||||
|             .into_report() | ||||
|             .async_and_then(|item| async { | ||||
|                 item.convert(self, merchant_id, self.get_migration_timestamp()) | ||||
|                 item.convert(self, merchant_id) | ||||
|                     .await | ||||
|                     .change_context(errors::StorageError::DecryptionError) | ||||
|             }) | ||||
| @ -197,7 +196,7 @@ impl MerchantAccountInterface for Store { | ||||
|             .into_report() | ||||
|             .async_and_then(|item| async { | ||||
|                 let merchant_id = item.merchant_id.clone(); | ||||
|                 item.convert(self, &merchant_id, self.get_migration_timestamp()) | ||||
|                 item.convert(self, &merchant_id) | ||||
|                     .await | ||||
|                     .change_context(errors::StorageError::DecryptionError) | ||||
|             }) | ||||
| @ -248,7 +247,7 @@ impl MerchantAccountInterface for MockDb { | ||||
|         accounts.push(account.clone()); | ||||
|  | ||||
|         account | ||||
|             .convert(self, &merchant_id, self.get_migration_timestamp()) | ||||
|             .convert(self, &merchant_id) | ||||
|             .await | ||||
|             .change_context(errors::StorageError::DecryptionError) | ||||
|     } | ||||
| @ -264,7 +263,7 @@ impl MerchantAccountInterface for MockDb { | ||||
|             .find(|account| account.merchant_id == merchant_id) | ||||
|             .cloned() | ||||
|             .async_map(|a| async { | ||||
|                 a.convert(self, merchant_id, self.get_migration_timestamp()) | ||||
|                 a.convert(self, merchant_id) | ||||
|                     .await | ||||
|                     .change_context(errors::StorageError::DecryptionError) | ||||
|             }) | ||||
|  | ||||
| @ -7,7 +7,6 @@ use super::{MockDb, Store}; | ||||
| use crate::{ | ||||
|     connection, | ||||
|     core::errors::{self, CustomResult}, | ||||
|     db::MasterKeyInterface, | ||||
|     services::logger, | ||||
|     types::{ | ||||
|         self, | ||||
| @ -166,7 +165,7 @@ impl MerchantConnectorAccountInterface for Store { | ||||
|         .map_err(Into::into) | ||||
|         .into_report() | ||||
|         .async_and_then(|item| async { | ||||
|             item.convert(self, merchant_id, self.get_migration_timestamp()) | ||||
|             item.convert(self, merchant_id) | ||||
|                 .await | ||||
|                 .change_context(errors::StorageError::DecryptionError) | ||||
|         }) | ||||
| @ -194,7 +193,7 @@ impl MerchantConnectorAccountInterface for Store { | ||||
|         { | ||||
|             find_call() | ||||
|                 .await? | ||||
|                 .convert(self, merchant_id, self.get_migration_timestamp()) | ||||
|                 .convert(self, merchant_id) | ||||
|                 .await | ||||
|                 .change_context(errors::StorageError::DeserializationFailed) | ||||
|         } | ||||
| @ -203,7 +202,7 @@ impl MerchantConnectorAccountInterface for Store { | ||||
|         { | ||||
|             cache::get_or_populate_redis(self, merchant_connector_id, find_call) | ||||
|                 .await? | ||||
|                 .convert(self, merchant_id, self.get_migration_timestamp()) | ||||
|                 .convert(self, merchant_id) | ||||
|                 .await | ||||
|                 .change_context(errors::StorageError::DeserializationFailed) | ||||
|         } | ||||
| @ -223,7 +222,7 @@ impl MerchantConnectorAccountInterface for Store { | ||||
|             .into_report() | ||||
|             .async_and_then(|item| async { | ||||
|                 let merchant_id = item.merchant_id.clone(); | ||||
|                 item.convert(self, &merchant_id, self.get_migration_timestamp()) | ||||
|                 item.convert(self, &merchant_id) | ||||
|                     .await | ||||
|                     .change_context(errors::StorageError::DecryptionError) | ||||
|             }) | ||||
| @ -244,7 +243,7 @@ impl MerchantConnectorAccountInterface for Store { | ||||
|                 let mut output = Vec::with_capacity(items.len()); | ||||
|                 for item in items.into_iter() { | ||||
|                     output.push( | ||||
|                         item.convert(self, merchant_id, self.get_migration_timestamp()) | ||||
|                         item.convert(self, merchant_id) | ||||
|                             .await | ||||
|                             .change_context(errors::StorageError::DecryptionError)?, | ||||
|                     ) | ||||
| @ -271,7 +270,7 @@ impl MerchantConnectorAccountInterface for Store { | ||||
|                 .into_report() | ||||
|                 .async_and_then(|item| async { | ||||
|                     let merchant_id = item.merchant_id.clone(); | ||||
|                     item.convert(self, &merchant_id, self.get_migration_timestamp()) | ||||
|                     item.convert(self, &merchant_id) | ||||
|                         .await | ||||
|                         .change_context(errors::StorageError::DecryptionError) | ||||
|                 }) | ||||
| @ -324,7 +323,7 @@ impl MerchantConnectorAccountInterface for MockDb { | ||||
|             .cloned() | ||||
|             .unwrap(); | ||||
|         account | ||||
|             .convert(self, merchant_id, self.get_migration_timestamp()) | ||||
|             .convert(self, merchant_id) | ||||
|             .await | ||||
|             .change_context(errors::StorageError::DecryptionError) | ||||
|     } | ||||
| @ -367,7 +366,7 @@ impl MerchantConnectorAccountInterface for MockDb { | ||||
|         }; | ||||
|         accounts.push(account.clone()); | ||||
|         account | ||||
|             .convert(self, &merchant_id, self.get_migration_timestamp()) | ||||
|             .convert(self, &merchant_id) | ||||
|             .await | ||||
|             .change_context(errors::StorageError::DecryptionError) | ||||
|     } | ||||
|  | ||||
| @ -1,6 +1,5 @@ | ||||
| use error_stack::{IntoReport, ResultExt}; | ||||
|  | ||||
| use super::MasterKeyInterface; | ||||
| use crate::{ | ||||
|     connection, | ||||
|     core::errors::{self, CustomResult}, | ||||
| @ -41,7 +40,7 @@ impl MerchantKeyStoreInterface for Store { | ||||
|             .await | ||||
|             .map_err(Into::into) | ||||
|             .into_report()? | ||||
|             .convert(self, &merchant_id, self.get_migration_timestamp()) | ||||
|             .convert(self, &merchant_id) | ||||
|             .await | ||||
|             .change_context(errors::StorageError::DecryptionError) | ||||
|     } | ||||
| @ -57,7 +56,7 @@ impl MerchantKeyStoreInterface for Store { | ||||
|         .await | ||||
|         .map_err(Into::into) | ||||
|         .into_report()? | ||||
|         .convert(self, merchant_id, self.get_migration_timestamp()) | ||||
|         .convert(self, merchant_id) | ||||
|         .await | ||||
|         .change_context(errors::StorageError::DecryptionError) | ||||
|     } | ||||
|  | ||||
| @ -19,7 +19,6 @@ pub mod scheduler; | ||||
| pub mod middleware; | ||||
| #[cfg(feature = "openapi")] | ||||
| pub mod openapi; | ||||
| pub mod scripts; | ||||
| pub mod services; | ||||
| pub mod types; | ||||
| pub mod utils; | ||||
|  | ||||
| @ -1,2 +0,0 @@ | ||||
| #[cfg(feature = "pii-encryption-script")] | ||||
| pub mod pii_encryption; | ||||
| @ -1,421 +0,0 @@ | ||||
| use async_bb8_diesel::AsyncConnection; | ||||
| use common_utils::errors::CustomResult; | ||||
| use diesel::{associations::HasTable, ExpressionMethods, Table}; | ||||
| use error_stack::{IntoReport, ResultExt}; | ||||
| use storage_models::{ | ||||
|     address::Address, | ||||
|     customers::Customer, | ||||
|     merchant_account::MerchantAccount, | ||||
|     merchant_connector_account::MerchantConnectorAccount, | ||||
|     query::generics::generic_filter, | ||||
|     schema::{ | ||||
|         address::dsl as ad_dsl, customers::dsl as cu_dsl, merchant_account::dsl as ma_dsl, | ||||
|         merchant_connector_account::dsl as mca_dsl, | ||||
|     }, | ||||
| }; | ||||
|  | ||||
| use crate::{ | ||||
|     connection, | ||||
|     core::errors, | ||||
|     db::{ | ||||
|         merchant_account::MerchantAccountInterface, merchant_key_store::MerchantKeyStoreInterface, | ||||
|         MasterKeyInterface, | ||||
|     }, | ||||
|     services::{self, Store}, | ||||
|     types::{ | ||||
|         domain::{ | ||||
|             self, | ||||
|             behaviour::{Conversion, ReverseConversion}, | ||||
|             merchant_key_store, types, | ||||
|         }, | ||||
|         storage, | ||||
|     }, | ||||
| }; | ||||
|  | ||||
| pub async fn create_merchant_key_store( | ||||
|     state: &Store, | ||||
|     merchant_id: &str, | ||||
|     key: Vec<u8>, | ||||
| ) -> CustomResult<(), errors::ApiErrorResponse> { | ||||
|     crate::logger::info!("Trying to create MerchantKeyStore for {}", merchant_id); | ||||
|     let master_key = state.get_master_key(); | ||||
|     let key_store = merchant_key_store::MerchantKeyStore { | ||||
|         merchant_id: merchant_id.to_string(), | ||||
|         key: types::encrypt(key.into(), master_key) | ||||
|             .await | ||||
|             .change_context(errors::ApiErrorResponse::InternalServerError) | ||||
|             .attach_printable("Failed to decrypt data from key store")?, | ||||
|         created_at: common_utils::date_time::now(), | ||||
|     }; | ||||
|  | ||||
|     match state.insert_merchant_key_store(key_store).await { | ||||
|         Ok(_) => Ok(()), | ||||
|         Err(err) => match err.current_context() { | ||||
|             errors::StorageError::DatabaseError(f) => match f.current_context() { | ||||
|                 storage_models::errors::DatabaseError::UniqueViolation => Ok(()), | ||||
|                 _ => Err(err.change_context(errors::ApiErrorResponse::InternalServerError)), | ||||
|             }, | ||||
|             _ => Err(err.change_context(errors::ApiErrorResponse::InternalServerError)), | ||||
|         }, | ||||
|     } | ||||
| } | ||||
|  | ||||
| pub async fn encrypt_merchant_account_fields( | ||||
|     state: &Store, | ||||
| ) -> CustomResult<(), errors::ApiErrorResponse> { | ||||
|     let conn = connection::pg_connection_write(state) | ||||
|         .await | ||||
|         .change_context(errors::ApiErrorResponse::InternalServerError)?; | ||||
|     let merchants: Vec<MerchantAccount> = generic_filter::< | ||||
|         <MerchantAccount as HasTable>::Table, | ||||
|         _, | ||||
|         <<MerchantAccount as HasTable>::Table as Table>::PrimaryKey, | ||||
|         _, | ||||
|     >( | ||||
|         &conn, | ||||
|         ma_dsl::merchant_id.eq(ma_dsl::merchant_id), | ||||
|         None, | ||||
|         None, | ||||
|         None, | ||||
|     ) | ||||
|     .await | ||||
|     .change_context(errors::ApiErrorResponse::InternalServerError)?; | ||||
|  | ||||
|     for mer in merchants.iter() { | ||||
|         let key = services::generate_aes256_key() | ||||
|             .change_context(errors::ApiErrorResponse::InternalServerError)?; | ||||
|  | ||||
|         create_merchant_key_store(state, &mer.merchant_id, key.to_vec()).await?; | ||||
|     } | ||||
|     let mut domain_merchants = Vec::with_capacity(merchants.len()); | ||||
|     for mf in merchants.into_iter() { | ||||
|         let merchant_id = mf.merchant_id.clone(); | ||||
|         let domain_merchant: domain::MerchantAccount = mf | ||||
|             .convert(state, &merchant_id, state.get_migration_timestamp()) | ||||
|             .await | ||||
|             .change_context(errors::ApiErrorResponse::InternalServerError)?; | ||||
|         domain_merchants.push(domain_merchant); | ||||
|     } | ||||
|     for m in domain_merchants { | ||||
|         let merchant_id = m.merchant_id.clone(); | ||||
|         let updated_merchant_account = storage::MerchantAccountUpdate::Update { | ||||
|             merchant_name: m.merchant_name.clone(), | ||||
|             merchant_details: m.merchant_details.clone(), | ||||
|             return_url: None, | ||||
|             webhook_details: None, | ||||
|             sub_merchants_enabled: None, | ||||
|             parent_merchant_id: None, | ||||
|             primary_business_details: None, | ||||
|             enable_payment_response_hash: None, | ||||
|             payment_response_hash_key: None, | ||||
|             redirect_to_merchant_with_http_post: None, | ||||
|             routing_algorithm: None, | ||||
|             locker_id: None, | ||||
|             publishable_key: None, | ||||
|             metadata: None, | ||||
|             intent_fulfillment_time: None, | ||||
|             frm_routing_algorithm: None, | ||||
|         }; | ||||
|         crate::logger::warn!("Started for {}", merchant_id); | ||||
|         state | ||||
|             .update_merchant(m, updated_merchant_account) | ||||
|             .await | ||||
|             .change_context(errors::ApiErrorResponse::InternalServerError)?; | ||||
|         encrypt_merchant_connector_account_fields(state, &merchant_id).await?; | ||||
|         encrypt_customer_fields(state, &merchant_id).await?; | ||||
|         encrypt_address_fields(state, &merchant_id).await?; | ||||
|         crate::logger::warn!("Done for {}", merchant_id); | ||||
|     } | ||||
|  | ||||
|     Ok(()) | ||||
| } | ||||
|  | ||||
| pub async fn encrypt_merchant_connector_account_fields( | ||||
|     state: &Store, | ||||
|     merchant_id: &str, | ||||
| ) -> CustomResult<(), errors::ApiErrorResponse> { | ||||
|     crate::logger::warn!("Updating MerchantConnectorAccount for {}", merchant_id); | ||||
|     let conn = connection::pg_connection_write(state) | ||||
|         .await | ||||
|         .change_context(errors::ApiErrorResponse::InternalServerError)?; | ||||
|  | ||||
|     let merchants: Vec<MerchantConnectorAccount> = generic_filter::< | ||||
|         <MerchantConnectorAccount as HasTable>::Table, | ||||
|         _, | ||||
|         <<MerchantConnectorAccount as HasTable>::Table as Table>::PrimaryKey, | ||||
|         _, | ||||
|     >( | ||||
|         &conn, | ||||
|         mca_dsl::merchant_id.eq(merchant_id.to_string()), | ||||
|         None, | ||||
|         None, | ||||
|         None, | ||||
|     ) | ||||
|     .await | ||||
|     .change_context(errors::ApiErrorResponse::InternalServerError)?; | ||||
|  | ||||
|     let mut domain_merchants = Vec::with_capacity(merchants.len()); | ||||
|     for m in merchants.into_iter() { | ||||
|         let merchant_id = m.merchant_id.clone(); | ||||
|         let domain_merchant: domain::MerchantConnectorAccount = m | ||||
|             .convert(state, &merchant_id, state.get_migration_timestamp()) | ||||
|             .await | ||||
|             .change_context(errors::ApiErrorResponse::InternalServerError)?; | ||||
|         domain_merchants.push(domain_merchant); | ||||
|     } | ||||
|  | ||||
|     conn.transaction_async::<(), async_bb8_diesel::ConnectionError, _, _>(|conn| async move { | ||||
|         for m in domain_merchants { | ||||
|             let updated_merchant_connector_account = | ||||
|                 storage::MerchantConnectorAccountUpdate::Update { | ||||
|                     merchant_id: None, | ||||
|                     connector_name: None, | ||||
|                     connector_type: None, | ||||
|                     frm_configs: None, | ||||
|                     test_mode: None, | ||||
|                     disabled: None, | ||||
|                     merchant_connector_id: None, | ||||
|                     payment_methods_enabled: None, | ||||
|                     metadata: None, | ||||
|                     connector_account_details: Some(m.connector_account_details.clone()), | ||||
|                 }; | ||||
|  | ||||
|             Conversion::convert(m) | ||||
|                 .await | ||||
|                 .map_err(|_| { | ||||
|                     async_bb8_diesel::ConnectionError::Query( | ||||
|                         diesel::result::Error::QueryBuilderError( | ||||
|                             "Error while decrypting MerchantConnectorAccount".into(), | ||||
|                         ), | ||||
|                     ) | ||||
|                 })? | ||||
|                 .update(&conn, updated_merchant_connector_account.into()) | ||||
|                 .await | ||||
|                 .map_err(|_| { | ||||
|                     async_bb8_diesel::ConnectionError::Query( | ||||
|                         diesel::result::Error::QueryBuilderError( | ||||
|                             "Error while updating MerchantConnectorAccount".into(), | ||||
|                         ), | ||||
|                     ) | ||||
|                 })?; | ||||
|         } | ||||
|         Ok(()) | ||||
|     }) | ||||
|     .await | ||||
|     .into_report() | ||||
|     .change_context(errors::ApiErrorResponse::InternalServerError)?; | ||||
|  | ||||
|     crate::logger::warn!( | ||||
|         "Done: Updating MerchantConnectorAccount for {}", | ||||
|         merchant_id | ||||
|     ); | ||||
|     Ok(()) | ||||
| } | ||||
|  | ||||
| pub async fn encrypt_customer_fields( | ||||
|     state: &Store, | ||||
|     merchant_id: &str, | ||||
| ) -> CustomResult<(), errors::ApiErrorResponse> { | ||||
|     crate::logger::warn!("Updating Customer for {}", merchant_id); | ||||
|     let conn = connection::pg_connection_write(state) | ||||
|         .await | ||||
|         .change_context(errors::ApiErrorResponse::InternalServerError)?; | ||||
|  | ||||
|     let merchants: Vec<Customer> = generic_filter::< | ||||
|         <Customer as HasTable>::Table, | ||||
|         _, | ||||
|         <<Customer as HasTable>::Table as Table>::PrimaryKey, | ||||
|         _, | ||||
|     >( | ||||
|         &conn, | ||||
|         cu_dsl::merchant_id.eq(merchant_id.to_string()), | ||||
|         None, | ||||
|         None, | ||||
|         None, | ||||
|     ) | ||||
|     .await | ||||
|     .change_context(errors::ApiErrorResponse::InternalServerError)?; | ||||
|  | ||||
|     let mut domain_merchants = Vec::with_capacity(merchants.len()); | ||||
|     for m in merchants.into_iter() { | ||||
|         let merchant_id = m.merchant_id.clone(); | ||||
|         let domain_merchant: domain::Customer = m | ||||
|             .convert(state, &merchant_id, state.get_migration_timestamp()) | ||||
|             .await | ||||
|             .change_context(errors::ApiErrorResponse::InternalServerError)?; | ||||
|         domain_merchants.push(domain_merchant); | ||||
|     } | ||||
|  | ||||
|     conn.transaction_async::<(), async_bb8_diesel::ConnectionError, _, _>(|conn| async move { | ||||
|         for m in domain_merchants { | ||||
|             let update_customer = storage::CustomerUpdate::Update { | ||||
|                 name: m.name.clone(), | ||||
|                 email: m.email.clone(), | ||||
|                 phone: m.phone.clone(), | ||||
|                 description: None, | ||||
|                 metadata: None, | ||||
|                 phone_country_code: None, | ||||
|                 connector_customer: None, | ||||
|             }; | ||||
|  | ||||
|             Customer::update_by_customer_id_merchant_id( | ||||
|                 &conn, | ||||
|                 m.customer_id.to_string(), | ||||
|                 m.merchant_id.to_string(), | ||||
|                 update_customer.into(), | ||||
|             ) | ||||
|             .await | ||||
|             .map_err(|_| { | ||||
|                 async_bb8_diesel::ConnectionError::Query(diesel::result::Error::QueryBuilderError( | ||||
|                     "Error while updating Customer".into(), | ||||
|                 )) | ||||
|             })?; | ||||
|         } | ||||
|  | ||||
|         Ok(()) | ||||
|     }) | ||||
|     .await | ||||
|     .into_report() | ||||
|     .change_context(errors::ApiErrorResponse::InternalServerError)?; | ||||
|  | ||||
|     crate::logger::warn!("Done: Updating Customer for {}", merchant_id); | ||||
|     Ok(()) | ||||
| } | ||||
|  | ||||
| pub async fn encrypt_address_fields( | ||||
|     state: &Store, | ||||
|     merchant_id: &str, | ||||
| ) -> CustomResult<(), errors::ApiErrorResponse> { | ||||
|     crate::logger::warn!("Updating Address for {}", merchant_id); | ||||
|     let conn = connection::pg_connection_write(state) | ||||
|         .await | ||||
|         .change_context(errors::ApiErrorResponse::InternalServerError)?; | ||||
|  | ||||
|     let merchants: Vec<Address> = generic_filter::< | ||||
|         <Address as HasTable>::Table, | ||||
|         _, | ||||
|         <<Address as HasTable>::Table as Table>::PrimaryKey, | ||||
|         _, | ||||
|     >( | ||||
|         &conn, | ||||
|         ad_dsl::merchant_id.eq(merchant_id.to_string()), | ||||
|         None, | ||||
|         None, | ||||
|         None, | ||||
|     ) | ||||
|     .await | ||||
|     .change_context(errors::ApiErrorResponse::InternalServerError)?; | ||||
|  | ||||
|     let mut domain_merchants = Vec::with_capacity(merchants.len()); | ||||
|     for m in merchants.into_iter() { | ||||
|         let merchant_id = m.merchant_id.clone(); | ||||
|         let domain_merchant: domain::Address = m | ||||
|             .convert(state, &merchant_id, state.get_migration_timestamp()) | ||||
|             .await | ||||
|             .change_context(errors::ApiErrorResponse::InternalServerError)?; | ||||
|         domain_merchants.push(domain_merchant); | ||||
|     } | ||||
|  | ||||
|     conn.transaction_async::<(), async_bb8_diesel::ConnectionError, _, _>(|conn| async move { | ||||
|         for m in domain_merchants { | ||||
|             let update_address = storage::address::AddressUpdate::Update { | ||||
|                 line1: m.line1.clone(), | ||||
|                 line2: m.line2.clone(), | ||||
|                 line3: m.line3.clone(), | ||||
|                 state: m.state.clone(), | ||||
|                 zip: m.zip.clone(), | ||||
|                 first_name: m.first_name.clone(), | ||||
|                 last_name: m.last_name.clone(), | ||||
|                 phone_number: m.phone_number.clone(), | ||||
|                 city: None, | ||||
|                 country: None, | ||||
|                 country_code: None, | ||||
|             }; | ||||
|  | ||||
|             Address::update_by_address_id(&conn, m.address_id, update_address.into()) | ||||
|                 .await | ||||
|                 .map_err(|_| { | ||||
|                     async_bb8_diesel::ConnectionError::Query( | ||||
|                         diesel::result::Error::QueryBuilderError( | ||||
|                             "Error while updating Address".into(), | ||||
|                         ), | ||||
|                     ) | ||||
|                 })?; | ||||
|         } | ||||
|         Ok(()) | ||||
|     }) | ||||
|     .await | ||||
|     .into_report() | ||||
|     .change_context(errors::ApiErrorResponse::InternalServerError)?; | ||||
|  | ||||
|     crate::logger::warn!("Done: Updating Address for {}", merchant_id); | ||||
|     Ok(()) | ||||
| } | ||||
|  | ||||
| /// | ||||
| /// # Panics | ||||
| /// | ||||
| /// The functions runs at the start of the migration and tests, all the functional parts of | ||||
| /// encryption. | ||||
| /// | ||||
| #[allow(clippy::unwrap_used)] | ||||
| pub async fn test_2_step_encryption(store: &Store) { | ||||
|     use masking::ExposeInterface; | ||||
|     let (encrypted_merchant_key, master_key) = { | ||||
|         let master_key = store.get_master_key(); | ||||
|         let merchant_key: Vec<u8> = services::generate_aes256_key().unwrap().into(); | ||||
|         let encrypted_merchant_key = | ||||
|             types::encrypt::<_, crate::pii::WithType>(merchant_key.into(), master_key) | ||||
|                 .await | ||||
|                 .unwrap() | ||||
|                 .into_encrypted(); | ||||
|         let encrypted_merchant_key = | ||||
|             storage_models::encryption::Encryption::new(encrypted_merchant_key); | ||||
|         (encrypted_merchant_key, master_key) | ||||
|     }; | ||||
|  | ||||
|     let dummy_data = "Hello, World!".to_string(); | ||||
|     let encrypted_dummy_data = storage_models::encryption::Encryption::new( | ||||
|         types::encrypt::<_, crate::pii::WithType>( | ||||
|             masking::Secret::new(dummy_data.clone()), | ||||
|             &types::decrypt::<Vec<u8>, crate::pii::WithType>( | ||||
|                 Some(encrypted_merchant_key.clone()), | ||||
|                 master_key, | ||||
|                 0, | ||||
|                 0, | ||||
|             ) | ||||
|             .await | ||||
|             .unwrap() | ||||
|             .unwrap() | ||||
|             .into_inner() | ||||
|             .expose(), | ||||
|         ) | ||||
|         .await | ||||
|         .unwrap() | ||||
|         .into_encrypted(), | ||||
|     ); | ||||
|  | ||||
|     let dummy_data_returned = types::decrypt::<String, crate::pii::WithType>( | ||||
|         Some(encrypted_dummy_data), | ||||
|         &types::decrypt::<Vec<u8>, crate::pii::WithType>( | ||||
|             Some(encrypted_merchant_key), | ||||
|             master_key, | ||||
|             0, | ||||
|             0, | ||||
|         ) | ||||
|         .await | ||||
|         .unwrap() | ||||
|         .unwrap() | ||||
|         .into_inner() | ||||
|         .expose(), | ||||
|         0, | ||||
|         0, | ||||
|     ) | ||||
|     .await | ||||
|     .unwrap() | ||||
|     .unwrap() | ||||
|     .into_inner() | ||||
|     .expose(); | ||||
|  | ||||
|     assert!(dummy_data_returned == dummy_data) | ||||
| } | ||||
| @ -119,7 +119,6 @@ pub struct Store { | ||||
|     #[cfg(feature = "kv_store")] | ||||
|     pub(crate) config: StoreConfig, | ||||
|     pub master_key: Vec<u8>, | ||||
|     pub migration_timestamp: i64, | ||||
| } | ||||
|  | ||||
| #[cfg(feature = "kv_store")] | ||||
| @ -183,7 +182,6 @@ impl Store { | ||||
|                 drainer_num_partitions: config.drainer.num_partitions, | ||||
|             }, | ||||
|             master_key: master_enc_key, | ||||
|             migration_timestamp: config.secrets.migration_encryption_timestamp, | ||||
|         } | ||||
|     } | ||||
|  | ||||
|  | ||||
| @ -74,7 +74,6 @@ impl behaviour::Conversion for Address { | ||||
|         other: Self::DstType, | ||||
|         db: &dyn StorageInterface, | ||||
|         merchant_id: &str, | ||||
|         migration_timestamp: i64, | ||||
|     ) -> CustomResult<Self, ValidationError> { | ||||
|         let key = types::get_merchant_enc_key(db, merchant_id) | ||||
|             .await | ||||
| @ -83,9 +82,7 @@ impl behaviour::Conversion for Address { | ||||
|             })?; | ||||
|  | ||||
|         async { | ||||
|             let modified_at = other.modified_at.assume_utc().unix_timestamp(); | ||||
|             let inner_decrypt = | ||||
|                 |inner| types::decrypt(inner, &key, modified_at, migration_timestamp); | ||||
|             let inner_decrypt = |inner| types::decrypt(inner, &key); | ||||
|             Ok(Self { | ||||
|                 id: Some(other.id), | ||||
|                 address_id: other.address_id, | ||||
|  | ||||
| @ -13,7 +13,6 @@ pub trait Conversion { | ||||
|         item: Self::DstType, | ||||
|         db: &dyn StorageInterface, | ||||
|         merchant_id: &str, | ||||
|         migration_timestamp: i64, | ||||
|     ) -> CustomResult<Self, ValidationError> | ||||
|     where | ||||
|         Self: Sized; | ||||
| @ -27,7 +26,6 @@ pub trait ReverseConversion<SrcType: Conversion> { | ||||
|         self, | ||||
|         db: &dyn StorageInterface, | ||||
|         merchant_id: &str, | ||||
|         migration_timestamp: i64, | ||||
|     ) -> CustomResult<SrcType, ValidationError>; | ||||
| } | ||||
|  | ||||
| @ -37,8 +35,7 @@ impl<T: Send, U: Conversion<DstType = T>> ReverseConversion<U> for T { | ||||
|         self, | ||||
|         db: &dyn StorageInterface, | ||||
|         merchant_id: &str, | ||||
|         migration_timestamp: i64, | ||||
|     ) -> CustomResult<U, ValidationError> { | ||||
|         U::convert_back(self, db, merchant_id, migration_timestamp).await | ||||
|         U::convert_back(self, db, merchant_id).await | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -55,7 +55,6 @@ impl super::behaviour::Conversion for Customer { | ||||
|         item: Self::DstType, | ||||
|         db: &dyn StorageInterface, | ||||
|         merchant_id: &str, | ||||
|         migration_timestamp: i64, | ||||
|     ) -> CustomResult<Self, ValidationError> | ||||
|     where | ||||
|         Self: Sized, | ||||
| @ -66,12 +65,8 @@ impl super::behaviour::Conversion for Customer { | ||||
|                 message: "Failed while getting key from key store".to_string(), | ||||
|             })?; | ||||
|         async { | ||||
|             let modified_at = item.modified_at.assume_utc().unix_timestamp(); | ||||
|  | ||||
|             let inner_decrypt = | ||||
|                 |inner| types::decrypt(inner, &key, modified_at, migration_timestamp); | ||||
|             let inner_decrypt_email = | ||||
|                 |inner| types::decrypt(inner, &key, modified_at, migration_timestamp); | ||||
|             let inner_decrypt = |inner| types::decrypt(inner, &key); | ||||
|             let inner_decrypt_email = |inner| types::decrypt(inner, &key); | ||||
|             Ok(Self { | ||||
|                 id: Some(item.id), | ||||
|                 customer_id: item.customer_id, | ||||
|  | ||||
| @ -149,7 +149,6 @@ impl super::behaviour::Conversion for MerchantAccount { | ||||
|         item: Self::DstType, | ||||
|         db: &dyn StorageInterface, | ||||
|         merchant_id: &str, | ||||
|         migration_timestamp: i64, | ||||
|     ) -> CustomResult<Self, ValidationError> | ||||
|     where | ||||
|         Self: Sized, | ||||
| @ -160,7 +159,6 @@ impl super::behaviour::Conversion for MerchantAccount { | ||||
|                 message: "Failed while getting key from key store".to_string(), | ||||
|             })?; | ||||
|         async { | ||||
|             let modified_at = item.modified_at.assume_utc().unix_timestamp(); | ||||
|             Ok(Self { | ||||
|                 id: Some(item.id), | ||||
|                 merchant_id: item.merchant_id, | ||||
| @ -170,15 +168,11 @@ impl super::behaviour::Conversion for MerchantAccount { | ||||
|                 redirect_to_merchant_with_http_post: item.redirect_to_merchant_with_http_post, | ||||
|                 merchant_name: item | ||||
|                     .merchant_name | ||||
|                     .async_lift(|inner| { | ||||
|                         types::decrypt(inner, &key, modified_at, migration_timestamp) | ||||
|                     }) | ||||
|                     .async_lift(|inner| types::decrypt(inner, &key)) | ||||
|                     .await?, | ||||
|                 merchant_details: item | ||||
|                     .merchant_details | ||||
|                     .async_lift(|inner| { | ||||
|                         types::decrypt(inner, &key, modified_at, migration_timestamp) | ||||
|                     }) | ||||
|                     .async_lift(|inner| types::decrypt(inner, &key)) | ||||
|                     .await?, | ||||
|                 webhook_details: item.webhook_details, | ||||
|                 sub_merchants_enabled: item.sub_merchants_enabled, | ||||
|  | ||||
| @ -89,14 +89,12 @@ impl behaviour::Conversion for MerchantConnectorAccount { | ||||
|         other: Self::DstType, | ||||
|         db: &dyn StorageInterface, | ||||
|         merchant_id: &str, | ||||
|         migration_timestamp: i64, | ||||
|     ) -> CustomResult<Self, ValidationError> { | ||||
|         let key = types::get_merchant_enc_key(db, merchant_id) | ||||
|             .await | ||||
|             .change_context(ValidationError::InvalidValue { | ||||
|                 message: "Error while getting key from keystore".to_string(), | ||||
|             })?; | ||||
|         let modified_at = other.modified_at.assume_utc().unix_timestamp(); | ||||
|  | ||||
|         Ok(Self { | ||||
|             id: Some(other.id), | ||||
| @ -105,9 +103,7 @@ impl behaviour::Conversion for MerchantConnectorAccount { | ||||
|             connector_account_details: Encryptable::decrypt( | ||||
|                 other.connector_account_details, | ||||
|                 &key, | ||||
|                 GcmAes256 {}, | ||||
|                 modified_at, | ||||
|                 migration_timestamp, | ||||
|                 GcmAes256, | ||||
|             ) | ||||
|             .await | ||||
|             .change_context(ValidationError::InvalidValue { | ||||
|  | ||||
| @ -36,14 +36,13 @@ impl super::behaviour::Conversion for MerchantKeyStore { | ||||
|         item: Self::DstType, | ||||
|         db: &dyn StorageInterface, | ||||
|         _merchant_id: &str, | ||||
|         migration_timestamp: i64, | ||||
|     ) -> CustomResult<Self, ValidationError> | ||||
|     where | ||||
|         Self: Sized, | ||||
|     { | ||||
|         let key = &db.get_master_key(); | ||||
|         Ok(Self { | ||||
|             key: Encryptable::decrypt(item.key, key, GcmAes256 {}, i64::MAX, migration_timestamp) | ||||
|             key: Encryptable::decrypt(item.key, key, GcmAes256) | ||||
|                 .await | ||||
|                 .change_context(ValidationError::InvalidValue { | ||||
|                     message: "Failed while decrypting customer data".to_string(), | ||||
|  | ||||
| @ -23,12 +23,11 @@ pub trait TypeEncryption< | ||||
|         key: &[u8], | ||||
|         crypt_algo: V, | ||||
|     ) -> CustomResult<Self, errors::CryptoError>; | ||||
|  | ||||
|     async fn decrypt( | ||||
|         encrypted_data: Encryption, | ||||
|         key: &[u8], | ||||
|         crypt_algo: V, | ||||
|         timestamp: i64, | ||||
|         migration_timestamp: i64, | ||||
|     ) -> CustomResult<Self, errors::CryptoError>; | ||||
| } | ||||
|  | ||||
| @ -54,22 +53,9 @@ impl< | ||||
|         encrypted_data: Encryption, | ||||
|         key: &[u8], | ||||
|         crypt_algo: V, | ||||
|         timestamp: i64, | ||||
|         migration_timestamp: i64, | ||||
|     ) -> CustomResult<Self, errors::CryptoError> { | ||||
|         let encrypted = encrypted_data.into_inner(); | ||||
|  | ||||
|         let (data, encrypted) = if timestamp < migration_timestamp { | ||||
|             ( | ||||
|                 encrypted.clone(), | ||||
|                 crypt_algo.encode_message(key, &encrypted)?, | ||||
|             ) | ||||
|         } else { | ||||
|             ( | ||||
|                 crypt_algo.decode_message(key, encrypted.clone())?, | ||||
|                 encrypted, | ||||
|             ) | ||||
|         }; | ||||
|         let data = crypt_algo.decode_message(key, encrypted.clone())?; | ||||
|  | ||||
|         let value: String = std::str::from_utf8(&data) | ||||
|             .into_report() | ||||
| @ -106,21 +92,9 @@ impl< | ||||
|         encrypted_data: Encryption, | ||||
|         key: &[u8], | ||||
|         crypt_algo: V, | ||||
|         timestamp: i64, | ||||
|         migration_timestamp: i64, | ||||
|     ) -> CustomResult<Self, errors::CryptoError> { | ||||
|         let encrypted = encrypted_data.into_inner(); | ||||
|         let (data, encrypted) = if timestamp < migration_timestamp { | ||||
|             ( | ||||
|                 encrypted.clone(), | ||||
|                 crypt_algo.encode_message(key, &encrypted)?, | ||||
|             ) | ||||
|         } else { | ||||
|             ( | ||||
|                 crypt_algo.decode_message(key, encrypted.clone())?, | ||||
|                 encrypted, | ||||
|             ) | ||||
|         }; | ||||
|         let data = crypt_algo.decode_message(key, encrypted.clone())?; | ||||
|  | ||||
|         let value: serde_json::Value = serde_json::from_slice(&data) | ||||
|             .into_report() | ||||
| @ -152,22 +126,10 @@ impl< | ||||
|         encrypted_data: Encryption, | ||||
|         key: &[u8], | ||||
|         crypt_algo: V, | ||||
|         timestamp: i64, | ||||
|         migration_timestamp: i64, | ||||
|     ) -> CustomResult<Self, errors::CryptoError> { | ||||
|         let encrypted = encrypted_data.into_inner(); | ||||
|         let data = crypt_algo.decode_message(key, encrypted.clone())?; | ||||
|  | ||||
|         let (data, encrypted) = if timestamp < migration_timestamp { | ||||
|             ( | ||||
|                 encrypted.clone(), | ||||
|                 crypt_algo.encode_message(key, &encrypted)?, | ||||
|             ) | ||||
|         } else { | ||||
|             ( | ||||
|                 crypt_algo.decode_message(key, encrypted.clone())?, | ||||
|                 encrypted, | ||||
|             ) | ||||
|         }; | ||||
|         Ok(Self::new(data.into(), encrypted)) | ||||
|     } | ||||
| } | ||||
| @ -241,7 +203,7 @@ where | ||||
|     crypto::Encryptable<Secret<E, S>>: TypeEncryption<E, crypto::GcmAes256, S>, | ||||
| { | ||||
|     request::record_operation_time( | ||||
|         crypto::Encryptable::encrypt(inner, key, crypto::GcmAes256 {}), | ||||
|         crypto::Encryptable::encrypt(inner, key, crypto::GcmAes256), | ||||
|         &ENCRYPTION_TIME, | ||||
|     ) | ||||
|     .await | ||||
| @ -264,22 +226,12 @@ where | ||||
| pub async fn decrypt<T: Clone, S: masking::Strategy<T>>( | ||||
|     inner: Option<Encryption>, | ||||
|     key: &[u8], | ||||
|     timestamp: i64, | ||||
|     migration_timestamp: i64, | ||||
| ) -> CustomResult<Option<crypto::Encryptable<Secret<T, S>>>, errors::CryptoError> | ||||
| where | ||||
|     crypto::Encryptable<Secret<T, S>>: TypeEncryption<T, crypto::GcmAes256, S>, | ||||
| { | ||||
|     request::record_operation_time( | ||||
|         inner.async_map(|item| { | ||||
|             crypto::Encryptable::decrypt( | ||||
|                 item, | ||||
|                 key, | ||||
|                 crypto::GcmAes256 {}, | ||||
|                 timestamp, | ||||
|                 migration_timestamp, | ||||
|             ) | ||||
|         }), | ||||
|         inner.async_map(|item| crypto::Encryptable::decrypt(item, key, crypto::GcmAes256)), | ||||
|         &DECRYPTION_TIME, | ||||
|     ) | ||||
|     .await | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 Sanchith Hegde
					Sanchith Hegde