feat(hashicorp): implement hashicorp secrets manager solution (#3297)

Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
This commit is contained in:
Nishant Joshi
2024-01-24 14:06:52 +05:30
committed by GitHub
parent cc7e33a575
commit 629d546aa7
28 changed files with 1094 additions and 84 deletions

View File

@ -13,15 +13,15 @@ pub mod recon;
#[cfg(feature = "email")]
pub mod email;
#[cfg(feature = "kms")]
#[cfg(any(feature = "kms", feature = "hashicorp-vault"))]
use data_models::errors::StorageError;
use data_models::errors::StorageResult;
use error_stack::{IntoReport, ResultExt};
#[cfg(feature = "hashicorp-vault")]
use external_services::hashicorp_vault::decrypt::VaultFetch;
#[cfg(feature = "kms")]
use external_services::kms::{self, decrypt::KmsDecrypt};
#[cfg(not(feature = "kms"))]
use masking::PeekInterface;
use masking::StrongSecret;
use masking::{PeekInterface, StrongSecret};
#[cfg(feature = "kv_store")]
use storage_impl::KVRouterStore;
use storage_impl::RouterStore;
@ -48,39 +48,58 @@ pub async fn get_store(
#[cfg(feature = "kms")]
let kms_client = kms::get_kms_client(&config.kms).await;
#[cfg(feature = "hashicorp-vault")]
let hc_client = external_services::hashicorp_vault::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::<external_services::hashicorp_vault::Kv2>(hc_client)
.await
.change_context(StorageError::InitializationError)
.attach_printable("Failed to fetch data from hashicorp vault")?;
#[cfg(feature = "kms")]
let master_config = config
.master_database
.clone()
let master_config = master_config
.decrypt_inner(kms_client)
.await
.change_context(StorageError::InitializationError)
.attach_printable("Failed to decrypt master database config")?;
#[cfg(not(feature = "kms"))]
let master_config = config.master_database.clone().into();
#[cfg(feature = "olap")]
let replica_config = config.replica_database.clone();
#[cfg(all(feature = "olap", feature = "hashicorp-vault"))]
let replica_config = replica_config
.fetch_inner::<external_services::hashicorp_vault::Kv2>(hc_client)
.await
.change_context(StorageError::InitializationError)
.attach_printable("Failed to fetch data from hashicorp vault")?;
#[cfg(all(feature = "olap", feature = "kms"))]
let replica_config = config
.replica_database
.clone()
let replica_config = replica_config
.decrypt_inner(kms_client)
.await
.change_context(StorageError::InitializationError)
.attach_printable("Failed to decrypt replica database config")?;
#[cfg(all(feature = "olap", not(feature = "kms")))]
let replica_config = config.replica_database.clone().into();
let master_enc_key = get_master_enc_key(
config,
#[cfg(feature = "kms")]
kms_client,
#[cfg(feature = "hashicorp-vault")]
hc_client,
)
.await;
#[cfg(not(feature = "olap"))]
let conf = master_config;
let conf = master_config.into();
#[cfg(feature = "olap")]
let conf = (master_config, replica_config);
// this would get abstracted, for all cases
#[allow(clippy::useless_conversion)]
let conf = (master_config.into(), replica_config.into());
let store: RouterStore<StoreType> = if test_transaction {
RouterStore::test_store(conf, &config.redis, master_enc_key).await?
@ -110,21 +129,26 @@ pub async fn get_store(
async fn get_master_enc_key(
conf: &crate::configs::settings::Settings,
#[cfg(feature = "kms")] kms_client: &kms::KmsClient,
#[cfg(feature = "hashicorp-vault")]
hc_client: &external_services::hashicorp_vault::HashiCorpVault,
) -> StrongSecret<Vec<u8>> {
let master_enc_key = conf.secrets.master_enc_key.clone();
#[cfg(feature = "hashicorp-vault")]
let master_enc_key = master_enc_key
.fetch_inner::<external_services::hashicorp_vault::Kv2>(hc_client)
.await
.expect("Failed to fetch master enc key");
#[cfg(feature = "kms")]
let master_enc_key = hex::decode(
conf.secrets
.master_enc_key
.clone()
let master_enc_key = masking::Secret::<_, masking::WithType>::new(
master_enc_key
.decrypt_inner(kms_client)
.await
.expect("Failed to decrypt master enc key"),
)
.expect("Failed to decode from hex");
);
#[cfg(not(feature = "kms"))]
let master_enc_key =
hex::decode(conf.secrets.master_enc_key.peek()).expect("Failed to decode from hex");
let master_enc_key = hex::decode(master_enc_key.peek()).expect("Failed to decode from hex");
StrongSecret::new(master_enc_key)
}