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.

113 lines
3.3 KiB

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