From 00f0b2e9ed341bf19b5bbeb4bda38c9cdf2ac7a1 Mon Sep 17 00:00:00 2001 From: Anderson Toshiyuki Sasaki Date: Thu, 12 May 2022 12:36:07 +0200 Subject: [PATCH] Make support for legacy python revocation actions optional Add the 'legacy-python-actions' feature, enabled by default, to control whether the agent supports python revocation actions loaded as modules. Note that this is the only kind of revocation actions script supported by the python agent implementation, which means that removing this feature will make existing revocation actions unusable. Disabling the 'legacy-python-actions' feature will not disable the support for running stand-alone python revocation action scripts, i.e. executable python scripts can be used as a revocation actions scripts, as well as any other executable. Signed-off-by: Anderson Toshiyuki Sasaki --- Cargo.toml | 7 +- src/main.rs | 22 +++--- src/revocation.rs | 87 +++++++++++++++-------- tests/actions/local_action_stand_alone.py | 26 +++++++ tests/unzipped/action_list | 2 - 5 files changed, 102 insertions(+), 42 deletions(-) create mode 100755 tests/actions/local_action_stand_alone.py diff --git a/Cargo.toml b/Cargo.toml index 2c8c1cd1..95bbfabe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -50,9 +50,14 @@ wiremock = "0.5" [features] # The features enabled by default -default = ["with-zmq"] +default = ["with-zmq", "legacy-python-actions"] # this should change to dev-dependencies when we have integration testing testing = [] # Whether the agent should be compiled with support to listen for notification # messages on ZeroMQ with-zmq = ["zmq"] +# Whether the agent should be compiled with support for python revocation +# actions loaded as modules, which is the only kind supported by the python +# agent (unless the enhancement-55 is implemented). See: +# https://github.com/keylime/enhancements/blob/master/55_revocation_actions_without_python.md +legacy-python-actions = [] diff --git a/src/main.rs b/src/main.rs index 91e0f58b..bc7216a9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -424,15 +424,19 @@ async fn main() -> Result<()> { warn!("INSECURE: Only use Keylime in this mode for testing or debugging purposes."); } - // Verify if the python shim is installed in the expected location - let python_shim = - PathBuf::from(&config.revocation_actions_dir).join("shim.py"); - if !python_shim.exists() { - error!("Could not find python shim at {}", python_shim.display()); - return Err(Error::Configuration(format!( - "Could not find python shim at {}", - python_shim.display() - ))); + cfg_if::cfg_if! { + if #[cfg(feature = "legacy-python-actions")] { + // Verify if the python shim is installed in the expected location + let python_shim = + PathBuf::from(&config.revocation_actions_dir).join("shim.py"); + if !python_shim.exists() { + error!("Could not find python shim at {}", python_shim.display()); + return Err(Error::Configuration(format!( + "Could not find python shim at {}", + python_shim.display() + ))); + } + } } // Gather EK values and certs diff --git a/src/revocation.rs b/src/revocation.rs index c015b4e7..e95bcff1 100644 --- a/src/revocation.rs +++ b/src/revocation.rs @@ -22,6 +22,7 @@ use serde_json::Value; /// The lookup goes in the following order: /// 1. Look for pre-installed action /// 2. Look for the action in the tenant-provided initial payload +/// Then, if python revocation actions are allowed: /// 3. Look for pre-installed Python action /// 4. Look for the Python action in the tenant-provided initial payload fn lookup_action( @@ -44,7 +45,9 @@ fn lookup_action( let possible_paths = [ (actions_dir.join(action), false, false), (payload_dir.join(action), false, true), + #[cfg(feature = "legacy-python-actions")] (actions_dir.join(&py_action), true, false), + #[cfg(feature = "legacy-python-actions")] (payload_dir.join(&py_action), true, true), ]; @@ -460,7 +463,7 @@ mod tests { assert!(outputs.is_ok()); let outputs = outputs.unwrap(); //#[allow_ci] - assert!(outputs.len() == 4); + assert!(outputs.len() == 2); for output in outputs { assert_eq!( @@ -506,8 +509,16 @@ mod tests { env!("CARGO_MANIFEST_DIR"), "/tests/unzipped/test_ok.json" ); - test_config.revocation_actions = - String::from("local_action_hello, local_action_payload"); + cfg_if::cfg_if! { + if #[cfg(feature = "legacy-python-actions")] { + test_config.revocation_actions = + String::from("local_action_hello, local_action_payload, local_action_stand_alone.py, local_action_rev_script1.py"); + } else { + test_config.revocation_actions = String::from( + "local_action_stand_alone.py, local_action_rev_script1.py", + ); + } + } let json_str = std::fs::read_to_string(json_file).unwrap(); //#[allow_ci] let json = serde_json::from_str(&json_str).unwrap(); //#[allow_ci] let actions_dir = @@ -531,7 +542,13 @@ mod tests { assert!(outputs.is_ok()); let outputs = outputs.unwrap(); //#[allow_ci] - assert!(outputs.len() == 6); + cfg_if::cfg_if! { + if #[cfg(feature = "legacy-python-actions")] { + assert!(outputs.len() == 6); + } else { + assert!(outputs.len() == 4); + } + } for output in outputs { assert_eq!( @@ -593,19 +610,24 @@ mod tests { let payload_dir = Path::new(&work_dir).join("unzipped/"); let actions_dir = Path::new(&work_dir).join("actions/"); - // Test local python action - let expected = format!("{}", &actions_dir.join("shim.py").display(),); - - assert_eq!( - lookup_action( - &payload_dir, - &actions_dir, - "local_action_hello", - true - ) - .unwrap(), //#[allow_ci] - (expected, true, false) - ); + cfg_if::cfg_if! { + if #[cfg(feature = "legacy-python-actions")] { + // Test local python action + let expected = + format!("{}", &actions_dir.join("shim.py").display(),); + + assert_eq!( + lookup_action( + &payload_dir, + &actions_dir, + "local_action_hello", + true + ) + .unwrap(), //#[allow_ci] + (expected, true, false) + ); + } + } // Test local non-python action let expected = format!( @@ -624,19 +646,24 @@ mod tests { (expected, false, false) ); - // Test payload python action - let expected = format!("{}", &actions_dir.join("shim.py").display(),); - - assert_eq!( - lookup_action( - &payload_dir, - &actions_dir, - "local_action_payload", - true, - ) - .unwrap(), //#[allow_ci] - (expected, true, true), - ); + cfg_if::cfg_if! { + if #[cfg(feature = "legacy-python-actions")] { + // Test payload python action + let expected = + format!("{}", &actions_dir.join("shim.py").display(),); + + assert_eq!( + lookup_action( + &payload_dir, + &actions_dir, + "local_action_payload", + true, + ) + .unwrap(), //#[allow_ci] + (expected, true, true), + ); + } + } // Test payload non-python action let expected = format!( diff --git a/tests/actions/local_action_stand_alone.py b/tests/actions/local_action_stand_alone.py new file mode 100755 index 00000000..50f5a572 --- /dev/null +++ b/tests/actions/local_action_stand_alone.py @@ -0,0 +1,26 @@ +#!/usr/bin/python3 +''' +SPDX-License-Identifier: Apache-2.0 +Copyright 2021 Keylime Authors +''' + +import argparse +import json +import sys + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('json_file') + args = parser.parse_args() + + with open(args.json_file, 'r') as f: + input_json = json.load(f) + value = input_json['hello'] + + print(value) + + +if __name__ == "__main__": + main() + diff --git a/tests/unzipped/action_list b/tests/unzipped/action_list index 41ccbbcc..91d710e5 100644 --- a/tests/unzipped/action_list +++ b/tests/unzipped/action_list @@ -1,4 +1,2 @@ local_action_rev_script1.py local_action_rev_script2.py -local_action_payload -local_action_hello