Skip to content

Commit

Permalink
Isolate config logic and add e2e config tests
Browse files Browse the repository at this point in the history
This commit puts the serialised version of the config file into one
single Rust file. This file is put under a CODEOWNERS rule so that it is
carefully check for breaking changes.

It also adds one end-to-end config test checking the behaviour of
various fields.

Signed-off-by: Hugues de Valon <hugues.devalon@arm.com>
  • Loading branch information
hug-dev committed May 19, 2021
1 parent 92b7a7c commit 86cd9ca
Show file tree
Hide file tree
Showing 14 changed files with 291 additions and 239 deletions.
3 changes: 3 additions & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# The content of the config.rs file should not change in a breaking way.
# See https://github.com/parallaxsecond/parsec/issues/393 for details.
src/utils/config.rs @parallaxsecond/admin
19 changes: 1 addition & 18 deletions e2e_tests/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,8 @@ use parsec_client::core::interface::operations::psa_key_attributes::{
Attributes, EccFamily, Lifetime, Policy, Type, UsageFlags,
};
use parsec_client::core::interface::requests::{Opcode, ProviderId, ResponseStatus, Result};
use parsec_client::core::ipc_handler::unix_socket;
use parsec_client::error::Error;
use std::collections::HashSet;
use std::time::Duration;

const TEST_SOCKET_PATH: &str = "/tmp/parsec.sock";
const TEST_TIMEOUT: Duration = Duration::from_secs(60);

/// Client structure automatically choosing a provider and high-level operation functions.
#[derive(Debug)]
Expand Down Expand Up @@ -58,20 +53,8 @@ impl TestClient {
env_logger::try_init();
}

let mut basic_client = BasicClient::new_naked();

let ipc_handler =
unix_socket::Handler::new(TEST_SOCKET_PATH.into(), Some(TEST_TIMEOUT)).unwrap();
basic_client.set_ipc_handler(Box::from(ipc_handler));
basic_client.set_timeout(Some(Duration::from_secs(10)));

basic_client.set_default_provider().unwrap();
basic_client
.set_default_auth(Some(String::from("root")))
.unwrap();

TestClient {
basic_client,
basic_client: BasicClient::new(Some(String::from("root"))).unwrap(),
created_keys: Some(HashSet::new()),
}
}
Expand Down
31 changes: 31 additions & 0 deletions e2e_tests/tests/all_providers/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
use e2e_tests::TestClient;
use log::{error, info};
use parsec_client::core::interface::operations::list_providers::Uuid;
use parsec_client::core::interface::operations::psa_algorithm::Hash;
use parsec_client::core::interface::requests::ResponseStatus;
use std::env;
use std::fs;
use std::path::PathBuf;
Expand Down Expand Up @@ -129,3 +131,32 @@ fn pkcs11_encrypt_software() {
.unwrap();
assert_eq!(&plaintext_msg[..], &plaintext[..]);
}

#[test]
fn various_fields() {
set_config("various_field_check.toml");
reload_service();

env::set_var("PARSEC_SERVICE_ENDPOINT", "unix:/tmp/toto.sock");

let mut client = TestClient::new();
// Try to send a bit less than 1KiB, should work
let _ = client
.hash_compute(Hash::Sha256, &vec![0xDD; 1019])
.unwrap();
// Try to send 1KiB and one byte, should fail
assert_eq!(
client
.hash_compute(Hash::Sha256, &vec![0xDD; 1025])
.unwrap_err(),
ResponseStatus::BodySizeExceedsLimit
);

let _ = client.generate_bytes(1024).unwrap();
assert_eq!(
client.generate_bytes(1025).unwrap_err(),
ResponseStatus::ResponseTooLarge
);

env::set_var("PARSEC_SERVICE_ENDPOINT", "unix:/tmp/parsec.sock");
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
[core_settings]
allow_root = true
thread_pool_size = 2
idle_listener_sleep_duration = 12
log_level = "trace"
log_timestamp = true
# 1 KiB max for requests
body_len_limit = 1024
log_error_details = true
# 1 KiB max for responses
buffer_size_limit = 1024

[listener]
listener_type = "DomainSocket"
timeout = 202
socket_path = "/tmp/toto.sock"

[authenticator]
auth_type = "Direct"

[[key_manager]]
name = "I-want-to-speak-to-the-manager"
manager_type = "OnDisk"
store_path = "/tmp/the-mappings"

[[provider]]
provider_type = "MbedCrypto"
key_info_manager = "I-want-to-speak-to-the-manager"
11 changes: 5 additions & 6 deletions src/authenticators/direct_authenticator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@
//! This authenticator does not offer any security value and should only be used in environments
//! where all the clients and the service are mutually trustworthy.

use super::{Admin, AdminList, Application, Authenticate};
use super::{AdminList, Application, Authenticate};
use crate::front::listener::ConnectionMetadata;
use crate::utils::config::Admin;
use log::error;
use parsec_interface::operations::list_authenticators;
use parsec_interface::requests::request::RequestAuth;
Expand Down Expand Up @@ -73,7 +74,7 @@ impl Authenticate for DirectAuthenticator {

#[cfg(test)]
mod test {
use super::super::{Admin, Authenticate};
use super::super::Authenticate;
use super::DirectAuthenticator;
use crate::authenticators::ApplicationName;
use parsec_interface::requests::request::RequestAuth;
Expand Down Expand Up @@ -126,11 +127,9 @@ mod test {
#[test]
fn admin_check() {
let admin_name = String::from("admin_name");
let admin = toml::from_str(&format!("name = '{}'", admin_name)).unwrap();
let authenticator = DirectAuthenticator {
admins: vec![Admin {
name: admin_name.clone(),
}]
.into(),
admins: vec![admin].into(),
};

let app_name = "app_name".to_string();
Expand Down
33 changes: 1 addition & 32 deletions src/authenticators/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,11 @@ pub mod direct_authenticator;
pub mod unix_peer_credentials_authenticator;

use crate::front::listener::ConnectionMetadata;
use crate::utils::config::Admin;
use parsec_interface::operations::list_authenticators;
use parsec_interface::requests::request::RequestAuth;
use parsec_interface::requests::Result;
use serde::Deserialize;
use std::ops::Deref;
use zeroize::Zeroize;

/// String wrapper for app names
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
Expand Down Expand Up @@ -114,36 +113,6 @@ impl std::fmt::Display for ApplicationName {
}
}

/// Authenticator configuration structure
#[derive(Deserialize, Debug, Zeroize)]
#[zeroize(drop)]
#[serde(tag = "auth_type")]
pub enum AuthenticatorConfig {
/// Direct authentication
Direct {
/// List of service admins
admins: Option<Vec<Admin>>,
},
/// Unix Peer Credentials authentication
UnixPeerCredentials {
/// List of service admins
admins: Option<Vec<Admin>>,
},
}

/// Structure defining the properties of a service admin
#[derive(Deserialize, Debug, Zeroize, Clone)]
#[zeroize(drop)]
pub struct Admin {
name: String,
}

impl Admin {
fn name(&self) -> &str {
&self.name
}
}

#[derive(Debug, Clone, Default)]
struct AdminList(Vec<Admin>);

Expand Down
11 changes: 5 additions & 6 deletions src/authenticators/unix_peer_credentials_authenticator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@
//!
//! Currently, the stringified UID is used as the application name.

use super::{Admin, AdminList, Application, Authenticate};
use super::{AdminList, Application, Authenticate};
use crate::front::listener::ConnectionMetadata;
use crate::utils::config::Admin;
use log::error;
use parsec_interface::operations::list_authenticators;
use parsec_interface::requests::request::RequestAuth;
Expand Down Expand Up @@ -98,7 +99,7 @@ impl Authenticate for UnixPeerCredentialsAuthenticator {

#[cfg(test)]
mod test {
use super::super::{Admin, Authenticate};
use super::super::Authenticate;
use super::UnixPeerCredentialsAuthenticator;
use crate::authenticators::ApplicationName;
use crate::front::domain_socket::peer_credentials;
Expand Down Expand Up @@ -227,11 +228,9 @@ mod test {
peer_credentials::peer_cred(&_sock_b).unwrap(),
);

let admin = toml::from_str(&format!("name = '{}'", get_current_uid())).unwrap();
let authenticator = UnixPeerCredentialsAuthenticator {
admins: vec![Admin {
name: get_current_uid().to_string(),
}]
.into(),
admins: vec![admin].into(),
};

let req_auth_data = cred_a.uid.to_le_bytes().to_vec();
Expand Down
2 changes: 1 addition & 1 deletion src/bin/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@

use anyhow::Result;
use log::{info, trace};
use parsec_service::utils::{ServiceBuilder, ServiceConfig};
use parsec_service::utils::{config::ServiceConfig, ServiceBuilder};
use signal_hook::{consts::SIGHUP, consts::SIGINT, consts::SIGTERM, flag};
use std::io::{Error, ErrorKind};
use std::sync::{
Expand Down
19 changes: 0 additions & 19 deletions src/front/listener.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
//! trait acts as an interface for the operations that must be supported by any implementation
//! of the IPC mechanism used as a Parsec front.
use derivative::Derivative;
use serde::Deserialize;
use std::time::Duration;

/// This trait is created to allow the iterator returned by incoming to iterate over a trait object
Expand All @@ -15,24 +14,6 @@ pub trait ReadWrite: std::io::Read + std::io::Write {}
// Automatically implements ReadWrite for all types that implement Read and Write.
impl<T: std::io::Read + std::io::Write> ReadWrite for T {}

/// Type of the Listener used
#[derive(Copy, Clone, Deserialize, Debug)]
pub enum ListenerType {
/// Listener using Unix Domain Socket
DomainSocket,
}

/// Configuration of the Listener
#[derive(Clone, Deserialize, Debug)]
pub struct ListenerConfig {
/// Type of the Listener
pub listener_type: ListenerType,
/// Timeout of the Listener before the connection errors out (in milliseconds)
pub timeout: u64,
/// Path of the Unix Domain socket
pub socket_path: Option<String>,
}

/// Specifies metadata associated with a connection, if any.
#[derive(Copy, Clone, Debug)]
pub enum ConnectionMetadata {
Expand Down
19 changes: 1 addition & 18 deletions src/key_info_managers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
//! means but it has to be persistent.

use crate::authenticators::ApplicationName;
use crate::utils::config::{KeyInfoManagerConfig, KeyInfoManagerType};
use anyhow::Result;
use derivative::Derivative;
use parsec_interface::operations::psa_key_attributes::Attributes;
Expand All @@ -20,24 +21,6 @@ use zeroize::Zeroize;

pub mod on_disk_manager;

/// Type of the KeyInfoManager
#[derive(Copy, Clone, Deserialize, Debug)]
pub enum KeyInfoManagerType {
/// KeyInfoManager storing the mappings on disk
OnDisk,
}

/// KeyInfoManager configuration
#[derive(Deserialize, Debug)]
pub struct KeyInfoManagerConfig {
/// Name of the KeyInfoManager
pub name: String,
/// Type of the KeyInfoManager
pub manager_type: KeyInfoManagerType,
/// Path used to store the mappings
pub store_path: Option<String>,
}

/// This structure corresponds to a unique identifier of the key. It is used internally by the Key
/// ID manager to refer to a key.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
Expand Down
Loading

0 comments on commit 86cd9ca

Please sign in to comment.