From 9f2832f60078b98e6faae34b05b63d2dab6b7969 Mon Sep 17 00:00:00 2001 From: Sanchith Hegde <22217505+SanchithHegde@users.noreply.github.com> Date: Mon, 5 Jun 2023 18:18:00 +0530 Subject: [PATCH] refactor(router): remove `pii-encryption-script` feature and use of timestamps for decryption (#1350) --- config/config.example.toml | 1 - config/development.toml | 1 - crates/router/Cargo.toml | 5 +- crates/router/src/bin/router.rs | 18 - crates/router/src/configs/defaults.rs | 1 - crates/router/src/configs/settings.rs | 4 - crates/router/src/core/customers.rs | 4 +- crates/router/src/db.rs | 8 - crates/router/src/db/address.rs | 18 +- crates/router/src/db/customers.rs | 14 +- crates/router/src/db/merchant_account.rs | 17 +- .../src/db/merchant_connector_account.rs | 17 +- crates/router/src/db/merchant_key_store.rs | 5 +- crates/router/src/lib.rs | 1 - crates/router/src/scripts.rs | 2 - crates/router/src/scripts/pii_encryption.rs | 421 ------------------ crates/router/src/services.rs | 2 - crates/router/src/types/domain/address.rs | 5 +- crates/router/src/types/domain/behaviour.rs | 5 +- crates/router/src/types/domain/customer.rs | 9 +- .../src/types/domain/merchant_account.rs | 10 +- .../domain/merchant_connector_account.rs | 6 +- .../src/types/domain/merchant_key_store.rs | 3 +- crates/router/src/types/domain/types.rs | 60 +-- 24 files changed, 52 insertions(+), 585 deletions(-) delete mode 100644 crates/router/src/scripts.rs delete mode 100644 crates/router/src/scripts/pii_encryption.rs diff --git a/config/config.example.toml b/config/config.example.toml index 28113bfb3c..645908ee8d 100644 --- a/config/config.example.toml +++ b/config/config.example.toml @@ -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 diff --git a/config/development.toml b/config/development.toml index 48a476231c..1921e0791e 100644 --- a/config/development.toml +++ b/config/development.toml @@ -32,7 +32,6 @@ connection_timeout = 10 [secrets] admin_api_key = "test_admin" -migration_encryption_timestamp = 1682425530 master_enc_key = "73ad7bbbbc640c845a150f67d058b279849370cd2c1f3c67c4dd6c869213e13a" [locker] diff --git a/crates/router/Cargo.toml b/crates/router/Cargo.toml index 04838e9113..254503f57d 100644 --- a/crates/router/Cargo.toml +++ b/crates/router/Cargo.toml @@ -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"] diff --git a/crates/router/src/bin/router.rs b/crates/router/src/bin/router.rs index de786275ba..02ff2c241e 100644 --- a/crates/router/src/bin/router.rs +++ b/crates/router/src/bin/router.rs @@ -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)] diff --git a/crates/router/src/configs/defaults.rs b/crates/router/src/configs/defaults.rs index 3a3980aac6..fc2cec0546 100644 --- a/crates/router/src/configs/defaults.rs +++ b/crates/router/src/configs/defaults.rs @@ -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, } } } diff --git a/crates/router/src/configs/settings.rs b/crates/router/src/configs/settings.rs index 3b39124e12..4d4f6d66d7 100644 --- a/crates/router/src/configs/settings.rs +++ b/crates/router/src/configs/settings.rs @@ -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)] diff --git a/crates/router/src/core/customers.rs b/crates/router/src/core/customers.rs index 5fc35af9f2..508c4045ab 100644 --- a/crates/router/src/core/customers.rs +++ b/crates/router/src/core/customers.rs @@ -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> = - 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)?, ), diff --git a/crates/router/src/db.rs b/crates/router/src/db.rs index 317e8d34fa..d5f05bfb73 100644 --- a/crates/router/src/db.rs +++ b/crates/router/src/db.rs @@ -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] diff --git a/crates/router/src/db/address.rs b/crates/router/src/db/address.rs index 1e94911bed..8df8b03330 100644 --- a/crates/router/src/db/address.rs +++ b/crates/router/src/db/address.rs @@ -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]) diff --git a/crates/router/src/db/customers.rs b/crates/router/src/db/customers.rs index fe8610a643..130c64508d 100644 --- a/crates/router/src/db/customers.rs +++ b/crates/router/src/db/customers.rs @@ -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) } diff --git a/crates/router/src/db/merchant_account.rs b/crates/router/src/db/merchant_account.rs index 7200ec61b6..b7cade2f2b 100644 --- a/crates/router/src/db/merchant_account.rs +++ b/crates/router/src/db/merchant_account.rs @@ -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) }) diff --git a/crates/router/src/db/merchant_connector_account.rs b/crates/router/src/db/merchant_connector_account.rs index 8bc484f4e5..997cc130c7 100644 --- a/crates/router/src/db/merchant_connector_account.rs +++ b/crates/router/src/db/merchant_connector_account.rs @@ -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) } diff --git a/crates/router/src/db/merchant_key_store.rs b/crates/router/src/db/merchant_key_store.rs index 3e78e8b2b8..b4637af8c0 100644 --- a/crates/router/src/db/merchant_key_store.rs +++ b/crates/router/src/db/merchant_key_store.rs @@ -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) } diff --git a/crates/router/src/lib.rs b/crates/router/src/lib.rs index 67234af661..380448bab7 100644 --- a/crates/router/src/lib.rs +++ b/crates/router/src/lib.rs @@ -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; diff --git a/crates/router/src/scripts.rs b/crates/router/src/scripts.rs deleted file mode 100644 index dc9f789c16..0000000000 --- a/crates/router/src/scripts.rs +++ /dev/null @@ -1,2 +0,0 @@ -#[cfg(feature = "pii-encryption-script")] -pub mod pii_encryption; diff --git a/crates/router/src/scripts/pii_encryption.rs b/crates/router/src/scripts/pii_encryption.rs deleted file mode 100644 index ce71edffb0..0000000000 --- a/crates/router/src/scripts/pii_encryption.rs +++ /dev/null @@ -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, -) -> 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 = generic_filter::< - ::Table, - _, - <::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 = generic_filter::< - ::Table, - _, - <::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 = generic_filter::< - ::Table, - _, - <::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
= generic_filter::< -
::Table, - _, - <
::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 = 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::, 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::( - Some(encrypted_dummy_data), - &types::decrypt::, 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) -} diff --git a/crates/router/src/services.rs b/crates/router/src/services.rs index 1e1bd40db6..957aa026dc 100644 --- a/crates/router/src/services.rs +++ b/crates/router/src/services.rs @@ -119,7 +119,6 @@ pub struct Store { #[cfg(feature = "kv_store")] pub(crate) config: StoreConfig, pub master_key: Vec, - 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, } } diff --git a/crates/router/src/types/domain/address.rs b/crates/router/src/types/domain/address.rs index ed3851ea8f..5ecbafda5d 100644 --- a/crates/router/src/types/domain/address.rs +++ b/crates/router/src/types/domain/address.rs @@ -74,7 +74,6 @@ impl behaviour::Conversion for Address { other: Self::DstType, db: &dyn StorageInterface, merchant_id: &str, - migration_timestamp: i64, ) -> CustomResult { 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, diff --git a/crates/router/src/types/domain/behaviour.rs b/crates/router/src/types/domain/behaviour.rs index 5046622f6d..2f95fe1611 100644 --- a/crates/router/src/types/domain/behaviour.rs +++ b/crates/router/src/types/domain/behaviour.rs @@ -13,7 +13,6 @@ pub trait Conversion { item: Self::DstType, db: &dyn StorageInterface, merchant_id: &str, - migration_timestamp: i64, ) -> CustomResult where Self: Sized; @@ -27,7 +26,6 @@ pub trait ReverseConversion { self, db: &dyn StorageInterface, merchant_id: &str, - migration_timestamp: i64, ) -> CustomResult; } @@ -37,8 +35,7 @@ impl> ReverseConversion for T { self, db: &dyn StorageInterface, merchant_id: &str, - migration_timestamp: i64, ) -> CustomResult { - U::convert_back(self, db, merchant_id, migration_timestamp).await + U::convert_back(self, db, merchant_id).await } } diff --git a/crates/router/src/types/domain/customer.rs b/crates/router/src/types/domain/customer.rs index 060a15928d..03c5c535c2 100644 --- a/crates/router/src/types/domain/customer.rs +++ b/crates/router/src/types/domain/customer.rs @@ -55,7 +55,6 @@ impl super::behaviour::Conversion for Customer { item: Self::DstType, db: &dyn StorageInterface, merchant_id: &str, - migration_timestamp: i64, ) -> CustomResult 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, diff --git a/crates/router/src/types/domain/merchant_account.rs b/crates/router/src/types/domain/merchant_account.rs index 10106b1afe..83ef523767 100644 --- a/crates/router/src/types/domain/merchant_account.rs +++ b/crates/router/src/types/domain/merchant_account.rs @@ -149,7 +149,6 @@ impl super::behaviour::Conversion for MerchantAccount { item: Self::DstType, db: &dyn StorageInterface, merchant_id: &str, - migration_timestamp: i64, ) -> CustomResult 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, diff --git a/crates/router/src/types/domain/merchant_connector_account.rs b/crates/router/src/types/domain/merchant_connector_account.rs index a0a1a8a3e1..9e97b58795 100644 --- a/crates/router/src/types/domain/merchant_connector_account.rs +++ b/crates/router/src/types/domain/merchant_connector_account.rs @@ -89,14 +89,12 @@ impl behaviour::Conversion for MerchantConnectorAccount { other: Self::DstType, db: &dyn StorageInterface, merchant_id: &str, - migration_timestamp: i64, ) -> CustomResult { 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 { diff --git a/crates/router/src/types/domain/merchant_key_store.rs b/crates/router/src/types/domain/merchant_key_store.rs index efe4fb8403..6917261e97 100644 --- a/crates/router/src/types/domain/merchant_key_store.rs +++ b/crates/router/src/types/domain/merchant_key_store.rs @@ -36,14 +36,13 @@ impl super::behaviour::Conversion for MerchantKeyStore { item: Self::DstType, db: &dyn StorageInterface, _merchant_id: &str, - migration_timestamp: i64, ) -> CustomResult 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(), diff --git a/crates/router/src/types/domain/types.rs b/crates/router/src/types/domain/types.rs index aa6b63af06..d159b63164 100644 --- a/crates/router/src/types/domain/types.rs +++ b/crates/router/src/types/domain/types.rs @@ -23,12 +23,11 @@ pub trait TypeEncryption< key: &[u8], crypt_algo: V, ) -> CustomResult; + async fn decrypt( encrypted_data: Encryption, key: &[u8], crypt_algo: V, - timestamp: i64, - migration_timestamp: i64, ) -> CustomResult; } @@ -54,22 +53,9 @@ impl< encrypted_data: Encryption, key: &[u8], crypt_algo: V, - timestamp: i64, - migration_timestamp: i64, ) -> CustomResult { 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 { 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 { 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>: TypeEncryption, { 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>( inner: Option, key: &[u8], - timestamp: i64, - migration_timestamp: i64, ) -> CustomResult>>, errors::CryptoError> where crypto::Encryptable>: TypeEncryption, { 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