use crate::command_runner::CommandRunner; use crate::symbols::Symbol; use std::borrow::Borrow; use std::error::Error; use std::fs::File as FsFile; use std::io::Write; use std::marker::PhantomData; use std::path::Path; #[derive(Debug)] pub struct Cert<_C, C, D, P> { domain: D, command_runner: C, root_cert_path: P, account_key_path: P, challenges_path: P, csr_path: P, cert_path: P, phantom: PhantomData<_C>, } impl<_C, C, D, P> Cert<_C, C, D, P> { pub fn new( domain: D, command_runner: C, root_cert_path: P, account_key_path: P, challenges_path: P, csr_path: P, cert_path: P, ) -> Self { Self { domain, command_runner, root_cert_path, account_key_path, challenges_path, csr_path, cert_path, phantom: PhantomData::default(), } } } const DAYS_IN_SECONDS: u32 = 24 * 60 * 60; impl<_C: CommandRunner, C: Borrow<_C>, D: AsRef, P: AsRef> Symbol for Cert<_C, C, D, P> { fn target_reached(&self) -> Result> { if !self.cert_path.as_ref().exists() { return Ok(false); } let output = self.command_runner.borrow().run_with_args( "openssl", args![ "x509", "-in", self.cert_path.as_ref(), "-noout", "-subject", "-checkend", (30 * DAYS_IN_SECONDS).to_string(), ], )?; if output.status.success() && output.stdout == format!( "subject=CN = {}\nCertificate will not expire\n", self.domain.as_ref() ) .as_bytes() { Ok( self .command_runner .borrow() .run_successfully( "openssl", args![ "verify", "--untrusted", self.root_cert_path.as_ref(), self.cert_path.as_ref(), ], ) .is_ok(), ) } else if output.status.code() == Some(1) && output.stdout == format!( "subject=CN = {}\nCertificate will expire\n", self.domain.as_ref() ) .as_bytes() { Ok(false) } else { Err(String::from_utf8(output.stderr)?.into()) } } fn execute(&self) -> Result<(), Box> { let output = self.command_runner.borrow().get_output( "acme-tiny", args![ "--account-key", self.account_key_path.as_ref(), "--csr", self.csr_path.as_ref(), "--acme-dir", self.challenges_path.as_ref(), ], )?; let mut file = FsFile::create(self.cert_path.as_ref())?; file.write_all(&output)?; Ok(()) } } #[cfg(test)] mod test {}