diff --git a/Cargo.toml b/Cargo.toml index 658f0a7..86de97b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,4 +19,3 @@ nonzero_ext = "0.3.0" [dev-dependencies] tempfile = "3" -mockall = "0.11.4" diff --git a/src/builder.rs b/src/builder.rs index aa385bc..3230844 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -121,7 +121,7 @@ impl ImplementationBuilder> for DefaultBuilder { fn create( resource: &Cert, target: & as Resource>::Artifact, - (csr, root_cert, account_key, challenges_dir, (user_name, _), _): ::Artifact, + (csr, root_cert, account_key, challenges_dir, user_name, _): ::Artifact, ) -> Self::Implementation { CertSymbol::new( resource.0.clone(), @@ -552,13 +552,13 @@ impl ImplementationBuilder> for DefaultBuilder { type Prerequisites = (); fn prerequisites(_resource: &UserForDomain) -> Self::Prerequisites {} - type Implementation = UserSymbol, Rc, StdCommandRunner>; + type Implementation = UserSymbol, StdCommandRunner>; fn create( _resource: &UserForDomain, - (user_name, home_path): & as Resource>::Artifact, + (user_name, _home_path): & as Resource>::Artifact, (): ::Artifact, ) -> Self::Implementation { - UserSymbol::new(user_name.0.clone(), home_path.into(), StdCommandRunner) + UserSymbol::new(user_name.0.clone(), StdCommandRunner) } } @@ -566,13 +566,13 @@ impl ImplementationBuilder for DefaultBuilder { type Prerequisites = (); fn prerequisites(_resource: &User) -> Self::Prerequisites {} - type Implementation = UserSymbol, Rc, StdCommandRunner>; + type Implementation = UserSymbol, StdCommandRunner>; fn create( resource: &User, - home_path: &::Artifact, + (): &::Artifact, (): ::Artifact, ) -> Self::Implementation { - UserSymbol::new(resource.0.clone(), home_path.into(), StdCommandRunner) + UserSymbol::new(resource.0.clone(), StdCommandRunner) } } @@ -594,13 +594,13 @@ impl ImplementationBuilder for DefaultBuilder { type Prerequisites = (); fn prerequisites(_resource: &AcmeUser) -> Self::Prerequisites {} - type Implementation = UserSymbol, Rc, StdCommandRunner>; + type Implementation = UserSymbol, StdCommandRunner>; fn create( _resource: &AcmeUser, - (user_name, home_path): &::Artifact, + user_name: &::Artifact, (): ::Artifact, ) -> Self::Implementation { - UserSymbol::new(user_name.0.clone(), home_path.into(), StdCommandRunner) + UserSymbol::new(user_name.0.clone(), StdCommandRunner) } } @@ -617,7 +617,7 @@ impl ImplementationBuilder for DefaultBuilder { fn create( _resource: &AcmeChallengesDir, target: &::Artifact, - (user_name, _): ::Artifact, + user_name: ::Artifact, ) -> Self::Implementation { ( DirSymbol::new(target.clone_rc()), @@ -658,7 +658,7 @@ impl ImplementationBuilder for DefaultBuilder { fn create( _resource: &AcmeAccountKey, target: &::Artifact, - (user_name, _): ::Artifact, + user_name: ::Artifact, ) -> Self::Implementation { ( KeySymbol::new(StdCommandRunner, target.clone_rc()), @@ -781,7 +781,7 @@ impl ImplementationBuilder> for DefaultBuilder { UserForDomain(resource.0.clone()) } - type Implementation = CronSymbol<'static, Box<[u8]>, Rc, StdCommandRunner>; + type Implementation = CronSymbol<'static, Box, Rc, StdCommandRunner>; fn create( resource: &Cron, (): & as Resource>::Artifact, diff --git a/src/command_runner.rs b/src/command_runner.rs index 75a1d3b..ec10437 100644 --- a/src/command_runner.rs +++ b/src/command_runner.rs @@ -1,6 +1,4 @@ use async_trait::async_trait; -#[cfg(test)] -use mockall::mock; use std::error::Error; use std::ffi::OsStr; use std::io::Result as IoResult; @@ -35,57 +33,30 @@ pub fn get_output(output: Output) -> Result, Box> { #[async_trait(?Send)] pub trait CommandRunner { - async fn run<'a>(&self, program: &str, args: &'a [&'a OsStr], input: &[u8]) -> IoResult; + async fn run(&self, program: &str, args: &[&OsStr], stdin: &[u8]) -> IoResult; - async fn run_with_args<'a>(&self, program: &str, args: &'a [&'a OsStr]) -> IoResult { + async fn run_with_args(&self, program: &str, args: &[&OsStr]) -> IoResult { self.run(program, args, b"").await } - async fn get_output<'a>( - &self, - program: &str, - args: &'a [&'a OsStr], - ) -> Result, Box> { + async fn get_output(&self, program: &str, args: &[&OsStr]) -> Result, Box> { let output = self.run_with_args(program, args).await?; get_output(output) } - async fn run_successfully<'a>( - &self, - program: &str, - args: &'a [&'a OsStr], - ) -> Result<(), Box> { + async fn run_successfully(&self, program: &str, args: &[&OsStr]) -> Result<(), Box> { is_success(self.run(program, args, b"").await)?; Ok(()) } - async fn get_stderr<'a>( - &self, - program: &str, - args: &'a [&'a OsStr], - ) -> Result, Box> { + async fn get_stderr(&self, program: &str, args: &[&OsStr]) -> Result, Box> { Ok(is_success(self.run_with_args(program, args).await)?.stderr) } } -#[cfg(test)] -mock! { - pub CommandRunner { - } - #[async_trait(?Send)] - impl CommandRunner for CommandRunner { - async fn run<'a>(&self, program: &str, args: &'a [&'a OsStr], input: &[u8]) -> IoResult; - - async fn run_with_args<'a>(&self, program: &str, args: &'a [&'a OsStr]) -> IoResult; - async fn get_output<'a>(&self, program: &str, args: &'a [&'a OsStr]) -> Result, Box>; - async fn run_successfully<'a>(&self, program: &str, args: &'a [&'a OsStr]) -> Result<(), Box>; - async fn get_stderr<'a>(&self, program: &str, args: &'a [&'a OsStr]) -> Result, Box>; - } -} - #[derive(Debug)] pub struct StdCommandRunner; #[async_trait(?Send)] impl CommandRunner for StdCommandRunner { - async fn run<'a>(&self, program: &str, args: &'a [&'a OsStr], input: &[u8]) -> IoResult { + async fn run(&self, program: &str, args: &[&OsStr], input: &[u8]) -> IoResult { //println!("{} {:?}", program, args); let mut child = Command::new(program) .args(args) @@ -143,7 +114,7 @@ impl Drop for TempSetEnv<'_> { #[async_trait(?Send)] impl> CommandRunner for SetuidCommandRunner { - async fn run<'a>(&self, program: &str, args: &'a [&'a OsStr], input: &[u8]) -> IoResult { + async fn run(&self, program: &str, args: &[&OsStr], input: &[u8]) -> IoResult { let uid = get_user_by_name(self.user_name.as_ref()) .expect("User does not exist") .uid(); diff --git a/src/locator.rs b/src/locator.rs index 01a6e41..2591253 100644 --- a/src/locator.rs +++ b/src/locator.rs @@ -202,9 +202,8 @@ impl ResourceLocator for DefaultLocator

{ impl ResourceLocator for DefaultLocator

{ type Prerequisites = (); fn locate(_resource: &AcmeUser) -> (::Artifact, Self::Prerequisites) { - let user_name = P::acme_user(); - let home = P::user_home(&user_name); - ((UserNameArtifact(user_name.into()), PathArtifact::from(home)), ()) + let acme_user = P::acme_user(); + (UserNameArtifact(acme_user.into()), ()) } } @@ -265,11 +264,10 @@ impl> ResourceLocator> for DefaultLoca } } -impl ResourceLocator for DefaultLocator

{ +impl

ResourceLocator for DefaultLocator

{ type Prerequisites = (); - fn locate(resource: &User) -> (::Artifact, Self::Prerequisites) { - let home = P::user_home(&resource.0); - ((PathArtifact::from(home)), ()) + fn locate(_resource: &User) -> (::Artifact, Self::Prerequisites) { + ((), ()) } } diff --git a/src/resources/mod.rs b/src/resources/mod.rs index 8c56a67..0d06c78 100644 --- a/src/resources/mod.rs +++ b/src/resources/mod.rs @@ -91,7 +91,7 @@ impl Resource for AcmeAccountKey { #[derive(Debug, Hash, PartialEq, Eq)] pub struct AcmeUser; impl Resource for AcmeUser { - type Artifact = (UserNameArtifact, PathArtifact); + type Artifact = UserNameArtifact; } #[derive(Debug, Hash, PartialEq, Eq)] @@ -138,7 +138,7 @@ pub fn get_saved_directory( #[derive(Debug, Hash, PartialEq, Eq)] pub struct User(pub Rc); impl Resource for User { - type Artifact = PathArtifact; + type Artifact = (); } #[derive(Debug, Hash, PartialEq, Eq)] diff --git a/src/setup/cache.rs b/src/setup/cache.rs index 895b89b..1e28287 100644 --- a/src/setup/cache.rs +++ b/src/setup/cache.rs @@ -1,4 +1,5 @@ use super::{Add, AddResult, AddableResource}; +use crate::async_utils::sleep; use crate::resources::{FromArtifact, FromResource}; use async_trait::async_trait; use futures_util::future::{FutureExt, Shared}; @@ -10,10 +11,9 @@ use std::future::Future; use std::hash::Hash; use std::pin::Pin; use std::rc::Rc; +use std::time::Duration; -// FIXME: Switch Error to Rc -type ResourceCache = - HashMap>>>>>; +type ResourceCache = HashMap>>>>; #[derive(Debug)] pub struct Cache { @@ -42,17 +42,19 @@ where async fn add(&self, logger: &Rc, resource: Rc, force_run: bool) -> AddResult { let (storable_resource, weak_resource) = Rs::from_resource(&resource); let mut resources = self.resources.borrow_mut(); - let future = if let Some(future) = resources.get(&storable_resource) { + let result = if let Some(future) = resources.remove(&storable_resource) { assert!( !force_run, "Forcing to run an already-added resource is a logical error" ); + resources.insert(storable_resource, future.clone()); + drop(resources); trace!(logger, "Resource already added"); - future.clone() + Ok(future.await) } else { let inner_weak = Rc::downgrade(&self.inner); let logger_weak = Rc::downgrade(logger); - let future = (Box::pin(async move { + let future = Box::pin(async move { let inner = inner_weak.upgrade().expect("Dangling!"); let logger = logger_weak.upgrade().expect("Dangling!"); let resource = weak_resource.upgrade().expect("Dangling!"); @@ -62,92 +64,25 @@ where result .map(|(t, did_run)| (As::from_artifact(t), did_run)) .map_err(|e| e.to_string()) - }) as Pin>>>) - .shared(); - resources.insert(storable_resource, future.clone()); - future + }) + .shared(); + let future_clone = future.clone(); + resources.insert( + storable_resource, + (Box::pin(async move { + let result = future_clone.await; + if result.is_err() { + // Step back to give the initial caller time to handle the error before unwrapping + sleep(Duration::from_millis(0)).await; + } + result.unwrap() + }) as Pin>>) + .shared(), + ); + drop(resources); + let result = future.await; + result.map_err(std::convert::Into::into) }; - drop(resources); - future - .await - .map(|(t, did_run)| (t.into_artifact(), did_run)) - .map_err(std::convert::Into::into) - } -} - -#[cfg(test)] -mod test { - use super::{Add, AddResult, Cache, Logger}; - use crate::async_utils::{join, run}; - use crate::resources::{FromArtifact, FromResource, Resource}; - use async_trait::async_trait; - use std::fmt::Debug; - use std::rc::{Rc, Weak}; - - #[derive(Debug, PartialEq, Eq, Hash)] - struct TestResource(&'static str, T); - impl Resource for TestResource { - type Artifact = (); - } - - #[derive(Debug, Hash, PartialEq, Eq)] - enum Resources { - A(Rc>), - B(Rc>), - } - impl FromResource> for Resources { - fn from_resource( - inner: &Rc>, - ) -> (Self, Weak>) { - (Self::A(Rc::clone(&inner)), Rc::downgrade(&inner)) - } - } - impl FromResource> for Resources { - fn from_resource(inner: &Rc>) -> (Self, Weak>) { - (Self::B(Rc::clone(&inner)), Rc::downgrade(&inner)) - } - } - - #[derive(Clone)] - struct Artifacts; - impl FromArtifact> for Artifacts { - fn from_artifact(_from: ()) -> Self { - Self - } - #[allow(clippy::unused_unit)] - fn into_artifact(self) -> () { - #[allow(clippy::unused_unit)] - () - } - } - - struct Inner; - - #[async_trait(?Send)] - impl Add> for Inner { - async fn add( - &self, - logger: &Rc, - resource: Rc>, - force_run: bool, - ) -> AddResult> { - Ok(((), resource.0 != "reached")) - } - } - - #[test] - fn test() { - let log = Rc::new(slog::Logger::root(slog::Discard, slog::o!())); - - let cache: Cache<_, Resources, Artifacts> = Cache::new(Inner); - run(async { - let reached = cache.add(&log, Rc::new(TestResource("reached", ())), false); - let a = cache.add(&log, Rc::new(TestResource("a", ())), false); - let b = cache.add(&log, Rc::new(TestResource("b", ())), false); - let (reached, a, b) = join!(reached, a, b); - assert_eq!(((), false), reached.unwrap()); - assert_eq!(((), true), a.unwrap()); - assert_eq!(((), true), b.unwrap()); - }) + result.map(|(t, did_run)| (t.into_artifact(), did_run)) } } diff --git a/src/setup/mod.rs b/src/setup/mod.rs index e1f3722..e90ebf0 100644 --- a/src/setup/mod.rs +++ b/src/setup/mod.rs @@ -191,40 +191,21 @@ mod test { #[derive(Debug, Hash, PartialEq, Eq)] enum Resources { - A(Rc>), - B(Rc>), - C(Rc>), - D(Rc>), - } - impl FromResource> for Resources { - fn from_resource(inner: &Rc>) -> (Self, Weak>) { - (Self::A(Rc::clone(&inner)), Rc::downgrade(&inner)) - } + A(Rc>), + B(Rc>), } impl FromResource> for Resources { fn from_resource( inner: &Rc>, ) -> (Self, Weak>) { + (Self::A(Rc::clone(&inner)), Rc::downgrade(&inner)) + } + } + impl FromResource> for Resources { + fn from_resource(inner: &Rc>) -> (Self, Weak>) { (Self::B(Rc::clone(&inner)), Rc::downgrade(&inner)) } } - impl FromResource> for Resources { - fn from_resource( - inner: &Rc>, - ) -> (Self, Weak>) { - (Self::C(Rc::clone(&inner)), Rc::downgrade(&inner)) - } - } - impl FromResource> for Resources { - fn from_resource( - inner: &Rc>, - ) -> ( - Self, - Weak>, - ) { - (Self::D(Rc::clone(&inner)), Rc::downgrade(&inner)) - } - } #[derive(Clone)] struct Artifacts; @@ -247,78 +228,7 @@ mod test { } } - #[derive(Debug)] - struct TestSymbol { - result: Result>, - } - impl TestSymbol { - fn new(def: &str) -> Self { - let first_char = def.chars().next().unwrap(); - Self { - result: if first_char == '!' { - Err(def.into()) - } else { - Ok(first_char.is_uppercase()) - }, - } - } - } - #[async_trait(?Send)] - impl Symbol for TestSymbol { - async fn target_reached(&self) -> Result> { - self.result.clone().map_err(|s| s.to_string().into()) - } - async fn execute(&self) -> Result<(), Box> { - Ok(()) - } - } - struct TestImplementationBuilder; - - impl ImplementationBuilder> - for TestImplementationBuilder - { - type Implementation = TestSymbol; - type Prerequisites = (TestResource<(&'static str, &'static str)>, TestResource<()>); - - fn prerequisites( - resource: &TestResource<((&'static str, &'static str), &'static str)>, - ) -> Self::Prerequisites { - ( - TestResource("complex_resource", (resource.1).0), // FIXME: Only one of these can exist - TestResource((resource.1).1, ()), - ) - } - fn create( - resource: &TestResource<((&'static str, &'static str), &'static str)>, - (): &(), - _inputs: ::Artifact, - ) -> Self::Implementation { - TestSymbol::new(resource.0) - } - } - - impl ImplementationBuilder> - for TestImplementationBuilder - { - type Implementation = TestSymbol; - type Prerequisites = (TestResource<()>, TestResource<()>); - - fn prerequisites(resource: &TestResource<(&'static str, &'static str)>) -> Self::Prerequisites { - ( - TestResource((resource.1).0, ()), - TestResource((resource.1).1, ()), - ) - } - fn create( - resource: &TestResource<(&'static str, &'static str)>, - (): &(), - _inputs: ::Artifact, - ) -> Self::Implementation { - TestSymbol::new(resource.0) - } - } - impl ImplementationBuilder> for TestImplementationBuilder { type Implementation = TestSymbol; type Prerequisites = TestResource<()>; @@ -331,17 +241,35 @@ mod test { (): &(), _inputs: ::Artifact, ) -> Self::Implementation { - TestSymbol::new(resource.0) + TestSymbol { + reached: resource.0.chars().next().unwrap().is_uppercase(), + } } } - impl ImplementationBuilder> for TestImplementationBuilder { type Implementation = TestSymbol; type Prerequisites = (); fn prerequisites(_resource: &TestResource<()>) -> Self::Prerequisites {} fn create(resource: &TestResource<()>, (): &(), (): ()) -> Self::Implementation { - TestSymbol::new(resource.0) + TestSymbol { + reached: resource.0.chars().next().unwrap().is_uppercase(), + } + } + } + + #[derive(Debug)] + struct TestSymbol { + reached: bool, + } + + #[async_trait(?Send)] + impl Symbol for TestSymbol { + async fn target_reached(&self) -> Result> { + Ok(self.reached) + } + async fn execute(&self) -> Result<(), Box> { + Ok(()) } } @@ -378,28 +306,12 @@ mod test { }); } - #[test] - fn failing_dependencies_deadlock() { - run(async { - let (count, setup, _) = get_setup(); - assert_eq!( - setup - .add(TestResource("a", (("b", "!x"), "!x"))) - .await - .unwrap_err() - .to_string(), - "!x" - ); - assert_eq!(*count.borrow(), 1); - }); - } - #[test] fn run_reached_symbol() { run(async { let (count, setup, log) = get_setup(); let did_run = setup - .run_symbol(TestSymbol { result: Ok(true) }, false) + .run_symbol(TestSymbol { reached: true }, false) .await .unwrap(); drop(setup); @@ -414,7 +326,7 @@ mod test { run(async { let (count, setup, log) = get_setup(); let did_run = setup - .run_symbol(TestSymbol { result: Ok(false) }, false) + .run_symbol(TestSymbol { reached: false }, false) .await .unwrap(); drop(setup); @@ -423,8 +335,7 @@ mod test { let log = log.release(); assert_eq!(log.len(), 1); assert_eq!(log[0].0, 3); - let re = Regex::new(r"^symbol: TestSymbol \{ result: Ok\(false\) \}\n \w+ \d{1,2} \d{2}:\d{2}:\d{2}.\d{3} INFO run\n$").unwrap(); - + let re = Regex::new(r"^symbol: TestSymbol \{ reached: false \}\n \w+ \d{1,2} \d{2}:\d{2}:\d{2}.\d{3} INFO run\n$").unwrap(); assert!(re.is_match(&log[0].1)); }); } diff --git a/src/symbols/cron.rs b/src/symbols/cron.rs index 1152a30..c0d7008 100644 --- a/src/symbols/cron.rs +++ b/src/symbols/cron.rs @@ -10,11 +10,11 @@ pub struct Cron<'r, C, U, R> { command_runner: &'r R, } -impl<'r, U, R> Cron<'r, Box<[u8]>, U, R> { +impl<'r, U, R> Cron<'r, Box, U, R> { pub fn new>(user: U, content: C, command_runner: &'r R) -> Self { Self { user, - content: (String::from(content.as_ref()) + "\n").as_bytes().into(), + content: (String::from(content.as_ref()) + "\n").into(), command_runner, } } diff --git a/src/symbols/git/checkout.rs b/src/symbols/git/checkout.rs index b859425..43be14b 100644 --- a/src/symbols/git/checkout.rs +++ b/src/symbols/git/checkout.rs @@ -92,30 +92,63 @@ impl<_C: CommandRunner, C: Borrow<_C>, P: AsRef, S: AsRef, B: AsRef>>, + } + #[async_trait(?Send)] + impl CommandRunner for DummyCommandRunner { + async fn run(&self, program: &str, args: &[&OsStr], stdin: &[u8]) -> IoResult { + assert_eq!(program, "git"); + assert_eq!(stdin, b""); + sleep(Duration::from_millis(50)).await; + self + .args + .borrow_mut() + .push(args.iter().map(|a| a.to_os_string()).collect()); + Ok(Output { + status: ExitStatus::from_raw(0), + stdout: vec![], + stderr: vec![], + }) + } + } #[test] fn test() { - let mut seq = Sequence::new(); - let mut c = MockCommandRunner::new(); - c.expect_get_output() - .times(1) - .withf(|cmd, args| cmd == "git" && args == ["-C", ".", "rev-list", "-1", "HEAD"]) - .returning(|_, _| Ok("".into())); - c.expect_get_output() - .times(1) - .in_sequence(&mut seq) - .withf(|cmd, args| cmd == "git" && args == ["-C", ".", "fetch", "source", "branch"]) - .returning(|_, _| Ok("".into())); - c.expect_get_output() - .times(1) - .in_sequence(&mut seq) - .withf(|cmd, args| cmd == "git" && args == ["-C", ".", "rev-list", "-1", "FETCH_HEAD"]) - .returning(|_, _| Ok("".into())); - let checkout = Checkout::new(".", "source", "branch", c); + let c = DummyCommandRunner { + args: RefCell::new(vec![]), + }; + let checkout: Checkout = + Checkout::new(".", "source", "branch", &c); + let start = Instant::now(); assert!(run(checkout.target_reached()).unwrap()); + let end = Instant::now(); + let mut args = c.args.into_inner(); + let first_two_args = &mut args[0..2]; + first_two_args.sort_unstable(); + assert_eq!( + first_two_args, + [ + ["-C", ".", "fetch", "source", "branch"], + ["-C", ".", "rev-list", "-1", "HEAD"], + ] + ); + assert_eq!(args[2], ["-C", ".", "rev-list", "-1", "FETCH_HEAD"]); + + assert!((end - start).as_millis() >= 100); + assert!((end - start).as_millis() < 150); } } diff --git a/src/symbols/tls/csr.rs b/src/symbols/tls/csr.rs index a5894fd..4af3683 100644 --- a/src/symbols/tls/csr.rs +++ b/src/symbols/tls/csr.rs @@ -2,7 +2,6 @@ use crate::command_runner::CommandRunner; use crate::symbols::Symbol; use async_trait::async_trait; use std::borrow::Borrow; -use std::convert::AsRef; use std::error::Error; use std::path::Path; @@ -26,9 +25,11 @@ impl Csr { } #[async_trait(?Send)] -impl, K: AsRef, P: AsRef> Symbol for Csr { +impl, K: Borrow, P: Borrow> Symbol + for Csr +{ async fn target_reached(&self) -> Result> { - if !self.csr_path.as_ref().exists() { + if !self.csr_path.borrow().exists() { return Ok(false); } @@ -36,10 +37,10 @@ impl, K: AsRef, P: AsRef> Symbol fo .command_runner .get_stderr( "openssl", - args!["req", "-in", self.csr_path.as_ref(), "-noout", "-verify",], + args!["req", "-in", self.csr_path.borrow(), "-noout", "-verify",], ) .await?; - Ok(output == b"verify OK\n" || output == b"Certificate request self-signature verify OK\n") + Ok(output == b"verify OK\n") } async fn execute(&self) -> Result<(), Box> { @@ -52,9 +53,9 @@ impl, K: AsRef, P: AsRef> Symbol fo "-new", "-sha256", "-key", - self.key_path.as_ref(), + self.key_path.borrow(), "-out", - self.csr_path.as_ref(), + self.csr_path.borrow(), "-subj", format!("/CN={}", self.domain.borrow()), ], @@ -64,68 +65,4 @@ impl, K: AsRef, P: AsRef> Symbol fo } #[cfg(test)] -mod test { - use super::{Csr, Symbol}; - use crate::async_utils::run; - use crate::command_runner::MockCommandRunner; - - #[test] - fn test_bookworm_success() { - let mut command_runner = MockCommandRunner::new(); - command_runner - .expect_get_stderr() - .times(1) - .returning(|_, _| Ok("Certificate request self-signature verify OK\n".into())); - let symbol = Csr::new(command_runner, "", "/nonexisting", "/"); // FIXME: Csr path has to be an existing file - run(async { - assert_eq!(symbol.target_reached().await.unwrap(), true); - }); - } - - #[test] - fn test_bookworm_invalid() { - let mut command_runner = MockCommandRunner::new(); - command_runner - .expect_get_stderr() - .times(1) - .returning(|_, _| { - Ok("Unable to load X509 request -40F746B61E7F0000:error:0480006C:PEM routines:get_name:no start line:../crypto/pem/pem_lib.c:763:Expecting: CERTIFICATE REQUEST -" .into()) - }); - let symbol = Csr::new(command_runner, "", "/nonexisting", "/"); // FIXME: Csr path has to be an existing file - run(async { - assert_eq!(symbol.target_reached().await.unwrap(), false); - }); - } - - #[test] - fn test_bullseye_success() { - let mut command_runner = MockCommandRunner::new(); - command_runner - .expect_get_stderr() - .times(1) - .returning(|_, _| Ok("verify OK\n".into())); - let symbol = Csr::new(command_runner, "", "/nonexisting", "/"); // FIXME: Csr path has to be an existing file - run(async { - assert_eq!(symbol.target_reached().await.unwrap(), true); - }); - } - - #[test] - fn test_bullseye_invalid() { - let mut command_runner = MockCommandRunner::new(); - command_runner - .expect_get_stderr() - .times(1) - .returning(|_, _| { - Ok("unable to load X509 request -140032085857600:error:0909006C:PEM routines:get_name:no start line:../crypto/pem/pem_lib.c:745:Expecting: CERTIFICATE REQUEST -" .into()) - }); - let symbol = Csr::new(command_runner, "", "/nonexisting", "/"); // FIXME: Csr path has to be an existing file - run(async { - assert_eq!(symbol.target_reached().await.unwrap(), false); - }); - } -} +mod test {} diff --git a/src/symbols/tls/key.rs b/src/symbols/tls/key.rs index 811d773..acbb8cc 100644 --- a/src/symbols/tls/key.rs +++ b/src/symbols/tls/key.rs @@ -30,7 +30,7 @@ impl> Symbol for Key { return Ok(false); } - let mut stdout = self + let stdout = self .command_runner .get_output( "openssl", @@ -44,12 +44,9 @@ impl> Symbol for Key { ], ) .await?; - if stdout.starts_with("RSA ".as_ref()) { - stdout = stdout.split_off(4); - } Ok( stdout.ends_with(b"RSA key ok\n") - && stdout.starts_with(format!("Private-Key: ({} bit, 2 primes)\n", self.bits).as_ref()), + && stdout.starts_with(format!("RSA Private-Key: ({} bit, 2 primes)\n", self.bits).as_ref()), ) } @@ -70,213 +67,4 @@ impl> Symbol for Key { } #[cfg(test)] -mod test { - use super::{Key, Symbol}; - use crate::async_utils::run; - use crate::command_runner::MockCommandRunner; - - #[test] - fn test_bookworm_success() { - let mut command_runner = MockCommandRunner::new(); - command_runner - .expect_get_output() - .times(1) - .returning(|_, _| { - Ok( - "Private-Key: (4096 bit, 2 primes) -modulus: - 00:... -publicExponent: 65537 (0x10001) -privateExponent: - 57:... -prime1: - 00:... -prime2: - 00:... -exponent1: - 2b:... -exponent2: - 0e:... -coefficient: - 43:... -RSA key ok -" - .into(), - ) - }); - let symbol = Key::new(command_runner, "/"); // FIXME: Has to be an existing file - run(async { - assert_eq!(symbol.target_reached().await.unwrap(), true); - }); - } - - #[test] - fn test_bookworm_short_key() { - let mut command_runner = MockCommandRunner::new(); - command_runner - .expect_get_output() - .times(1) - .returning(|_, _| { - Ok( - "Private-Key: (2048 bit, 2 primes) -modulus: - 00:... -publicExponent: 65537 (0x10001) -privateExponent: - 57:... -prime1: - 00:... -prime2: - 00:... -exponent1: - 2b:... -exponent2: - 0e:... -coefficient: - 43:... -RSA key ok -" - .into(), - ) - }); - let symbol = Key::new(command_runner, "/"); // FIXME: Has to be an existing file - run(async { - assert_eq!(symbol.target_reached().await.unwrap(), false); - }); - } - - #[test] - fn test_bookworm_broken_key() { - let mut command_runner = MockCommandRunner::new(); - command_runner.expect_get_output() - .times(1) - .returning(|_, _| Ok("Private-Key: (4096 bit, 2 primes) -modulus: - 00:... -publicExponent: 65537 (0x10001) -privateExponent: - 57:... -prime1: - 00:... -prime2: - 00:... -exponent1: - 2b:... -exponent2: - 0e:... -coefficient: - 43:... -RSA key not ok -40C782E5E77F0000:error:0200007E:rsa routines:rsa_validate_keypair_multiprime:iqmp not inverse of q:../crypto/rsa/rsa_chk.c:196: -".into())); - let symbol = Key::new(command_runner, "/"); // FIXME: Has to be an existing file - run(async { - assert_eq!(symbol.target_reached().await.unwrap(), false); - }); - } - - #[test] - fn test_bullseye_success() { - let mut command_runner = MockCommandRunner::new(); - command_runner - .expect_get_output() - .times(1) - .returning(|_, _| { - Ok( - "RSA Private-Key: (4096 bit, 2 primes) -modulus: - 00:... -publicExponent: 65537 (0x10001) -privateExponent: - 57:... -prime1: - 00:... -prime2: - 00:... -exponent1: - 2b:... -exponent2: - 0e:... -coefficient: - 43:... -RSA key ok -" - .into(), - ) - }); - let symbol = Key::new(command_runner, "/"); // FIXME: Has to be an existing file - run(async { - assert_eq!(symbol.target_reached().await.unwrap(), true); - }); - } - - #[test] - fn test_bullseye_short_key() { - let mut command_runner = MockCommandRunner::new(); - command_runner - .expect_get_output() - .times(1) - .returning(|_, _| { - Ok( - "RSA Private-Key: (2048 bit, 2 primes) -modulus: - 00:... -publicExponent: 65537 (0x10001) -privateExponent: - 57:... -prime1: - 00:... -prime2: - 00:... -exponent1: - 2b:... -exponent2: - 0e:... -coefficient: - 43:... -RSA key ok -" - .into(), - ) - }); - let symbol = Key::new(command_runner, "/"); // FIXME: Has to be an existing file - run(async { - assert_eq!(symbol.target_reached().await.unwrap(), false); - }); - } - - #[test] - fn test_bullseye_broken_key() { - let mut command_runner = MockCommandRunner::new(); - command_runner - .expect_get_output() - .times(1) - .returning(|_, _| { - Ok( - "RSA Private-Key: (4096 bit, 2 primes) -modulus: - 00:... -publicExponent: 65537 (0x10001) -privateExponent: - 57:... -prime1: - 00:... -prime2: - 00:... -exponent1: - 2b:... -exponent2: - 0e:... -coefficient: - 43:... -RSA key error: iqmp not inverse of q -" - .into(), - ) - }); - let symbol = Key::new(command_runner, "/"); // FIXME: Has to be an existing file - run(async { - assert_eq!(symbol.target_reached().await.unwrap(), false); - }); - } -} +mod test {} diff --git a/src/symbols/user.rs b/src/symbols/user.rs index c32bec3..db784a7 100644 --- a/src/symbols/user.rs +++ b/src/symbols/user.rs @@ -4,30 +4,27 @@ use async_trait::async_trait; use once_cell::sync::Lazy; use std::error::Error; use tokio::sync::Semaphore; -use std::path::Path; pub type Wait = Lazy; static WAIT: Wait = Lazy::new(|| Semaphore::new(1)); #[derive(Debug)] -pub struct User { +pub struct User { user_name: U, - home_path: H, command_runner: C, } -impl User { - pub const fn new(user_name: U, home_path: H, command_runner: C) -> Self { +impl User { + pub const fn new(user_name: U, command_runner: C) -> Self { Self { user_name, - home_path, command_runner, } } } #[async_trait(?Send)] -impl, H: AsRef, C: CommandRunner> Symbol for User { +impl, C: CommandRunner> Symbol for User { async fn target_reached(&self) -> Result> { let output = self .command_runner @@ -51,8 +48,6 @@ impl, H: AsRef, C: CommandRunner> Symbol for User { args![ // "-m", // Necessary for Fedora, not accepted in Debian "--system", - "--home", - self.home_path.as_ref(), self.user_name.as_ref(), ], )