Browse Source

Update

master
Adrian Heine 8 years ago
parent
commit
eadd5f5b07
  1. 2
      Cargo.toml
  2. 23
      src/command_runner.rs
  3. 1
      src/lib.rs
  4. 25
      src/symbols/acme/account_key.rs
  5. 33
      src/symbols/acme/cert.rs
  6. 13
      src/symbols/git/checkout.rs
  7. 9
      src/symbols/git/submodules.rs
  8. 10
      src/symbols/mariadb/database.rs
  9. 10
      src/symbols/mariadb/database_dump.rs
  10. 7
      src/symbols/mariadb/user.rs
  11. 2
      src/symbols/mod.rs
  12. 3
      src/symbols/nginx/server.rs
  13. 44
      src/symbols/not_a_symlink.rs
  14. 7
      src/symbols/npm.rs
  15. 3
      src/symbols/owner.rs
  16. 24
      src/symbols/stored_directory.rs
  17. 2
      src/symbols/systemd/node_js_user_service.rs
  18. 3
      src/symbols/systemd/reload.rs
  19. 10
      src/symbols/systemd/user_session.rs
  20. 16
      src/symbols/tls/csr.rs
  21. 20
      src/symbols/tls/key.rs
  22. 19
      src/symbols/tls/self_signed_cert.rs
  23. 13
      src/symbols/user.rs
  24. 2
      src/symbols/wordpress/translation.rs

2
Cargo.toml

@ -5,7 +5,7 @@ authors = ["Adrian Heine <mail@adrianheine.de>"]
[dependencies] [dependencies]
users = "0.5.0" users = "0.5.0"
regex = "0.2"
[dev-dependencies] [dev-dependencies]
tempdir = "0.3" tempdir = "0.3"
regex = "0.2"

23
src/command_runner.rs

@ -1,9 +1,32 @@
use std::error::Error;
use std::io::Result as IoResult; use std::io::Result as IoResult;
use std::process::Command; use std::process::Command;
use std::process::Output; use std::process::Output;
pub trait CommandRunner { pub trait CommandRunner {
fn run_with_args(&self, program: &str, args: &[&str]) -> IoResult<Output>; fn run_with_args(&self, program: &str, args: &[&str]) -> IoResult<Output>;
fn get_output(&self, program: &str, args: &[&str]) -> Result<Vec<u8>, Box<Error>> {
let output = try!(self.run_with_args(program, args));
if !output.status.success() {
return Err(try!(String::from_utf8(output.stderr)).into());
}
Ok(output.stdout)
}
fn get_stderr(&self, program: &str, args: &[&str]) -> Result<Vec<u8>, Box<Error>> {
let output = try!(self.run_with_args(program, args));
if !output.status.success() {
return Err(try!(String::from_utf8(output.stderr)).into());
}
Ok(output.stderr)
}
fn run_successfully(&self, program: &str, args: &[&str]) -> Result<(), Box<Error>> {
let output = try!(self.run_with_args(program, args));
if output.status.success() {
Ok(())
} else {
Err(try!(String::from_utf8(output.stderr)).into())
}
}
} }
#[derive(Debug)] #[derive(Debug)]

1
src/lib.rs

@ -20,6 +20,7 @@ missing_debug_implementations
#![allow(box_pointers)] #![allow(box_pointers)]
extern crate regex;
extern crate users; extern crate users;
pub mod command_runner; pub mod command_runner;

25
src/symbols/acme/account_key.rs

@ -1,6 +1,7 @@
use std::borrow::Cow;
use std::borrow::{Borrow, Cow};
use std::error::Error; use std::error::Error;
use std::fmt; use std::fmt;
use std::path::Path;
use command_runner::CommandRunner; use command_runner::CommandRunner;
use symbols::Symbol; use symbols::Symbol;
@ -18,8 +19,8 @@ impl<'a> AcmeAccountKey<'a> {
} }
} }
fn get_path(&self) -> String {
self.path.clone().into_owned()
fn get_path(&self) -> &str {
self.path.borrow()
} }
fn get_bytes(&self) -> u32 { fn get_bytes(&self) -> u32 {
@ -35,23 +36,15 @@ impl<'a> fmt::Display for AcmeAccountKey<'a> {
impl<'a> Symbol for AcmeAccountKey<'a> { impl<'a> Symbol for AcmeAccountKey<'a> {
fn target_reached(&self) -> Result<bool, Box<Error>> { fn target_reached(&self) -> Result<bool, Box<Error>> {
let result = self.command_runner.run_with_args("openssl", &["rsa", "-in", &self.get_path(), "-noout", "-check", "-text"]);
match result {
Err(e) => Err(Box::new(e)),
Ok(output) => match output.status.code() {
Some(0) => Ok(output.stdout.starts_with(format!("Private-Key: ({} bit)\n", self.get_bytes()).as_bytes())),
Some(_) => Ok(false),
_ => Err("Didn't work".to_string().into())
}
if !Path::new(self.get_path()).exists() {
return Ok(false);
} }
let stdout = try!(self.command_runner.get_output("openssl", &["rsa", "-in", self.get_path(), "-noout", "-check", "-text"]));
Ok(stdout.starts_with(&format!("Private-Key: ({} bit)\n", self.get_bytes()).as_bytes()))
} }
fn execute(&self) -> Result<(), Box<Error>> { fn execute(&self) -> Result<(), Box<Error>> {
let output = self.command_runner.run_with_args("openssl", &["genrsa", "-out", &self.get_path(), &self.get_bytes().to_string()]);
match output {
Err(e) => Err(Box::new(e)),
Ok(_) => Ok(())
}
self.command_runner.run_successfully("openssl", &["genrsa", "-out", self.get_path(), &self.get_bytes().to_string()])
} }
} }

33
src/symbols/acme/cert.rs

@ -2,7 +2,8 @@ use std::borrow::Cow;
use std::error::Error; use std::error::Error;
use std::fmt; use std::fmt;
use std::fs::File as FsFile; use std::fs::File as FsFile;
use std::io::{self, Write};
use std::io::Write;
use std::path::Path;
use command_runner::CommandRunner; use command_runner::CommandRunner;
use symbols::Symbol; use symbols::Symbol;
@ -40,35 +41,23 @@ const DAYS_IN_SECONDS: u32 = 24*60*60;
impl<'a> Symbol for AcmeCert<'a> { impl<'a> Symbol for AcmeCert<'a> {
fn target_reached(&self) -> Result<bool, Box<Error>> { fn target_reached(&self) -> Result<bool, Box<Error>> {
let file = FsFile::open(self.get_cert_path());
// Check first if file exists to support dry-run mode where the acme user is not even created
if let Err(e) = file {
return if e.kind() == io::ErrorKind::NotFound {
Ok(false)
} else {
Err(Box::new(e))
};
if !Path::new(&self.get_cert_path()).exists() {
return Ok(false);
} }
// FIXME: check who signed it // FIXME: check who signed it
let result = self.command_runner.run_with_args("openssl", &["x509", "-in", &self.get_cert_path(), "-noout", "-subject", "-checkend", &(30*DAYS_IN_SECONDS).to_string()]);
match result {
Err(e) => Err(Box::new(e)),
Ok(output) => match output.status.code() {
Some(0) => if output.stdout == format!("subject=CN = {}\nCertificate will not expire\n", self.domain).as_bytes() {
let result = try!(self.command_runner.run_with_args("openssl", &["verify", "--untrusted", "/home/acme/lets_encrypt_x3_cross_signed.pem", &self.get_cert_path()]).map_err(|e| Box::new(e)));
Ok(result.status.code() == Some(0))
} else { Ok(false) },
Some(_) => Ok(false),
_ => Err("Didn't work".to_string().into())
}
let stdout = try!(self.command_runner.get_output("openssl", &["x509", "-in", &self.get_cert_path(), "-noout", "-subject", "-checkend", &(30*DAYS_IN_SECONDS).to_string()]));
if stdout != format!("subject=CN = {}\nCertificate will not expire\n", self.domain).as_bytes() {
return Ok(false);
} }
try!(self.command_runner.run_successfully("openssl", &["verify", "--untrusted", "/home/acme/lets_encrypt_x3_cross_signed.pem", &self.get_cert_path()]));
Ok(true)
} }
fn execute(&self) -> Result<(), Box<Error>> { fn execute(&self) -> Result<(), Box<Error>> {
let output = try!(self.command_runner.run_with_args("acme-tiny", &["--account-key", "/home/acme/account.key", "--csr", &self.get_csr_path(), "--acme-dir", "/home/acme/challenges/"]).map_err(|e| Box::new(e)));
let output = try!(self.command_runner.get_output("acme-tiny", &["--account-key", "/home/acme/account.key", "--csr", &self.get_csr_path(), "--acme-dir", "/home/acme/challenges/"]));
let mut file = try!(FsFile::create(self.get_cert_path())); let mut file = try!(FsFile::create(self.get_cert_path()));
try!(file.write_all(&output.stdout));
try!(file.write_all(&output));
Ok(()) Ok(())
} }

13
src/symbols/git/checkout.rs

@ -34,10 +34,10 @@ impl<'a> fmt::Display for GitCheckout<'a> {
use std::fs::metadata; use std::fs::metadata;
impl<'a> GitCheckout<'a> { impl<'a> GitCheckout<'a> {
fn _run_in_target_repo(&self, args: &[&str]) -> Result<Vec<u8>, io::Error> {
fn _run_in_target_repo(&self, args: &[&str]) -> Result<Vec<u8>, Box<Error>> {
let mut new_args = vec!["-C", self.target]; let mut new_args = vec!["-C", self.target];
new_args.extend_from_slice(args); new_args.extend_from_slice(args);
self.command_runner.run_with_args("git", &new_args).map(|res| res.stdout)
self.command_runner.get_output("git", &new_args)
} }
} }
@ -57,13 +57,8 @@ impl<'a> Symbol for GitCheckout<'a> {
} }
fn execute(&self) -> Result<(), Box<Error>> { fn execute(&self) -> Result<(), Box<Error>> {
if let Err(e) = metadata(self.target) {
return if e.kind() == io::ErrorKind::NotFound {
try!(self.command_runner.run_with_args("git", &["clone", "--depth", "1", "-b", self.branch, self.source, self.target]));
Ok(())
} else {
Err(Box::new(e))
};
if !Path::new(self.target).exists() {
return self.command_runner.run_successfully("git", &["clone", "--depth", "1", "-b", self.branch, self.source, self.target]);
} }
try!(self._run_in_target_repo(&["fetch", self.source, self.branch])); try!(self._run_in_target_repo(&["fetch", self.source, self.branch]));
try!(self._run_in_target_repo(&["merge", "FETCH_HEAD"])); try!(self._run_in_target_repo(&["merge", "FETCH_HEAD"]));

9
src/symbols/git/submodules.rs

@ -1,6 +1,5 @@
use std::error::Error; use std::error::Error;
use std::fmt; use std::fmt;
use std::io;
use command_runner::CommandRunner; use command_runner::CommandRunner;
use symbols::Symbol; use symbols::Symbol;
@ -26,17 +25,17 @@ impl<'a> fmt::Display for GitSubmodules<'a> {
} }
impl<'a> GitSubmodules<'a> { impl<'a> GitSubmodules<'a> {
fn _run_in_target_repo(&self, args: &[&str]) -> Result<Vec<u8>, io::Error> {
fn _run_in_target_repo(&self, args: &[&str]) -> Result<Vec<u8>, Box<Error>> {
let mut new_args = vec!["-C", self.target]; let mut new_args = vec!["-C", self.target];
new_args.extend_from_slice(args); new_args.extend_from_slice(args);
self.command_runner.run_with_args("git", &new_args).map(|res| res.stdout)
self.command_runner.get_output("git", &new_args)
} }
} }
impl<'a> Symbol for GitSubmodules<'a> { impl<'a> Symbol for GitSubmodules<'a> {
fn target_reached(&self) -> Result<bool, Box<Error>> { fn target_reached(&self) -> Result<bool, Box<Error>> {
let output = try!(self._run_in_target_repo(&["submodule", "status"]));
Ok(String::from_utf8(output).unwrap().lines().all(|line| line.len() == 0 || line.starts_with(' ')))
let output = try!(String::from_utf8(try!(self._run_in_target_repo(&["submodule", "status"]))));
Ok(output.lines().all(|line| line.len() == 0 || line.starts_with(' ')))
} }
fn execute(&self) -> Result<(), Box<Error>> { fn execute(&self) -> Result<(), Box<Error>> {

10
src/symbols/mariadb/database.rs

@ -21,11 +21,8 @@ impl<'a> MariaDBDatabase<'a> {
} }
fn run_sql(&self, sql: &str) -> Result<String, Box<Error>> { fn run_sql(&self, sql: &str) -> Result<String, Box<Error>> {
let output = try!(self.command_runner.run_with_args("mariadb", &["--skip-column-names", "-B", "-e", sql]));
if output.status.code() != Some(0) {
return Err(try!(String::from_utf8(output.stderr)).into());
}
Ok(try!(String::from_utf8(output.stdout)))
let b = try!(self.command_runner.get_output("mariadb", &["--skip-column-names", "-B", "-e", sql]));
Ok(try!(String::from_utf8(b)))
} }
} }
@ -42,8 +39,7 @@ impl<'a> Symbol for MariaDBDatabase<'a> {
fn execute(&self) -> Result<(), Box<Error>> { fn execute(&self) -> Result<(), Box<Error>> {
try!(self.run_sql(&format!("CREATE DATABASE {}", self.db_name))); try!(self.run_sql(&format!("CREATE DATABASE {}", self.db_name)));
try!(self.command_runner.run_with_args("sh", &["-c", &format!("mariadb '{}' < {}", self.db_name, self.seed_file)]));
Ok(())
self.command_runner.run_successfully("sh", &["-c", &format!("mariadb '{}' < {}", self.db_name, self.seed_file)])
} }
} }

10
src/symbols/mariadb/database_dump.rs

@ -23,11 +23,8 @@ impl<'a, S> DatabaseDump<'a, S> where S: Storage {
} }
fn run_sql(&self, sql: &str) -> Result<String, Box<Error>> { fn run_sql(&self, sql: &str) -> Result<String, Box<Error>> {
let output = try!(self.command_runner.run_with_args("mariadb", &["--skip-column-names", "-B", "-e", sql]));
if output.status.code() != Some(0) {
return Err(try!(String::from_utf8(output.stderr)).into());
}
Ok(try!(String::from_utf8(output.stdout)))
let b = try!(self.command_runner.get_output("mariadb", &["--skip-column-names", "-B", "-e", sql]));
Ok(try!(String::from_utf8(b)))
} }
} }
@ -45,8 +42,7 @@ impl<'a, S> Symbol for DatabaseDump<'a, S> where S: Storage {
} }
fn execute(&self) -> Result<(), Box<Error>> { fn execute(&self) -> Result<(), Box<Error>> {
try!(self.command_runner.run_with_args("sh", &["-c", &format!("mysqldump '{}' > {}", self.db_name, self.storage.write_filename())]));
Ok(())
self.command_runner.run_successfully("sh", &["-c", &format!("mysqldump '{}' > {}", self.db_name, self.storage.write_filename())])
} }
} }

7
src/symbols/mariadb/user.rs

@ -20,11 +20,8 @@ impl<'a> MariaDBUser<'a> {
} }
fn run_sql(&self, sql: &str) -> Result<String, Box<Error>> { fn run_sql(&self, sql: &str) -> Result<String, Box<Error>> {
let output = try!(self.command_runner.run_with_args("mariadb", &["--skip-column-names", "-e", sql]));
if output.status.code() != Some(0) {
return Err(try!(String::from_utf8(output.stderr)).into());
}
Ok(try!(String::from_utf8(output.stdout)))
let b = try!(self.command_runner.get_output("mariadb", &["--skip-column-names", "-B", "-e", sql]));
Ok(try!(String::from_utf8(b)))
} }
} }

2
src/symbols/mod.rs

@ -22,10 +22,10 @@ pub mod if_already_present;
pub mod list; pub mod list;
pub mod mariadb; pub mod mariadb;
pub mod nginx; pub mod nginx;
pub mod not_a_symlink;
pub mod npm; pub mod npm;
pub mod owner; pub mod owner;
pub mod stored_directory; pub mod stored_directory;
pub mod systemd; pub mod systemd;
pub mod tls; pub mod tls;
pub mod user; pub mod user;
pub mod wordpress;

3
src/symbols/nginx/server.rs

@ -140,8 +140,7 @@ impl<'a, C> Symbol for NginxServer<'a, C> where C: Deref<Target=str> {
fn execute(&self) -> Result<(), Box<Error>> { fn execute(&self) -> Result<(), Box<Error>> {
try!(self.file.execute()); try!(self.file.execute());
try!(self.command_runner.run_with_args("systemctl", &["reload-or-restart", "nginx"]));
Ok(())
self.command_runner.run_successfully("systemctl", &["reload-or-restart", "nginx"])
} }
fn get_prerequisites(&self) -> Vec<Resource> { fn get_prerequisites(&self) -> Vec<Resource> {

44
src/symbols/not_a_symlink.rs

@ -1,44 +0,0 @@
use std::error::Error;
use std::fmt;
use std::fs;
use std::io;
use symbols::Symbol;
pub struct NotASymlink<D> where D: AsRef<str> + fmt::Display {
path: D
}
impl<D> NotASymlink<D> where D: AsRef<str> + fmt::Display {
pub fn new(path: D) -> Self {
NotASymlink {
path: path
}
}
}
impl<D> Symbol for NotASymlink<D> where D: AsRef<str> + fmt::Display {
fn target_reached(&self) -> Result<bool, Box<Error>> {
let metadata = fs::symlink_metadata(self.path.as_ref());
// Check if file exists
if let Err(e) = metadata {
return if e.kind() == io::ErrorKind::NotFound {
Ok(true)
} else {
Err(Box::new(e))
};
}
Ok(!metadata.unwrap().file_type().is_symlink())
}
fn execute(&self) -> Result<(), Box<Error>> {
try!(fs::remove_file(self.path.as_ref()));
Ok(())
}
}
impl<D> fmt::Display for NotASymlink<D> where D: AsRef<str> + fmt::Display {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error>{
write!(f, "NotASymlink {}", self.path)
}
}

7
src/symbols/npm.rs

@ -1,5 +1,6 @@
use std::error::Error; use std::error::Error;
use std::fmt; use std::fmt;
use std::path::Path;
use command_runner::CommandRunner; use command_runner::CommandRunner;
use symbols::Symbol; use symbols::Symbol;
@ -26,13 +27,15 @@ impl<'a> fmt::Display for NpmInstall<'a> {
impl<'a> Symbol for NpmInstall<'a> { impl<'a> Symbol for NpmInstall<'a> {
fn target_reached(&self) -> Result<bool, Box<Error>> { fn target_reached(&self) -> Result<bool, Box<Error>> {
if !Path::new(self.target).exists() {
return Ok(false);
}
let result = try!(self.command_runner.run_with_args("sh", &["-c", &format!("cd '{}' && npm ls", self.target)])); let result = try!(self.command_runner.run_with_args("sh", &["-c", &format!("cd '{}' && npm ls", self.target)]));
Ok(result.status.success() && !String::from_utf8(result.stdout).unwrap().contains("(empty)")) Ok(result.status.success() && !String::from_utf8(result.stdout).unwrap().contains("(empty)"))
} }
fn execute(&self) -> Result<(), Box<Error>> { fn execute(&self) -> Result<(), Box<Error>> {
try!(self.command_runner.run_with_args("sh", &["-c", &format!("cd '{}' && npm install --production --unsafe-perm", self.target)]));
Ok(())
self.command_runner.run_successfully("sh", &["-c", &format!("cd '{}' && npm install --production --unsafe-perm", self.target)])
} }
} }

3
src/symbols/owner.rs

@ -30,8 +30,7 @@ impl<'a, D> Symbol for Owner<'a, D> where D: AsRef<str> + fmt::Display {
} }
fn execute(&self) -> Result<(), Box<Error>> { fn execute(&self) -> Result<(), Box<Error>> {
try!(self.command_runner.run_with_args("chown", &[self.user_name.borrow(), self.path.as_ref()]));
Ok(())
self.command_runner.run_successfully("chown", &[self.user_name.borrow(), self.path.as_ref()])
} }
fn get_prerequisites(&self) -> Vec<Resource> { fn get_prerequisites(&self) -> Vec<Resource> {

24
src/symbols/stored_directory.rs

@ -12,7 +12,7 @@ use symbols::Symbol;
use storage::Storage; use storage::Storage;
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub enum StorageDirection { load, save }
pub enum StorageDirection { Load, Save }
pub struct StoredDirectory<'a, S> where S: Storage { pub struct StoredDirectory<'a, S> where S: Storage {
path: Cow<'a, str>, path: Cow<'a, str>,
@ -44,7 +44,7 @@ impl<'a, S> Symbol for StoredDirectory<'a, S> where S: Storage {
// Check if dir exists // Check if dir exists
if let Err(e) = metadata { if let Err(e) = metadata {
return if e.kind() == io::ErrorKind::NotFound { return if e.kind() == io::ErrorKind::NotFound {
Ok(self.dir == StorageDirection::save)
Ok(self.dir == StorageDirection::Save)
} else { } else {
Err(Box::new(e)) Err(Box::new(e))
}; };
@ -54,25 +54,21 @@ impl<'a, S> Symbol for StoredDirectory<'a, S> where S: Storage {
} }
let dump_date = try!(self.storage.recent_date()); let dump_date = try!(self.storage.recent_date());
let output = try!(self.command_runner.run_with_args("sh", &["-c", &format!("find {} -printf '%T@\\n' | sort -r | head -n1 | grep '^[0-9]\\+' -o", self.path)]));
if output.status.code() != Some(0) {
return Err(try!(String::from_utf8(output.stderr)).into());
}
let modified_date = try!(u64::from_str(try!(String::from_utf8(output.stdout)).trim_right()));
Ok(if self.dir == StorageDirection::save { modified_date <= dump_date } else { dump_date <= modified_date })
let output = try!(self.command_runner.get_output("sh", &["-c", &format!("find {} -printf '%T@\\n' | sort -r | head -n1 | grep '^[0-9]\\+' -o", self.path)]));
let modified_date = try!(u64::from_str(try!(String::from_utf8(output)).trim_right()));
Ok(if self.dir == StorageDirection::Save { modified_date <= dump_date } else { dump_date <= modified_date })
} }
fn execute(&self) -> Result<(), Box<Error>> { fn execute(&self) -> Result<(), Box<Error>> {
if self.dir == StorageDirection::load {
try!(self.command_runner.run_with_args("cp", &["-a", &try!(self.storage.read_filename()), self.path.borrow()]));
if self.dir == StorageDirection::Load {
self.command_runner.run_successfully("cp", &["-a", &try!(self.storage.read_filename()), self.path.borrow()])
} else { } else {
try!(self.command_runner.run_with_args("cp", &["-a", self.path.borrow(), &self.storage.write_filename()]));
self.command_runner.run_successfully("cp", &["-a", self.path.borrow(), &self.storage.write_filename()])
} }
Ok(())
} }
fn get_prerequisites(&self) -> Vec<Resource> { fn get_prerequisites(&self) -> Vec<Resource> {
if self.dir == StorageDirection::save { return vec![]; }
if self.dir == StorageDirection::Save { return vec![]; }
if let Some(parent) = Path::new(self.path.as_ref()).parent() { if let Some(parent) = Path::new(self.path.as_ref()).parent() {
vec![ Resource::new("dir", parent.to_string_lossy()) ] vec![ Resource::new("dir", parent.to_string_lossy()) ]
} else { } else {
@ -81,7 +77,7 @@ impl<'a, S> Symbol for StoredDirectory<'a, S> where S: Storage {
} }
fn provides(&self) -> Option<Vec<Resource>> { fn provides(&self) -> Option<Vec<Resource>> {
if self.dir == StorageDirection::load {
if self.dir == StorageDirection::Load {
Some(vec![ Resource::new("dir", self.path.to_string()) ]) Some(vec![ Resource::new("dir", self.path.to_string()) ])
} else { } else {
None None

2
src/symbols/systemd/node_js_user_service.rs

@ -159,7 +159,7 @@ impl<'a, C, R> Symbol for NodeJsSystemdUserService<'a, C, R> where C: Deref<Targ
fn execute(&self) -> Result<(), Box<Error>> { fn execute(&self) -> Result<(), Box<Error>> {
try!(self.file.execute()); try!(self.file.execute());
try!(self.systemctl_wait_for_dbus(&["--user", "enable", self.service_name])); try!(self.systemctl_wait_for_dbus(&["--user", "enable", self.service_name]));
try!(self.systemctl_wait_for_dbus(&["--user", "start", self.service_name]));
try!(self.systemctl_wait_for_dbus(&["--user", "restart", self.service_name]));
if !(try!(self.check_if_service())) { if !(try!(self.check_if_service())) {
return Err(Box::new(NodeJsSystemdUserServiceError::GenericError as NodeJsSystemdUserServiceError<io::Error>)); return Err(Box::new(NodeJsSystemdUserServiceError::GenericError as NodeJsSystemdUserServiceError<io::Error>));

3
src/symbols/systemd/reload.rs

@ -24,8 +24,7 @@ impl<'a> Symbol for ReloadService<'a> {
} }
fn execute(&self) -> Result<(), Box<Error>> { fn execute(&self) -> Result<(), Box<Error>> {
try!(self.command_runner.run_with_args("systemctl", &["reload-or-restart", self.service]));
Ok(())
self.command_runner.run_successfully("systemctl", &["reload-or-restart", self.service])
} }
} }

10
src/symbols/systemd/user_session.rs

@ -1,9 +1,7 @@
use std::borrow::{ Borrow, Cow }; use std::borrow::{ Borrow, Cow };
use std::error::Error; use std::error::Error;
use std::fmt; use std::fmt;
use std::io::Error as IoError;
use std::path::PathBuf; use std::path::PathBuf;
use std::str::from_utf8;
use command_runner::CommandRunner; use command_runner::CommandRunner;
use symbols::Symbol; use symbols::Symbol;
@ -58,13 +56,7 @@ impl<'a> Symbol for SystemdUserSession<'a> {
} }
fn execute(&self) -> Result<(), Box<Error>> { fn execute(&self) -> Result<(), Box<Error>> {
match self.command_runner.run_with_args("loginctl", &["enable-linger", self.user_name.borrow()]) {
Ok(output) => { println!("{:?} {:?}", from_utf8(&output.stdout).unwrap(), from_utf8(&output.stderr).unwrap() ); match output.status.code() {
Some(0) => Ok(()),
_ => Err(Box::new(SystemdUserSessionError::GenericError as SystemdUserSessionError<IoError>))
} },
Err(e) => Err(Box::new(SystemdUserSessionError::ExecError(e)))
}
self.command_runner.run_successfully("loginctl", &["enable-linger", self.user_name.borrow()])
} }
} }

16
src/symbols/tls/csr.rs

@ -1,6 +1,7 @@
use std::borrow::Cow; use std::borrow::Cow;
use std::error::Error; use std::error::Error;
use std::fmt; use std::fmt;
use std::path::Path;
use command_runner::CommandRunner; use command_runner::CommandRunner;
use resources::Resource; use resources::Resource;
@ -36,19 +37,16 @@ impl<'a> fmt::Display for TlsCsr<'a> {
impl<'a> Symbol for TlsCsr<'a> { impl<'a> Symbol for TlsCsr<'a> {
fn target_reached(&self) -> Result<bool, Box<Error>> { fn target_reached(&self) -> Result<bool, Box<Error>> {
let result = self.command_runner.run_with_args("openssl", &["req", "-in", &self.get_csr_path(), "-noout", "-verify"]);
match result {
Err(e) => Err(Box::new(e)),
Ok(output) => match output.status.code() {
Some(0) => Ok(output.stderr == "verify OK\n".as_bytes()),
Some(_) => Ok(false),
_ => Err("Didn't work".to_string().into())
}
if !Path::new(&self.get_csr_path()).exists() {
return Ok(false);
} }
let output = try!(self.command_runner.get_stderr("openssl", &["req", "-in", &self.get_csr_path(), "-noout", "-verify"]));
Ok(output == b"verify OK\n")
} }
fn execute(&self) -> Result<(), Box<Error>> { fn execute(&self) -> Result<(), Box<Error>> {
let output = try!(self.command_runner.run_with_args("openssl", &["req", "-new", "-sha256", "-key", &self.get_key_path(), "-out", &self.get_csr_path(), "-subj", &format!("/CN={}", self.domain)]).map_err(|e| Box::new(e)));
try!(self.command_runner.run_successfully("openssl", &["req", "-new", "-sha256", "-key", &self.get_key_path(), "-out", &self.get_csr_path(), "-subj", &format!("/CN={}", self.domain)]));
Ok(()) Ok(())
} }

20
src/symbols/tls/key.rs

@ -1,6 +1,7 @@
use std::borrow::Cow; use std::borrow::Cow;
use std::error::Error; use std::error::Error;
use std::fmt; use std::fmt;
use std::path::Path;
use command_runner::CommandRunner; use command_runner::CommandRunner;
use symbols::Symbol; use symbols::Symbol;
@ -35,23 +36,16 @@ impl<'a> fmt::Display for TlsKey<'a> {
impl<'a> Symbol for TlsKey<'a> { impl<'a> Symbol for TlsKey<'a> {
fn target_reached(&self) -> Result<bool, Box<Error>> { fn target_reached(&self) -> Result<bool, Box<Error>> {
let result = self.command_runner.run_with_args("openssl", &["rsa", "-in", &self.get_path(), "-noout", "-check", "-text"]);
match result {
Err(e) => Err(Box::new(e)),
Ok(output) => match output.status.code() {
Some(0) => Ok(output.stdout.starts_with(format!("Private-Key: ({} bit)\n", self.get_bytes()).as_bytes())),
Some(_) => Ok(false),
_ => Err("Didn't work".to_string().into())
}
if !Path::new(&self.get_path()).exists() {
return Ok(false);
} }
let output = try!(self.command_runner.get_output("openssl", &["rsa", "-in", &self.get_path(), "-noout", "-check", "-text"]));
Ok(output.starts_with(&format!("Private-Key: ({} bit)\n", self.get_bytes()).as_bytes()))
} }
fn execute(&self) -> Result<(), Box<Error>> { fn execute(&self) -> Result<(), Box<Error>> {
let output = self.command_runner.run_with_args("openssl", &["genrsa", "-out", &self.get_path(), &self.get_bytes().to_string()]);
match output {
Err(e) => Err(Box::new(e)),
Ok(_) => Ok(())
}
self.command_runner.run_successfully("openssl", &["genrsa", "-out", &self.get_path(), &self.get_bytes().to_string()])
} }
} }

19
src/symbols/tls/self_signed_cert.rs

@ -1,6 +1,7 @@
use std::borrow::Cow; use std::borrow::Cow;
use std::error::Error; use std::error::Error;
use std::fmt; use std::fmt;
use std::path::Path;
use command_runner::CommandRunner; use command_runner::CommandRunner;
use resources::Resource; use resources::Resource;
@ -38,23 +39,15 @@ const DAYS_IN_SECONDS: u32 = 24*60*60;
impl<'a> Symbol for SelfSignedTlsCert<'a> { impl<'a> Symbol for SelfSignedTlsCert<'a> {
fn target_reached(&self) -> Result<bool, Box<Error>> { fn target_reached(&self) -> Result<bool, Box<Error>> {
let result = self.command_runner.run_with_args("openssl", &["x509", "-in", &self.get_cert_path(), "-noout", "-subject", "-checkend", &(30*DAYS_IN_SECONDS).to_string()]);
match result {
Err(e) => Err(Box::new(e)),
Ok(output) => match output.status.code() {
Some(0) => Ok(output.stdout == format!("subject=CN = {}\nCertificate will not expire\n", self.domain).as_bytes()),
Some(_) => Ok(false),
_ => Err("Didn't work".to_string().into())
}
if !Path::new(&self.get_cert_path()).exists() {
return Ok(false);
} }
let output = try!(self.command_runner.get_output("openssl", &["x509", "-in", &self.get_cert_path(), "-noout", "-subject", "-checkend", &(30*DAYS_IN_SECONDS).to_string()]));
Ok(output == format!("subject=CN = {}\nCertificate will not expire\n", self.domain).as_bytes())
} }
fn execute(&self) -> Result<(), Box<Error>> { fn execute(&self) -> Result<(), Box<Error>> {
let output = self.command_runner.run_with_args("openssl", &["req", "-x509", "-sha256", "-days", "90", "-key", &self.get_key_path(), "-out", &self.get_cert_path(), "-subj", &format!("/CN={}", self.domain)]);
match output {
Err(e) => Err(Box::new(e)),
Ok(_) => Ok(())
}
self.command_runner.run_successfully("openssl", &["req", "-x509", "-sha256", "-days", "90", "-key", &self.get_key_path(), "-out", &self.get_cert_path(), "-subj", &format!("/CN={}", self.domain)])
} }
fn get_prerequisites(&self) -> Vec<Resource> { fn get_prerequisites(&self) -> Vec<Resource> {

13
src/symbols/user.rs

@ -95,14 +95,11 @@ impl<'a, E: Error, A: UserAdder<SubE=E>> fmt::Display for User<'a, E, A> {
impl<'a, E: 'static + Error, A: UserAdder<SubE=E>> Symbol for User<'a, E, A> { impl<'a, E: 'static + Error, A: UserAdder<SubE=E>> Symbol for User<'a, E, A> {
fn target_reached(&self) -> Result<bool, Box<Error>> { fn target_reached(&self) -> Result<bool, Box<Error>> {
let output = self.command_runner.run_with_args("getent", &["passwd", &*self.user_name]);
match output {
Ok(output) => match output.status.code() {
Some(2) => Ok(false),
Some(0) => Ok(true),
_ => Err(Box::new(UserError::GenericError))
},
Err(e) => Err(Box::new(e))
let output = try!(self.command_runner.run_with_args("getent", &["passwd", &*self.user_name]));
match output.status.code() {
Some(2) => Ok(false),
Some(0) => Ok(true),
_ => Err(Box::new(UserError::GenericError))
} }
} }

2
src/symbols/wordpress/translation.rs

@ -75,7 +75,7 @@ impl<'a, C, D, R> Symbol for WordpressTranslation<'a, C, D, R> where C: Deref<Ta
} }
} }
let upstream = try!(self.command_runner.get_output("curl", &["https://api.wordpress.org/core/version-check/1.7/?version=4.7.5&locale=de_DE"])); let upstream = try!(self.command_runner.get_output("curl", &["https://api.wordpress.org/core/version-check/1.7/?version=4.7.5&locale=de_DE"]));
Ok(upstream.contains(&format!(r###"language":"de_DE","version":"4.7.5","updated":"{}"###, newest)))
Ok(try!(String::from_utf8(upstream)).contains(&format!(r###"language":"de_DE","version":"4.7.5","updated":"{}"###, newest)))
} }
fn execute(&self) -> Result<(), Box<Error>> { fn execute(&self) -> Result<(), Box<Error>> {

Loading…
Cancel
Save