From 2185cd38c1ddf08d9dbb7a320b627fc03f0e7026 Mon Sep 17 00:00:00 2001 From: Chethan Rao <70657455+Chethan-rao@users.noreply.github.com> Date: Mon, 26 Feb 2024 19:18:18 +0530 Subject: [PATCH] refactor: incorporate `hyperswitch_interface` into router (#3669) Co-authored-by: Narayan Bhat --- config/config.example.toml | 30 +- config/deployments/env_specific.toml | 31 +- crates/drainer/Cargo.toml | 4 +- crates/drainer/src/main.rs | 3 +- crates/drainer/src/secrets_transformers.rs | 5 +- crates/drainer/src/settings.rs | 2 +- crates/external_services/src/aws_kms.rs | 2 - crates/external_services/src/aws_kms/core.rs | 79 +--- .../external_services/src/aws_kms/decrypt.rs | 29 -- .../external_services/src/hashicorp_vault.rs | 2 - .../src/hashicorp_vault/decrypt.rs | 54 --- .../src/secrets_interface/secret_handler.rs | 2 +- crates/router/Cargo.toml | 5 +- crates/router/src/configs.rs | 9 +- crates/router/src/configs/aws_kms.rs | 110 ------ crates/router/src/configs/defaults.rs | 12 +- crates/router/src/configs/hc_vault.rs | 135 ------- .../src/configs/secrets_transformers.rs | 357 ++++++++++++++++++ crates/router/src/configs/settings.rs | 124 +++--- crates/router/src/configs/validations.rs | 51 +-- crates/router/src/connection.rs | 2 +- crates/router/src/core.rs | 2 +- crates/router/src/core/api_keys.rs | 87 +---- .../router/src/core/blocklist/transformers.rs | 47 +-- .../router/src/core/connector_onboarding.rs | 14 +- .../src/core/connector_onboarding/paypal.rs | 8 +- crates/router/src/core/currency.rs | 15 +- .../router/src/core/payment_methods/cards.rs | 22 +- .../src/core/payment_methods/transformers.rs | 55 +-- .../src/core/payments/flows/session_flow.rs | 145 ++----- crates/router/src/core/payments/helpers.rs | 95 +---- crates/router/src/core/pm_auth.rs | 39 +- crates/router/src/core/utils.rs | 6 +- crates/router/src/core/verification.rs | 41 +- crates/router/src/lib.rs | 5 +- crates/router/src/routes.rs | 4 +- crates/router/src/routes/api_keys.rs | 24 +- crates/router/src/routes/app.rs | 128 ++----- crates/router/src/routes/metrics.rs | 4 - crates/router/src/routes/verification.rs | 3 - crates/router/src/services.rs | 96 +---- crates/router/src/services/api.rs | 2 +- crates/router/src/services/authentication.rs | 142 +------ crates/router/src/services/email/types.rs | 18 +- crates/router/src/services/jwt.rs | 12 +- crates/router/src/services/recon.rs | 2 +- .../src/utils/connector_onboarding/paypal.rs | 3 +- crates/router/src/utils/currency.rs | 217 +---------- 48 files changed, 671 insertions(+), 1613 deletions(-) delete mode 100644 crates/external_services/src/aws_kms/decrypt.rs delete mode 100644 crates/external_services/src/hashicorp_vault/decrypt.rs delete mode 100644 crates/router/src/configs/aws_kms.rs delete mode 100644 crates/router/src/configs/hc_vault.rs create mode 100644 crates/router/src/configs/secrets_transformers.rs diff --git a/config/config.example.toml b/config/config.example.toml index 1a13293343..abe3f6b4e0 100644 --- a/config/config.example.toml +++ b/config/config.example.toml @@ -115,12 +115,9 @@ route_to_trace = ["*/confirm"] # This section provides some secret values. [secrets] master_enc_key = "sample_key" # Master Encryption key used to encrypt merchant wise encryption key. Should be 32-byte long. -admin_api_key = "test_admin" # admin API key for admin authentication. Only applicable when KMS is disabled. -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. -recon_admin_api_key = "recon_test_admin" # recon_admin API key for recon authentication. Only applicable when KMS is disabled. -kms_encrypted_recon_admin_api_key = "" # Base64-encoded (KMS encrypted) ciphertext of the recon_admin_api_key. Only applicable when KMS is enabled +admin_api_key = "test_admin" # admin API key for admin authentication. +jwt_secret = "secret" # JWT secret used for user authentication. +recon_admin_api_key = "recon_test_admin" # recon_admin API key for recon authentication. # Locker settings contain details for accessing a card locker, a # PCI Compliant storage entity which stores payment method information @@ -156,8 +153,6 @@ outgoing_enabled = true validity = 1 [api_keys] -# Base64-encoded (KMS encrypted) ciphertext of the API key hashing key -kms_encrypted_hash_key = "" # Hex-encoded 32-byte long (64 characters long when hex-encoded) key used for calculating hashes of API keys hash_key = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" @@ -322,11 +317,6 @@ paypal = { currency = "USD,INR", country = "US" } # ^------------------------------- any valid payment method type (can be multiple) (for cards this should be card_network) # If either currency or country isn't provided then, all possible values are accepted -# AWS KMS configuration. Only applicable when the `aws_kms` feature flag is enabled. -[kms] -key_id = "" # The AWS key ID used by the KMS SDK for decrypting data. -region = "" # The AWS region used by the KMS SDK for decrypting data. - [cors] max_age = 30 # Maximum time (in seconds) for which this CORS request may be cached. origins = "http://localhost:8080" # List of origins that are allowed to make requests. @@ -568,3 +558,17 @@ file_storage_backend = "aws_s3" # File storage backend to be used [file_storage.aws_s3] region = "us-east-1" # The AWS region used by the AWS S3 for file storage bucket_name = "bucket1" # The AWS S3 bucket name for file storage + +[secrets_management] +secrets_manager = "aws_kms" # Secrets manager client to be used + +[secrets_management.aws_kms] +key_id = "kms_key_id" # The AWS key ID used by the KMS SDK for decrypting data. +region = "kms_region" # The AWS region used by the KMS SDK for decrypting data. + +[encryption_management] +encryption_manager = "aws_kms" # Encryption manager client to be used + +[encryption_management.aws_kms] +key_id = "kms_key_id" # The AWS key ID used by the KMS SDK for decrypting data. +region = "kms_region" # The AWS region used by the KMS SDK for decrypting data. diff --git a/config/deployments/env_specific.toml b/config/deployments/env_specific.toml index 39bf7060b6..c8c118d982 100644 --- a/config/deployments/env_specific.toml +++ b/config/deployments/env_specific.toml @@ -21,8 +21,7 @@ connection_timeout = 10 # Timeout for database connection in seconds queue_strategy = "Fifo" # Add the queue strategy used by the database bb8 client [api_keys] -kms_encrypted_hash_key = "base64_encoded_ciphertext" # Base64-encoded (KMS encrypted) ciphertext of the API key hashing key -hash_key = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" # API key hashing key. Only applicable when KMS is disabled. +hash_key = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" # API key hashing key. [applepay_decrypt_keys] apple_pay_ppc = "APPLE_PAY_PAYMENT_PROCESSING_CERTIFICATE" # Payment Processing Certificate provided by Apple Pay (https://developer.apple.com/) Certificates, Identifiers & Profiles > Apple Pay Payment Processing Certificate @@ -99,11 +98,6 @@ vault_encryption_key = "" # public key in pem format, corresponding privat rust_locker_encryption_key = "" # public key in pem format, corresponding private key in rust locker vault_private_key = "" # private key in pem format, corresponding public key in rust locker -# KMS configuration. Only applicable when the `kms` feature flag is enabled. -[kms] -key_id = "" # The AWS key ID used by the KMS SDK for decrypting data. -region = "" # The AWS region used by the KMS SDK for decrypting data. - # Locker settings contain details for accessing a card locker, a # PCI Compliant storage entity which stores payment method information # like card details @@ -201,12 +195,9 @@ region = "report_download_config_region" # Region of the buc # This section provides some secret values. [secrets] master_enc_key = "sample_key" # Master Encryption key used to encrypt merchant wise encryption key. Should be 32-byte long. -admin_api_key = "test_admin" # admin API key for admin authentication. Only applicable when KMS is disabled. -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. -recon_admin_api_key = "recon_test_admin" # recon_admin API key for recon authentication. Only applicable when KMS is disabled. -kms_encrypted_recon_admin_api_key = "" # Base64-encoded (KMS encrypted) ciphertext of the recon_admin_api_key. Only applicable when KMS is enabled +admin_api_key = "test_admin" # admin API key for admin authentication. +jwt_secret = "secret" # JWT secret used for user authentication. +recon_admin_api_key = "recon_test_admin" # recon_admin API key for recon authentication. # Server configuration [server] @@ -219,3 +210,17 @@ host = "127.0.0.1" shutdown_timeout = 30 # HTTP Request body limit. Defaults to 32kB request_body_limit = 32_768 + +[secrets_management] +secrets_manager = "aws_kms" # Secrets manager client to be used + +[secrets_management.aws_kms] +key_id = "kms_key_id" # The AWS key ID used by the KMS SDK for decrypting data. +region = "kms_region" # The AWS region used by the KMS SDK for decrypting data. + +[encryption_management] +encryption_manager = "aws_kms" # Encryption manager client to be used + +[encryption_management.aws_kms] +key_id = "kms_key_id" # The AWS key ID used by the KMS SDK for decrypting data. +region = "kms_region" # The AWS region used by the KMS SDK for decrypting data. diff --git a/crates/drainer/Cargo.toml b/crates/drainer/Cargo.toml index 725c6a123f..2eea5b513c 100644 --- a/crates/drainer/Cargo.toml +++ b/crates/drainer/Cargo.toml @@ -8,9 +8,7 @@ readme = "README.md" license.workspace = true [features] -release = ["aws_kms", "vergen"] -aws_kms = ["external_services/aws_kms"] -hashicorp-vault = ["external_services/hashicorp-vault"] +release = ["vergen", "external_services/aws_kms"] vergen = ["router_env/vergen"] [dependencies] diff --git a/crates/drainer/src/main.rs b/crates/drainer/src/main.rs index 377fdcd156..64e66619d7 100644 --- a/crates/drainer/src/main.rs +++ b/crates/drainer/src/main.rs @@ -17,8 +17,7 @@ async fn main() -> DrainerResult<()> { let state = settings::AppState::new(conf.clone()).await; - let store = services::Store::new(&state.conf, false).await; - let store = std::sync::Arc::new(store); + let store = std::sync::Arc::new(services::Store::new(&state.conf, false).await); #[cfg(feature = "vergen")] println!("Starting drainer (Version: {})", router_env::git_tag!()); diff --git a/crates/drainer/src/secrets_transformers.rs b/crates/drainer/src/secrets_transformers.rs index c0447725a7..4ffb584a15 100644 --- a/crates/drainer/src/secrets_transformers.rs +++ b/crates/drainer/src/secrets_transformers.rs @@ -11,7 +11,7 @@ use crate::settings::{Database, Settings}; impl SecretsHandler for Database { async fn convert_to_raw_secret( value: SecretStateContainer, - secret_management_client: Box, + secret_management_client: &dyn SecretManagementInterface, ) -> CustomResult, SecretsManagementError> { let secured_db_config = value.get_inner(); let raw_db_password = secret_management_client @@ -28,10 +28,9 @@ impl SecretsHandler for Database { /// # Panics /// /// Will panic even if fetching raw secret fails for at least one config value -#[allow(clippy::unwrap_used)] pub async fn fetch_raw_secrets( conf: Settings, - secret_management_client: Box, + secret_management_client: &dyn SecretManagementInterface, ) -> Settings { #[allow(clippy::expect_used)] let database = Database::convert_to_raw_secret(conf.master_database, secret_management_client) diff --git a/crates/drainer/src/settings.rs b/crates/drainer/src/settings.rs index ec24c472af..e68ede9e8b 100644 --- a/crates/drainer/src/settings.rs +++ b/crates/drainer/src/settings.rs @@ -47,7 +47,7 @@ impl AppState { .expect("Failed to create secret management client"); let raw_conf = - secrets_transformers::fetch_raw_secrets(conf, secret_management_client).await; + secrets_transformers::fetch_raw_secrets(conf, &*secret_management_client).await; #[allow(clippy::expect_used)] let encryption_client = raw_conf diff --git a/crates/external_services/src/aws_kms.rs b/crates/external_services/src/aws_kms.rs index 3e5353fd9e..a01062f26e 100644 --- a/crates/external_services/src/aws_kms.rs +++ b/crates/external_services/src/aws_kms.rs @@ -2,6 +2,4 @@ pub mod core; -pub mod decrypt; - pub mod implementers; diff --git a/crates/external_services/src/aws_kms/core.rs b/crates/external_services/src/aws_kms/core.rs index c01bcbfb09..d211f1def9 100644 --- a/crates/external_services/src/aws_kms/core.rs +++ b/crates/external_services/src/aws_kms/core.rs @@ -7,23 +7,9 @@ use aws_sdk_kms::{config::Region, primitives::Blob, Client}; use base64::Engine; use common_utils::errors::CustomResult; use error_stack::{IntoReport, ResultExt}; -use masking::{PeekInterface, Secret}; use router_env::logger; -#[cfg(feature = "hashicorp-vault")] -use crate::hashicorp_vault; -use crate::{aws_kms::decrypt::AwsKmsDecrypt, consts, metrics}; - -pub(crate) static AWS_KMS_CLIENT: tokio::sync::OnceCell = - tokio::sync::OnceCell::const_new(); - -/// Returns a shared AWS KMS client, or initializes a new one if not previously initialized. -#[inline] -pub async fn get_aws_kms_client(config: &AwsKmsConfig) -> &'static AwsKmsClient { - AWS_KMS_CLIENT - .get_or_init(|| AwsKmsClient::new(config)) - .await -} +use crate::{consts, metrics}; /// Configuration parameters required for constructing a [`AwsKmsClient`]. #[derive(Clone, Debug, Default, serde::Deserialize)] @@ -188,69 +174,6 @@ impl AwsKmsConfig { } } -/// A wrapper around a AWS KMS value that can be decrypted. -#[derive(Clone, Debug, Default, serde::Deserialize, Eq, PartialEq)] -#[serde(transparent)] -pub struct AwsKmsValue(Secret); - -impl common_utils::ext_traits::ConfigExt for AwsKmsValue { - fn is_empty_after_trim(&self) -> bool { - self.0.peek().is_empty_after_trim() - } -} - -impl From for AwsKmsValue { - fn from(value: String) -> Self { - Self(Secret::new(value)) - } -} - -impl From> for AwsKmsValue { - fn from(value: Secret) -> Self { - Self(value) - } -} - -#[cfg(feature = "hashicorp-vault")] -#[async_trait::async_trait] -impl hashicorp_vault::decrypt::VaultFetch for AwsKmsValue { - async fn fetch_inner( - self, - client: &hashicorp_vault::core::HashiCorpVault, - ) -> error_stack::Result - where - for<'a> En: hashicorp_vault::core::Engine< - ReturnType<'a, String> = std::pin::Pin< - Box< - dyn std::future::Future< - Output = error_stack::Result< - String, - hashicorp_vault::core::HashiCorpError, - >, - > + Send - + 'a, - >, - >, - > + 'a, - { - self.0.fetch_inner::(client).await.map(AwsKmsValue) - } -} - -#[async_trait::async_trait] -impl AwsKmsDecrypt for &AwsKmsValue { - type Output = String; - async fn decrypt_inner( - self, - aws_kms_client: &AwsKmsClient, - ) -> CustomResult { - aws_kms_client - .decrypt(self.0.peek()) - .await - .attach_printable("Failed to decrypt AWS KMS value") - } -} - #[cfg(test)] mod tests { #![allow(clippy::expect_used)] diff --git a/crates/external_services/src/aws_kms/decrypt.rs b/crates/external_services/src/aws_kms/decrypt.rs deleted file mode 100644 index 47edb8f958..0000000000 --- a/crates/external_services/src/aws_kms/decrypt.rs +++ /dev/null @@ -1,29 +0,0 @@ -//! Decrypting data using the AWS KMS SDK. -use common_utils::errors::CustomResult; - -use crate::aws_kms::core::{AwsKmsClient, AwsKmsError, AWS_KMS_CLIENT}; - -#[async_trait::async_trait] -/// This trait performs in place decryption of the structure on which this is implemented -pub trait AwsKmsDecrypt { - /// The output type of the decryption - type Output; - /// Decrypts the structure given a AWS KMS client - async fn decrypt_inner( - self, - aws_kms_client: &AwsKmsClient, - ) -> CustomResult - where - Self: Sized; - - /// Tries to use the Singleton client to decrypt the structure - async fn try_decrypt_inner(self) -> CustomResult - where - Self: Sized, - { - let client = AWS_KMS_CLIENT - .get() - .ok_or(AwsKmsError::AwsKmsClientNotInitialized)?; - self.decrypt_inner(client).await - } -} diff --git a/crates/external_services/src/hashicorp_vault.rs b/crates/external_services/src/hashicorp_vault.rs index 5a3ba53968..6bf234ff42 100644 --- a/crates/external_services/src/hashicorp_vault.rs +++ b/crates/external_services/src/hashicorp_vault.rs @@ -2,6 +2,4 @@ pub mod core; -pub mod decrypt; - pub mod implementers; diff --git a/crates/external_services/src/hashicorp_vault/decrypt.rs b/crates/external_services/src/hashicorp_vault/decrypt.rs deleted file mode 100644 index 650b219841..0000000000 --- a/crates/external_services/src/hashicorp_vault/decrypt.rs +++ /dev/null @@ -1,54 +0,0 @@ -//! Utilities for supporting decryption of data - -use std::{future::Future, pin::Pin}; - -use masking::ExposeInterface; - -use crate::hashicorp_vault::core::{Engine, HashiCorpError, HashiCorpVault}; - -/// A trait for types that can be asynchronously fetched and decrypted from HashiCorp Vault. -#[async_trait::async_trait] -pub trait VaultFetch: Sized { - /// Asynchronously decrypts the inner content of the type. - /// - /// # Returns - /// - /// An `Result` representing the decrypted instance if successful, - /// or an `super::HashiCorpError` with details about the encountered error. - /// - async fn fetch_inner( - self, - client: &HashiCorpVault, - ) -> error_stack::Result - where - for<'a> En: Engine< - ReturnType<'a, String> = Pin< - Box< - dyn Future> - + Send - + 'a, - >, - >, - > + 'a; -} - -#[async_trait::async_trait] -impl VaultFetch for masking::Secret { - async fn fetch_inner( - self, - client: &HashiCorpVault, - ) -> error_stack::Result - where - for<'a> En: Engine< - ReturnType<'a, String> = Pin< - Box< - dyn Future> - + Send - + 'a, - >, - >, - > + 'a, - { - client.fetch::(self.expose()).await - } -} diff --git a/crates/hyperswitch_interfaces/src/secrets_interface/secret_handler.rs b/crates/hyperswitch_interfaces/src/secrets_interface/secret_handler.rs index a0915b8de6..d823eba870 100644 --- a/crates/hyperswitch_interfaces/src/secrets_interface/secret_handler.rs +++ b/crates/hyperswitch_interfaces/src/secrets_interface/secret_handler.rs @@ -16,6 +16,6 @@ where /// Construct `Self` with raw secret value and transitions its type from `SecuredSecret` to `RawSecret` async fn convert_to_raw_secret( value: SecretStateContainer, - kms_client: Box, + kms_client: &dyn SecretManagementInterface, ) -> CustomResult, SecretsManagementError>; } diff --git a/crates/router/Cargo.toml b/crates/router/Cargo.toml index c511947cd1..5dbeb1bb19 100644 --- a/crates/router/Cargo.toml +++ b/crates/router/Cargo.toml @@ -10,13 +10,10 @@ license.workspace = true [features] default = ["kv_store", "stripe", "oltp", "olap", "backwards_compatibility", "accounts_cache", "dummy_connector", "payouts", "business_profile_routing", "connector_choice_mca_id", "profile_specific_fallback_routing", "retry", "frm"] -aws_s3 = ["external_services/aws_s3"] -aws_kms = ["external_services/aws_kms"] -hashicorp-vault = ["external_services/hashicorp-vault"] email = ["external_services/email", "scheduler/email", "olap"] frm = [] stripe = ["dep:serde_qs"] -release = ["aws_kms", "stripe", "aws_s3", "email", "backwards_compatibility", "business_profile_routing", "accounts_cache", "kv_store", "connector_choice_mca_id", "profile_specific_fallback_routing", "vergen", "recon"] +release = ["stripe", "email", "backwards_compatibility", "business_profile_routing", "accounts_cache", "kv_store", "connector_choice_mca_id", "profile_specific_fallback_routing", "vergen", "recon", "external_services/aws_kms", "external_services/aws_s3"] olap = ["data_models/olap", "storage_impl/olap", "scheduler/olap", "api_models/olap", "dep:analytics"] oltp = ["storage_impl/oltp"] kv_store = ["scheduler/kv_store"] diff --git a/crates/router/src/configs.rs b/crates/router/src/configs.rs index d069c89b82..f7514a312a 100644 --- a/crates/router/src/configs.rs +++ b/crates/router/src/configs.rs @@ -1,7 +1,8 @@ -#[cfg(feature = "aws_kms")] -pub mod aws_kms; +use hyperswitch_interfaces::secrets_interface::secret_state::RawSecret; + mod defaults; -#[cfg(feature = "hashicorp-vault")] -pub mod hc_vault; +pub mod secrets_transformers; pub mod settings; mod validations; + +pub type Settings = settings::Settings; diff --git a/crates/router/src/configs/aws_kms.rs b/crates/router/src/configs/aws_kms.rs deleted file mode 100644 index 9bb5fcc6f2..0000000000 --- a/crates/router/src/configs/aws_kms.rs +++ /dev/null @@ -1,110 +0,0 @@ -use common_utils::errors::CustomResult; -use external_services::aws_kms::{ - core::{AwsKmsClient, AwsKmsError}, - decrypt::AwsKmsDecrypt, -}; -use masking::ExposeInterface; - -use crate::configs::settings; - -#[async_trait::async_trait] -impl AwsKmsDecrypt for settings::Jwekey { - type Output = Self; - - async fn decrypt_inner( - mut self, - aws_kms_client: &AwsKmsClient, - ) -> CustomResult { - ( - self.vault_encryption_key, - self.rust_locker_encryption_key, - self.vault_private_key, - self.tunnel_private_key, - ) = tokio::try_join!( - aws_kms_client.decrypt(self.vault_encryption_key), - aws_kms_client.decrypt(self.rust_locker_encryption_key), - aws_kms_client.decrypt(self.vault_private_key), - aws_kms_client.decrypt(self.tunnel_private_key), - )?; - Ok(self) - } -} - -#[async_trait::async_trait] -impl AwsKmsDecrypt for settings::ActiveKmsSecrets { - type Output = Self; - async fn decrypt_inner( - mut self, - aws_kms_client: &AwsKmsClient, - ) -> CustomResult { - self.jwekey = self - .jwekey - .expose() - .decrypt_inner(aws_kms_client) - .await? - .into(); - Ok(self) - } -} - -#[async_trait::async_trait] -impl AwsKmsDecrypt for settings::Database { - type Output = storage_impl::config::Database; - - async fn decrypt_inner( - mut self, - aws_kms_client: &AwsKmsClient, - ) -> CustomResult { - Ok(storage_impl::config::Database { - host: self.host, - port: self.port, - dbname: self.dbname, - username: self.username, - password: self.password.decrypt_inner(aws_kms_client).await?.into(), - pool_size: self.pool_size, - connection_timeout: self.connection_timeout, - queue_strategy: self.queue_strategy, - min_idle: self.min_idle, - max_lifetime: self.max_lifetime, - }) - } -} - -#[cfg(feature = "olap")] -#[async_trait::async_trait] -impl AwsKmsDecrypt for settings::PayPalOnboarding { - type Output = Self; - - async fn decrypt_inner( - mut self, - aws_kms_client: &AwsKmsClient, - ) -> CustomResult { - self.client_id = aws_kms_client - .decrypt(self.client_id.expose()) - .await? - .into(); - self.client_secret = aws_kms_client - .decrypt(self.client_secret.expose()) - .await? - .into(); - self.partner_id = aws_kms_client - .decrypt(self.partner_id.expose()) - .await? - .into(); - Ok(self) - } -} - -#[cfg(feature = "olap")] -#[async_trait::async_trait] -impl AwsKmsDecrypt for settings::ConnectorOnboarding { - type Output = Self; - - async fn decrypt_inner( - mut self, - aws_kms_client: &AwsKmsClient, - ) -> CustomResult { - self.paypal = self.paypal.decrypt_inner(aws_kms_client).await?; - Ok(self) - } -} diff --git a/crates/router/src/configs/defaults.rs b/crates/router/src/configs/defaults.rs index e56acde78c..5c2d62b40b 100644 --- a/crates/router/src/configs/defaults.rs +++ b/crates/router/src/configs/defaults.rs @@ -1,10 +1,8 @@ use std::collections::{HashMap, HashSet}; use api_models::{enums, payment_methods::RequiredFieldInfo}; -#[cfg(feature = "aws_kms")] -use external_services::aws_kms::core::AwsKmsValue; -use super::settings::{ConnectorFields, Password, PaymentMethodType, RequiredFieldFinal}; +use super::settings::{ConnectorFields, PaymentMethodType, RequiredFieldFinal}; impl Default for super::settings::Server { fn default() -> Self { @@ -37,7 +35,7 @@ impl Default for super::settings::Database { fn default() -> Self { Self { username: String::new(), - password: Password::default(), + password: String::new().into(), host: "localhost".into(), port: 5432, dbname: String::new(), @@ -6518,13 +6516,9 @@ impl Default for super::settings::RequiredFields { impl Default for super::settings::ApiKeys { fn default() -> Self { Self { - #[cfg(feature = "aws_kms")] - kms_encrypted_hash_key: AwsKmsValue::default(), - // Hex-encoded 32-byte long (64 characters long when hex-encoded) key used for calculating // hashes of API keys - #[cfg(not(feature = "aws_kms"))] - hash_key: String::new(), + hash_key: String::new().into(), // Specifies the number of days before API key expiry when email reminders should be sent #[cfg(feature = "email")] diff --git a/crates/router/src/configs/hc_vault.rs b/crates/router/src/configs/hc_vault.rs deleted file mode 100644 index fa6596f749..0000000000 --- a/crates/router/src/configs/hc_vault.rs +++ /dev/null @@ -1,135 +0,0 @@ -use external_services::hashicorp_vault::{ - core::{Engine, HashiCorpError, HashiCorpVault}, - decrypt::VaultFetch, -}; -use masking::ExposeInterface; - -use crate::configs::settings; - -#[async_trait::async_trait] -impl VaultFetch for settings::Jwekey { - async fn fetch_inner( - mut self, - client: &HashiCorpVault, - ) -> error_stack::Result - where - for<'a> En: Engine< - ReturnType<'a, String> = std::pin::Pin< - Box< - dyn std::future::Future< - Output = error_stack::Result, - > + Send - + 'a, - >, - >, - > + 'a, - { - ( - self.vault_encryption_key, - self.rust_locker_encryption_key, - self.vault_private_key, - self.tunnel_private_key, - ) = ( - masking::Secret::new(self.vault_encryption_key) - .fetch_inner::(client) - .await? - .expose(), - masking::Secret::new(self.rust_locker_encryption_key) - .fetch_inner::(client) - .await? - .expose(), - masking::Secret::new(self.vault_private_key) - .fetch_inner::(client) - .await? - .expose(), - masking::Secret::new(self.tunnel_private_key) - .fetch_inner::(client) - .await? - .expose(), - ); - Ok(self) - } -} - -#[async_trait::async_trait] -impl VaultFetch for settings::Database { - async fn fetch_inner( - mut self, - client: &HashiCorpVault, - ) -> error_stack::Result - where - for<'a> En: Engine< - ReturnType<'a, String> = std::pin::Pin< - Box< - dyn std::future::Future< - Output = error_stack::Result, - > + Send - + 'a, - >, - >, - > + 'a, - { - Ok(Self { - host: self.host, - port: self.port, - dbname: self.dbname, - username: self.username, - password: self.password.fetch_inner::(client).await?, - pool_size: self.pool_size, - connection_timeout: self.connection_timeout, - queue_strategy: self.queue_strategy, - min_idle: self.min_idle, - max_lifetime: self.max_lifetime, - }) - } -} - -#[cfg(feature = "olap")] -#[async_trait::async_trait] -impl VaultFetch for settings::PayPalOnboarding { - async fn fetch_inner( - mut self, - client: &HashiCorpVault, - ) -> error_stack::Result - where - for<'a> En: Engine< - ReturnType<'a, String> = std::pin::Pin< - Box< - dyn std::future::Future< - Output = error_stack::Result, - > + Send - + 'a, - >, - >, - > + 'a, - { - self.client_id = self.client_id.fetch_inner::(client).await?; - self.client_secret = self.client_secret.fetch_inner::(client).await?; - self.partner_id = self.partner_id.fetch_inner::(client).await?; - Ok(self) - } -} - -#[cfg(feature = "olap")] -#[async_trait::async_trait] -impl VaultFetch for settings::ConnectorOnboarding { - async fn fetch_inner( - mut self, - client: &HashiCorpVault, - ) -> error_stack::Result - where - for<'a> En: Engine< - ReturnType<'a, String> = std::pin::Pin< - Box< - dyn std::future::Future< - Output = error_stack::Result, - > + Send - + 'a, - >, - >, - > + 'a, - { - self.paypal = self.paypal.fetch_inner::(client).await?; - Ok(self) - } -} diff --git a/crates/router/src/configs/secrets_transformers.rs b/crates/router/src/configs/secrets_transformers.rs new file mode 100644 index 0000000000..1306cdd80b --- /dev/null +++ b/crates/router/src/configs/secrets_transformers.rs @@ -0,0 +1,357 @@ +use common_utils::errors::CustomResult; +use hyperswitch_interfaces::secrets_interface::{ + secret_handler::SecretsHandler, + secret_state::{RawSecret, SecretStateContainer, SecuredSecret}, + SecretManagementInterface, SecretsManagementError, +}; + +use crate::settings::{self, Settings}; + +#[async_trait::async_trait] +impl SecretsHandler for settings::Database { + async fn convert_to_raw_secret( + value: SecretStateContainer, + secret_management_client: &dyn SecretManagementInterface, + ) -> CustomResult, SecretsManagementError> { + let db = value.get_inner(); + let db_password = secret_management_client + .get_secret(db.password.clone()) + .await?; + + Ok(value.transition_state(|db| Self { + password: db_password, + ..db + })) + } +} + +#[async_trait::async_trait] +impl SecretsHandler for settings::Jwekey { + async fn convert_to_raw_secret( + value: SecretStateContainer, + secret_management_client: &dyn SecretManagementInterface, + ) -> CustomResult, SecretsManagementError> { + let jwekey = value.get_inner(); + let ( + vault_encryption_key, + rust_locker_encryption_key, + vault_private_key, + tunnel_private_key, + ) = tokio::try_join!( + secret_management_client.get_secret(jwekey.vault_encryption_key.clone()), + secret_management_client.get_secret(jwekey.rust_locker_encryption_key.clone()), + secret_management_client.get_secret(jwekey.vault_private_key.clone()), + secret_management_client.get_secret(jwekey.tunnel_private_key.clone()) + )?; + Ok(value.transition_state(|_| Self { + vault_encryption_key, + rust_locker_encryption_key, + vault_private_key, + tunnel_private_key, + })) + } +} + +#[cfg(feature = "olap")] +#[async_trait::async_trait] +impl SecretsHandler for settings::ConnectorOnboarding { + async fn convert_to_raw_secret( + value: SecretStateContainer, + secret_management_client: &dyn SecretManagementInterface, + ) -> CustomResult, SecretsManagementError> { + let onboarding_config = &value.get_inner().paypal; + + let (client_id, client_secret, partner_id) = tokio::try_join!( + secret_management_client.get_secret(onboarding_config.client_id.clone()), + secret_management_client.get_secret(onboarding_config.client_secret.clone()), + secret_management_client.get_secret(onboarding_config.partner_id.clone()) + )?; + + Ok(value.transition_state(|onboarding_config| Self { + paypal: settings::PayPalOnboarding { + client_id, + client_secret, + partner_id, + ..onboarding_config.paypal + }, + })) + } +} + +#[async_trait::async_trait] +impl SecretsHandler for settings::ForexApi { + async fn convert_to_raw_secret( + value: SecretStateContainer, + secret_management_client: &dyn SecretManagementInterface, + ) -> CustomResult, SecretsManagementError> { + let forex_api = value.get_inner(); + + let (api_key, fallback_api_key) = tokio::try_join!( + secret_management_client.get_secret(forex_api.api_key.clone()), + secret_management_client.get_secret(forex_api.fallback_api_key.clone()), + )?; + + Ok(value.transition_state(|forex_api| Self { + api_key, + fallback_api_key, + ..forex_api + })) + } +} + +#[async_trait::async_trait] +impl SecretsHandler for settings::ApiKeys { + async fn convert_to_raw_secret( + value: SecretStateContainer, + secret_management_client: &dyn SecretManagementInterface, + ) -> CustomResult, SecretsManagementError> { + let api_keys = value.get_inner(); + + let hash_key = secret_management_client + .get_secret(api_keys.hash_key.clone()) + .await?; + + #[cfg(feature = "email")] + let expiry_reminder_days = api_keys.expiry_reminder_days.clone(); + + Ok(value.transition_state(|_| Self { + hash_key, + #[cfg(feature = "email")] + expiry_reminder_days, + })) + } +} + +#[async_trait::async_trait] +impl SecretsHandler for settings::ApplePayDecryptConifg { + async fn convert_to_raw_secret( + value: SecretStateContainer, + secret_management_client: &dyn SecretManagementInterface, + ) -> CustomResult, SecretsManagementError> { + let applepay_decrypt_keys = value.get_inner(); + + let ( + apple_pay_ppc, + apple_pay_ppc_key, + apple_pay_merchant_cert, + apple_pay_merchant_cert_key, + ) = tokio::try_join!( + secret_management_client.get_secret(applepay_decrypt_keys.apple_pay_ppc.clone()), + secret_management_client.get_secret(applepay_decrypt_keys.apple_pay_ppc_key.clone()), + secret_management_client + .get_secret(applepay_decrypt_keys.apple_pay_merchant_cert.clone()), + secret_management_client + .get_secret(applepay_decrypt_keys.apple_pay_merchant_cert_key.clone()), + )?; + + Ok(value.transition_state(|_| Self { + apple_pay_ppc, + apple_pay_ppc_key, + apple_pay_merchant_cert, + apple_pay_merchant_cert_key, + })) + } +} + +#[async_trait::async_trait] +impl SecretsHandler for settings::ApplepayMerchantConfigs { + async fn convert_to_raw_secret( + value: SecretStateContainer, + secret_management_client: &dyn SecretManagementInterface, + ) -> CustomResult, SecretsManagementError> { + let applepay_merchant_configs = value.get_inner(); + + let (merchant_cert, merchant_cert_key, common_merchant_identifier) = tokio::try_join!( + secret_management_client.get_secret(applepay_merchant_configs.merchant_cert.clone()), + secret_management_client + .get_secret(applepay_merchant_configs.merchant_cert_key.clone()), + secret_management_client + .get_secret(applepay_merchant_configs.common_merchant_identifier.clone()), + )?; + + Ok(value.transition_state(|applepay_merchant_configs| Self { + merchant_cert, + merchant_cert_key, + common_merchant_identifier, + ..applepay_merchant_configs + })) + } +} + +#[async_trait::async_trait] +impl SecretsHandler for settings::PaymentMethodAuth { + async fn convert_to_raw_secret( + value: SecretStateContainer, + secret_management_client: &dyn SecretManagementInterface, + ) -> CustomResult, SecretsManagementError> { + let payment_method_auth = value.get_inner(); + + let pm_auth_key = secret_management_client + .get_secret(payment_method_auth.pm_auth_key.clone()) + .await?; + + Ok(value.transition_state(|payment_method_auth| Self { + pm_auth_key, + ..payment_method_auth + })) + } +} + +#[async_trait::async_trait] +impl SecretsHandler for settings::Secrets { + async fn convert_to_raw_secret( + value: SecretStateContainer, + secret_management_client: &dyn SecretManagementInterface, + ) -> CustomResult, SecretsManagementError> { + let secrets = value.get_inner(); + let (jwt_secret, admin_api_key, recon_admin_api_key, master_enc_key) = tokio::try_join!( + secret_management_client.get_secret(secrets.jwt_secret.clone()), + secret_management_client.get_secret(secrets.admin_api_key.clone()), + secret_management_client.get_secret(secrets.recon_admin_api_key.clone()), + secret_management_client.get_secret(secrets.master_enc_key.clone()) + )?; + + Ok(value.transition_state(|_| Self { + jwt_secret, + admin_api_key, + recon_admin_api_key, + master_enc_key, + })) + } +} + +/// # Panics +/// +/// Will panic even if kms decryption fails for at least one field +pub(crate) async fn fetch_raw_secrets( + conf: Settings, + secret_management_client: &dyn SecretManagementInterface, +) -> Settings { + #[allow(clippy::expect_used)] + let master_database = + settings::Database::convert_to_raw_secret(conf.master_database, secret_management_client) + .await + .expect("Failed to decrypt master database configuration"); + + #[cfg(feature = "olap")] + #[allow(clippy::expect_used)] + let replica_database = + settings::Database::convert_to_raw_secret(conf.replica_database, secret_management_client) + .await + .expect("Failed to decrypt replica database configuration"); + + #[allow(clippy::expect_used)] + let secrets = settings::Secrets::convert_to_raw_secret(conf.secrets, secret_management_client) + .await + .expect("Failed to decrypt secrets"); + + #[allow(clippy::expect_used)] + let forex_api = + settings::ForexApi::convert_to_raw_secret(conf.forex_api, secret_management_client) + .await + .expect("Failed to decrypt forex api configs"); + + #[allow(clippy::expect_used)] + let jwekey = settings::Jwekey::convert_to_raw_secret(conf.jwekey, secret_management_client) + .await + .expect("Failed to decrypt jwekey configs"); + + #[allow(clippy::expect_used)] + let api_keys = + settings::ApiKeys::convert_to_raw_secret(conf.api_keys, secret_management_client) + .await + .expect("Failed to decrypt api_keys configs"); + + #[cfg(feature = "olap")] + #[allow(clippy::expect_used)] + let connector_onboarding = settings::ConnectorOnboarding::convert_to_raw_secret( + conf.connector_onboarding, + secret_management_client, + ) + .await + .expect("Failed to decrypt connector_onboarding configs"); + + #[allow(clippy::expect_used)] + let applepay_decrypt_keys = settings::ApplePayDecryptConifg::convert_to_raw_secret( + conf.applepay_decrypt_keys, + secret_management_client, + ) + .await + .expect("Failed to decrypt applepay decrypt configs"); + + #[allow(clippy::expect_used)] + let applepay_merchant_configs = settings::ApplepayMerchantConfigs::convert_to_raw_secret( + conf.applepay_merchant_configs, + secret_management_client, + ) + .await + .expect("Failed to decrypt applepay merchant configs"); + + #[allow(clippy::expect_used)] + let payment_method_auth = settings::PaymentMethodAuth::convert_to_raw_secret( + conf.payment_method_auth, + secret_management_client, + ) + .await + .expect("Failed to decrypt payment method auth configs"); + + Settings { + server: conf.server, + master_database, + redis: conf.redis, + log: conf.log, + #[cfg(feature = "kv_store")] + drainer: conf.drainer, + encryption_management: conf.encryption_management, + secrets_management: conf.secrets_management, + proxy: conf.proxy, + env: conf.env, + #[cfg(feature = "olap")] + replica_database, + secrets, + locker: conf.locker, + connectors: conf.connectors, + forex_api, + refund: conf.refund, + eph_key: conf.eph_key, + scheduler: conf.scheduler, + jwekey, + webhooks: conf.webhooks, + pm_filters: conf.pm_filters, + bank_config: conf.bank_config, + api_keys, + file_storage: conf.file_storage, + tokenization: conf.tokenization, + connector_customer: conf.connector_customer, + #[cfg(feature = "dummy_connector")] + dummy_connector: conf.dummy_connector, + #[cfg(feature = "email")] + email: conf.email, + mandates: conf.mandates, + required_fields: conf.required_fields, + delayed_session_response: conf.delayed_session_response, + webhook_source_verification_call: conf.webhook_source_verification_call, + payment_method_auth, + connector_request_reference_id_config: conf.connector_request_reference_id_config, + #[cfg(feature = "payouts")] + payouts: conf.payouts, + applepay_decrypt_keys, + multiple_api_version_supported_connectors: conf.multiple_api_version_supported_connectors, + applepay_merchant_configs, + lock_settings: conf.lock_settings, + temp_locker_enable_config: conf.temp_locker_enable_config, + payment_link: conf.payment_link, + #[cfg(feature = "olap")] + analytics: conf.analytics, + #[cfg(feature = "kv_store")] + kv_config: conf.kv_config, + #[cfg(feature = "frm")] + frm: conf.frm, + #[cfg(feature = "olap")] + report_download_config: conf.report_download_config, + events: conf.events, + #[cfg(feature = "olap")] + connector_onboarding, + cors: conf.cors, + } +} diff --git a/crates/router/src/configs/settings.rs b/crates/router/src/configs/settings.rs index 8ed2daef5f..8fb55491fe 100644 --- a/crates/router/src/configs/settings.rs +++ b/crates/router/src/configs/settings.rs @@ -8,12 +8,8 @@ use analytics::ReportConfig; use api_models::{enums, payment_methods::RequiredFieldInfo}; use common_utils::ext_traits::ConfigExt; use config::{Environment, File}; -#[cfg(feature = "aws_kms")] -use external_services::aws_kms; #[cfg(feature = "email")] use external_services::email::EmailSettings; -#[cfg(feature = "hashicorp-vault")] -use external_services::hashicorp_vault; use external_services::{ file_storage::FileStorageConfig, managers::{ @@ -21,6 +17,10 @@ use external_services::{ secrets_management::SecretsManagementConfig, }, }; +use hyperswitch_interfaces::secrets_interface::secret_state::{ + SecretState, SecretStateContainer, SecuredSecret, +}; +use masking::Secret; use redis_interface::RedisSettings; pub use router_env::config::{Log, LogConsole, LogFile, LogTelemetry}; use rust_decimal::Decimal; @@ -35,10 +35,6 @@ use crate::{ env::{self, logger, Env}, events::EventsConfig, }; -#[cfg(feature = "aws_kms")] -pub type Password = aws_kms::core::AwsKmsValue; -#[cfg(not(feature = "aws_kms"))] -pub type Password = masking::Secret; #[derive(clap::Parser, Default)] #[cfg_attr(feature = "vergen", command(version = router_env::version!()))] @@ -59,48 +55,34 @@ pub enum Subcommand { GenerateOpenapiSpec, } -#[cfg(feature = "aws_kms")] -/// Store the decrypted aws kms secret values for active use in the application -/// Currently using `StrongSecret` won't have any effect as this struct have smart pointers to heap -/// allocations. -/// note: we can consider adding such behaviour in the future with custom implementation -#[derive(Clone)] -pub struct ActiveKmsSecrets { - pub jwekey: masking::Secret, -} - #[derive(Debug, Deserialize, Clone, Default)] #[serde(default)] -pub struct Settings { +pub struct Settings { pub server: Server, pub proxy: Proxy, pub env: Env, - pub master_database: Database, + pub master_database: SecretStateContainer, #[cfg(feature = "olap")] - pub replica_database: Database, + pub replica_database: SecretStateContainer, pub redis: RedisSettings, pub log: Log, - pub secrets: Secrets, + pub secrets: SecretStateContainer, pub locker: Locker, pub connectors: Connectors, - pub forex_api: ForexApi, + pub forex_api: SecretStateContainer, pub refund: Refund, pub eph_key: EphemeralConfig, pub scheduler: Option, #[cfg(feature = "kv_store")] pub drainer: DrainerSettings, - pub jwekey: Jwekey, + pub jwekey: SecretStateContainer, pub webhooks: WebhooksSettings, pub pm_filters: ConnectorFilters, pub bank_config: BankRedirectConfig, - pub api_keys: ApiKeys, - #[cfg(feature = "aws_kms")] - pub kms: aws_kms::core::AwsKmsConfig, + pub api_keys: SecretStateContainer, pub file_storage: FileStorageConfig, pub encryption_management: EncryptionManagementConfig, pub secrets_management: SecretsManagementConfig, - #[cfg(feature = "hashicorp-vault")] - pub hc_vault: hashicorp_vault::core::HashiCorpVaultConfig, pub tokenization: TokenizationConfig, pub connector_customer: ConnectorCustomer, #[cfg(feature = "dummy_connector")] @@ -112,13 +94,13 @@ pub struct Settings { pub required_fields: RequiredFields, pub delayed_session_response: DelayedSessionConfig, pub webhook_source_verification_call: WebhookSourceVerificationCall, - pub payment_method_auth: PaymentMethodAuth, + pub payment_method_auth: SecretStateContainer, pub connector_request_reference_id_config: ConnectorRequestReferenceIdConfig, #[cfg(feature = "payouts")] pub payouts: Payouts, - pub applepay_decrypt_keys: ApplePayDecryptConifg, + pub applepay_decrypt_keys: SecretStateContainer, pub multiple_api_version_supported_connectors: MultipleApiVersionSupportedConnectors, - pub applepay_merchant_configs: ApplepayMerchantConfigs, + pub applepay_merchant_configs: SecretStateContainer, pub lock_settings: LockSettings, pub temp_locker_enable_config: TempLockerEnableConfig, pub payment_link: PaymentLink, @@ -132,7 +114,7 @@ pub struct Settings { pub report_download_config: ReportConfig, pub events: EventsConfig, #[cfg(feature = "olap")] - pub connector_onboarding: ConnectorOnboarding, + pub connector_onboarding: SecretStateContainer, } #[cfg(feature = "frm")] @@ -155,8 +137,8 @@ pub struct PaymentLink { #[serde(default)] pub struct ForexApi { pub local_fetch_retry_count: u64, - pub api_key: masking::Secret, - pub fallback_api_key: masking::Secret, + pub api_key: Secret, + pub fallback_api_key: Secret, /// in ms pub call_delay: i64, /// in ms @@ -170,7 +152,7 @@ pub struct ForexApi { #[derive(Debug, Deserialize, Clone, Default)] pub struct PaymentMethodAuth { pub redis_expiry: i64, - pub pm_auth_key: String, + pub pm_auth_key: Secret, } #[derive(Debug, Deserialize, Clone, Default)] @@ -191,9 +173,9 @@ pub struct Conversion { #[derive(Debug, Deserialize, Clone, Default)] #[serde(default)] pub struct ApplepayMerchantConfigs { - pub merchant_cert: String, - pub merchant_cert_key: String, - pub common_merchant_identifier: String, + pub merchant_cert: Secret, + pub merchant_cert_key: Secret, + pub common_merchant_identifier: Secret, pub applepay_endpoint: String, } @@ -380,19 +362,10 @@ pub struct RequiredFieldFinal { #[derive(Debug, Default, Deserialize, Clone)] #[serde(default)] pub struct Secrets { - #[cfg(not(feature = "aws_kms"))] - pub jwt_secret: String, - #[cfg(not(feature = "aws_kms"))] - pub admin_api_key: String, - #[cfg(not(feature = "aws_kms"))] - pub recon_admin_api_key: String, - pub master_enc_key: Password, - #[cfg(feature = "aws_kms")] - pub kms_encrypted_jwt_secret: aws_kms::core::AwsKmsValue, - #[cfg(feature = "aws_kms")] - pub kms_encrypted_admin_api_key: aws_kms::core::AwsKmsValue, - #[cfg(feature = "aws_kms")] - pub kms_encrypted_recon_admin_api_key: aws_kms::core::AwsKmsValue, + pub jwt_secret: Secret, + pub admin_api_key: Secret, + pub recon_admin_api_key: Secret, + pub master_enc_key: Secret, } #[derive(Debug, Deserialize, Clone)] @@ -422,10 +395,10 @@ pub struct EphemeralConfig { #[derive(Debug, Deserialize, Clone, Default)] #[serde(default)] pub struct Jwekey { - pub vault_encryption_key: String, - pub rust_locker_encryption_key: String, - pub vault_private_key: String, - pub tunnel_private_key: String, + pub vault_encryption_key: Secret, + pub rust_locker_encryption_key: Secret, + pub vault_private_key: Secret, + pub tunnel_private_key: Secret, } #[derive(Debug, Deserialize, Clone)] @@ -451,7 +424,7 @@ pub struct Server { #[serde(default)] pub struct Database { pub username: String, - pub password: Password, + pub password: Secret, pub host: String, pub port: u16, pub dbname: String, @@ -462,7 +435,6 @@ pub struct Database { pub max_lifetime: Option, } -#[cfg(not(feature = "aws_kms"))] impl From for storage_impl::config::Database { fn from(val: Database) -> Self { Self { @@ -615,15 +587,9 @@ pub struct WebhookIgnoreErrorSettings { #[derive(Debug, Deserialize, Clone)] #[serde(default)] pub struct ApiKeys { - /// Base64-encoded (KMS encrypted) ciphertext of the key used for calculating hashes of API - /// keys - #[cfg(feature = "aws_kms")] - pub kms_encrypted_hash_key: aws_kms::core::AwsKmsValue, - /// Hex-encoded 32-byte long (64 characters long when hex-encoded) key used for calculating /// hashes of API keys - #[cfg(not(feature = "aws_kms"))] - pub hash_key: String, + pub hash_key: Secret, // Specifies the number of days before API key expiry when email reminders should be sent #[cfg(feature = "email")] @@ -644,10 +610,10 @@ pub struct WebhookSourceVerificationCall { #[derive(Debug, Deserialize, Clone, Default)] pub struct ApplePayDecryptConifg { - pub apple_pay_ppc: String, - pub apple_pay_ppc_key: String, - pub apple_pay_merchant_cert: String, - pub apple_pay_merchant_cert_key: String, + pub apple_pay_ppc: Secret, + pub apple_pay_ppc_key: Secret, + pub apple_pay_merchant_cert: Secret, + pub apple_pay_merchant_cert_key: Secret, } #[derive(Debug, Deserialize, Clone, Default)] @@ -655,7 +621,7 @@ pub struct ConnectorRequestReferenceIdConfig { pub merchant_ids_send_payment_id_as_connector_request_id: HashSet, } -impl Settings { +impl Settings { pub fn new() -> ApplicationResult { Self::with_config_path(None) } @@ -702,9 +668,9 @@ impl Settings { pub fn validate(&self) -> ApplicationResult<()> { self.server.validate()?; - self.master_database.validate()?; + self.master_database.get_inner().validate()?; #[cfg(feature = "olap")] - self.replica_database.validate()?; + self.replica_database.get_inner().validate()?; self.redis.validate().map_err(|error| { println!("{error}"); ApplicationError::InvalidConfigurationValueError("Redis configuration".into()) @@ -722,7 +688,7 @@ impl Settings { )); } } - self.secrets.validate()?; + self.secrets.get_inner().validate()?; self.locker.validate()?; self.connectors.validate("connectors")?; @@ -734,11 +700,7 @@ impl Settings { .transpose()?; #[cfg(feature = "kv_store")] self.drainer.validate()?; - self.api_keys.validate()?; - #[cfg(feature = "aws_kms")] - self.kms - .validate() - .map_err(|error| ApplicationError::InvalidConfigurationValueError(error.into()))?; + self.api_keys.get_inner().validate()?; self.file_storage .validate() @@ -802,9 +764,9 @@ pub struct ConnectorOnboarding { #[cfg(feature = "olap")] #[derive(Debug, Deserialize, Clone, Default)] pub struct PayPalOnboarding { - pub client_id: masking::Secret, - pub client_secret: masking::Secret, - pub partner_id: masking::Secret, + pub client_id: Secret, + pub client_secret: Secret, + pub partner_id: Secret, pub enabled: bool, } diff --git a/crates/router/src/configs/validations.rs b/crates/router/src/configs/validations.rs index 851b7ba757..f3118cf840 100644 --- a/crates/router/src/configs/validations.rs +++ b/crates/router/src/configs/validations.rs @@ -1,42 +1,23 @@ use common_utils::ext_traits::ConfigExt; +use masking::PeekInterface; use storage_impl::errors::ApplicationError; impl super::settings::Secrets { pub fn validate(&self) -> Result<(), ApplicationError> { use common_utils::fp_utils::when; - #[cfg(not(feature = "aws_kms"))] - { - when(self.jwt_secret.is_default_or_empty(), || { - Err(ApplicationError::InvalidConfigurationValueError( - "JWT secret must not be empty".into(), - )) - })?; + when(self.jwt_secret.is_default_or_empty(), || { + Err(ApplicationError::InvalidConfigurationValueError( + "JWT secret must not be empty".into(), + )) + })?; - when(self.admin_api_key.is_default_or_empty(), || { - Err(ApplicationError::InvalidConfigurationValueError( - "admin API key must not be empty".into(), - )) - })?; - } + when(self.admin_api_key.is_default_or_empty(), || { + Err(ApplicationError::InvalidConfigurationValueError( + "admin API key must not be empty".into(), + )) + })?; - #[cfg(feature = "aws_kms")] - { - when(self.kms_encrypted_jwt_secret.is_default_or_empty(), || { - Err(ApplicationError::InvalidConfigurationValueError( - "KMS encrypted JWT secret must not be empty".into(), - )) - })?; - - when( - self.kms_encrypted_admin_api_key.is_default_or_empty(), - || { - Err(ApplicationError::InvalidConfigurationValueError( - "KMS encrypted admin API key must not be empty".into(), - )) - }, - )?; - } when(self.master_enc_key.is_default_or_empty(), || { Err(ApplicationError::InvalidConfigurationValueError( "Master encryption key must not be empty".into(), @@ -155,15 +136,7 @@ impl super::settings::ApiKeys { pub fn validate(&self) -> Result<(), ApplicationError> { use common_utils::fp_utils::when; - #[cfg(feature = "aws_kms")] - when(self.kms_encrypted_hash_key.is_default_or_empty(), || { - Err(ApplicationError::InvalidConfigurationValueError( - "API key hashing key must not be empty when KMS feature is enabled".into(), - )) - })?; - - #[cfg(not(feature = "aws_kms"))] - when(self.hash_key.is_empty(), || { + when(self.hash_key.peek().is_empty(), || { Err(ApplicationError::InvalidConfigurationValueError( "API key hashing key must not be empty".into(), )) diff --git a/crates/router/src/connection.rs b/crates/router/src/connection.rs index 1a48b6e0e2..6c10f95ea7 100644 --- a/crates/router/src/connection.rs +++ b/crates/router/src/connection.rs @@ -15,7 +15,7 @@ pub type PgPooledConn = async_bb8_diesel::Connection; /// Panics if failed to create a redis pool #[allow(clippy::expect_used)] pub async fn redis_connection( - conf: &crate::configs::settings::Settings, + conf: &crate::configs::Settings, ) -> redis_interface::RedisConnectionPool { redis_interface::RedisConnectionPool::new(&conf.redis) .await diff --git a/crates/router/src/core.rs b/crates/router/src/core.rs index 58f95e1371..50bae175f6 100644 --- a/crates/router/src/core.rs +++ b/crates/router/src/core.rs @@ -35,7 +35,7 @@ pub mod user; #[cfg(feature = "olap")] pub mod user_role; pub mod utils; -#[cfg(all(feature = "olap", feature = "aws_kms"))] +#[cfg(feature = "olap")] pub mod verification; #[cfg(feature = "olap")] pub mod verify_connector; diff --git a/crates/router/src/core/api_keys.rs b/crates/router/src/core/api_keys.rs index b3f8931cde..7d2069618d 100644 --- a/crates/router/src/core/api_keys.rs +++ b/crates/router/src/core/api_keys.rs @@ -2,12 +2,6 @@ use common_utils::date_time; #[cfg(feature = "email")] use diesel_models::{api_keys::ApiKey, enums as storage_enums}; use error_stack::{report, IntoReport, ResultExt}; -#[cfg(feature = "aws_kms")] -use external_services::aws_kms; -#[cfg(feature = "hashicorp-vault")] -use external_services::hashicorp_vault::decrypt::VaultFetch; -#[cfg(not(feature = "aws_kms"))] -use masking::ExposeInterface; use masking::{PeekInterface, StrongSecret}; use router_env::{instrument, tracing}; @@ -29,49 +23,16 @@ const API_KEY_EXPIRY_NAME: &str = "API_KEY_EXPIRY"; const API_KEY_EXPIRY_RUNNER: diesel_models::ProcessTrackerRunner = diesel_models::ProcessTrackerRunner::ApiKeyExpiryWorkflow; -#[cfg(feature = "aws_kms")] -use external_services::aws_kms::decrypt::AwsKmsDecrypt; - -static HASH_KEY: tokio::sync::OnceCell> = - tokio::sync::OnceCell::const_new(); - -pub async fn get_hash_key( - api_key_config: &settings::ApiKeys, - #[cfg(feature = "aws_kms")] aws_kms_client: &aws_kms::core::AwsKmsClient, - #[cfg(feature = "hashicorp-vault")] - hc_client: &external_services::hashicorp_vault::core::HashiCorpVault, -) -> errors::RouterResult<&'static StrongSecret<[u8; PlaintextApiKey::HASH_KEY_LEN]>> { - HASH_KEY - .get_or_try_init(|| async { - let hash_key = { - #[cfg(feature = "aws_kms")] - { - api_key_config.kms_encrypted_hash_key.clone() - } - #[cfg(not(feature = "aws_kms"))] - { - masking::Secret::<_, masking::WithType>::new(api_key_config.hash_key.clone()) - } - }; - - #[cfg(feature = "hashicorp-vault")] - let hash_key = hash_key - .fetch_inner::(hc_client) - .await - .change_context(errors::ApiErrorResponse::InternalServerError)?; - - #[cfg(feature = "aws_kms")] - let hash_key = hash_key - .decrypt_inner(aws_kms_client) - .await - .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable("Failed to AWS KMS decrypt API key hashing key")?; - - #[cfg(not(feature = "aws_kms"))] - let hash_key = hash_key.expose(); +static HASH_KEY: once_cell::sync::OnceCell> = + once_cell::sync::OnceCell::new(); +impl settings::ApiKeys { + pub fn get_hash_key( + &self, + ) -> errors::RouterResult<&'static StrongSecret<[u8; PlaintextApiKey::HASH_KEY_LEN]>> { + HASH_KEY.get_or_try_init(|| { <[u8; PlaintextApiKey::HASH_KEY_LEN]>::try_from( - hex::decode(hash_key) + hex::decode(self.hash_key.peek()) .into_report() .change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable("API key hash key has invalid hexadecimal data")? @@ -82,7 +43,7 @@ pub async fn get_hash_key( .attach_printable("The API hashing key has incorrect length") .map(StrongSecret::new) }) - .await + } } // Defining new types `PlaintextApiKey` and `HashedApiKey` in the hopes of reducing the possibility @@ -152,13 +113,10 @@ impl PlaintextApiKey { #[instrument(skip_all)] pub async fn create_api_key( state: AppState, - #[cfg(feature = "aws_kms")] aws_kms_client: &aws_kms::core::AwsKmsClient, - #[cfg(feature = "hashicorp-vault")] - hc_client: &external_services::hashicorp_vault::core::HashiCorpVault, api_key: api::CreateApiKeyRequest, merchant_id: String, ) -> RouterResponse { - let api_key_config = &state.conf.api_keys; + let api_key_config = state.conf.api_keys.get_inner(); let store = state.store.as_ref(); // We are not fetching merchant account as the merchant key store is needed to search for a // merchant account. @@ -172,14 +130,7 @@ pub async fn create_api_key( .await .to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)?; - let hash_key = get_hash_key( - api_key_config, - #[cfg(feature = "aws_kms")] - aws_kms_client, - #[cfg(feature = "hashicorp-vault")] - hc_client, - ) - .await?; + let hash_key = api_key_config.get_hash_key()?; let plaintext_api_key = PlaintextApiKey::new(consts::API_KEY_LENGTH); let api_key = storage::ApiKeyNew { key_id: PlaintextApiKey::new_key_id(), @@ -210,7 +161,7 @@ pub async fn create_api_key( #[cfg(feature = "email")] { if api_key.expires_at.is_some() { - let expiry_reminder_days = state.conf.api_keys.expiry_reminder_days.clone(); + let expiry_reminder_days = state.conf.api_keys.get_inner().expiry_reminder_days.clone(); add_api_key_expiry_task(store, &api_key, expiry_reminder_days) .await @@ -330,7 +281,7 @@ pub async fn update_api_key( #[cfg(feature = "email")] { - let expiry_reminder_days = state.conf.api_keys.expiry_reminder_days.clone(); + let expiry_reminder_days = state.conf.api_keys.get_inner().expiry_reminder_days.clone(); let task_id = generate_task_id_for_api_key_expiry_workflow(&key_id); // In order to determine how to update the existing process in the process_tracker table, @@ -575,17 +526,7 @@ mod tests { let settings = settings::Settings::new().expect("invalid settings"); let plaintext_api_key = PlaintextApiKey::new(consts::API_KEY_LENGTH); - let hash_key = get_hash_key( - &settings.api_keys, - #[cfg(feature = "aws_kms")] - external_services::aws_kms::core::get_aws_kms_client(&settings.kms).await, - #[cfg(feature = "hashicorp-vault")] - external_services::hashicorp_vault::core::get_hashicorp_client(&settings.hc_vault) - .await - .unwrap(), - ) - .await - .unwrap(); + let hash_key = settings.api_keys.get_inner().get_hash_key().unwrap(); let hashed_api_key = plaintext_api_key.keyed_hash(hash_key.peek()); assert_ne!( diff --git a/crates/router/src/core/blocklist/transformers.rs b/crates/router/src/core/blocklist/transformers.rs index f4122a6a65..6d6834f0b6 100644 --- a/crates/router/src/core/blocklist/transformers.rs +++ b/crates/router/src/core/blocklist/transformers.rs @@ -5,9 +5,7 @@ use common_utils::{ }; use error_stack::ResultExt; use josekit::jwe; -#[cfg(feature = "aws_kms")] -use masking::PeekInterface; -use masking::StrongSecret; +use masking::{PeekInterface, StrongSecret}; use router_env::{instrument, tracing}; use crate::{ @@ -35,8 +33,7 @@ impl ForeignFrom for blocklist::AddToBlocklistResponse { } async fn generate_fingerprint_request<'a>( - #[cfg(not(feature = "aws_kms"))] jwekey: &settings::Jwekey, - #[cfg(feature = "aws_kms")] jwekey: &settings::ActiveKmsSecrets, + jwekey: &settings::Jwekey, locker: &settings::Locker, payload: &blocklist::GenerateFingerprintRequest, locker_choice: api_enums::LockerChoice, @@ -45,11 +42,7 @@ async fn generate_fingerprint_request<'a>( .encode_to_vec() .change_context(errors::VaultError::RequestEncodingFailed)?; - #[cfg(feature = "aws_kms")] - let private_key = jwekey.jwekey.peek().vault_private_key.as_bytes(); - - #[cfg(not(feature = "aws_kms"))] - let private_key = jwekey.vault_private_key.as_bytes(); + let private_key = jwekey.vault_private_key.peek().as_bytes(); let jws = encryption::jws_sign_payload(&payload, &locker.locker_signing_key_id, private_key) .await @@ -67,8 +60,7 @@ async fn generate_fingerprint_request<'a>( } async fn generate_jwe_payload_for_request( - #[cfg(feature = "aws_kms")] jwekey: &settings::ActiveKmsSecrets, - #[cfg(not(feature = "aws_kms"))] jwekey: &settings::Jwekey, + jwekey: &settings::Jwekey, jws: &str, locker_choice: api_enums::LockerChoice, ) -> CustomResult { @@ -89,18 +81,12 @@ async fn generate_jwe_payload_for_request( .encode_to_vec() .change_context(errors::VaultError::GenerateFingerprintFailed)?; - #[cfg(feature = "aws_kms")] let public_key = match locker_choice { api_enums::LockerChoice::HyperswitchCardVault => { - jwekey.jwekey.peek().vault_encryption_key.as_bytes() + jwekey.vault_encryption_key.peek().as_bytes() } }; - #[cfg(not(feature = "aws_kms"))] - let public_key = match locker_choice { - api_enums::LockerChoice::HyperswitchCardVault => jwekey.vault_encryption_key.as_bytes(), - }; - let jwe_encrypted = encryption::encrypt_jwe(&payload, public_key) .await .change_context(errors::VaultError::SaveCardFailed) @@ -148,10 +134,7 @@ async fn call_to_locker_for_fingerprint( locker_choice: api_enums::LockerChoice, ) -> CustomResult { let locker = &state.conf.locker; - #[cfg(not(feature = "aws_kms"))] - let jwekey = &state.conf.jwekey; - #[cfg(feature = "aws_kms")] - let jwekey = &state.kms_secrets; + let jwekey = state.conf.jwekey.get_inner(); let request = generate_fingerprint_request(jwekey, locker, payload, locker_choice).await?; let response = services::call_connector_api(state, request) @@ -175,30 +158,20 @@ async fn call_to_locker_for_fingerprint( } async fn decrypt_generate_fingerprint_response_payload( - #[cfg(not(feature = "aws_kms"))] jwekey: &settings::Jwekey, - #[cfg(feature = "aws_kms")] jwekey: &settings::ActiveKmsSecrets, + jwekey: &settings::Jwekey, + jwe_body: encryption::JweBody, locker_choice: Option, ) -> CustomResult { let target_locker = locker_choice.unwrap_or(api_enums::LockerChoice::HyperswitchCardVault); - #[cfg(feature = "aws_kms")] let public_key = match target_locker { api_enums::LockerChoice::HyperswitchCardVault => { - jwekey.jwekey.peek().vault_encryption_key.as_bytes() + jwekey.vault_encryption_key.peek().as_bytes() } }; - #[cfg(feature = "aws_kms")] - let private_key = jwekey.jwekey.peek().vault_private_key.as_bytes(); - - #[cfg(not(feature = "aws_kms"))] - let public_key = match target_locker { - api_enums::LockerChoice::HyperswitchCardVault => jwekey.vault_encryption_key.as_bytes(), - }; - - #[cfg(not(feature = "aws_kms"))] - let private_key = jwekey.vault_private_key.as_bytes(); + let private_key = jwekey.vault_private_key.peek().as_bytes(); let jwt = payment_methods::get_dotted_jwe(jwe_body); let alg = jwe::RSA_OAEP; diff --git a/crates/router/src/core/connector_onboarding.rs b/crates/router/src/core/connector_onboarding.rs index e6c1fc9d37..21377d0ba0 100644 --- a/crates/router/src/core/connector_onboarding.rs +++ b/crates/router/src/core/connector_onboarding.rs @@ -24,8 +24,8 @@ pub async fn get_action_url( utils::check_if_connector_exists(&state, &request.connector_id, &user_from_token.merchant_id) .await?; - let connector_onboarding_conf = state.conf.connector_onboarding.clone(); - let is_enabled = utils::is_enabled(request.connector, &connector_onboarding_conf); + let connector_onboarding_conf = state.conf.connector_onboarding.get_inner(); + let is_enabled = utils::is_enabled(request.connector, connector_onboarding_conf); let tracking_id = utils::get_tracking_id_from_configs(&state, &request.connector_id, request.connector) .await?; @@ -58,8 +58,8 @@ pub async fn sync_onboarding_status( utils::check_if_connector_exists(&state, &request.connector_id, &user_from_token.merchant_id) .await?; - let connector_onboarding_conf = state.conf.connector_onboarding.clone(); - let is_enabled = utils::is_enabled(request.connector, &connector_onboarding_conf); + let connector_onboarding_conf = state.conf.connector_onboarding.get_inner(); + let is_enabled = utils::is_enabled(request.connector, connector_onboarding_conf); let tracking_id = utils::get_tracking_id_from_configs(&state, &request.connector_id, request.connector) .await?; @@ -75,10 +75,10 @@ pub async fn sync_onboarding_status( ref paypal_onboarding_data, )) = status { - let connector_onboarding_conf = state.conf.connector_onboarding.clone(); + let connector_onboarding_conf = state.conf.connector_onboarding.get_inner(); let auth_details = oss_types::ConnectorAuthType::SignatureKey { - api_key: connector_onboarding_conf.paypal.client_secret, - key1: connector_onboarding_conf.paypal.client_id, + api_key: connector_onboarding_conf.paypal.client_secret.clone(), + key1: connector_onboarding_conf.paypal.client_id.clone(), api_secret: Secret::new(paypal_onboarding_data.payer_id.clone()), }; let update_mca_data = paypal::update_mca( diff --git a/crates/router/src/core/connector_onboarding/paypal.rs b/crates/router/src/core/connector_onboarding/paypal.rs index 644a2220ae..4c1f16e913 100644 --- a/crates/router/src/core/connector_onboarding/paypal.rs +++ b/crates/router/src/core/connector_onboarding/paypal.rs @@ -63,7 +63,13 @@ pub async fn get_action_url_from_paypal( } fn merchant_onboarding_status_url(state: AppState, tracking_id: String) -> String { - let partner_id = state.conf.connector_onboarding.paypal.partner_id.to_owned(); + let partner_id = state + .conf + .connector_onboarding + .get_inner() + .paypal + .partner_id + .to_owned(); format!( "{}v1/customer/partners/{}/merchant-integrations?tracking_id={}", state.conf.connectors.paypal.base_url, diff --git a/crates/router/src/core/currency.rs b/crates/router/src/core/currency.rs index b0d06f9fd6..f2791deb7b 100644 --- a/crates/router/src/core/currency.rs +++ b/crates/router/src/core/currency.rs @@ -11,16 +11,13 @@ use crate::{ pub async fn retrieve_forex( state: AppState, ) -> CustomResult, ApiErrorResponse> { + let forex_api = state.conf.forex_api.get_inner(); Ok(ApplicationResponse::Json( get_forex_rates( &state, - state.conf.forex_api.call_delay, - state.conf.forex_api.local_fetch_retry_delay, - state.conf.forex_api.local_fetch_retry_count, - #[cfg(feature = "aws_kms")] - &state.conf.kms, - #[cfg(feature = "hashicorp-vault")] - &state.conf.hc_vault, + forex_api.call_delay, + forex_api.local_fetch_retry_delay, + forex_api.local_fetch_retry_count, ) .await .change_context(ApiErrorResponse::GenericNotFoundError { @@ -44,10 +41,6 @@ pub async fn convert_forex( amount, to_currency, from_currency, - #[cfg(feature = "aws_kms")] - &state.conf.kms, - #[cfg(feature = "hashicorp-vault")] - &state.conf.hc_vault, )) .await .change_context(ApiErrorResponse::InternalServerError)?, diff --git a/crates/router/src/core/payment_methods/cards.rs b/crates/router/src/core/payment_methods/cards.rs index 9ebcc61fce..882d384edd 100644 --- a/crates/router/src/core/payment_methods/cards.rs +++ b/crates/router/src/core/payment_methods/cards.rs @@ -653,10 +653,7 @@ pub async fn get_payment_method_from_hs_locker<'a>( locker_choice: Option, ) -> errors::CustomResult, errors::VaultError> { let locker = &state.conf.locker; - #[cfg(not(feature = "aws_kms"))] - let jwekey = &state.conf.jwekey; - #[cfg(feature = "aws_kms")] - let jwekey = &state.kms_secrets; + let jwekey = state.conf.jwekey.get_inner(); let payment_method_data = if !locker.mock_locker { let request = payment_methods::mk_get_card_request_hs( @@ -716,10 +713,7 @@ pub async fn call_to_locker_hs<'a>( locker_choice: api_enums::LockerChoice, ) -> errors::CustomResult { let locker = &state.conf.locker; - #[cfg(not(feature = "aws_kms"))] - let jwekey = &state.conf.jwekey; - #[cfg(feature = "aws_kms")] - let jwekey = &state.kms_secrets; + let jwekey = state.conf.jwekey.get_inner(); let db = &*state.store; let stored_card_response = if !locker.mock_locker { let request = @@ -777,10 +771,7 @@ pub async fn get_card_from_hs_locker<'a>( locker_choice: api_enums::LockerChoice, ) -> errors::CustomResult { let locker = &state.conf.locker; - #[cfg(not(feature = "aws_kms"))] - let jwekey = &state.conf.jwekey; - #[cfg(feature = "aws_kms")] - let jwekey = &state.kms_secrets; + let jwekey = &state.conf.jwekey.get_inner(); if !locker.mock_locker { let request = payment_methods::mk_get_card_request_hs( @@ -832,10 +823,7 @@ pub async fn delete_card_from_hs_locker<'a>( card_reference: &'a str, ) -> errors::RouterResult { let locker = &state.conf.locker; - #[cfg(not(feature = "aws_kms"))] - let jwekey = &state.conf.jwekey; - #[cfg(feature = "aws_kms")] - let jwekey = &state.kms_secrets; + let jwekey = &state.conf.jwekey.get_inner(); let request = payment_methods::mk_delete_card_request_hs( jwekey, @@ -1445,7 +1433,7 @@ pub async fn list_payment_methods( } let pm_auth_key = format!("pm_auth_{}", payment_intent.payment_id); - let redis_expiry = state.conf.payment_method_auth.redis_expiry; + let redis_expiry = state.conf.payment_method_auth.get_inner().redis_expiry; if let Some(rc) = redis_conn { rc.serialize_and_set_key_with_expiry(pm_auth_key.as_str(), val, redis_expiry) diff --git a/crates/router/src/core/payment_methods/transformers.rs b/crates/router/src/core/payment_methods/transformers.rs index 57e46bc976..ea25c73499 100644 --- a/crates/router/src/core/payment_methods/transformers.rs +++ b/crates/router/src/core/payment_methods/transformers.rs @@ -197,30 +197,19 @@ pub fn get_dotted_jws(jws: encryption::JwsBody) -> String { } pub async fn get_decrypted_response_payload( - #[cfg(not(feature = "aws_kms"))] jwekey: &settings::Jwekey, - #[cfg(feature = "aws_kms")] jwekey: &settings::ActiveKmsSecrets, + jwekey: &settings::Jwekey, jwe_body: encryption::JweBody, locker_choice: Option, ) -> CustomResult { let target_locker = locker_choice.unwrap_or(api_enums::LockerChoice::HyperswitchCardVault); - #[cfg(feature = "aws_kms")] let public_key = match target_locker { api_enums::LockerChoice::HyperswitchCardVault => { - jwekey.jwekey.peek().vault_encryption_key.as_bytes() + jwekey.vault_encryption_key.peek().as_bytes() } }; - #[cfg(feature = "aws_kms")] - let private_key = jwekey.jwekey.peek().vault_private_key.as_bytes(); - - #[cfg(not(feature = "aws_kms"))] - let public_key = match target_locker { - api_enums::LockerChoice::HyperswitchCardVault => jwekey.vault_encryption_key.as_bytes(), - }; - - #[cfg(not(feature = "aws_kms"))] - let private_key = jwekey.vault_private_key.as_bytes(); + let private_key = jwekey.vault_private_key.peek().as_bytes(); let jwt = get_dotted_jwe(jwe_body); let alg = jwe::RSA_OAEP; @@ -246,8 +235,7 @@ pub async fn get_decrypted_response_payload( } pub async fn mk_basilisk_req( - #[cfg(feature = "aws_kms")] jwekey: &settings::ActiveKmsSecrets, - #[cfg(not(feature = "aws_kms"))] jwekey: &settings::Jwekey, + jwekey: &settings::Jwekey, jws: &str, locker_choice: api_enums::LockerChoice, ) -> CustomResult { @@ -267,18 +255,12 @@ pub async fn mk_basilisk_req( .encode_to_vec() .change_context(errors::VaultError::SaveCardFailed)?; - #[cfg(feature = "aws_kms")] let public_key = match locker_choice { api_enums::LockerChoice::HyperswitchCardVault => { - jwekey.jwekey.peek().vault_encryption_key.as_bytes() + jwekey.vault_encryption_key.peek().as_bytes() } }; - #[cfg(not(feature = "aws_kms"))] - let public_key = match locker_choice { - api_enums::LockerChoice::HyperswitchCardVault => jwekey.vault_encryption_key.as_bytes(), - }; - let jwe_encrypted = encryption::encrypt_jwe(&payload, public_key) .await .change_context(errors::VaultError::SaveCardFailed) @@ -301,8 +283,7 @@ pub async fn mk_basilisk_req( } pub async fn mk_add_locker_request_hs<'a>( - #[cfg(not(feature = "aws_kms"))] jwekey: &settings::Jwekey, - #[cfg(feature = "aws_kms")] jwekey: &settings::ActiveKmsSecrets, + jwekey: &settings::Jwekey, locker: &settings::Locker, payload: &StoreLockerReq<'a>, locker_choice: api_enums::LockerChoice, @@ -311,11 +292,7 @@ pub async fn mk_add_locker_request_hs<'a>( .encode_to_vec() .change_context(errors::VaultError::RequestEncodingFailed)?; - #[cfg(feature = "aws_kms")] - let private_key = jwekey.jwekey.peek().vault_private_key.as_bytes(); - - #[cfg(not(feature = "aws_kms"))] - let private_key = jwekey.vault_private_key.as_bytes(); + let private_key = jwekey.vault_private_key.peek().as_bytes(); let jws = encryption::jws_sign_payload(&payload, &locker.locker_signing_key_id, private_key) .await @@ -471,8 +448,7 @@ pub fn mk_add_card_request( } pub async fn mk_get_card_request_hs( - #[cfg(not(feature = "aws_kms"))] jwekey: &settings::Jwekey, - #[cfg(feature = "aws_kms")] jwekey: &settings::ActiveKmsSecrets, + jwekey: &settings::Jwekey, locker: &settings::Locker, customer_id: &str, merchant_id: &str, @@ -489,11 +465,7 @@ pub async fn mk_get_card_request_hs( .encode_to_vec() .change_context(errors::VaultError::RequestEncodingFailed)?; - #[cfg(feature = "aws_kms")] - let private_key = jwekey.jwekey.peek().vault_private_key.as_bytes(); - - #[cfg(not(feature = "aws_kms"))] - let private_key = jwekey.vault_private_key.as_bytes(); + let private_key = jwekey.vault_private_key.peek().as_bytes(); let jws = encryption::jws_sign_payload(&payload, &locker.locker_signing_key_id, private_key) .await @@ -548,8 +520,7 @@ pub fn mk_get_card_response(card: GetCardResponse) -> errors::RouterResult } pub async fn mk_delete_card_request_hs( - #[cfg(feature = "aws_kms")] jwekey: &settings::ActiveKmsSecrets, - #[cfg(not(feature = "aws_kms"))] jwekey: &settings::Jwekey, + jwekey: &settings::Jwekey, locker: &settings::Locker, customer_id: &str, merchant_id: &str, @@ -565,11 +536,7 @@ pub async fn mk_delete_card_request_hs( .encode_to_vec() .change_context(errors::VaultError::RequestEncodingFailed)?; - #[cfg(feature = "aws_kms")] - let private_key = jwekey.jwekey.peek().vault_private_key.as_bytes(); - - #[cfg(not(feature = "aws_kms"))] - let private_key = jwekey.vault_private_key.as_bytes(); + let private_key = jwekey.vault_private_key.peek().as_bytes(); let jws = encryption::jws_sign_payload(&payload, &locker.locker_signing_key_id, private_key) .await diff --git a/crates/router/src/core/payments/flows/session_flow.rs b/crates/router/src/core/payments/flows/session_flow.rs index 479a0685a9..e29b66ea0c 100644 --- a/crates/router/src/core/payments/flows/session_flow.rs +++ b/crates/router/src/core/payments/flows/session_flow.rs @@ -2,13 +2,6 @@ use api_models::payments as payment_types; use async_trait::async_trait; use common_utils::{ext_traits::ByteSliceExt, request::RequestContent}; use error_stack::{IntoReport, Report, ResultExt}; -#[cfg(feature = "aws_kms")] -use external_services::aws_kms; -#[cfg(feature = "hashicorp-vault")] -use external_services::hashicorp_vault; -#[cfg(feature = "hashicorp-vault")] -use external_services::hashicorp_vault::decrypt::VaultFetch; -#[cfg(feature = "hashicorp-vault")] use masking::ExposeInterface; use super::{ConstructFlowSpecificData, Feature}; @@ -183,130 +176,40 @@ async fn create_applepay_session_token( payment_request_data, session_token_data, } => { - let ( - apple_pay_merchant_cert, - apple_pay_merchant_cert_key, - common_merchant_identifier, - ) = async { - #[cfg(feature = "hashicorp-vault")] - let client = - external_services::hashicorp_vault::core::get_hashicorp_client( - &state.conf.hc_vault, - ) - .await - .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable("Failed while building hashicorp client")?; - - #[cfg(feature = "hashicorp-vault")] - { - Ok::<_, Report>(( - masking::Secret::new( - state - .conf - .applepay_decrypt_keys - .apple_pay_merchant_cert - .clone(), - ) - .fetch_inner::(client) - .await - .change_context(errors::ApiErrorResponse::InternalServerError)? - .expose(), - masking::Secret::new( - state - .conf - .applepay_decrypt_keys - .apple_pay_merchant_cert_key - .clone(), - ) - .fetch_inner::(client) - .await - .change_context(errors::ApiErrorResponse::InternalServerError)? - .expose(), - masking::Secret::new( - state - .conf - .applepay_merchant_configs - .common_merchant_identifier - .clone(), - ) - .fetch_inner::(client) - .await - .change_context(errors::ApiErrorResponse::InternalServerError)? - .expose(), - )) - } - - #[cfg(not(feature = "hashicorp-vault"))] - { - Ok::<_, Report>(( - state - .conf - .applepay_decrypt_keys - .apple_pay_merchant_cert - .clone(), - state - .conf - .applepay_decrypt_keys - .apple_pay_merchant_cert_key - .clone(), - state - .conf - .applepay_merchant_configs - .common_merchant_identifier - .clone(), - )) - } - } - .await?; - - #[cfg(feature = "aws_kms")] - let decrypted_apple_pay_merchant_cert = - aws_kms::core::get_aws_kms_client(&state.conf.kms) - .await - .decrypt(apple_pay_merchant_cert) - .await - .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable("Apple pay merchant certificate decryption failed")?; - - #[cfg(feature = "aws_kms")] - let decrypted_apple_pay_merchant_cert_key = - aws_kms::core::get_aws_kms_client(&state.conf.kms) - .await - .decrypt(apple_pay_merchant_cert_key) - .await - .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable( - "Apple pay merchant certificate key decryption failed", - )?; - - #[cfg(feature = "aws_kms")] - let decrypted_merchant_identifier = - aws_kms::core::get_aws_kms_client(&state.conf.kms) - .await - .decrypt(common_merchant_identifier) - .await - .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable("Apple pay merchant identifier decryption failed")?; - - #[cfg(not(feature = "aws_kms"))] - let decrypted_merchant_identifier = common_merchant_identifier; + let merchant_identifier = state + .conf + .applepay_merchant_configs + .get_inner() + .common_merchant_identifier + .clone() + .expose(); let apple_pay_session_request = get_session_request_for_simplified_apple_pay( - decrypted_merchant_identifier.to_string(), + merchant_identifier, session_token_data, ); - #[cfg(not(feature = "aws_kms"))] - let decrypted_apple_pay_merchant_cert = apple_pay_merchant_cert; + let apple_pay_merchant_cert = state + .conf + .applepay_decrypt_keys + .get_inner() + .apple_pay_merchant_cert + .clone() + .expose(); - #[cfg(not(feature = "aws_kms"))] - let decrypted_apple_pay_merchant_cert_key = apple_pay_merchant_cert_key; + let apple_pay_merchant_cert_key = state + .conf + .applepay_decrypt_keys + .get_inner() + .apple_pay_merchant_cert_key + .clone() + .expose(); ( payment_request_data, apple_pay_session_request, - decrypted_apple_pay_merchant_cert.to_owned(), - decrypted_apple_pay_merchant_cert_key.to_owned(), + apple_pay_merchant_cert, + apple_pay_merchant_cert_key, ) } payment_types::ApplePayCombinedMetadata::Manual { diff --git a/crates/router/src/core/payments/helpers.rs b/crates/router/src/core/payments/helpers.rs index b6e28faa4e..0eaf3c07ee 100644 --- a/crates/router/src/core/payments/helpers.rs +++ b/crates/router/src/core/payments/helpers.rs @@ -13,12 +13,6 @@ use data_models::{ use diesel_models::enums; // TODO : Evaluate all the helper functions () use error_stack::{report, IntoReport, ResultExt}; -#[cfg(feature = "aws_kms")] -use external_services::aws_kms; -#[cfg(feature = "hashicorp-vault")] -use external_services::hashicorp_vault; -#[cfg(feature = "hashicorp-vault")] -use external_services::hashicorp_vault::decrypt::VaultFetch; use josekit::jwe; use masking::{ExposeInterface, PeekInterface}; use openssl::{ @@ -2903,17 +2897,14 @@ pub async fn get_merchant_connector_account( }, )?; - #[cfg(feature = "aws_kms")] let private_key = state - .kms_secrets + .conf .jwekey - .peek() + .get_inner() .tunnel_private_key + .peek() .as_bytes(); - #[cfg(not(feature = "aws_kms"))] - let private_key = state.conf.jwekey.tunnel_private_key.as_bytes(); - let decrypted_mca = services::decrypt_jwe(mca_config.config.as_str(), services::KeyIdCheck::SkipKeyIdCheck, private_key, jwe::RSA_OAEP_256) .await .change_context(errors::ApiErrorResponse::UnprocessableEntity{ @@ -3550,39 +3541,13 @@ impl ApplePayData { &self, state: &AppState, ) -> CustomResult { - let apple_pay_ppc = async { - #[cfg(feature = "hashicorp-vault")] - let client = external_services::hashicorp_vault::core::get_hashicorp_client( - &state.conf.hc_vault, - ) - .await - .change_context(errors::ApplePayDecryptionError::DecryptionFailed) - .attach_printable("Failed while creating client")?; - - #[cfg(feature = "hashicorp-vault")] - let output = - masking::Secret::new(state.conf.applepay_decrypt_keys.apple_pay_ppc.clone()) - .fetch_inner::(client) - .await - .change_context(errors::ApplePayDecryptionError::DecryptionFailed)? - .expose(); - - #[cfg(not(feature = "hashicorp-vault"))] - let output = state.conf.applepay_decrypt_keys.apple_pay_ppc.clone(); - - Ok::<_, error_stack::Report>(output) - } - .await?; - - #[cfg(feature = "aws_kms")] - let cert_data = aws_kms::core::get_aws_kms_client(&state.conf.kms) - .await - .decrypt(&apple_pay_ppc) - .await - .change_context(errors::ApplePayDecryptionError::DecryptionFailed)?; - - #[cfg(not(feature = "aws_kms"))] - let cert_data = &apple_pay_ppc; + let cert_data = state + .conf + .applepay_decrypt_keys + .get_inner() + .apple_pay_ppc + .clone() + .expose(); let base64_decode_cert_data = BASE64_ENGINE .decode(cert_data) @@ -3634,40 +3599,14 @@ impl ApplePayData { .change_context(errors::ApplePayDecryptionError::KeyDeserializationFailed) .attach_printable("Failed to deserialize the public key")?; - let apple_pay_ppc_key = async { - #[cfg(feature = "hashicorp-vault")] - let client = external_services::hashicorp_vault::core::get_hashicorp_client( - &state.conf.hc_vault, - ) - .await - .change_context(errors::ApplePayDecryptionError::DecryptionFailed) - .attach_printable("Failed while creating client")?; + let decrypted_apple_pay_ppc_key = state + .conf + .applepay_decrypt_keys + .get_inner() + .apple_pay_ppc_key + .clone() + .expose(); - #[cfg(feature = "hashicorp-vault")] - let output = - masking::Secret::new(state.conf.applepay_decrypt_keys.apple_pay_ppc_key.clone()) - .fetch_inner::(client) - .await - .change_context(errors::ApplePayDecryptionError::DecryptionFailed) - .attach_printable("Failed while creating client")? - .expose(); - - #[cfg(not(feature = "hashicorp-vault"))] - let output = state.conf.applepay_decrypt_keys.apple_pay_ppc_key.clone(); - - Ok::<_, error_stack::Report>(output) - } - .await?; - - #[cfg(feature = "aws_kms")] - let decrypted_apple_pay_ppc_key = aws_kms::core::get_aws_kms_client(&state.conf.kms) - .await - .decrypt(&apple_pay_ppc_key) - .await - .change_context(errors::ApplePayDecryptionError::DecryptionFailed)?; - - #[cfg(not(feature = "aws_kms"))] - let decrypted_apple_pay_ppc_key = &apple_pay_ppc_key; // Create PKey objects from EcKey let private_key = PKey::private_key_from_pem(decrypted_apple_pay_ppc_key.as_bytes()) .into_report() diff --git a/crates/router/src/core/pm_auth.rs b/crates/router/src/core/pm_auth.rs index f00c452f3e..982ed9cae9 100644 --- a/crates/router/src/core/pm_auth.rs +++ b/crates/router/src/core/pm_auth.rs @@ -5,8 +5,6 @@ use api_models::{ payment_methods::{self, BankAccountAccessCreds}, payments::{AddressDetails, BankDebitBilling, BankDebitData, PaymentMethodData}, }; -#[cfg(feature = "hashicorp-vault")] -use external_services::hashicorp_vault::{self, decrypt::VaultFetch}; use hex; pub mod helpers; pub mod transformers; @@ -19,8 +17,6 @@ use common_utils::{ }; use data_models::payments::PaymentIntent; use error_stack::{IntoReport, ResultExt}; -#[cfg(feature = "aws_kms")] -pub use external_services::aws_kms; use helpers::PaymentAuthConnectorDataExt; use masking::{ExposeInterface, PeekInterface}; use pm_auth::{ @@ -347,34 +343,13 @@ async fn store_bank_details_in_payment_methods( } } - let pm_auth_key = async { - #[cfg(feature = "hashicorp-vault")] - let client = - external_services::hashicorp_vault::core::get_hashicorp_client(&state.conf.hc_vault) - .await - .change_context(ApiErrorResponse::InternalServerError) - .attach_printable("Failed while creating client")?; - - #[cfg(feature = "hashicorp-vault")] - let output = masking::Secret::new(state.conf.payment_method_auth.pm_auth_key.clone()) - .fetch_inner::(client) - .await - .change_context(ApiErrorResponse::InternalServerError)? - .expose(); - - #[cfg(not(feature = "hashicorp-vault"))] - let output = state.conf.payment_method_auth.pm_auth_key.clone(); - - Ok::<_, error_stack::Report>(output) - } - .await?; - - #[cfg(feature = "aws_kms")] - let pm_auth_key = aws_kms::core::get_aws_kms_client(&state.conf.kms) - .await - .decrypt(pm_auth_key) - .await - .change_context(ApiErrorResponse::InternalServerError)?; + let pm_auth_key = state + .conf + .payment_method_auth + .get_inner() + .pm_auth_key + .clone() + .expose(); let mut update_entries: Vec<(storage::PaymentMethod, storage::PaymentMethodUpdate)> = Vec::new(); diff --git a/crates/router/src/core/utils.rs b/crates/router/src/core/utils.rs index ff51668ec5..d749163aa2 100644 --- a/crates/router/src/core/utils.rs +++ b/crates/router/src/core/utils.rs @@ -15,7 +15,7 @@ use super::payouts::PayoutData; #[cfg(feature = "payouts")] use crate::core::payments; use crate::{ - configs::settings, + configs::Settings, consts, core::errors::{self, RouterResult, StorageErrorExt}, db::StorageInterface, @@ -942,7 +942,7 @@ pub async fn construct_retrieve_file_router_data<'a>( } pub fn is_merchant_enabled_for_payment_id_as_connector_request_id( - conf: &settings::Settings, + conf: &Settings, merchant_id: &str, ) -> bool { let config_map = &conf @@ -952,7 +952,7 @@ pub fn is_merchant_enabled_for_payment_id_as_connector_request_id( } pub fn get_connector_request_reference_id( - conf: &settings::Settings, + conf: &Settings, merchant_id: &str, payment_attempt: &data_models::payments::payment_attempt::PaymentAttempt, ) -> String { diff --git a/crates/router/src/core/verification.rs b/crates/router/src/core/verification.rs index 79513bfb30..04ccdc32f2 100644 --- a/crates/router/src/core/verification.rs +++ b/crates/router/src/core/verification.rs @@ -2,8 +2,7 @@ pub mod utils; use api_models::verifications::{self, ApplepayMerchantResponse}; use common_utils::{errors::CustomResult, request::RequestContent}; use error_stack::ResultExt; -#[cfg(feature = "aws_kms")] -use external_services::aws_kms; +use masking::ExposeInterface; use crate::{core::errors::api_error_response, headers, logger, routes::AppState, services}; @@ -11,44 +10,26 @@ const APPLEPAY_INTERNAL_MERCHANT_NAME: &str = "Applepay_merchant"; pub async fn verify_merchant_creds_for_applepay( state: AppState, - _req: &actix_web::HttpRequest, body: verifications::ApplepayMerchantVerificationRequest, - kms_config: &aws_kms::core::AwsKmsConfig, merchant_id: String, ) -> CustomResult< services::ApplicationResponse, api_error_response::ApiErrorResponse, > { - let encrypted_merchant_identifier = &state - .conf - .applepay_merchant_configs - .common_merchant_identifier; - let encrypted_cert = &state.conf.applepay_merchant_configs.merchant_cert; - let encrypted_key = &state.conf.applepay_merchant_configs.merchant_cert_key; - let applepay_endpoint = &state.conf.applepay_merchant_configs.applepay_endpoint; + let applepay_merchant_configs = state.conf.applepay_merchant_configs.get_inner(); - let applepay_internal_merchant_identifier = aws_kms::core::get_aws_kms_client(kms_config) - .await - .decrypt(encrypted_merchant_identifier) - .await - .change_context(api_error_response::ApiErrorResponse::InternalServerError)?; - - let cert_data = aws_kms::core::get_aws_kms_client(kms_config) - .await - .decrypt(encrypted_cert) - .await - .change_context(api_error_response::ApiErrorResponse::InternalServerError)?; - - let key_data = aws_kms::core::get_aws_kms_client(kms_config) - .await - .decrypt(encrypted_key) - .await - .change_context(api_error_response::ApiErrorResponse::InternalServerError)?; + let applepay_internal_merchant_identifier = applepay_merchant_configs + .common_merchant_identifier + .clone() + .expose(); + let cert_data = applepay_merchant_configs.merchant_cert.clone().expose(); + let key_data = applepay_merchant_configs.merchant_cert_key.clone().expose(); + let applepay_endpoint = &applepay_merchant_configs.applepay_endpoint; let request_body = verifications::ApplepayMerchantVerificationConfigs { domain_names: body.domain_names.clone(), - encrypt_to: applepay_internal_merchant_identifier.to_string(), - partner_internal_merchant_identifier: applepay_internal_merchant_identifier.to_string(), + encrypt_to: applepay_internal_merchant_identifier.clone(), + partner_internal_merchant_identifier: applepay_internal_merchant_identifier, partner_merchant_name: APPLEPAY_INTERNAL_MERCHANT_NAME.to_string(), }; diff --git a/crates/router/src/lib.rs b/crates/router/src/lib.rs index 5b5bc414d2..97d981c68e 100644 --- a/crates/router/src/lib.rs +++ b/crates/router/src/lib.rs @@ -30,6 +30,7 @@ use actix_web::{ middleware::ErrorHandlers, }; use http::StatusCode; +use hyperswitch_interfaces::secrets_interface::secret_state::SecuredSecret; use routes::AppState; use storage_impl::errors::ApplicationResult; use tokio::sync::{mpsc, oneshot}; @@ -141,7 +142,7 @@ pub fn mk_app( .service(routes::ConnectorOnboarding::server(state.clone())) } - #[cfg(all(feature = "olap", feature = "aws_kms"))] + #[cfg(feature = "olap")] { server_app = server_app.service(routes::Verify::server(state.clone())); } @@ -174,7 +175,7 @@ pub fn mk_app( /// /// Unwrap used because without the value we can't start the server #[allow(clippy::expect_used, clippy::unwrap_used)] -pub async fn start_server(conf: settings::Settings) -> ApplicationResult { +pub async fn start_server(conf: settings::Settings) -> ApplicationResult { logger::debug!(startup_config=?conf); let server = conf.server.clone(); let (tx, rx) = oneshot::channel(); diff --git a/crates/router/src/routes.rs b/crates/router/src/routes.rs index 51c938b097..0d7c903b06 100644 --- a/crates/router/src/routes.rs +++ b/crates/router/src/routes.rs @@ -37,7 +37,7 @@ pub mod routing; pub mod user; #[cfg(feature = "olap")] pub mod user_role; -#[cfg(all(feature = "olap", feature = "aws_kms"))] +#[cfg(feature = "olap")] pub mod verification; #[cfg(feature = "olap")] pub mod verify_connector; @@ -57,7 +57,7 @@ pub use self::app::Forex; pub use self::app::Payouts; #[cfg(all(feature = "olap", feature = "recon"))] pub use self::app::Recon; -#[cfg(all(feature = "olap", feature = "aws_kms"))] +#[cfg(feature = "olap")] pub use self::app::Verify; pub use self::app::{ ApiKeys, AppState, BusinessProfile, Cache, Cards, Configs, ConnectorOnboarding, Customers, diff --git a/crates/router/src/routes/api_keys.rs b/crates/router/src/routes/api_keys.rs index cf0f009a0b..2e95fd536c 100644 --- a/crates/router/src/routes/api_keys.rs +++ b/crates/router/src/routes/api_keys.rs @@ -1,6 +1,4 @@ use actix_web::{web, HttpRequest, Responder}; -#[cfg(feature = "hashicorp-vault")] -use error_stack::ResultExt; use router_env::{instrument, tracing, Flow}; use super::app::AppState; @@ -44,27 +42,7 @@ pub async fn api_key_create( &req, payload, |state, _, payload| async { - #[cfg(feature = "aws_kms")] - let aws_kms_client = - external_services::aws_kms::core::get_aws_kms_client(&state.clone().conf.kms).await; - - #[cfg(feature = "hashicorp-vault")] - let hc_client = external_services::hashicorp_vault::core::get_hashicorp_client( - &state.clone().conf.hc_vault, - ) - .await - .change_context(crate::core::errors::ApiErrorResponse::InternalServerError)?; - - api_keys::create_api_key( - state, - #[cfg(feature = "aws_kms")] - aws_kms_client, - #[cfg(feature = "hashicorp-vault")] - hc_client, - payload, - merchant_id.clone(), - ) - .await + api_keys::create_api_key(state, payload, merchant_id.clone()).await }, auth::auth_type( &auth::AdminApiAuth, diff --git a/crates/router/src/routes/app.rs b/crates/router/src/routes/app.rs index e204ef3b9e..73558c78d7 100644 --- a/crates/router/src/routes/app.rs +++ b/crates/router/src/routes/app.rs @@ -1,25 +1,17 @@ use std::sync::Arc; use actix_web::{web, Scope}; -#[cfg(all( - feature = "olap", - any(feature = "hashicorp-vault", feature = "aws_kms") -))] -use analytics::AnalyticsConfig; #[cfg(all(feature = "business_profile_routing", feature = "olap"))] use api_models::routing::RoutingRetrieveQuery; #[cfg(feature = "olap")] use common_enums::TransactionType; -#[cfg(feature = "aws_kms")] -use external_services::aws_kms::{self, decrypt::AwsKmsDecrypt}; #[cfg(feature = "email")] use external_services::email::{ses::AwsSes, EmailService}; use external_services::file_storage::FileStorageInterface; -#[cfg(all(feature = "olap", feature = "hashicorp-vault"))] -use external_services::hashicorp_vault::decrypt::VaultFetch; -use hyperswitch_interfaces::encryption_interface::EncryptionManagementInterface; -#[cfg(all(feature = "olap", feature = "aws_kms"))] -use masking::PeekInterface; +use hyperswitch_interfaces::{ + encryption_interface::EncryptionManagementInterface, + secrets_interface::secret_state::{RawSecret, SecuredSecret}, +}; use router_env::tracing_actix_web::RequestId; use scheduler::SchedulerInterface; use storage_impl::MockDb; @@ -37,7 +29,7 @@ use super::payouts::*; use super::pm_auth; #[cfg(feature = "olap")] use super::routing as cloud_routing; -#[cfg(all(feature = "olap", feature = "aws_kms"))] +#[cfg(feature = "olap")] use super::verification::{apple_pay_merchant_registration, retrieve_apple_pay_verified_domains}; #[cfg(feature = "olap")] use super::{ @@ -49,6 +41,7 @@ use super::{cache::*, health::*}; use super::{configs::*, customers::*, mandates::*, payments::*, refunds::*}; #[cfg(feature = "oltp")] use super::{ephemeral_key::*, payment_methods::*, webhooks::*}; +use crate::configs::secrets_transformers; #[cfg(all(feature = "frm", feature = "oltp"))] use crate::routes::fraud_check as frm_routes; #[cfg(all(feature = "recon", feature = "olap"))] @@ -68,12 +61,10 @@ pub use crate::{ pub struct AppState { pub flow_name: String, pub store: Box, - pub conf: Arc, + pub conf: Arc>, pub event_handler: EventsHandler, #[cfg(feature = "email")] pub email_client: Arc, - #[cfg(feature = "aws_kms")] - pub kms_secrets: Arc, pub api_client: Box, #[cfg(feature = "olap")] pub pool: crate::analytics::AnalyticsProvider, @@ -89,7 +80,7 @@ impl scheduler::SchedulerAppState for AppState { } pub trait AppStateInfo { - fn conf(&self) -> settings::Settings; + fn conf(&self) -> settings::Settings; fn store(&self) -> Box; fn event_handler(&self) -> EventsHandler; #[cfg(feature = "email")] @@ -101,7 +92,7 @@ pub trait AppStateInfo { } impl AppStateInfo for AppState { - fn conf(&self) -> settings::Settings { + fn conf(&self) -> settings::Settings { self.conf.as_ref().to_owned() } fn store(&self) -> Box { @@ -138,7 +129,7 @@ impl AsRef for AppState { } #[cfg(feature = "email")] -pub async fn create_email_client(settings: &settings::Settings) -> impl EmailService { +pub async fn create_email_client(settings: &settings::Settings) -> impl EmailService { match settings.email.active_email_client { external_services::email::AvailableEmailClients::SES => { AwsSes::create(&settings.email, settings.proxy.https_url.to_owned()).await @@ -151,12 +142,20 @@ impl AppState { /// /// Panics if Store can't be created or JWE decryption fails pub async fn with_storage( - #[cfg_attr(not(all(feature = "olap", feature = "aws_kms")), allow(unused_mut))] - mut conf: settings::Settings, + conf: settings::Settings, storage_impl: StorageImpl, shut_down_signal: oneshot::Sender<()>, api_client: Box, ) -> Self { + #[allow(clippy::expect_used)] + let secret_management_client = conf + .secrets_management + .get_secret_management_client() + .await + .expect("Failed to create secret management client"); + + let conf = secrets_transformers::fetch_raw_secrets(conf, &*secret_management_client).await; + #[allow(clippy::expect_used)] let encryption_client = conf .encryption_management @@ -165,14 +164,6 @@ impl AppState { .expect("Failed to create encryption client"); Box::pin(async move { - #[cfg(feature = "aws_kms")] - let aws_kms_client = aws_kms::core::get_aws_kms_client(&conf.kms).await; - #[cfg(all(feature = "hashicorp-vault", feature = "olap"))] - #[allow(clippy::expect_used)] - let hc_client = - external_services::hashicorp_vault::core::get_hashicorp_client(&conf.hc_vault) - .await - .expect("Failed while creating hashicorp_client"); let testable = storage_impl == StorageImpl::PostgresqlTest; #[allow(clippy::expect_used)] let event_handler = conf @@ -208,80 +199,9 @@ impl AppState { ), }; - #[cfg(all(feature = "hashicorp-vault", feature = "olap"))] - #[allow(clippy::expect_used)] - match conf.analytics { - AnalyticsConfig::Clickhouse { .. } => {} - AnalyticsConfig::Sqlx { ref mut sqlx } - | AnalyticsConfig::CombinedCkh { ref mut sqlx, .. } - | AnalyticsConfig::CombinedSqlx { ref mut sqlx, .. } => { - sqlx.password = sqlx - .password - .clone() - .fetch_inner::(hc_client) - .await - .expect("Failed while fetching from hashicorp vault"); - } - }; - - #[cfg(all(feature = "aws_kms", feature = "olap"))] - #[allow(clippy::expect_used)] - match conf.analytics { - AnalyticsConfig::Clickhouse { .. } => {} - AnalyticsConfig::Sqlx { ref mut sqlx } - | AnalyticsConfig::CombinedCkh { ref mut sqlx, .. } - | AnalyticsConfig::CombinedSqlx { ref mut sqlx, .. } => { - sqlx.password = aws_kms_client - .decrypt(&sqlx.password.peek()) - .await - .expect("Failed to decrypt password") - .into(); - } - }; - - #[cfg(all(feature = "hashicorp-vault", feature = "olap"))] - #[allow(clippy::expect_used)] - { - conf.connector_onboarding = conf - .connector_onboarding - .fetch_inner::(hc_client) - .await - .expect("Failed to decrypt connector onboarding credentials"); - } - - #[cfg(all(feature = "aws_kms", feature = "olap"))] - #[allow(clippy::expect_used)] - { - conf.connector_onboarding = conf - .connector_onboarding - .decrypt_inner(aws_kms_client) - .await - .expect("Failed to decrypt connector onboarding credentials"); - } - #[cfg(feature = "olap")] let pool = crate::analytics::AnalyticsProvider::from_conf(&conf.analytics).await; - #[cfg(all(feature = "hashicorp-vault", feature = "olap"))] - #[allow(clippy::expect_used)] - { - conf.jwekey = conf - .jwekey - .clone() - .fetch_inner::(hc_client) - .await - .expect("Failed to decrypt connector onboarding credentials"); - } - - #[cfg(feature = "aws_kms")] - #[allow(clippy::expect_used)] - let kms_secrets = settings::ActiveKmsSecrets { - jwekey: conf.jwekey.clone().into(), - } - .decrypt_inner(aws_kms_client) - .await - .expect("Failed while performing AWS KMS decryption"); - #[cfg(feature = "email")] let email_client = Arc::new(create_email_client(&conf).await); @@ -293,8 +213,6 @@ impl AppState { conf: Arc::new(conf), #[cfg(feature = "email")] email_client, - #[cfg(feature = "aws_kms")] - kms_secrets: Arc::new(kms_secrets), api_client, event_handler, #[cfg(feature = "olap")] @@ -308,7 +226,7 @@ impl AppState { } pub async fn new( - conf: settings::Settings, + conf: settings::Settings, shut_down_signal: oneshot::Sender<()>, api_client: Box, ) -> Self { @@ -1114,10 +1032,10 @@ impl Gsm { } } -#[cfg(all(feature = "olap", feature = "aws_kms"))] +#[cfg(feature = "olap")] pub struct Verify; -#[cfg(all(feature = "olap", feature = "aws_kms"))] +#[cfg(feature = "olap")] impl Verify { pub fn server(state: AppState) -> Scope { web::scope("/verify") diff --git a/crates/router/src/routes/metrics.rs b/crates/router/src/routes/metrics.rs index 770ae9aafc..f667479cea 100644 --- a/crates/router/src/routes/metrics.rs +++ b/crates/router/src/routes/metrics.rs @@ -5,10 +5,6 @@ global_meter!(GLOBAL_METER, "ROUTER_API"); counter_metric!(HEALTH_METRIC, GLOBAL_METER); // No. of health API hits counter_metric!(KV_MISS, GLOBAL_METER); // No. of KV misses -#[cfg(feature = "aws_kms")] -counter_metric!(AWS_KMS_ENCRYPTION_FAILURES, GLOBAL_METER); // No. of AWS KMS Encryption failures -#[cfg(feature = "aws_kms")] -counter_metric!(AWS_KMS_DECRYPTION_FAILURES, GLOBAL_METER); // No. of AWS KMS Decryption failures // API Level Metrics counter_metric!(REQUESTS_RECEIVED, GLOBAL_METER); diff --git a/crates/router/src/routes/verification.rs b/crates/router/src/routes/verification.rs index 4bcbacdf99..91fd204ba2 100644 --- a/crates/router/src/routes/verification.rs +++ b/crates/router/src/routes/verification.rs @@ -17,7 +17,6 @@ pub async fn apple_pay_merchant_registration( ) -> impl Responder { let flow = Flow::Verification; let merchant_id = path.into_inner(); - let kms_conf = &state.clone().conf.kms; Box::pin(api::server_wrap( flow, state, @@ -26,9 +25,7 @@ pub async fn apple_pay_merchant_registration( |state, _, body| { verification::verify_merchant_creds_for_applepay( state.clone(), - &req, body, - kms_conf, merchant_id.clone(), ) }, diff --git a/crates/router/src/services.rs b/crates/router/src/services.rs index dc7bf14fec..617b9df712 100644 --- a/crates/router/src/services.rs +++ b/crates/router/src/services.rs @@ -13,22 +13,16 @@ pub mod recon; #[cfg(feature = "email")] pub mod email; -#[cfg(any(feature = "aws_kms", feature = "hashicorp-vault"))] -use data_models::errors::StorageError; use data_models::errors::StorageResult; use error_stack::{IntoReport, ResultExt}; -#[cfg(feature = "aws_kms")] -use external_services::aws_kms::{self, decrypt::AwsKmsDecrypt}; -#[cfg(feature = "hashicorp-vault")] -use external_services::hashicorp_vault::decrypt::VaultFetch; -use masking::{PeekInterface, StrongSecret}; +use masking::{ExposeInterface, StrongSecret}; #[cfg(feature = "kv_store")] use storage_impl::KVRouterStore; use storage_impl::RouterStore; use tokio::sync::oneshot; pub use self::{api::*, encryption::*}; -use crate::{configs::settings, consts, core::errors}; +use crate::{configs::Settings, consts, core::errors}; #[cfg(not(feature = "olap"))] pub type StoreType = storage_impl::database::store::Store; @@ -40,61 +34,25 @@ pub type Store = RouterStore; #[cfg(feature = "kv_store")] pub type Store = KVRouterStore; +/// # Panics +/// +/// Will panic if hex decode of master key fails +#[allow(clippy::expect_used)] pub async fn get_store( - config: &settings::Settings, + config: &Settings, shut_down_signal: oneshot::Sender<()>, test_transaction: bool, ) -> StorageResult { - #[cfg(feature = "aws_kms")] - let aws_kms_client = aws_kms::core::get_aws_kms_client(&config.kms).await; - - #[cfg(feature = "hashicorp-vault")] - let hc_client = - external_services::hashicorp_vault::core::get_hashicorp_client(&config.hc_vault) - .await - .change_context(StorageError::InitializationError)?; - - let master_config = config.master_database.clone(); - - #[cfg(feature = "hashicorp-vault")] - let master_config = master_config - .fetch_inner::(hc_client) - .await - .change_context(StorageError::InitializationError) - .attach_printable("Failed to fetch data from hashicorp vault")?; - - #[cfg(feature = "aws_kms")] - let master_config = master_config - .decrypt_inner(aws_kms_client) - .await - .change_context(StorageError::InitializationError) - .attach_printable("Failed to decrypt master database config")?; + let master_config = config.master_database.clone().into_inner(); #[cfg(feature = "olap")] - let replica_config = config.replica_database.clone(); + let replica_config = config.replica_database.clone().into_inner(); - #[cfg(all(feature = "olap", feature = "hashicorp-vault"))] - let replica_config = replica_config - .fetch_inner::(hc_client) - .await - .change_context(StorageError::InitializationError) - .attach_printable("Failed to fetch data from hashicorp vault")?; + #[allow(clippy::expect_used)] + let master_enc_key = hex::decode(config.secrets.get_inner().master_enc_key.clone().expose()) + .map(StrongSecret::new) + .expect("Failed to decode master key from hex"); - #[cfg(all(feature = "olap", feature = "aws_kms"))] - let replica_config = replica_config - .decrypt_inner(aws_kms_client) - .await - .change_context(StorageError::InitializationError) - .attach_printable("Failed to decrypt replica database config")?; - - let master_enc_key = get_master_enc_key( - config, - #[cfg(feature = "aws_kms")] - aws_kms_client, - #[cfg(feature = "hashicorp-vault")] - hc_client, - ) - .await; #[cfg(not(feature = "olap"))] let conf = master_config.into(); #[cfg(feature = "olap")] @@ -126,34 +84,6 @@ pub async fn get_store( Ok(store) } -#[allow(clippy::expect_used)] -async fn get_master_enc_key( - conf: &crate::configs::settings::Settings, - #[cfg(feature = "aws_kms")] aws_kms_client: &aws_kms::core::AwsKmsClient, - #[cfg(feature = "hashicorp-vault")] - hc_client: &external_services::hashicorp_vault::core::HashiCorpVault, -) -> StrongSecret> { - let master_enc_key = conf.secrets.master_enc_key.clone(); - - #[cfg(feature = "hashicorp-vault")] - let master_enc_key = master_enc_key - .fetch_inner::(hc_client) - .await - .expect("Failed to fetch master enc key"); - - #[cfg(feature = "aws_kms")] - let master_enc_key = masking::Secret::<_, masking::WithType>::new( - master_enc_key - .decrypt_inner(aws_kms_client) - .await - .expect("Failed to decrypt master enc key"), - ); - - let master_enc_key = hex::decode(master_enc_key.peek()).expect("Failed to decode from hex"); - - StrongSecret::new(master_enc_key) -} - #[inline] pub fn generate_aes256_key() -> errors::CustomResult<[u8; 32], common_utils::errors::CryptoError> { use ring::rand::SecureRandom; diff --git a/crates/router/src/services/api.rs b/crates/router/src/services/api.rs index 1c4d1810c8..738f57e9d7 100644 --- a/crates/router/src/services/api.rs +++ b/crates/router/src/services/api.rs @@ -29,7 +29,7 @@ use tera::{Context, Tera}; use self::request::{HeaderExt, RequestBuilderExt}; use super::authentication::AuthenticateAndFetch; use crate::{ - configs::settings::{Connectors, Settings}, + configs::{settings::Connectors, Settings}, consts, core::{ api_locking, diff --git a/crates/router/src/services/authentication.rs b/crates/router/src/services/authentication.rs index 455dc97d03..7cf1855b44 100644 --- a/crates/router/src/services/authentication.rs +++ b/crates/router/src/services/authentication.rs @@ -3,14 +3,8 @@ use api_models::{payment_methods::PaymentMethodListRequest, payments}; use async_trait::async_trait; use common_utils::date_time; use error_stack::{report, IntoReport, ResultExt}; -#[cfg(feature = "aws_kms")] -use external_services::aws_kms::{self, decrypt::AwsKmsDecrypt}; -#[cfg(feature = "hashicorp-vault")] -use external_services::hashicorp_vault::decrypt::VaultFetch; use jsonwebtoken::{decode, Algorithm, DecodingKey, Validation}; -#[cfg(feature = "hashicorp-vault")] -use masking::ExposeInterface; -use masking::{PeekInterface, StrongSecret}; +use masking::PeekInterface; use serde::Serialize; use self::blacklist::BlackList; @@ -20,13 +14,14 @@ use super::jwt; #[cfg(feature = "recon")] use super::recon::ReconToken; #[cfg(feature = "olap")] +use crate::configs::Settings; +#[cfg(feature = "olap")] use crate::consts; #[cfg(feature = "olap")] use crate::core::errors::UserResult; #[cfg(feature = "recon")] use crate::routes::AppState; use crate::{ - configs::settings, core::{ api_keys, errors::{self, utils::StorageErrorExt, RouterResult}, @@ -108,7 +103,7 @@ pub struct UserAuthToken { #[cfg(feature = "olap")] impl UserAuthToken { - pub async fn new_token(user_id: String, settings: &settings::Settings) -> UserResult { + pub async fn new_token(user_id: String, settings: &Settings) -> UserResult { let exp_duration = std::time::Duration::from_secs(consts::JWT_TOKEN_TIME_IN_SECS); let exp = jwt::generate_exp(exp_duration)?.as_secs(); let token_payload = Self { user_id, exp }; @@ -131,7 +126,7 @@ impl AuthToken { user_id: String, merchant_id: String, role_id: String, - settings: &settings::Settings, + settings: &Settings, org_id: String, ) -> UserResult { let exp_duration = std::time::Duration::from_secs(consts::JWT_TOKEN_TIME_IN_SECS); @@ -224,16 +219,7 @@ where let api_key = api_keys::PlaintextApiKey::from(api_key); let hash_key = { let config = state.conf(); - api_keys::get_hash_key( - &config.api_keys, - #[cfg(feature = "aws_kms")] - aws_kms::core::get_aws_kms_client(&config.kms).await, - #[cfg(feature = "hashicorp-vault")] - external_services::hashicorp_vault::core::get_hashicorp_client(&config.hc_vault) - .await - .change_context(errors::ApiErrorResponse::InternalServerError)?, - ) - .await? + config.api_keys.get_inner().get_hash_key()? }; let hashed_api_key = api_key.keyed_hash(hash_key.peek()); @@ -285,41 +271,6 @@ where } } -static ADMIN_API_KEY: tokio::sync::OnceCell> = - tokio::sync::OnceCell::const_new(); - -pub async fn get_admin_api_key( - secrets: &settings::Secrets, - #[cfg(feature = "aws_kms")] aws_kms_client: &aws_kms::core::AwsKmsClient, - #[cfg(feature = "hashicorp-vault")] - hc_client: &external_services::hashicorp_vault::core::HashiCorpVault, -) -> RouterResult<&'static StrongSecret> { - ADMIN_API_KEY - .get_or_try_init(|| async { - #[cfg(not(feature = "aws_kms"))] - let admin_api_key = secrets.admin_api_key.clone(); - - #[cfg(feature = "aws_kms")] - let admin_api_key = secrets - .kms_encrypted_admin_api_key - .decrypt_inner(aws_kms_client) - .await - .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable("Failed to AWS KMS decrypt admin API key")?; - - #[cfg(feature = "hashicorp-vault")] - let admin_api_key = masking::Secret::new(admin_api_key) - .fetch_inner::(hc_client) - .await - .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable("Failed to KMS decrypt admin API key")? - .expose(); - - Ok(StrongSecret::new(admin_api_key)) - }) - .await -} - #[derive(Debug)] pub struct UserWithoutMerchantJWTAuth; @@ -367,17 +318,7 @@ where get_api_key(request_headers).change_context(errors::ApiErrorResponse::Unauthorized)?; let conf = state.conf(); - let admin_api_key = get_admin_api_key( - &conf.secrets, - #[cfg(feature = "aws_kms")] - aws_kms::core::get_aws_kms_client(&conf.kms).await, - #[cfg(feature = "hashicorp-vault")] - external_services::hashicorp_vault::core::get_hashicorp_client(&conf.hc_vault) - .await - .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable("Failed while getting admin api key")?, - ) - .await?; + let admin_api_key = &conf.secrets.get_inner().admin_api_key; if request_admin_api_key != admin_api_key.peek() { Err(report!(errors::ApiErrorResponse::Unauthorized) @@ -912,43 +853,12 @@ pub fn is_jwt_auth(headers: &HeaderMap) -> bool { headers.get(crate::headers::AUTHORIZATION).is_some() } -static JWT_SECRET: tokio::sync::OnceCell> = tokio::sync::OnceCell::const_new(); - -pub async fn get_jwt_secret( - secrets: &settings::Secrets, - #[cfg(feature = "aws_kms")] aws_kms_client: &aws_kms::core::AwsKmsClient, -) -> RouterResult<&'static StrongSecret> { - JWT_SECRET - .get_or_try_init(|| async { - #[cfg(feature = "aws_kms")] - let jwt_secret = secrets - .kms_encrypted_jwt_secret - .decrypt_inner(aws_kms_client) - .await - .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable("Failed to AWS KMS decrypt JWT secret")?; - - #[cfg(not(feature = "aws_kms"))] - let jwt_secret = secrets.jwt_secret.clone(); - - Ok(StrongSecret::new(jwt_secret)) - }) - .await -} - pub async fn decode_jwt(token: &str, state: &impl AppStateInfo) -> RouterResult where T: serde::de::DeserializeOwned, { let conf = state.conf(); - let secret = get_jwt_secret( - &conf.secrets, - #[cfg(feature = "aws_kms")] - aws_kms::core::get_aws_kms_client(&conf.kms).await, - ) - .await? - .peek() - .as_bytes(); + let secret = conf.secrets.get_inner().jwt_secret.peek().as_bytes(); let key = DecodingKey::from_secret(secret); decode::(token, &key, &Validation::new(Algorithm::HS256)) @@ -1008,33 +918,6 @@ where default_auth } -#[cfg(feature = "recon")] -static RECON_API_KEY: tokio::sync::OnceCell> = - tokio::sync::OnceCell::const_new(); - -#[cfg(feature = "recon")] -pub async fn get_recon_admin_api_key( - secrets: &settings::Secrets, - #[cfg(feature = "aws_kms")] kms_client: &aws_kms::core::AwsKmsClient, -) -> RouterResult<&'static StrongSecret> { - RECON_API_KEY - .get_or_try_init(|| async { - #[cfg(feature = "aws_kms")] - let recon_admin_api_key = secrets - .kms_encrypted_recon_admin_api_key - .decrypt_inner(kms_client) - .await - .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable("Failed to KMS decrypt recon admin API key")?; - - #[cfg(not(feature = "aws_kms"))] - let recon_admin_api_key = secrets.recon_admin_api_key.clone(); - - Ok(StrongSecret::new(recon_admin_api_key)) - }) - .await -} - #[cfg(feature = "recon")] pub struct ReconAdmin; @@ -1053,14 +936,9 @@ where get_api_key(request_headers).change_context(errors::ApiErrorResponse::Unauthorized)?; let conf = state.conf(); - let admin_api_key = get_recon_admin_api_key( - &conf.secrets, - #[cfg(feature = "aws_kms")] - aws_kms::core::get_aws_kms_client(&conf.kms).await, - ) - .await?; + let admin_api_key = conf.secrets.get_inner().recon_admin_api_key.peek(); - if request_admin_api_key != admin_api_key.peek() { + if request_admin_api_key != admin_api_key { Err(report!(errors::ApiErrorResponse::Unauthorized) .attach_printable("Recon Admin Authentication Failure"))?; } diff --git a/crates/router/src/services/email/types.rs b/crates/router/src/services/email/types.rs index 46cfad0878..fa1eecbaab 100644 --- a/crates/router/src/services/email/types.rs +++ b/crates/router/src/services/email/types.rs @@ -147,7 +147,7 @@ impl EmailToken { pub async fn new_token( email: domain::UserEmail, merchant_id: Option, - settings: &configs::settings::Settings, + settings: &configs::Settings, ) -> CustomResult { let expiration_duration = std::time::Duration::from_secs(consts::EMAIL_TOKEN_TIME_IN_SECS); let exp = jwt::generate_exp(expiration_duration)?.as_secs(); @@ -178,7 +178,7 @@ pub fn get_link_with_token( pub struct VerifyEmail { pub recipient_email: domain::UserEmail, - pub settings: std::sync::Arc, + pub settings: std::sync::Arc, pub subject: &'static str, } @@ -208,7 +208,7 @@ impl EmailData for VerifyEmail { pub struct ResetPassword { pub recipient_email: domain::UserEmail, pub user_name: domain::UserName, - pub settings: std::sync::Arc, + pub settings: std::sync::Arc, pub subject: &'static str, } @@ -238,7 +238,7 @@ impl EmailData for ResetPassword { pub struct MagicLink { pub recipient_email: domain::UserEmail, pub user_name: domain::UserName, - pub settings: std::sync::Arc, + pub settings: std::sync::Arc, pub subject: &'static str, } @@ -268,7 +268,7 @@ impl EmailData for MagicLink { pub struct InviteUser { pub recipient_email: domain::UserEmail, pub user_name: domain::UserName, - pub settings: std::sync::Arc, + pub settings: std::sync::Arc, pub subject: &'static str, pub merchant_id: String, } @@ -302,7 +302,7 @@ impl EmailData for InviteUser { pub struct InviteRegisteredUser { pub recipient_email: domain::UserEmail, pub user_name: domain::UserName, - pub settings: std::sync::Arc, + pub settings: std::sync::Arc, pub subject: &'static str, pub merchant_id: String, } @@ -339,7 +339,7 @@ impl EmailData for InviteRegisteredUser { pub struct ReconActivation { pub recipient_email: domain::UserEmail, pub user_name: domain::UserName, - pub settings: std::sync::Arc, + pub settings: std::sync::Arc, pub subject: &'static str, } @@ -365,7 +365,7 @@ pub struct BizEmailProd { pub legal_business_name: String, pub business_location: String, pub business_website: String, - pub settings: std::sync::Arc, + pub settings: std::sync::Arc, pub subject: &'static str, } @@ -413,7 +413,7 @@ pub struct ProFeatureRequest { pub feature_name: String, pub merchant_id: String, pub user_name: domain::UserName, - pub settings: std::sync::Arc, + pub settings: std::sync::Arc, pub subject: String, } diff --git a/crates/router/src/services/jwt.rs b/crates/router/src/services/jwt.rs index 05de1b4e11..6a78e2232a 100644 --- a/crates/router/src/services/jwt.rs +++ b/crates/router/src/services/jwt.rs @@ -3,8 +3,7 @@ use error_stack::{IntoReport, ResultExt}; use jsonwebtoken::{encode, EncodingKey, Header}; use masking::PeekInterface; -use super::authentication; -use crate::{configs::settings::Settings, core::errors::UserErrors}; +use crate::{configs::Settings, core::errors::UserErrors}; pub fn generate_exp( exp_duration: std::time::Duration, @@ -24,14 +23,7 @@ pub async fn generate_jwt( where T: serde::ser::Serialize, { - let jwt_secret = authentication::get_jwt_secret( - &settings.secrets, - #[cfg(feature = "aws_kms")] - external_services::aws_kms::core::get_aws_kms_client(&settings.kms).await, - ) - .await - .change_context(UserErrors::InternalServerError) - .attach_printable("Failed to obtain JWT secret")?; + let jwt_secret = &settings.secrets.get_inner().jwt_secret; encode( &Header::default(), claims_data, diff --git a/crates/router/src/services/recon.rs b/crates/router/src/services/recon.rs index d5a2151a48..cc10fb7c7f 100644 --- a/crates/router/src/services/recon.rs +++ b/crates/router/src/services/recon.rs @@ -3,9 +3,9 @@ use masking::Secret; use super::jwt; use crate::{ + configs::Settings, consts, core::{self, errors::RouterResult}, - routes::app::settings::Settings, }; #[derive(serde::Serialize, serde::Deserialize)] diff --git a/crates/router/src/utils/connector_onboarding/paypal.rs b/crates/router/src/utils/connector_onboarding/paypal.rs index 6d7f2692be..ff9b5ab59e 100644 --- a/crates/router/src/utils/connector_onboarding/paypal.rs +++ b/crates/router/src/utils/connector_onboarding/paypal.rs @@ -20,7 +20,8 @@ pub async fn generate_access_token(state: AppState) -> RouterResult CustomResult { for _n in 1..local_fetch_retry_count { sleep(Duration::from_millis(local_fetch_retry_delay)).await; @@ -148,15 +141,7 @@ async fn waited_fetch_and_update_caches( } } //acquire lock one last time and try to fetch and update local & redis - successive_fetch_and_save_forex( - state, - None, - #[cfg(feature = "aws_kms")] - aws_kms_config, - #[cfg(feature = "hashicorp-vault")] - hc_config, - ) - .await + successive_fetch_and_save_forex(state, None).await } impl TryFrom for ExchangeRates { @@ -192,23 +177,11 @@ pub async fn get_forex_rates( call_delay: i64, local_fetch_retry_delay: u64, local_fetch_retry_count: u64, - #[cfg(feature = "aws_kms")] aws_kms_config: &aws_kms::core::AwsKmsConfig, - #[cfg(feature = "hashicorp-vault")] - hc_config: &external_services::hashicorp_vault::core::HashiCorpVaultConfig, ) -> CustomResult { if let Some(local_rates) = retrieve_forex_from_local().await { if local_rates.is_expired(call_delay) { // expired local data - handler_local_expired( - state, - call_delay, - local_rates, - #[cfg(feature = "aws_kms")] - aws_kms_config, - #[cfg(feature = "hashicorp-vault")] - hc_config, - ) - .await + handler_local_expired(state, call_delay, local_rates).await } else { // Valid data present in local Ok(local_rates) @@ -220,10 +193,6 @@ pub async fn get_forex_rates( call_delay, local_fetch_retry_delay, local_fetch_retry_count, - #[cfg(feature = "aws_kms")] - aws_kms_config, - #[cfg(feature = "hashicorp-vault")] - hc_config, ) .await } @@ -234,46 +203,16 @@ async fn handler_local_no_data( call_delay: i64, _local_fetch_retry_delay: u64, _local_fetch_retry_count: u64, - #[cfg(feature = "aws_kms")] aws_kms_config: &aws_kms::core::AwsKmsConfig, - #[cfg(feature = "hashicorp-vault")] - hc_config: &external_services::hashicorp_vault::core::HashiCorpVaultConfig, ) -> CustomResult { match retrieve_forex_from_redis(state).await { - Ok(Some(data)) => { - fallback_forex_redis_check( - state, - data, - call_delay, - #[cfg(feature = "aws_kms")] - aws_kms_config, - #[cfg(feature = "hashicorp-vault")] - hc_config, - ) - .await - } + Ok(Some(data)) => fallback_forex_redis_check(state, data, call_delay).await, Ok(None) => { // No data in local as well as redis - Ok(successive_fetch_and_save_forex( - state, - None, - #[cfg(feature = "aws_kms")] - aws_kms_config, - #[cfg(feature = "hashicorp-vault")] - hc_config, - ) - .await?) + Ok(successive_fetch_and_save_forex(state, None).await?) } Err(err) => { logger::error!(?err); - Ok(successive_fetch_and_save_forex( - state, - None, - #[cfg(feature = "aws_kms")] - aws_kms_config, - #[cfg(feature = "hashicorp-vault")] - hc_config, - ) - .await?) + Ok(successive_fetch_and_save_forex(state, None).await?) } } } @@ -281,36 +220,19 @@ async fn handler_local_no_data( async fn successive_fetch_and_save_forex( state: &AppState, stale_redis_data: Option, - #[cfg(feature = "aws_kms")] aws_kms_config: &aws_kms::core::AwsKmsConfig, - #[cfg(feature = "hashicorp-vault")] - hc_config: &external_services::hashicorp_vault::core::HashiCorpVaultConfig, ) -> CustomResult { match acquire_redis_lock(state).await { Ok(lock_acquired) => { if !lock_acquired { return stale_redis_data.ok_or(ForexCacheError::CouldNotAcquireLock.into()); } - let api_rates = fetch_forex_rates( - state, - #[cfg(feature = "aws_kms")] - aws_kms_config, - #[cfg(feature = "hashicorp-vault")] - hc_config, - ) - .await; + let api_rates = fetch_forex_rates(state).await; match api_rates { Ok(rates) => successive_save_data_to_redis_local(state, rates).await, Err(err) => { // API not able to fetch data call secondary service logger::error!(?err); - let secondary_api_rates = fallback_fetch_forex_rates( - state, - #[cfg(feature = "aws_kms")] - aws_kms_config, - #[cfg(feature = "hashicorp-vault")] - hc_config, - ) - .await; + let secondary_api_rates = fallback_fetch_forex_rates(state).await; match secondary_api_rates { Ok(rates) => Ok(successive_save_data_to_redis_local(state, rates).await?), Err(err) => stale_redis_data.ok_or({ @@ -351,9 +273,6 @@ async fn fallback_forex_redis_check( state: &AppState, redis_data: FxExchangeRatesCacheEntry, call_delay: i64, - #[cfg(feature = "aws_kms")] aws_kms_config: &aws_kms::core::AwsKmsConfig, - #[cfg(feature = "hashicorp-vault")] - hc_config: &external_services::hashicorp_vault::core::HashiCorpVaultConfig, ) -> CustomResult { match is_redis_expired(Some(redis_data.clone()).as_ref(), call_delay).await { Some(redis_forex) => { @@ -364,15 +283,7 @@ async fn fallback_forex_redis_check( } None => { // redis expired - successive_fetch_and_save_forex( - state, - Some(redis_data), - #[cfg(feature = "aws_kms")] - aws_kms_config, - #[cfg(feature = "hashicorp-vault")] - hc_config, - ) - .await + successive_fetch_and_save_forex(state, Some(redis_data)).await } } } @@ -381,9 +292,6 @@ async fn handler_local_expired( state: &AppState, call_delay: i64, local_rates: FxExchangeRatesCacheEntry, - #[cfg(feature = "aws_kms")] aws_kms_config: &aws_kms::core::AwsKmsConfig, - #[cfg(feature = "hashicorp-vault")] - hc_config: &external_services::hashicorp_vault::core::HashiCorpVaultConfig, ) -> CustomResult { match retrieve_forex_from_redis(state).await { Ok(redis_data) => { @@ -397,71 +305,22 @@ async fn handler_local_expired( } None => { // Redis is expired going for API request - successive_fetch_and_save_forex( - state, - Some(local_rates), - #[cfg(feature = "aws_kms")] - aws_kms_config, - #[cfg(feature = "hashicorp-vault")] - hc_config, - ) - .await + successive_fetch_and_save_forex(state, Some(local_rates)).await } } } Err(e) => { // data not present in redis waited fetch logger::error!(?e); - successive_fetch_and_save_forex( - state, - Some(local_rates), - #[cfg(feature = "aws_kms")] - aws_kms_config, - #[cfg(feature = "hashicorp-vault")] - hc_config, - ) - .await + successive_fetch_and_save_forex(state, Some(local_rates)).await } } } async fn fetch_forex_rates( state: &AppState, - #[cfg(feature = "aws_kms")] aws_kms_config: &aws_kms::core::AwsKmsConfig, - - #[cfg(feature = "hashicorp-vault")] - hc_config: &external_services::hashicorp_vault::core::HashiCorpVaultConfig, ) -> Result> { - let forex_api_key = async { - #[cfg(feature = "hashicorp-vault")] - let client = hashicorp_vault::core::get_hashicorp_client(hc_config) - .await - .change_context(ForexCacheError::AwsKmsDecryptionFailed)?; - - #[cfg(not(feature = "hashicorp-vault"))] - let output = state.conf.forex_api.api_key.clone(); - #[cfg(feature = "hashicorp-vault")] - let output = state - .conf - .forex_api - .api_key - .clone() - .fetch_inner::(client) - .await - .change_context(ForexCacheError::AwsKmsDecryptionFailed)?; - - Ok::<_, error_stack::Report>(output) - } - .await?; - #[cfg(feature = "aws_kms")] - let forex_api_key = aws_kms::core::get_aws_kms_client(aws_kms_config) - .await - .decrypt(forex_api_key.peek()) - .await - .change_context(ForexCacheError::AwsKmsDecryptionFailed)?; - - #[cfg(not(feature = "aws_kms"))] - let forex_api_key = forex_api_key.peek(); + let forex_api_key = state.conf.forex_api.get_inner().api_key.peek(); let forex_url: String = format!("{}{}{}", FOREX_BASE_URL, forex_api_key, FOREX_BASE_CURRENCY); let forex_request = services::RequestBuilder::new() @@ -516,40 +375,8 @@ async fn fetch_forex_rates( pub async fn fallback_fetch_forex_rates( state: &AppState, - #[cfg(feature = "aws_kms")] aws_kms_config: &aws_kms::core::AwsKmsConfig, - #[cfg(feature = "hashicorp-vault")] - hc_config: &external_services::hashicorp_vault::core::HashiCorpVaultConfig, ) -> CustomResult { - let fallback_api_key = async { - #[cfg(feature = "hashicorp-vault")] - let client = hashicorp_vault::core::get_hashicorp_client(hc_config) - .await - .change_context(ForexCacheError::AwsKmsDecryptionFailed)?; - - #[cfg(not(feature = "hashicorp-vault"))] - let output = state.conf.forex_api.fallback_api_key.clone(); - #[cfg(feature = "hashicorp-vault")] - let output = state - .conf - .forex_api - .fallback_api_key - .clone() - .fetch_inner::(client) - .await - .change_context(ForexCacheError::AwsKmsDecryptionFailed)?; - - Ok::<_, error_stack::Report>(output) - } - .await?; - #[cfg(feature = "aws_kms")] - let fallback_forex_api_key = aws_kms::core::get_aws_kms_client(aws_kms_config) - .await - .decrypt(fallback_api_key.peek()) - .await - .change_context(ForexCacheError::AwsKmsDecryptionFailed)?; - - #[cfg(not(feature = "aws_kms"))] - let fallback_forex_api_key = fallback_api_key.peek(); + let fallback_forex_api_key = state.conf.forex_api.get_inner().fallback_api_key.peek(); let fallback_forex_url: String = format!("{}{}", FALLBACK_FOREX_BASE_URL, fallback_forex_api_key,); @@ -627,6 +454,7 @@ async fn release_redis_lock( } async fn acquire_redis_lock(app_state: &AppState) -> CustomResult { + let forex_api = app_state.conf.forex_api.get_inner(); app_state .store .get_redis_conn() @@ -635,9 +463,8 @@ async fn acquire_redis_lock(app_state: &AppState) -> CustomResult CustomResult { + let forex_api = state.conf.forex_api.get_inner(); let rates = get_forex_rates( &state, - state.conf.forex_api.call_delay, - state.conf.forex_api.local_fetch_retry_delay, - state.conf.forex_api.local_fetch_retry_count, - #[cfg(feature = "aws_kms")] - aws_kms_config, - #[cfg(feature = "hashicorp-vault")] - hc_config, + forex_api.call_delay, + forex_api.local_fetch_retry_delay, + forex_api.local_fetch_retry_count, ) .await .change_context(ForexCacheError::ApiError)?;