Bug: refactor: kms decrypt analytics config



Add support for kms decrypting the analytics config
diff --git a/Cargo.lock b/Cargo.lock
index 60bc557972c..4571d80fd87 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 82ac2dde030..f3e01492135 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 c9752bd27a6..d8de32a732b 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<Self, SecuredSecret>,
+        secret_management_client: &dyn SecretManagementInterface,
+    ) -> CustomResult<SecretStateContainer<Self, RawSecret>, 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 bbcc2b5bceb..f89d1811988 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 00897951ba8..70a173f1d95 100644
--- a/crates/router/src/configs/settings.rs
+++ b/crates/router/src/configs/settings.rs
@@ -105,7 +105,7 @@ pub struct Settings<S: SecretState> {
     pub temp_locker_enable_config: TempLockerEnableConfig,
     pub payment_link: PaymentLink,
     #[cfg(feature = "olap")]
-    pub analytics: AnalyticsConfig,
+    pub analytics: SecretStateContainer<AnalyticsConfig, S>,
     #[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 1d82bc7539f..798b07d149f 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);

## Type of Change
<!-- Put an `x` in the boxes that apply -->

- [ ] Bugfix
- [ ] New feature
- [ ] Enhancement
- [x] Refactoring
- [ ] Dependency updates
- [ ] Documentation
- [ ] CI/CD

## Description
<!-- Describe your changes in detail -->
This PR adds support for kms decrypting the analytics config

### Additional Changes

- [ ] This PR modifies the API contract
- [ ] This PR modifies the database schema
- [ ] This PR modifies application configuration/environment variables

<!--
Provide links to the files with corresponding changes.

Following are the paths where you can find config files:
1. `config`
2. `crates/router/src/configs`
3. `loadtest/config`
-->


## Motivation and Context
<!--
Why is this change required? What problem does it solve?
If it fixes an open issue, please link to the issue here.

If you don't have an issue, we'd recommend starting with one first so the PR
can focus on the implementation (unless it is an obvious bug or documentation fix
that will have little conversation).
-->


## How did you test it?
<!--
Did you write an integration/unit/API test to verify the code changes?
Or did you test this change manually (provide relevant screenshots)?
-->
Locally set up aws kms and decryption of analytics config was successful.

Currently Sandbox uses clickhouse setup, so this PR cannot be tested. Can be deployed in custom pod by using Sqlx there. 


## Checklist
<!-- Put an `x` in the boxes that apply -->

- [x] I formatted the code `cargo +nightly fmt --all`
- [x] I addressed lints thrown by `cargo clippy`
- [x] I reviewed the submitted code
- [ ] I added unit tests for my changes where possible
- [ ] I added a [CHANGELOG](/CHANGELOG.md) entry if applicable
