1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
use crate::chall::Challenge;
use crate::errors::*;
use crate::persist::FilePersist;
use acme_micro::create_p384_key;
use acme_micro::{Directory, DirectoryUrl};
#[derive(Debug)]
pub struct Request<'a> {
pub acme_url: &'a str,
pub account_email: Option<&'a str>,
pub primary_name: &'a str,
pub alt_names: &'a [String],
}
pub fn request(persist: FilePersist, challenge: &mut Challenge, req: &Request) -> Result<()> {
let url = DirectoryUrl::Other(&req.acme_url);
let dir = Directory::from_url(url)?;
let contact = if let Some(email) = req.account_email {
vec![format!("mailto:{}", email)]
} else {
vec![]
};
let acc = if let Some(acc) = persist.load_acc_privkey()? {
info!("authenticating with existing account");
dir.load_account(&acc, contact)?
} else {
info!("registering account");
let acc = dir.register_account(contact)?;
info!("successfully created account, saving private key");
persist.store_acc_privkey(&acc.acme_private_key_pem())?;
acc
};
let alt_names = req.alt_names.iter().map(AsRef::as_ref).collect::<Vec<_>>();
info!("sending certificate order");
let mut ord_new = acc.new_order(&req.primary_name, &alt_names)?;
let ord_csr = loop {
if let Some(ord_csr) = ord_new.confirm_validations() {
info!("order has been confirmed");
break ord_csr;
}
info!("fetch necessary authentications");
let auths = ord_new.authorizations()?;
for auth in &auths {
let chall = auth.http_challenge();
let token = chall.http_token();
let proof = chall.http_proof();
challenge.write(token, &proof)?;
chall.validate(5000)?;
}
ord_new.refresh()?;
};
let pkey_pri = create_p384_key();
let ord_cert = ord_csr.finalize_pkey(pkey_pri, 5000)?;
info!("downloading certificate");
let cert = ord_cert.download_cert()?;
info!("storing certificate");
persist
.store_cert(&req.primary_name, &cert)
.context("Failed to store certificate")?;
Ok(())
}