From cfade55e693594a772c18eee2c35d7b3dc03f84d Mon Sep 17 00:00:00 2001 From: Chethan Rao <70657455+Chethan-rao@users.noreply.github.com> Date: Wed, 6 Mar 2024 18:11:17 +0530 Subject: [PATCH] refactor: kms decrypt analytics config (#3984) --- Cargo.lock | 1 + crates/analytics/Cargo.toml | 5 +- crates/analytics/src/lib.rs | 51 +++++++++++++++++++ .../src/configs/secrets_transformers.rs | 9 +++- crates/router/src/configs/settings.rs | 2 +- crates/router/src/routes/app.rs | 3 +- 6 files changed, 66 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 60bc557972..4571d80fd8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -349,6 +349,7 @@ dependencies = [ "error-stack", "external_services", "futures 0.3.28", + "hyperswitch_interfaces", "masking", "once_cell", "reqwest", diff --git a/crates/analytics/Cargo.toml b/crates/analytics/Cargo.toml index 82ac2dde03..f3e0149213 100644 --- a/crates/analytics/Cargo.toml +++ b/crates/analytics/Cargo.toml @@ -11,8 +11,9 @@ edition = "2021" # First party crates api_models = { version = "0.1.0", path = "../api_models" , features = ["errors"]} storage_impl = { version = "0.1.0", path = "../storage_impl", default-features = false } -common_utils = { version = "0.1.0", path = "../common_utils"} -external_services = { version = "0.1.0", path = "../external_services", default-features = false} +common_utils = { version = "0.1.0", path = "../common_utils" } +external_services = { version = "0.1.0", path = "../external_services", default-features = false } +hyperswitch_interfaces = { version = "0.1.0", path = "../hyperswitch_interfaces" } masking = { version = "0.1.0", path = "../masking" } router_env = { version = "0.1.0", path = "../router_env", features = ["log_extra_implicit_fields", "log_custom_entries_to_extra"] } diesel_models = { version = "0.1.0", path = "../diesel_models", features = ["kv_store"] } diff --git a/crates/analytics/src/lib.rs b/crates/analytics/src/lib.rs index c9752bd27a..d8de32a732 100644 --- a/crates/analytics/src/lib.rs +++ b/crates/analytics/src/lib.rs @@ -15,7 +15,13 @@ pub mod sdk_events; mod sqlx; mod types; use api_event::metrics::{ApiEventMetric, ApiEventMetricRow}; +use common_utils::errors::CustomResult; use disputes::metrics::{DisputeMetric, DisputeMetricRow}; +use hyperswitch_interfaces::secrets_interface::{ + secret_handler::SecretsHandler, + secret_state::{RawSecret, SecretStateContainer, SecuredSecret}, + SecretManagementInterface, SecretsManagementError, +}; pub use types::AnalyticsDomain; pub mod lambda_utils; pub mod utils; @@ -598,6 +604,51 @@ pub enum AnalyticsConfig { }, } +#[async_trait::async_trait] +impl SecretsHandler for AnalyticsConfig { + async fn convert_to_raw_secret( + value: SecretStateContainer, + secret_management_client: &dyn SecretManagementInterface, + ) -> CustomResult, SecretsManagementError> { + let analytics_config = value.get_inner(); + let decrypted_password = match analytics_config { + // Todo: Perform kms decryption of clickhouse password + Self::Clickhouse { .. } => masking::Secret::new(String::default()), + Self::Sqlx { sqlx } + | Self::CombinedCkh { sqlx, .. } + | Self::CombinedSqlx { sqlx, .. } => { + secret_management_client + .get_secret(sqlx.password.clone()) + .await? + } + }; + + Ok(value.transition_state(|conf| match conf { + Self::Sqlx { sqlx } => Self::Sqlx { + sqlx: Database { + password: decrypted_password, + ..sqlx + }, + }, + Self::Clickhouse { clickhouse } => Self::Clickhouse { clickhouse }, + Self::CombinedCkh { sqlx, clickhouse } => Self::CombinedCkh { + sqlx: Database { + password: decrypted_password, + ..sqlx + }, + clickhouse, + }, + Self::CombinedSqlx { sqlx, clickhouse } => Self::CombinedSqlx { + sqlx: Database { + password: decrypted_password, + ..sqlx + }, + clickhouse, + }, + })) + } +} + impl Default for AnalyticsConfig { fn default() -> Self { Self::Sqlx { diff --git a/crates/router/src/configs/secrets_transformers.rs b/crates/router/src/configs/secrets_transformers.rs index bbcc2b5bce..f89d181198 100644 --- a/crates/router/src/configs/secrets_transformers.rs +++ b/crates/router/src/configs/secrets_transformers.rs @@ -233,6 +233,13 @@ pub(crate) async fn fetch_raw_secrets( .await .expect("Failed to decrypt master database configuration"); + #[cfg(feature = "olap")] + #[allow(clippy::expect_used)] + let analytics = + analytics::AnalyticsConfig::convert_to_raw_secret(conf.analytics, secret_management_client) + .await + .expect("Failed to decrypt analytics configuration"); + #[cfg(feature = "olap")] #[allow(clippy::expect_used)] let replica_database = @@ -342,7 +349,7 @@ pub(crate) async fn fetch_raw_secrets( temp_locker_enable_config: conf.temp_locker_enable_config, payment_link: conf.payment_link, #[cfg(feature = "olap")] - analytics: conf.analytics, + analytics, #[cfg(feature = "kv_store")] kv_config: conf.kv_config, #[cfg(feature = "frm")] diff --git a/crates/router/src/configs/settings.rs b/crates/router/src/configs/settings.rs index 00897951ba..70a173f1d9 100644 --- a/crates/router/src/configs/settings.rs +++ b/crates/router/src/configs/settings.rs @@ -105,7 +105,7 @@ pub struct Settings { pub temp_locker_enable_config: TempLockerEnableConfig, pub payment_link: PaymentLink, #[cfg(feature = "olap")] - pub analytics: AnalyticsConfig, + pub analytics: SecretStateContainer, #[cfg(feature = "kv_store")] pub kv_config: KvConfig, #[cfg(feature = "frm")] diff --git a/crates/router/src/routes/app.rs b/crates/router/src/routes/app.rs index 1d82bc7539..798b07d149 100644 --- a/crates/router/src/routes/app.rs +++ b/crates/router/src/routes/app.rs @@ -200,7 +200,8 @@ impl AppState { }; #[cfg(feature = "olap")] - let pool = crate::analytics::AnalyticsProvider::from_conf(&conf.analytics).await; + let pool = + crate::analytics::AnalyticsProvider::from_conf(conf.analytics.get_inner()).await; #[cfg(feature = "email")] let email_client = Arc::new(create_email_client(&conf).await);