feat: encrypt PII fields before saving it in the database (#1043)

Co-authored-by: Nishant Joshi <nishant.joshi@juspay.in>
This commit is contained in:
Kartikeya Hegde
2023-05-30 13:43:17 +05:30
committed by GitHub
parent 77e60c82fa
commit fa392c40a8
107 changed files with 3818 additions and 1267 deletions

View File

@ -6,6 +6,8 @@ pub mod logger;
use std::sync::{atomic, Arc};
use error_stack::{IntoReport, ResultExt};
#[cfg(feature = "kms")]
use external_services::kms;
use redis_interface::{errors as redis_errors, PubsubInterface, RedisValue};
use tokio::sync::oneshot;
@ -108,6 +110,12 @@ pub trait RedisConnInterface {
fn get_redis_conn(&self) -> Arc<redis_interface::RedisConnectionPool>;
}
impl RedisConnInterface for Store {
fn get_redis_conn(&self) -> Arc<redis_interface::RedisConnectionPool> {
self.redis_conn.clone()
}
}
#[derive(Clone)]
pub struct Store {
pub master_pool: PgPool,
@ -116,6 +124,8 @@ pub struct Store {
pub redis_conn: Arc<redis_interface::RedisConnectionPool>,
#[cfg(feature = "kv_store")]
pub(crate) config: StoreConfig,
pub master_key: Vec<u8>,
pub migration_timestamp: i64,
}
#[cfg(feature = "kv_store")]
@ -149,6 +159,13 @@ impl Store {
redis_clone.on_error(shut_down_signal).await;
});
let master_enc_key = get_master_enc_key(
config,
#[cfg(feature = "kms")]
&config.kms,
)
.await;
Self {
master_pool: diesel_make_pg_pool(
&config.master_database,
@ -171,6 +188,8 @@ impl Store {
drainer_stream_name: config.drainer.stream_name.clone(),
drainer_num_partitions: config.drainer.num_partitions,
},
master_key: master_enc_key,
migration_timestamp: config.secrets.migration_encryption_timestamp,
}
}
@ -219,8 +238,36 @@ impl Store {
}
}
impl RedisConnInterface for Store {
fn get_redis_conn(&self) -> Arc<redis_interface::RedisConnectionPool> {
self.redis_conn.clone()
}
#[allow(clippy::expect_used)]
async fn get_master_enc_key(
conf: &crate::configs::settings::Settings,
#[cfg(feature = "kms")] kms_config: &kms::KmsConfig,
) -> Vec<u8> {
#[cfg(feature = "kms")]
let master_enc_key = hex::decode(
kms::get_kms_client(kms_config)
.await
.decrypt(&conf.secrets.master_enc_key)
.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).expect("Failed to decode from hex");
master_enc_key
}
#[inline]
pub fn generate_aes256_key() -> errors::CustomResult<[u8; 32], common_utils::errors::CryptoError> {
use ring::rand::SecureRandom;
let rng = ring::rand::SystemRandom::new();
let mut key: [u8; 256 / 8] = [0_u8; 256 / 8];
rng.fill(&mut key)
.into_report()
.change_context(common_utils::errors::CryptoError::EncodingFailed)?;
Ok(key)
}