diff --git a/keylime-agent-rust.spec b/keylime-agent-rust.spec index 1bd1b6a..05e835e 100644 --- a/keylime-agent-rust.spec +++ b/keylime-agent-rust.spec @@ -1,8 +1,7 @@ # keylime-agent-rust.spec # Generated by rust2rpm 20 -# missing dev-dependencies: wiremock -%bcond_with check +%bcond_without check %global crate keylime_agent %global crate_version 0.1.0 @@ -59,6 +58,8 @@ Patch3: rust-keylime-descriptive-error-messages.patch Patch4: rust-keylime-set-supplementary-groups.patch # Adjust the supported and required features Patch5: rust-keylime-adjust-features.patch +# Load configuration file only once during startup +Patch6: rust-keylime-load-config-once.patch ExclusiveArch: %{rust_arches} diff --git a/rust-keylime-adjust-features.patch b/rust-keylime-adjust-features.patch index 2d68c2c..8be3369 100644 --- a/rust-keylime-adjust-features.patch +++ b/rust-keylime-adjust-features.patch @@ -1,6 +1,6 @@ ---- a/Cargo.toml 2022-07-01 10:59:27.103854970 +0200 -+++ b/Cargo.toml 2022-07-01 11:02:07.772529002 +0200 -@@ -37,25 +37,15 @@ +--- a/Cargo.toml 2022-07-04 14:30:04.244003909 +0200 ++++ b/Cargo.toml 2022-07-04 14:31:46.421291210 +0200 +@@ -37,28 +37,14 @@ static_assertions = "1" tempfile = "3.0.4" tokio = {version = "1", features = ["full"]} @@ -9,18 +9,19 @@ thiserror = "1.0" uuid = {version = "0.8", features = ["v4"]} -zmq = {version = "0.9.2", optional = true} +-# wiremock was moved to be a regular dependency because optional +-# dev-dependencies are not supported +-# see: https://github.com/rust-lang/cargo/issues/1596 +-wiremock = {version = "0.5", optional = true} [dev-dependencies] actix-rt = "2" --wiremock = "0.5" [features] --# The features enabled by default + # The features enabled by default -default = ["with-zmq", "legacy-python-actions"] -+# Removed default features to drop ZeroMQ and the need for the python shim -+default = [] - # this should change to dev-dependencies when we have integration testing - testing = [] +-# this should change to dev-dependencies when we have integration testing +-testing = ["wiremock"] -# Whether the agent should be compiled with support to listen for notification -# messages on ZeroMQ -with-zmq = ["zmq"] @@ -29,3 +30,5 @@ -# agent (unless the enhancement-55 is implemented). See: -# https://github.com/keylime/enhancements/blob/master/55_revocation_actions_without_python.md -legacy-python-actions = [] ++# Removed default features to drop ZeroMQ and the need for the python shim ++default = [] diff --git a/rust-keylime-drop-dependencies.patch b/rust-keylime-drop-dependencies.patch index c1b9973..9ff289d 100644 --- a/rust-keylime-drop-dependencies.patch +++ b/rust-keylime-drop-dependencies.patch @@ -1,3 +1,27 @@ +From 9229cb4673aad2cae7605e66bdf2160716e1f694 Mon Sep 17 00:00:00 2001 +From: Anderson Toshiyuki Sasaki +Date: Thu, 9 Jun 2022 18:34:34 +0200 +Subject: [PATCH 1/4] Update clap dependency to 3.1.18 + +This change replaces clap::App with clap::Command in main.rs file. + +On commit f3fa925 the clap dependency in Cargo.lock file was updated +from version 3.0.14 to version 3.1.18. + +In clap version 3.1.0, clap::App was deprecated in favor of +clap::Command. This causes warnings during the Keylime agent build due +to the usage of the deprecated structure. + +To avoid similar issues in the future, use the tilde dependency version +requirement to allow versions >= 3.1.18 but < 3.2.0. + +Signed-off-by: Anderson Toshiyuki Sasaki +--- + Cargo.lock | 76 ++++++++++++++++++++++------------------------------- + Cargo.toml | 2 +- + src/main.rs | 2 +- + 3 files changed, 33 insertions(+), 47 deletions(-) + diff --git a/Cargo.toml b/Cargo.toml index 92f3974..f0c7d39 100644 --- a/Cargo.toml @@ -28,6 +52,17 @@ index 1896104..8540597 100644 2.35.3 +From c61e3f389e4bde4d0a318a571c9b3dcf8a62749f Mon Sep 17 00:00:00 2001 +From: Anderson Toshiyuki Sasaki +Date: Tue, 17 May 2022 18:31:01 +0200 +Subject: [PATCH 2/4] Drop unused dependency rustc-serialize + +Signed-off-by: Anderson Toshiyuki Sasaki +--- + Cargo.lock | 7 ------- + Cargo.toml | 1 - + 2 files changed, 8 deletions(-) + diff --git a/Cargo.toml b/Cargo.toml index f0c7d39..0f4e4ab 100644 --- a/Cargo.toml @@ -47,7 +82,7 @@ index f0c7d39..0f4e4ab 100644 From f7b59a6a7739d275ffe15a915eb48a36ceafccdd Mon Sep 17 00:00:00 2001 From: Anderson Toshiyuki Sasaki Date: Tue, 17 May 2022 18:56:50 +0200 -Subject: [PATCH 3/3] Drop unused dependency flate2 +Subject: [PATCH 3/4] Drop unused dependency flate2 Signed-off-by: Anderson Toshiyuki Sasaki --- @@ -92,3 +127,67 @@ index 355dd0d..43129f1 100644 -- 2.35.3 + +From c3f0b4f603089d38715535f8e16b7a40f413e4de Mon Sep 17 00:00:00 2001 +From: Anderson Toshiyuki Sasaki +Date: Thu, 9 Jun 2022 16:21:06 +0200 +Subject: [PATCH 4/4] Make wiremock an optional dependency + +Make a wiremock optional, enabled when the 'testing' feature is enabled. +The goal is to reduce the number of dependencies, with the downside that +the test code coverage will drop. + +Wiremock is currently used only on 'registrar_agent' tests to mock +responses from the registrar service. + +Note: wiremock was moved to be an optional regular dependency because +optional dev-dependencies are not supported. +see: https://github.com/rust-lang/cargo/issues/1596 + +Signed-off-by: Anderson Toshiyuki Sasaki +--- + Cargo.toml | 7 +++++-- + src/registrar_agent.rs | 1 + + 2 files changed, 6 insertions(+), 2 deletions(-) + +diff --git a/Cargo.toml b/Cargo.toml +index 69d2eec..5052512 100644 +--- a/Cargo.toml ++++ b/Cargo.toml +@@ -43,16 +43,19 @@ tss-esapi = "7.1.0" + thiserror = "1.0" + uuid = {version = "0.8", features = ["v4"]} + zmq = {version = "0.9.2", optional = true} ++# wiremock was moved to be a regular dependency because optional ++# dev-dependencies are not supported ++# see: https://github.com/rust-lang/cargo/issues/1596 ++wiremock = {version = "0.5", optional = true} + + [dev-dependencies] + actix-rt = "2" +-wiremock = "0.5" + + [features] + # The features enabled by default + default = ["with-zmq", "legacy-python-actions"] + # this should change to dev-dependencies when we have integration testing +-testing = [] ++testing = ["wiremock"] + # Whether the agent should be compiled with support to listen for notification + # messages on ZeroMQ + with-zmq = ["zmq"] +diff --git a/src/registrar_agent.rs b/src/registrar_agent.rs +index 85b5931..b02ba48 100644 +--- a/src/registrar_agent.rs ++++ b/src/registrar_agent.rs +@@ -149,6 +149,7 @@ pub(crate) async fn do_register_agent( + } + } + ++#[cfg(feature = "testing")] + #[cfg(test)] + mod tests { + use super::*; +-- +2.35.3 + diff --git a/rust-keylime-load-config-once.patch b/rust-keylime-load-config-once.patch new file mode 100644 index 0000000..9601438 --- /dev/null +++ b/rust-keylime-load-config-once.patch @@ -0,0 +1,339 @@ +--- a/src/common.rs 2022-06-03 17:28:38.000000000 +0200 ++++ b/src/common.rs 2022-07-04 13:48:28.257066939 +0200 +@@ -231,59 +231,122 @@ + + impl KeylimeConfig { + pub fn build() -> Result { +- let agent_ip = +- config_get_env("cloud_agent", "cloudagent_ip", "CLOUDAGENT_IP")?; ++ let conf_name = config_file_get(); ++ let conf = Ini::load_from_file(&conf_name)?; ++ ++ let agent_ip = config_get_env( ++ &conf_name, ++ &conf, ++ "cloud_agent", ++ "cloudagent_ip", ++ "CLOUDAGENT_IP", ++ )?; + let agent_port = config_get_env( ++ &conf_name, ++ &conf, + "cloud_agent", + "cloudagent_port", + "CLOUDAGENT_PORT", + )?; +- let registrar_ip = +- config_get_env("cloud_agent", "registrar_ip", "REGISTRAR_IP")?; ++ let registrar_ip = config_get_env( ++ &conf_name, ++ &conf, ++ "cloud_agent", ++ "registrar_ip", ++ "REGISTRAR_IP", ++ )?; + let registrar_port = config_get_env( ++ &conf_name, ++ &conf, + "cloud_agent", + "registrar_port", + "REGISTRAR_PORT", + )?; +- let agent_uuid_config = config_get("cloud_agent", "agent_uuid")?; ++ let agent_uuid_config = ++ config_get(&conf_name, &conf, "cloud_agent", "agent_uuid")?; + let agent_uuid = get_uuid(&agent_uuid_config); +- let agent_contact_ip = cloudagent_contact_ip_get(); +- let agent_contact_port = cloudagent_contact_port_get()?; ++ let agent_contact_ip = cloudagent_contact_ip_get(&conf_name, &conf); ++ let agent_contact_port = ++ cloudagent_contact_port_get(&conf_name, &conf)?; + let hash_alg = HashAlgorithm::try_from( +- config_get("cloud_agent", "tpm_hash_alg")?.as_str(), ++ config_get(&conf_name, &conf, "cloud_agent", "tpm_hash_alg")? ++ .as_str(), + )?; + let enc_alg = EncryptionAlgorithm::try_from( +- config_get("cloud_agent", "tpm_encryption_alg")?.as_str(), ++ config_get( ++ &conf_name, ++ &conf, ++ "cloud_agent", ++ "tpm_encryption_alg", ++ )? ++ .as_str(), + )?; + let sign_alg = SignAlgorithm::try_from( +- config_get("cloud_agent", "tpm_signing_alg")?.as_str(), ++ config_get(&conf_name, &conf, "cloud_agent", "tpm_signing_alg")? ++ .as_str(), + )?; + // There was a typo in Python Keylime and this accounts for having a version + // of Keylime installed that still has this typo. TODO: Remove later + let run_revocation = bool::from_str( +- &config_get("cloud_agent", "listen_notifications") +- .or_else(|_| { +- config_get("cloud_agent", "listen_notfications") +- })? +- .to_lowercase(), +- )?; +- let revocation_cert = config_get("cloud_agent", "revocation_cert")?; +- let revocation_ip = config_get("general", "receive_revocation_ip")?; +- let revocation_port = +- config_get("general", "receive_revocation_port")?; ++ &config_get( ++ &conf_name, ++ &conf, ++ "cloud_agent", ++ "listen_notifications", ++ ) ++ .or_else(|_| { ++ config_get( ++ &conf_name, ++ &conf, ++ "cloud_agent", ++ "listen_notfications", ++ ) ++ })? ++ .to_lowercase(), ++ )?; ++ let revocation_cert = ++ config_get(&conf_name, &conf, "cloud_agent", "revocation_cert")?; ++ let revocation_ip = config_get( ++ &conf_name, ++ &conf, ++ "general", ++ "receive_revocation_ip", ++ )?; ++ let revocation_port = config_get( ++ &conf_name, ++ &conf, ++ "general", ++ "receive_revocation_port", ++ )?; + +- let secure_size = config_get("cloud_agent", "secure_size")?; +- let payload_script = config_get("cloud_agent", "payload_script")?; ++ let secure_size = ++ config_get(&conf_name, &conf, "cloud_agent", "secure_size")?; ++ let payload_script = ++ config_get(&conf_name, &conf, "cloud_agent", "payload_script")?; + let dec_payload_filename = +- config_get("cloud_agent", "dec_payload_file")?; +- let key_filename = config_get("cloud_agent", "enc_keyname")?; ++ config_get(&conf_name, &conf, "cloud_agent", "dec_payload_file")?; ++ ++ let key_filename = ++ config_get(&conf_name, &conf, "cloud_agent", "enc_keyname")?; + let extract_payload_zip = bool::from_str( +- &config_get("cloud_agent", "extract_payload_zip")?.to_lowercase(), ++ &config_get( ++ &conf_name, ++ &conf, ++ "cloud_agent", ++ "extract_payload_zip", ++ )? ++ .to_lowercase(), + )?; + +- let work_dir = +- config_get_env("cloud_agent", "keylime_dir", "KEYLIME_DIR") +- .or_else::(|_| Ok(String::from(WORK_DIR)))?; ++ ++ let work_dir = config_get_env( ++ &conf_name, ++ &conf, ++ "cloud_agent", ++ "keylime_dir", ++ "KEYLIME_DIR", ++ ) ++ .or_else::(|_| Ok(String::from(WORK_DIR)))?; + + let tpm_data_path = PathBuf::from(&work_dir).join(TPM_DATA); + let tpm_data = if tpm_data_path.exists() { +@@ -302,20 +365,31 @@ + None + }; + +- let mut keylime_ca_path = config_get("cloud_agent", "keylime_ca")?; ++ let mut keylime_ca_path = ++ config_get(&conf_name, &conf, "cloud_agent", "keylime_ca")?; + if keylime_ca_path == "default" { + keylime_ca_path = Path::new(&work_dir) + .join(DEFAULT_CA_PATH) + .display() + .to_string(); + } +- let revocation_actions = +- config_get("cloud_agent", "revocation_actions") +- .or_else::(|_| Ok(String::from(REV_ACTIONS)))?; +- let revocation_actions_dir = +- config_get("cloud_agent", "revocation_actions_dir") +- .or_else::(|_| Ok(String::from(REV_ACTIONS_DIR)))?; ++ let revocation_actions = config_get( ++ &conf_name, ++ &conf, ++ "cloud_agent", ++ "revocation_actions", ++ ) ++ .or_else::(|_| Ok(String::from(REV_ACTIONS)))?; ++ let revocation_actions_dir = config_get( ++ &conf_name, ++ &conf, ++ "cloud_agent", ++ "revocation_actions_dir", ++ ) ++ .or_else::(|_| Ok(String::from(REV_ACTIONS_DIR)))?; + let allow_payload_revocation_actions = match config_get( ++ &conf_name, ++ &conf, + "cloud_agent", + "allow_payload_revocation_actions", + ) { +@@ -323,7 +397,7 @@ + Err(_) => ALLOW_PAYLOAD_REV_ACTIONS, + }; + let run_as = if permissions::get_euid() == 0 { +- match config_get("cloud_agent", "run_as") { ++ match config_get(&conf_name, &conf, "cloud_agent", "run_as") { + Ok(user_group) => Some(user_group), + Err(_) => { + warn!("Cannot drop privileges since 'run_as' is empty or missing in 'cloud_agent' section of keylime.conf."); +@@ -334,19 +408,27 @@ + None + }; + +- let mtls_enabled = +- match config_get("cloud_agent", "mtls_cert_enabled") { +- Ok(enabled) => bool::from_str(&enabled.to_lowercase()) +- .or::(Ok(MTLS_ENABLED))?, +- Err(_) => true, +- }; +- +- let enable_insecure_payload = +- match config_get("cloud_agent", "enable_insecure_payload") { +- Ok(allowed) => bool::from_str(&allowed.to_lowercase()) +- .or::(Ok(ALLOW_INSECURE_PAYLOAD))?, +- Err(_) => false, +- }; ++ let mtls_enabled = match config_get( ++ &conf_name, ++ &conf, ++ "cloud_agent", ++ "mtls_cert_enabled", ++ ) { ++ Ok(enabled) => bool::from_str(&enabled.to_lowercase()) ++ .or::(Ok(MTLS_ENABLED))?, ++ Err(_) => true, ++ }; ++ ++ let enable_insecure_payload = match config_get( ++ &conf_name, ++ &conf, ++ "cloud_agent", ++ "enable_insecure_payload", ++ ) { ++ Ok(allowed) => bool::from_str(&allowed.to_lowercase()) ++ .or::(Ok(ALLOW_INSECURE_PAYLOAD))?, ++ Err(_) => false, ++ }; + + Ok(KeylimeConfig { + agent_ip, +@@ -477,19 +559,11 @@ + } + } + +-/// Returns revocation ip from keylime.conf if env var not present +-fn revocation_ip_get() -> Result { +- config_get_env("general", "receive_revocation_ip", "REVOCATION_IP") +-} +- +-/// Returns revocation port from keylime.conf if env var not present +-fn revocation_port_get() -> Result { +- config_get_env("general", "receive_revocation_port", "REVOCATION_PORT") +-} +- + /// Returns the contact ip for the agent if set +-fn cloudagent_contact_ip_get() -> Option { ++fn cloudagent_contact_ip_get(conf_name: &str, conf: &Ini) -> Option { + match config_get_env( ++ conf_name, ++ conf, + "cloud_agent", + "agent_contact_ip", + "KEYLIME_AGENT_CONTACT_IP", +@@ -500,8 +574,13 @@ + } + + /// Returns the contact ip for the agent if set +-fn cloudagent_contact_port_get() -> Result> { ++fn cloudagent_contact_port_get( ++ conf_name: &str, ++ conf: &Ini, ++) -> Result> { + match config_get_env( ++ conf_name, ++ conf, + "cloud_agent", + "agent_contact_port", + "KEYLIME_AGENT_CONTACT_PORT", +@@ -518,15 +597,18 @@ + } + + /* +- * Input: [section] and key ++ * Input: conf_name, conf, [section] and key + * Return: Returns the matched key + * + * Example call: +- * let port = common::config_get("general","cloudagent_port"); ++ * let port = common::config_get(conf_file_name, file_Ini,"general","cloudagent_port"); + */ +-fn config_get(section: &str, key: &str) -> Result { +- let conf_name = config_file_get(); +- let conf = Ini::load_from_file(&conf_name)?; ++fn config_get( ++ conf_name: &str, ++ conf: &Ini, ++ section: &str, ++ key: &str, ++) -> Result { + let section = match conf.section(Some(section.to_owned())) { + Some(section) => section, + None => +@@ -554,23 +636,29 @@ + } + + /* +- * Input: [section] and key and environment variable ++ * Input: conf_name, conf,[section] and key and environment variable + * Return: Returns the matched key + * + * Example call: +- * let port = common::config_get_env("general","cloudagent_port", "CLOUDAGENT_PORT"); ++ * let port = common::config_get_env(conf_file_name, file_Ini, "general","cloudagent_port", "CLOUDAGENT_PORT"); + */ +-fn config_get_env(section: &str, key: &str, env: &str) -> Result { ++fn config_get_env( ++ conf_name: &str, ++ conf: &Ini, ++ section: &str, ++ key: &str, ++ env: &str, ++) -> Result { + match env::var(env) { + Ok(ip) => { + // The variable length must be larger than 0 to accept + if !ip.is_empty() { + Ok(ip) + } else { +- config_get(section, key) ++ config_get(conf_name, conf, section, key) + } + } +- _ => config_get(section, key), ++ _ => config_get(conf_name, conf, section, key), + } + } +