Skip to content

Commit

Permalink
feat(crypto): CRP-2382 construct vault directly in the crypto component
Browse files Browse the repository at this point in the history
  • Loading branch information
fspreiss committed Feb 20, 2024
1 parent d490670 commit 473094d
Show file tree
Hide file tree
Showing 8 changed files with 151 additions and 133 deletions.
60 changes: 21 additions & 39 deletions rs/crypto/internal/crypto_service_provider/src/builder/mod.rs
@@ -1,19 +1,15 @@
use super::*;

pub struct CspBuilder<V> {
vault: Box<dyn FnOnce() -> Arc<V>>,
pub struct CspBuilder {
vault: Box<dyn FnOnce() -> Arc<dyn CspVault>>,
logger: ReplicaLogger,
metrics: Arc<CryptoMetrics>,
}

impl<V: CspVault + 'static> CspBuilder<V> {
pub fn with_vault<I, W>(self, vault: I) -> CspBuilder<W>
where
I: VaultIntoArc<Item = W> + 'static,
W: CspVault + 'static,
{
impl CspBuilder {
pub fn with_vault<I: IntoVaultArc + 'static>(self, vault: I) -> CspBuilder {
CspBuilder {
vault: Box::new(|| vault.into_arc()),
vault: Box::new(|| vault.into()),
logger: self.logger,
metrics: self.metrics,
}
Expand All @@ -29,61 +25,47 @@ impl<V: CspVault + 'static> CspBuilder<V> {
}

impl Csp {
pub fn builder<I, V>(
pub fn builder<I: IntoVaultArc + 'static>(
vault: I,
logger: ReplicaLogger,
metrics: Arc<CryptoMetrics>,
) -> CspBuilder<V>
where
I: VaultIntoArc<Item = V> + 'static,
V: CspVault + 'static,
{
) -> CspBuilder {
CspBuilder {
vault: Box::new(|| vault.into_arc()),
vault: Box::new(|| vault.into()),
logger,
metrics,
}
}
}

pub trait VaultIntoArc {
type Item;

fn into_arc(self) -> Arc<Self::Item>;
pub trait IntoVaultArc {
fn into(self) -> Arc<dyn CspVault>;
}

impl<V: CspVault> VaultIntoArc for Arc<V> {
type Item = V;

fn into_arc(self) -> Arc<Self::Item> {
impl<V: CspVault + 'static> IntoVaultArc for Arc<V> {
fn into(self) -> Arc<dyn CspVault> {
self
}
}

impl<V: CspVault> VaultIntoArc for V {
type Item = V;

fn into_arc(self) -> Arc<Self::Item> {
impl<V: CspVault + 'static> IntoVaultArc for V {
fn into(self) -> Arc<dyn CspVault> {
Arc::new(self)
}
}

impl IntoVaultArc for Arc<dyn CspVault> {
fn into(self) -> Arc<dyn CspVault> {
self
}
}

#[cfg(test)]
mod test_utils {
use super::*;
use crate::public_key_store::temp_pubkey_store::TempPublicKeyStore;
use crate::secret_key_store::temp_secret_key_store::TempSecretKeyStore;
use ic_crypto_test_utils_reproducible_rng::ReproducibleRng;

impl Csp {
pub fn builder_for_test() -> CspBuilder<
LocalCspVault<
ReproducibleRng,
TempSecretKeyStore,
TempSecretKeyStore,
TempPublicKeyStore,
>,
> {
pub fn builder_for_test() -> CspBuilder {
CspBuilder {
vault: Box::new(|| LocalCspVault::builder_for_test().build_into_arc()),
logger: no_op_logger(),
Expand Down
79 changes: 9 additions & 70 deletions rs/crypto/internal/crypto_service_provider/src/lib.rs
Expand Up @@ -22,7 +22,7 @@ pub mod vault;
pub use crate::vault::api::TlsHandshakeCspVault;
pub use crate::vault::local_csp_vault::LocalCspVault;
pub use crate::vault::remote_csp_vault::run_csp_vault_server;
use crate::vault::remote_csp_vault::RemoteCspVault;
pub use crate::vault::remote_csp_vault::RemoteCspVault;

use crate::api::{
CspIDkgProtocol, CspKeyGenerator, CspPublicAndSecretKeyStoreChecker, CspPublicKeyStore,
Expand All @@ -34,15 +34,13 @@ use crate::types::{CspPublicKey, ExternalPublicKeys};
use crate::vault::api::{
CspPublicKeyStoreError, CspVault, PksAndSksContainsErrors, ValidatePksAndSksError,
};
use ic_adapter_metrics::AdapterMetrics;
use ic_config::crypto::{CryptoConfig, CspVaultType};
use ic_config::crypto::CryptoConfig;
use ic_crypto_internal_logmon::metrics::CryptoMetrics;
use ic_crypto_node_key_validation::ValidNodePublicKeys;
use ic_logger::{info, new_logger, replica_logger::no_op_logger, ReplicaLogger};
use ic_logger::{new_logger, replica_logger::no_op_logger, ReplicaLogger};
use ic_types::crypto::CurrentNodePublicKeys;
use key_id::KeyId;
use parking_lot::{RwLock, RwLockReadGuard, RwLockWriteGuard};
use std::path::{Path, PathBuf};
use std::sync::Arc;
use std::time::Instant;

Expand Down Expand Up @@ -163,74 +161,15 @@ impl Csp {
tokio_runtime_handle: Option<tokio::runtime::Handle>,
logger: Option<ReplicaLogger>,
metrics: Arc<CryptoMetrics>,
) -> Self {
match &config.csp_vault_type {
CspVaultType::InReplica => Self::new_with_in_replica_vault(config, logger, metrics),
CspVaultType::UnixSocket {
logic: logic_socket_path,
metrics: metrics_socket_path,
} => Self::new_with_unix_socket_vault(
logic_socket_path,
metrics_socket_path.clone(),
tokio_runtime_handle.expect("missing tokio runtime handle"),
config,
logger,
metrics,
),
}
}

fn new_with_in_replica_vault(
config: &CryptoConfig,
logger: Option<ReplicaLogger>,
metrics: Arc<CryptoMetrics>,
) -> Self {
let logger = logger.unwrap_or_else(no_op_logger);
info!(
logger,
"Proceeding with an in-replica csp_vault, CryptoConfig: {:?}", config
);
let csp_vault =
LocalCspVault::new_in_dir(&config.crypto_root, metrics.clone(), new_logger!(&logger));
Csp::builder(csp_vault, logger, metrics).build()
}

fn new_with_unix_socket_vault(
socket_path: &Path,
metrics_socket_path: Option<PathBuf>,
rt_handle: tokio::runtime::Handle,
config: &CryptoConfig,
logger: Option<ReplicaLogger>,
metrics: Arc<CryptoMetrics>,
) -> Self {
let logger = logger.unwrap_or_else(no_op_logger);
info!(
logger,
"Proceeding with a remote csp_vault, CryptoConfig: {:?}", config
);
if let (Some(metrics_uds_path), Some(global_metrics)) =
(metrics_socket_path, metrics.metrics_registry())
{
global_metrics.register_adapter(AdapterMetrics::new(
"cryptocsp",
metrics_uds_path,
rt_handle.clone(),
));
}

let csp_vault = RemoteCspVault::new(
socket_path,
rt_handle,
let vault = vault::vault_from_config(
config,
tokio_runtime_handle,
new_logger!(&logger),
metrics.clone(),
)
.unwrap_or_else(|e| {
panic!(
"Could not connect to CspVault at socket {:?}: {:?}",
socket_path, e
)
});
Csp::builder(csp_vault, logger, metrics).build()
Arc::clone(&metrics),
);
Csp::builder(vault, logger, metrics).build()
}
}

Expand Down
83 changes: 83 additions & 0 deletions rs/crypto/internal/crypto_service_provider/src/vault/mod.rs
@@ -1,16 +1,99 @@
use self::api::CspVault;
use self::local_csp_vault::ProdLocalCspVault;
use self::remote_csp_vault::RemoteCspVault;
use crate::key_id::KeyIdInstantiationError;
use crate::vault::api::{
CspBasicSignatureError, CspBasicSignatureKeygenError, CspMultiSignatureError,
CspMultiSignatureKeygenError, CspSecretKeyStoreContainsError,
};
use ic_adapter_metrics::AdapterMetrics;
use ic_config::crypto::{CryptoConfig, CspVaultType};
use ic_crypto_internal_logmon::metrics::CryptoMetrics;
use ic_logger::{info, ReplicaLogger};
use ic_types::crypto::CryptoError;
use std::path::{Path, PathBuf};
use std::sync::Arc;

pub mod api;
pub mod local_csp_vault;
pub mod remote_csp_vault;
#[cfg(test)]
pub mod test_utils;

/// Creates a production-grade crypto vault.
///
/// If the `config`'s vault type is `UnixSocket`, a `tokio_runtime_handle`
/// is provided, which is then used for the `async`hronous communication
/// with the vault via RPC.
///
/// # Panics
/// Panics if the `config`'s vault type is `UnixSocket` and
/// `tokio_runtime_handle` is `None`.
pub fn vault_from_config(
config: &CryptoConfig,
tokio_runtime_handle: Option<tokio::runtime::Handle>,
logger: ReplicaLogger,
metrics: Arc<CryptoMetrics>,
) -> Arc<dyn CspVault> {
match &config.csp_vault_type {
CspVaultType::InReplica => in_replica_vault(config, logger, metrics),
CspVaultType::UnixSocket {
logic: logic_socket_path,
metrics: metrics_socket_path,
} => unix_socket_vault(
logic_socket_path,
metrics_socket_path.as_ref(),
tokio_runtime_handle.expect("missing tokio runtime handle"),
config,
logger,
metrics,
),
}
}

fn in_replica_vault(
config: &CryptoConfig,
logger: ReplicaLogger,
metrics: Arc<CryptoMetrics>,
) -> Arc<dyn CspVault> {
info!(
logger,
"Proceeding with an in-replica csp_vault, CryptoConfig: {:?}", config
);
let vault = ProdLocalCspVault::new_in_dir(&config.crypto_root, metrics, logger);
Arc::new(vault)
}

fn unix_socket_vault(
socket_path: &Path,
metrics_socket_path: Option<&PathBuf>,
rt_handle: tokio::runtime::Handle,
config: &CryptoConfig,
logger: ReplicaLogger,
metrics: Arc<CryptoMetrics>,
) -> Arc<dyn CspVault> {
info!(
logger,
"Proceeding with a remote csp_vault, CryptoConfig: {:?}", config
);
if let (Some(metrics_uds_path), Some(global_metrics)) =
(metrics_socket_path, metrics.metrics_registry())
{
global_metrics.register_adapter(AdapterMetrics::new(
"cryptocsp",
metrics_uds_path.clone(),
rt_handle.clone(),
));
}
let vault = RemoteCspVault::new(socket_path, rt_handle, logger, metrics).unwrap_or_else(|e| {
panic!(
"Could not connect to CspVault at socket {:?}: {:?}",
socket_path, e
)
});
Arc::new(vault)
}

impl From<CspBasicSignatureError> for CryptoError {
fn from(e: CspBasicSignatureError) -> CryptoError {
match e {
Expand Down
12 changes: 7 additions & 5 deletions rs/crypto/src/common/test_utils/crypto_component.rs
@@ -1,19 +1,21 @@
use crate::CryptoComponentImpl;
use ic_crypto_internal_csp::CryptoServiceProvider;
use ic_crypto_internal_logmon::metrics::CryptoMetrics;
use ic_crypto_test_utils_csp::MockAllCryptoServiceProvider;
use ic_crypto_test_utils_local_csp_vault::MockLocalCspVault;
use ic_interfaces_registry::RegistryClient;
use ic_logger::replica_logger::no_op_logger;
use ic_types_test_utils::ids::node_test_id;
use std::sync::Arc;

const NODE_ID: u64 = 42;

pub fn crypto_component_with_csp<C: CryptoServiceProvider>(
csp: C,
pub fn crypto_component_with_csp(
csp: MockAllCryptoServiceProvider,
registry_client: Arc<dyn RegistryClient>,
) -> CryptoComponentImpl<C> {
CryptoComponentImpl::new_with_csp_and_fake_node_id(
) -> CryptoComponentImpl<MockAllCryptoServiceProvider> {
CryptoComponentImpl::new_for_test(
csp,
Arc::new(MockLocalCspVault::new()),
no_op_logger(),
registry_client,
node_test_id(NODE_ID),
Expand Down

0 comments on commit 473094d

Please sign in to comment.