A library for writing host-specific, single-binary configuration management and deployment tools
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

97 lines
2.8 KiB

5 years ago
7 years ago
7 years ago
5 years ago
  1. use std::borrow::Cow;
  2. use std::path::{Path, PathBuf};
  3. use crate::command_runner::CommandRunner;
  4. use crate::command_runner::SetuidCommandRunner;
  5. use crate::symbols::dir::Dir;
  6. use crate::symbols::file::File;
  7. use crate::symbols::list::List;
  8. use crate::symbols::owner::Owner;
  9. use crate::symbols::Symbol;
  10. mod account_key;
  11. mod cert;
  12. mod chain;
  13. pub use self::account_key::AcmeAccountKey;
  14. pub use self::cert::AcmeCert;
  15. pub use self::chain::AcmeCertChain;
  16. const ROOT_CERT_FILE_NAME: &str = "lets_encrypt_x3_cross_signed.pem";
  17. const ACCOUNT_KEY_FILE_NAME: &str = "account.key";
  18. pub struct Factory<'a, U: AsRef<str>, H: AsRef<Path>, C: AsRef<str>, R: CommandRunner> {
  19. user_name: U,
  20. home_dir: H,
  21. cert: C,
  22. command_runner: &'a R,
  23. acme_command_runner: SetuidCommandRunner<'a, U, R>,
  24. }
  25. impl<'a, U: Clone + AsRef<str>, H: AsRef<Path>, C: AsRef<str>, R: CommandRunner>
  26. Factory<'a, U, H, C, R>
  27. {
  28. pub fn new(user_name: U, home_dir: H, cert: C, command_runner: &'a R) -> Self {
  29. let acme_command_runner = SetuidCommandRunner::new(user_name.clone(), command_runner);
  30. Self {
  31. user_name,
  32. home_dir,
  33. cert,
  34. command_runner,
  35. acme_command_runner,
  36. }
  37. }
  38. pub fn get_challenges_dir(&'a self) -> Cow<Path> {
  39. [self.home_dir.as_ref(), "challenges".as_ref()]
  40. .iter()
  41. .collect::<PathBuf>()
  42. .into()
  43. }
  44. pub fn get_init(&'a self) -> impl Symbol + 'a {
  45. let root_cert_path: PathBuf = [self.home_dir.as_ref(), ROOT_CERT_FILE_NAME.as_ref()]
  46. .iter()
  47. .collect();
  48. let account_key_file: PathBuf = [self.home_dir.as_ref(), ACCOUNT_KEY_FILE_NAME.as_ref()]
  49. .iter()
  50. .collect();
  51. List::from((
  52. AcmeAccountKey::new(account_key_file.clone(), self.command_runner),
  53. Owner::new(
  54. account_key_file,
  55. self.user_name.clone(),
  56. self.command_runner,
  57. ),
  58. Dir::new(self.get_challenges_dir()),
  59. Owner::new(
  60. self.get_challenges_dir(),
  61. self.user_name.clone(),
  62. self.command_runner,
  63. ),
  64. Dir::new("/etc/ssl/local_certs"),
  65. Owner::new(
  66. "/etc/ssl/local_certs",
  67. self.user_name.clone(),
  68. self.command_runner,
  69. ),
  70. File::new(root_cert_path, self.cert.as_ref()),
  71. ))
  72. }
  73. pub fn get_cert<HOST: 'a + Clone + AsRef<str>>(&'a self, host: HOST) -> impl Symbol + 'a {
  74. let root_cert_path: PathBuf = [self.home_dir.as_ref(), ROOT_CERT_FILE_NAME.as_ref()]
  75. .iter()
  76. .collect();
  77. let account_key_path: PathBuf = [self.home_dir.as_ref(), ACCOUNT_KEY_FILE_NAME.as_ref()]
  78. .iter()
  79. .collect();
  80. List::from((
  81. AcmeCert::new(
  82. host.clone(),
  83. &self.acme_command_runner,
  84. root_cert_path.clone(),
  85. account_key_path,
  86. self.get_challenges_dir(),
  87. ),
  88. AcmeCertChain::new(host, &self.acme_command_runner, root_cert_path),
  89. ))
  90. }
  91. }