Skip to content

Commit

Permalink
refactor: concrete error type for Identity::new
Browse files Browse the repository at this point in the history
  • Loading branch information
ericswanson-dfinity committed Sep 22, 2023
1 parent 88cae61 commit 6041a9d
Show file tree
Hide file tree
Showing 17 changed files with 165 additions and 54 deletions.
3 changes: 2 additions & 1 deletion src/dfx-core/src/error/identity/create_new_identity.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::error::fs::FsError;
use crate::error::identity::convert_mnemonic_to_key::ConvertMnemonicToKeyError;
use crate::error::identity::generate_key::GenerateKeyError;
use crate::error::identity::load_pem_from_file::LoadPemFromFileError;
use crate::error::identity::remove_identity::RemoveIdentityError;
use crate::error::identity::save_pem::SavePemError;
use crate::error::identity::IdentityError;
Expand Down Expand Up @@ -36,7 +37,7 @@ pub enum CreateNewIdentityError {
IdentityAlreadyExists(),

#[error("Failed to load pem file: {0}")]
LoadPemFromFileFailed(IdentityError),
LoadPemFromFileFailed(LoadPemFromFileError),

#[error("Failed to remove identity: {0}")]
RemoveIdentityFailed(RemoveIdentityError),
Expand Down
6 changes: 4 additions & 2 deletions src/dfx-core/src/error/identity/export_identity.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
use crate::error::identity::get_identity_config_or_default::GetIdentityConfigOrDefaultError;
use crate::error::identity::load_pem::LoadPemError;
use crate::error::identity::IdentityError;
use std::string::FromUtf8Error;
use thiserror::Error;

#[derive(Error, Debug)]
pub enum ExportIdentityError {
#[error("Failed to get identity config: {0}")]
GetIdentityConfigFailed(IdentityError),
GetIdentityConfigFailed(GetIdentityConfigOrDefaultError),

#[error("The specified identity does not exist: {0}")]
IdentityDoesNotExist(IdentityError),

#[error("Failed to load pem file: {0}")]
LoadPemFailed(IdentityError),
LoadPemFailed(LoadPemError),

#[error("Could not translate pem file to text: {0}")]
TranslatePemContentToTextFailed(FromUtf8Error),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
use crate::error::structured_file::StructuredFileError;
use thiserror::Error;

#[derive(Error, Debug)]
pub enum GetIdentityConfigOrDefaultError {
#[error("Failed to load configuration for identity '{0}': {1}")]
LoadIdentityConfigurationFailed(String, StructuredFileError),
}
15 changes: 15 additions & 0 deletions src/dfx-core/src/error/identity/instantiate_identity_from_name.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
use crate::error::identity::load_identity::LoadIdentityError;
use crate::error::identity::IdentityError;
use thiserror::Error;

#[derive(Error, Debug)]
pub enum InstantiateIdentityFromNameError {
#[error("Failed to get principal of identity: {0}")]
GetIdentityPrincipalFailed(String),

#[error("Failed to load identity: {0}")]
LoadIdentityFailed(LoadIdentityError),

#[error("Identity must exist: {0}")]
RequireIdentityExistsFailed(IdentityError),
}
12 changes: 12 additions & 0 deletions src/dfx-core/src/error/identity/load_identity.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
use crate::error::identity::get_identity_config_or_default::GetIdentityConfigOrDefaultError;
use crate::error::identity::new_identity::NewIdentityError;
use thiserror::Error;

#[derive(Error, Debug)]
pub enum LoadIdentityError {
#[error("Failed to get identity config: {0}")]
GetIdentityConfigOrDefaultFailed(GetIdentityConfigOrDefaultError),

#[error("Failed to instantiate identity: {0}")]
NewIdentityFailed(NewIdentityError),
}
12 changes: 12 additions & 0 deletions src/dfx-core/src/error/identity/load_pem.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
use crate::error::identity::load_pem_from_file::LoadPemFromFileError;
use crate::error::keyring::KeyringError;
use thiserror::Error;

#[derive(Error, Debug)]
pub enum LoadPemError {
#[error("Failed to load PEM file from file : {0}")]
LoadFromFileFailed(LoadPemFromFileError),

#[error("Failed to load PEM file from keyring for identity '{0}': {1}")]
LoadFromKeyringFailed(Box<String>, KeyringError),
}
13 changes: 13 additions & 0 deletions src/dfx-core/src/error/identity/load_pem_from_file.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use crate::error::encryption::EncryptionError;
use crate::error::fs::FsError;
use std::path::PathBuf;
use thiserror::Error;

#[derive(Error, Debug)]
pub enum LoadPemFromFileError {
#[error("Failed to decrypt PEM file: {0}")]
DecryptPemFileFailed(PathBuf, EncryptionError),

#[error("Failed to read pem file: {0}")]
ReadPemFileFailed(FsError),
}
8 changes: 8 additions & 0 deletions src/dfx-core/src/error/identity/load_pem_identity.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
use ic_agent::identity::PemError;
use thiserror::Error;

#[derive(Error, Debug)]
pub enum LoadPemIdentityError {
#[error("Cannot read identity file '{0}': {1:#}")]
ReadIdentityFileFailed(String, Box<PemError>),
}
31 changes: 8 additions & 23 deletions src/dfx-core/src/error/identity/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,16 @@ pub mod convert_mnemonic_to_key;
pub mod create_new_identity;
pub mod export_identity;
pub mod generate_key;
pub mod get_identity_config_or_default;
pub mod get_legacy_credentials_pem_path;
pub mod initialize_identity_manager;
pub mod instantiate_identity_from_name;
pub mod load_identity;
pub mod load_pem;
pub mod load_pem_from_file;
pub mod load_pem_identity;
pub mod new_hardware_identity;
pub mod new_identity;
pub mod new_identity_manager;
pub mod remove_identity;
pub mod rename_identity;
Expand All @@ -13,20 +21,15 @@ pub mod write_pem_to_file;
use crate::error::config::ConfigError;
use crate::error::encryption::EncryptionError;
use crate::error::fs::FsError;
use crate::error::keyring::KeyringError;
use crate::error::structured_file::StructuredFileError;
use crate::error::wallet_config::WalletConfigError;
use ic_agent::export::PrincipalError;
use ic_agent::identity::PemError;
use ic_identity_hsm::HardwareIdentityError;
use std::path::PathBuf;
use thiserror::Error;

#[derive(Error, Debug)]
pub enum IdentityError {
#[error("Failed to decrypt PEM file: {0}")]
DecryptPemFileFailed(PathBuf, EncryptionError),

#[error("Failed to ensure identity configuration directory exists: {0}")]
EnsureIdentityConfigurationDirExistsFailed(FsError),

Expand All @@ -39,30 +42,12 @@ pub enum IdentityError {
#[error("Failed to get shared network data directory: {0}")]
GetSharedNetworkDataDirectoryFailed(ConfigError),

#[error("Failed to get principal of identity: {0}")]
GetIdentityPrincipalFailed(String),

#[error("Identity {0} does not exist at '{1}'.")]
IdentityDoesNotExist(String, PathBuf),

#[error("Failed to instantiate hardware identity for identity '{0}': {1}.")]
InstantiateHardwareIdentityFailed(String, Box<HardwareIdentityError>),

#[error("Failed to load configuration for identity '{0}': {1}")]
LoadIdentityConfigurationFailed(String, StructuredFileError),

#[error("Failed to load PEM file from keyring for identity '{0}': {1}")]
LoadPemFromKeyringFailed(Box<String>, KeyringError),

#[error("Failed to read principal from id '{0}': {1}")]
ParsePrincipalFromIdFailed(String, PrincipalError),

#[error("Cannot read identity file '{0}': {1:#}")]
ReadIdentityFileFailed(String, Box<PemError>),

#[error("Failed to read pem file: {0}")]
ReadPemFileFailed(FsError),

#[error("Failed to rename '{0}' to '{1}' in the global wallet config: {2}")]
RenameWalletFailed(Box<String>, Box<String>, WalletConfigError),

Expand Down
8 changes: 8 additions & 0 deletions src/dfx-core/src/error/identity/new_hardware_identity.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
use ic_identity_hsm::HardwareIdentityError;
use thiserror::Error;

#[derive(Error, Debug)]
pub enum NewHardwareIdentityError {
#[error("Failed to instantiate hardware identity for identity '{0}': {1}.")]
InstantiateHardwareIdentityFailed(String, Box<HardwareIdentityError>),
}
16 changes: 16 additions & 0 deletions src/dfx-core/src/error/identity/new_identity.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
use crate::error::identity::load_pem::LoadPemError;
use crate::error::identity::load_pem_identity::LoadPemIdentityError;
use crate::error::identity::new_hardware_identity::NewHardwareIdentityError;
use thiserror::Error;

#[derive(Error, Debug)]
pub enum NewIdentityError {
#[error("Failed to load PEM: {0}")]
LoadPemFailed(LoadPemError),

#[error("Failed to load PEM identity: {0}")]
LoadPemIdentityFailed(LoadPemIdentityError),

#[error("Failed to instantiate hardware identity: {0}")]
NewHardwareIdentityFailed(NewHardwareIdentityError),
}
6 changes: 4 additions & 2 deletions src/dfx-core/src/error/identity/rename_identity.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use crate::error::fs::FsError;
use crate::error::identity::get_identity_config_or_default::GetIdentityConfigOrDefaultError;
use crate::error::identity::load_pem::LoadPemError;
use crate::error::identity::save_pem::SavePemError;
use crate::error::identity::IdentityError;
use crate::error::keyring::KeyringError;
Expand All @@ -10,7 +12,7 @@ pub enum RenameIdentityError {
CannotCreateAnonymousIdentity(),

#[error("Failed to get identity config: {0}")]
GetIdentityConfigFailed(IdentityError),
GetIdentityConfigFailed(GetIdentityConfigOrDefaultError),

#[error("Identity already exists.")]
IdentityAlreadyExists(),
Expand All @@ -19,7 +21,7 @@ pub enum RenameIdentityError {
IdentityDoesNotExist(IdentityError),

#[error("Failed to load pem: {0}")]
LoadPemFailed(IdentityError),
LoadPemFailed(LoadPemError),

#[error("Failed to map wallets to renamed identity: {0}")]
MapWalletsToRenamedIdentityFailed(IdentityError /*MapWalletsToRenamedIdentityError*/),
Expand Down
31 changes: 22 additions & 9 deletions src/dfx-core/src/identity/identity_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,20 @@ use crate::error::identity::export_identity::ExportIdentityError;
use crate::error::identity::export_identity::ExportIdentityError::TranslatePemContentToTextFailed;
use crate::error::identity::generate_key::GenerateKeyError;
use crate::error::identity::generate_key::GenerateKeyError::GenerateFreshSecp256k1KeyFailed;
use crate::error::identity::get_identity_config_or_default::GetIdentityConfigOrDefaultError;
use crate::error::identity::get_identity_config_or_default::GetIdentityConfigOrDefaultError::LoadIdentityConfigurationFailed;
use crate::error::identity::get_legacy_credentials_pem_path::GetLegacyCredentialsPemPathError;
use crate::error::identity::get_legacy_credentials_pem_path::GetLegacyCredentialsPemPathError::GetLegacyPemPathFailed;
use crate::error::identity::initialize_identity_manager::InitializeIdentityManagerError;
use crate::error::identity::initialize_identity_manager::InitializeIdentityManagerError::{
CreateIdentityDirectoryFailed, GenerateKeyFailed, MigrateLegacyIdentityFailed,
WritePemToFileFailed,
};
use crate::error::identity::instantiate_identity_from_name::InstantiateIdentityFromNameError;
use crate::error::identity::instantiate_identity_from_name::InstantiateIdentityFromNameError::{
GetIdentityPrincipalFailed, LoadIdentityFailed,
};
use crate::error::identity::load_identity::LoadIdentityError;
use crate::error::identity::new_identity_manager::NewIdentityManagerError;
use crate::error::identity::new_identity_manager::NewIdentityManagerError::LoadIdentityManagerConfigurationFailed;
use crate::error::identity::remove_identity::RemoveIdentityError;
Expand All @@ -39,7 +46,6 @@ use crate::error::identity::rename_identity::RenameIdentityError::{
use crate::error::identity::IdentityError;
use crate::error::identity::IdentityError::{
EnsureIdentityConfigurationDirExistsFailed, GenerateFreshEncryptionConfigurationFailed,
GetIdentityPrincipalFailed, LoadIdentityConfigurationFailed, SaveIdentityConfigurationFailed,
};
use crate::error::structured_file::StructuredFileError;
use crate::foundation::get_user_home;
Expand Down Expand Up @@ -238,7 +244,7 @@ impl IdentityManager {
pub fn instantiate_selected_identity(
&mut self,
log: &Logger,
) -> Result<Box<DfxIdentity>, IdentityError> {
) -> Result<Box<DfxIdentity>, InstantiateIdentityFromNameError> {
let name = self.selected_identity.clone();
self.instantiate_identity_from_name(name.as_str(), log)
}
Expand All @@ -248,12 +254,16 @@ impl IdentityManager {
&mut self,
identity_name: &str,
log: &Logger,
) -> Result<Box<DfxIdentity>, IdentityError> {
) -> Result<Box<DfxIdentity>, InstantiateIdentityFromNameError> {
let identity = match identity_name {
ANONYMOUS_IDENTITY_NAME => Box::new(DfxIdentity::anonymous()),
identity_name => {
self.require_identity_exists(log, identity_name)?;
Box::new(self.load_identity(identity_name, log)?)
self.require_identity_exists(log, identity_name)
.map_err(InstantiateIdentityFromNameError::RequireIdentityExistsFailed)?;
Box::new(
self.load_identity(identity_name, log)
.map_err(LoadIdentityFailed)?,
)
}
};
use ic_agent::identity::Identity;
Expand All @@ -262,9 +272,12 @@ impl IdentityManager {
Ok(identity)
}

fn load_identity(&self, name: &str, log: &Logger) -> Result<DfxIdentity, IdentityError> {
let config = self.get_identity_config_or_default(name)?;
fn load_identity(&self, name: &str, log: &Logger) -> Result<DfxIdentity, LoadIdentityError> {
let config = self
.get_identity_config_or_default(name)
.map_err(LoadIdentityError::GetIdentityConfigOrDefaultFailed)?;
DfxIdentity::new(name, config, self.file_locations(), log)
.map_err(LoadIdentityError::NewIdentityFailed)
}

/// Create a new identity (name -> generated key)
Expand Down Expand Up @@ -641,7 +654,7 @@ impl IdentityManager {
pub fn get_identity_config_or_default(
&self,
identity: &str,
) -> Result<IdentityConfiguration, IdentityError> {
) -> Result<IdentityConfiguration, GetIdentityConfigOrDefaultError> {
let json_path = self.get_identity_json_path(identity);
if json_path.exists() {
load_json_file(&json_path)
Expand Down Expand Up @@ -758,7 +771,7 @@ pub(super) fn save_identity_configuration(
trace!(log, "Writing identity configuration to {}", path.display());
ensure_parent_dir_exists(path).map_err(EnsureIdentityConfigurationDirExistsFailed)?;

save_json_file(path, &config).map_err(SaveIdentityConfigurationFailed)
save_json_file(path, &config).map_err(IdentityError::SaveIdentityConfigurationFailed)
}

/// Removes the file if it exists.
Expand Down
29 changes: 21 additions & 8 deletions src/dfx-core/src/identity/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@
//! Wallets are a map of network-identity, but don't have their own types or manager
//! type.
use crate::config::directories::{get_config_dfx_dir_path, get_shared_network_data_directory};
use crate::error::identity::load_pem_identity::LoadPemIdentityError;
use crate::error::identity::load_pem_identity::LoadPemIdentityError::ReadIdentityFileFailed;
use crate::error::identity::new_hardware_identity::NewHardwareIdentityError;
use crate::error::identity::new_hardware_identity::NewHardwareIdentityError::InstantiateHardwareIdentityFailed;
use crate::error::identity::new_identity::NewIdentityError;
use crate::error::identity::IdentityError;
use crate::error::identity::IdentityError::{
GetConfigDirectoryFailed, GetSharedNetworkDataDirectoryFailed,
InstantiateHardwareIdentityFailed, ReadIdentityFileFailed, RenameWalletFailed,
GetConfigDirectoryFailed, GetSharedNetworkDataDirectoryFailed, RenameWalletFailed,
};
use crate::error::wallet_config::WalletConfigError;
use crate::error::wallet_config::WalletConfigError::{
Expand Down Expand Up @@ -74,7 +78,11 @@ impl Identity {
}
}

fn basic(name: &str, pem_content: &[u8], was_encrypted: bool) -> Result<Self, IdentityError> {
fn basic(
name: &str,
pem_content: &[u8],
was_encrypted: bool,
) -> Result<Self, LoadPemIdentityError> {
let inner = Box::new(
BasicIdentity::from_pem(pem_content)
.map_err(|e| ReadIdentityFileFailed(name.into(), Box::new(e)))?,
Expand All @@ -91,7 +99,7 @@ impl Identity {
name: &str,
pem_content: &[u8],
was_encrypted: bool,
) -> Result<Self, IdentityError> {
) -> Result<Self, LoadPemIdentityError> {
let inner = Box::new(
Secp256k1Identity::from_pem(pem_content)
.map_err(|e| ReadIdentityFileFailed(name.into(), Box::new(e)))?,
Expand All @@ -104,7 +112,10 @@ impl Identity {
})
}

fn hardware(name: &str, hsm: HardwareIdentityConfiguration) -> Result<Self, IdentityError> {
fn hardware(
name: &str,
hsm: HardwareIdentityConfiguration,
) -> Result<Self, NewHardwareIdentityError> {
let inner = Box::new(
HardwareIdentity::new(
hsm.pkcs11_lib_path,
Expand All @@ -126,14 +137,16 @@ impl Identity {
config: IdentityConfiguration,
locations: &IdentityFileLocations,
log: &Logger,
) -> Result<Self, IdentityError> {
) -> Result<Self, NewIdentityError> {
if let Some(hsm) = config.hsm {
Identity::hardware(name, hsm)
Identity::hardware(name, hsm).map_err(NewIdentityError::NewHardwareIdentityFailed)
} else {
let (pem_content, was_encrypted) =
pem_safekeeping::load_pem(log, locations, name, &config)?;
pem_safekeeping::load_pem(log, locations, name, &config)
.map_err(NewIdentityError::LoadPemFailed)?;
Identity::secp256k1(name, &pem_content, was_encrypted)
.or_else(|e| Identity::basic(name, &pem_content, was_encrypted).map_err(|_| e))
.map_err(NewIdentityError::LoadPemIdentityFailed)
}
}

Expand Down
Loading

0 comments on commit 6041a9d

Please sign in to comment.