sysknife_daemon/actions/
certbot.rs1use super::{command_mechanism, ActionSpec};
12use sysknife_types::RiskLevel;
13
14pub fn specs() -> Vec<ActionSpec> {
15 vec![
16 get_certificates(),
17 obtain_certificate(
18 &["example.com".to_string()],
19 "admin@example.com",
20 "standalone",
21 ),
22 renew_certificates(),
23 ]
24}
25
26pub fn get_certificates() -> ActionSpec {
28 ActionSpec {
29 action_name: "GetCertificates",
30 mechanism: command_mechanism("certbot", ["certificates"]),
31 risk_level: RiskLevel::Low,
32 reboot_required: false,
33 rollback_available: false,
34 }
35}
36
37pub fn obtain_certificate(domains: &[String], email: &str, challenge: &str) -> ActionSpec {
40 let mut args = vec![
41 "certbot".to_string(),
42 "certonly".to_string(),
43 "--non-interactive".to_string(),
44 "--agree-tos".to_string(),
45 format!("--{challenge}"),
46 "-m".to_string(),
47 email.to_string(),
48 ];
49 for d in domains {
50 args.push("-d".to_string());
51 args.push(d.clone());
52 }
53 ActionSpec {
54 action_name: "ObtainCertificate",
55 mechanism: command_mechanism("sudo", args),
56 risk_level: RiskLevel::High,
57 reboot_required: false,
58 rollback_available: false,
59 }
60}
61
62pub fn renew_certificates() -> ActionSpec {
64 ActionSpec {
65 action_name: "RenewCertificates",
66 mechanism: command_mechanism("sudo", ["certbot", "renew"]),
67 risk_level: RiskLevel::Medium,
68 reboot_required: false,
69 rollback_available: false,
70 }
71}
72
73#[cfg(test)]
74mod tests {
75 use super::*;
76 use crate::actions::ActionMechanism;
77
78 fn args_of(spec: &ActionSpec) -> (&'static str, Vec<String>) {
79 match &spec.mechanism {
80 ActionMechanism::Command { program, args } => (program, args.clone()),
81 other => panic!("expected Command, got {other:?}"),
82 }
83 }
84
85 #[test]
86 fn get_certs_read_only() {
87 let (program, args) = args_of(&get_certificates());
88 assert_eq!(program, "certbot");
89 assert_eq!(args, vec!["certificates"]);
90 assert_eq!(get_certificates().risk_level, RiskLevel::Low);
91 }
92
93 #[test]
94 fn obtain_builds_multi_domain_argv() {
95 let (program, args) = args_of(&obtain_certificate(
96 &["a.example.com".to_string(), "b.example.com".to_string()],
97 "ops@example.com",
98 "standalone",
99 ));
100 assert_eq!(program, "sudo");
101 assert_eq!(
102 args,
103 vec![
104 "certbot",
105 "certonly",
106 "--non-interactive",
107 "--agree-tos",
108 "--standalone",
109 "-m",
110 "ops@example.com",
111 "-d",
112 "a.example.com",
113 "-d",
114 "b.example.com",
115 ]
116 );
117 assert_eq!(
118 obtain_certificate(&["x.io".to_string()], "e@x.io", "nginx").risk_level,
119 RiskLevel::High
120 );
121 }
122
123 #[test]
124 fn renew_shape() {
125 let (program, args) = args_of(&renew_certificates());
126 assert_eq!(program, "sudo");
127 assert_eq!(args, vec!["certbot", "renew"]);
128 }
129}