use crate::authenticators::ApplicationIdentity;
#[allow(deprecated)]
use crate::key_info_managers::on_disk_manager::KeyTriple;
use crate::providers::ProviderIdentity;
use crate::utils::config::{KeyInfoManagerConfig, KeyInfoManagerType};
use anyhow::Result;
use derivative::Derivative;
use parsec_interface::operations::psa_key_attributes::Attributes;
use parsec_interface::requests::{AuthType, ResponseStatus};
use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize};
use std::convert::TryFrom;
use std::fmt;
use std::hash::{Hash, Hasher};
use std::sync::{Arc, RwLock};
use zeroize::Zeroize;
pub mod on_disk_manager;
pub mod sqlite_manager;
#[derive(Debug, Clone)]
pub struct KeyIdentity {
application: ApplicationIdentity,
provider: ProviderIdentity,
key_name: String,
}
impl Hash for KeyIdentity {
fn hash<H: Hasher>(&self, state: &mut H) {
self.application.hash(state);
self.key_name.hash(state);
}
}
impl PartialEq for KeyIdentity {
fn eq(&self, other: &Self) -> bool {
self.key_name() == other.key_name() && self.application() == other.application()
}
}
impl Eq for KeyIdentity {}
impl fmt::Display for KeyIdentity {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"KeyIdentity: {{\n{},\n{},\nkey_name: \"{}\",\n}}",
self.application, self.provider, self.key_name
)
}
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Zeroize)]
#[zeroize(drop)]
struct KeyInfo {
id: Vec<u8>,
attributes: Attributes,
}
impl KeyIdentity {
pub fn new(
application: ApplicationIdentity,
provider: ProviderIdentity,
key_name: String,
) -> KeyIdentity {
KeyIdentity {
application,
provider,
key_name,
}
}
pub fn belongs_to_provider(&self, provider_identity: &ProviderIdentity) -> bool {
self.provider().name() == provider_identity.name()
&& self.provider().uuid() == provider_identity.uuid()
}
pub fn key_name(&self) -> &String {
&self.key_name
}
pub fn application(&self) -> &ApplicationIdentity {
&self.application
}
pub fn provider(&self) -> &ProviderIdentity {
&self.provider
}
}
pub fn to_response_status(error_string: String) -> ResponseStatus {
format_error!(
"Converting error to ResponseStatus:KeyInfoManagerError",
error_string
);
ResponseStatus::KeyInfoManagerError
}
trait ManageKeyInfo {
fn key_info_manager_type(&self) -> KeyInfoManagerType;
fn get(&self, key_identity: &KeyIdentity) -> Result<Option<&KeyInfo>, String>;
fn get_all(&self, provider_identity: ProviderIdentity) -> Result<Vec<KeyIdentity>, String>;
fn insert(
&mut self,
key_identity: KeyIdentity,
key_info: KeyInfo,
) -> Result<Option<KeyInfo>, String>;
fn remove(&mut self, key_identity: &KeyIdentity) -> Result<Option<KeyInfo>, String>;
fn exists(&self, key_identity: &KeyIdentity) -> Result<bool, String>;
}
#[derive(Derivative)]
#[derivative(Debug)]
pub struct KeyInfoManagerClient {
provider_identity: ProviderIdentity,
#[derivative(Debug = "ignore")]
key_info_manager_impl: Arc<RwLock<dyn ManageKeyInfo + Send + Sync>>,
}
impl KeyInfoManagerClient {
pub fn get_key_identity(
&self,
application: ApplicationIdentity,
key_name: String,
) -> KeyIdentity {
KeyIdentity::new(application, self.provider_identity.clone(), key_name)
}
pub fn get_key_id<T: DeserializeOwned>(
&self,
key_identity: &KeyIdentity,
) -> parsec_interface::requests::Result<T> {
let key_info_manager_impl = self
.key_info_manager_impl
.read()
.expect("Key Info Manager lock poisoned");
let key_info = match key_info_manager_impl.get(key_identity) {
Ok(Some(key_info)) => key_info,
Ok(None) => return Err(ResponseStatus::PsaErrorDoesNotExist),
Err(string) => return Err(to_response_status(string)),
};
Ok(bincode::deserialize(&key_info.id)?)
}
pub fn get_key_attributes(
&self,
key_identity: &KeyIdentity,
) -> parsec_interface::requests::Result<Attributes> {
let key_info_manager_impl = self
.key_info_manager_impl
.read()
.expect("Key Info Manager lock poisoned");
let key_info = match key_info_manager_impl.get(key_identity) {
Ok(Some(key_info)) => key_info,
Ok(None) => return Err(ResponseStatus::PsaErrorDoesNotExist),
Err(string) => return Err(to_response_status(string)),
};
Ok(key_info.attributes)
}
pub fn get_all(&self) -> parsec_interface::requests::Result<Vec<KeyIdentity>> {
let key_info_manager_impl = self
.key_info_manager_impl
.read()
.expect("Key Info Manager lock poisoned");
key_info_manager_impl
.get_all(self.provider_identity.clone())
.map_err(to_response_status)
}
pub fn remove_key_info(
&self,
key_identity: &KeyIdentity,
) -> parsec_interface::requests::Result<()> {
let mut key_info_manager_impl = self
.key_info_manager_impl
.write()
.expect("Key Info Manager lock poisoned");
match key_info_manager_impl.remove(key_identity) {
Ok(Some(_key_info)) => Ok(()),
Ok(None) => Err(ResponseStatus::PsaErrorDoesNotExist),
Err(string) => Err(to_response_status(string)),
}
}
pub fn insert_key_info<T: Serialize>(
&self,
key_identity: KeyIdentity,
key_id: &T,
attributes: Attributes,
) -> parsec_interface::requests::Result<()> {
let mut key_info_manager_impl = self
.key_info_manager_impl
.write()
.expect("Key Info Manager lock poisoned");
let key_info = KeyInfo {
id: bincode::serialize(key_id)?,
attributes,
};
match key_info_manager_impl.insert(key_identity, key_info) {
Ok(None) => Ok(()),
Ok(Some(_)) => Err(ResponseStatus::PsaErrorAlreadyExists),
Err(string) => Err(to_response_status(string)),
}
}
pub fn replace_key_info<T: Serialize>(
&self,
key_identity: KeyIdentity,
key_id: &T,
attributes: Attributes,
) -> parsec_interface::requests::Result<()> {
let mut key_info_manager_impl = self
.key_info_manager_impl
.write()
.expect("Key Info Manager lock poisoned");
let key_info = KeyInfo {
id: bincode::serialize(key_id)?,
attributes,
};
match key_info_manager_impl.insert(key_identity.clone(), key_info) {
Ok(None) => {
let _ = key_info_manager_impl
.remove(&key_identity)
.map_err(to_response_status)?;
Err(ResponseStatus::PsaErrorDoesNotExist)
}
Ok(Some(_)) => Ok(()),
Err(string) => Err(to_response_status(string)),
}
}
pub fn list_clients(&self) -> parsec_interface::requests::Result<Vec<ApplicationIdentity>> {
let key_info_manager_impl = self
.key_info_manager_impl
.read()
.expect("Key Info Manager lock poisoned");
let key_identities = key_info_manager_impl
.get_all(self.provider_identity.clone())
.map_err(to_response_status)?;
let mut clients = Vec::new();
for key_identity in key_identities {
if !clients.contains(&key_identity.application)
&& !key_identity.application.is_internal()
{
clients.push(key_identity.application.clone());
}
}
Ok(clients)
}
pub fn list_keys(
&self,
application_identity: &ApplicationIdentity,
) -> parsec_interface::requests::Result<Vec<parsec_interface::operations::list_keys::KeyInfo>>
{
use parsec_interface::operations::list_keys::KeyInfo;
let key_info_manager_impl = self
.key_info_manager_impl
.read()
.expect("Key Info Manager lock poisoned");
let mut keys: Vec<KeyInfo> = Vec::new();
let mut key_identities = key_info_manager_impl
.get_all(self.provider_identity.clone())
.map_err(to_response_status)?;
key_identities.retain(|key_identity| !key_identity.application().is_internal());
for key_identity in key_identities {
match key_info_manager_impl.key_info_manager_type() {
KeyInfoManagerType::OnDisk => {
if key_identity.application().name() != application_identity.name() {
continue;
}
}
_ => {
if key_identity.application() != application_identity {
continue;
}
}
}
let key_info = key_info_manager_impl
.get(&key_identity)
.map_err(to_response_status)?;
let key_info = match key_info {
Some(key_info) => key_info,
_ => continue,
};
#[allow(deprecated)]
let key_triple =
KeyTriple::try_from(key_identity.clone()).map_err(to_response_status)?;
#[allow(deprecated)]
keys.push(KeyInfo {
provider_id: *key_triple.provider_id(),
name: key_identity.key_name().to_string(),
attributes: key_info.attributes,
});
}
Ok(keys)
}
pub fn does_not_exist(&self, key_identity: &KeyIdentity) -> Result<(), ResponseStatus> {
let key_info_manager_impl = self
.key_info_manager_impl
.read()
.expect("Key Info Manager lock poisoned");
if key_info_manager_impl
.exists(key_identity)
.map_err(to_response_status)?
{
Err(ResponseStatus::PsaErrorAlreadyExists)
} else {
Ok(())
}
}
}
#[derive(Derivative)]
#[derivative(Debug)]
pub struct KeyInfoManagerFactory {
#[derivative(Debug = "ignore")]
key_info_manager_impl: Arc<RwLock<dyn ManageKeyInfo + Send + Sync>>,
}
impl KeyInfoManagerFactory {
pub fn new(config: &KeyInfoManagerConfig, default_auth_type: AuthType) -> Result<Self> {
let factory = match config.manager_type {
KeyInfoManagerType::OnDisk => {
let mut builder = on_disk_manager::OnDiskKeyInfoManagerBuilder::new();
if let Some(store_path) = &config.store_path {
builder = builder.with_mappings_dir_path(store_path.into());
}
builder = builder.with_auth_type(default_auth_type);
let manager = builder.build()?;
KeyInfoManagerFactory {
key_info_manager_impl: Arc::new(RwLock::new(manager)),
}
}
KeyInfoManagerType::SQLite => {
let mut builder = sqlite_manager::SQLiteKeyInfoManagerBuilder::new();
if let Some(sqlite_db_path) = &config.sqlite_db_path {
builder = builder.with_db_path(sqlite_db_path.into());
}
let manager = builder.build()?;
KeyInfoManagerFactory {
key_info_manager_impl: Arc::new(RwLock::new(manager)),
}
}
};
Ok(factory)
}
pub fn build_client(&self, provider_identity: ProviderIdentity) -> KeyInfoManagerClient {
KeyInfoManagerClient {
key_info_manager_impl: self.key_info_manager_impl.clone(),
provider_identity,
}
}
}