1-
21use std:: path:: PathBuf ;
32
43use chrono:: { DateTime , Duration , Utc } ;
54use rcgen:: { Certificate , CertificateParams , DistinguishedName } ;
5+ use reqwest;
66use serde:: { Deserialize , Serialize } ;
77use tokio:: time:: sleep;
8- use reqwest;
98
109use instant_acme:: {
11- Account , AccountCredentials , ChallengeType , Identifier , LetsEncrypt , NewAccount , NewOrder , OrderStatus
10+ Account , AccountCredentials , ChallengeType , Identifier , LetsEncrypt , NewAccount , NewOrder ,
11+ OrderStatus ,
1212} ;
1313use x509_parser:: { parse_x509_certificate, pem:: parse_x509_pem, time:: ASN1Time } ;
1414
15- use crate :: { error:: Error , server:: { get_config, get_server_file_path, get_server_file_string, write_server_file} , tools:: log:: { log_info, LogServiceType } , Result } ;
15+ use crate :: {
16+ error:: Error ,
17+ server:: { get_config, get_server_file_path, get_server_file_string, write_server_file} ,
18+ tools:: log:: { log_info, LogServiceType } ,
19+ Result ,
20+ } ;
1621
1722#[ derive( Debug , Serialize , Deserialize , Clone ) ]
1823pub struct TxtRecord {
1924 pub txt : Vec < String > ,
2025}
2126
22-
2327pub async fn dns_certify ( ) -> Result < ( PathBuf , PathBuf ) > {
2428 let config = get_config ( ) . await ;
2529
2630 let id = config. id . ok_or ( crate :: Error :: ServerNoServerId ) ?;
2731 let token = config. token . ok_or ( crate :: Error :: ServerNotYetRegistered ) ?;
2832
29-
30-
31- log_info ( LogServiceType :: Register , "Getting https certificate" . to_string ( ) ) ;
33+ log_info (
34+ LogServiceType :: Register ,
35+ "Getting https certificate" . to_string ( ) ,
36+ ) ;
3237 if ( config. domain . is_some ( ) ) {
33- return Err ( crate :: Error :: Error ( "Domain set, skipping certificate generation as we don't manage domain certs for now" . to_string ( ) ) ) ;
38+ return Err ( crate :: Error :: Error (
39+ "Domain set, skipping certificate generation as we don't manage domain certs for now"
40+ . to_string ( ) ,
41+ ) ) ;
3442 }
3543 const ACCOUNT_FILENAME : & str = "letsencrypt_account.json" ;
3644 const PUBLIC_FILENAME : & str = "cert_chain.pem" ;
3745 const PRIVATE_FILENAME : & str = "cert_private.pem" ;
3846
39- let existing_public_certificate = get_server_file_string ( PUBLIC_FILENAME ) . await . unwrap_or ( None ) ;
40- let existing_private_certificate = get_server_file_string ( PRIVATE_FILENAME ) . await . unwrap_or ( None ) ;
47+ let existing_public_certificate = get_server_file_string ( PUBLIC_FILENAME )
48+ . await
49+ . unwrap_or ( None ) ;
50+ let existing_private_certificate = get_server_file_string ( PRIVATE_FILENAME )
51+ . await
52+ . unwrap_or ( None ) ;
4153
4254 if existing_private_certificate. is_some ( ) && existing_public_certificate. is_some ( ) {
43- log_info ( LogServiceType :: Register , "Existing certificate, cheking validity" . to_string ( ) ) ;
55+ log_info (
56+ LogServiceType :: Register ,
57+ "Existing certificate, cheking validity" . to_string ( ) ,
58+ ) ;
4459
4560 let public = existing_public_certificate. unwrap ( ) ;
4661 let res = parse_x509_pem ( public. as_bytes ( ) ) . unwrap ( ) ;
4762 let res_x509 = parse_x509_certificate ( & res. 1 . contents ) . unwrap ( ) ;
48- log_info ( LogServiceType :: Register , format ! ( "certificate validity: {:?}" , res_x509. 1 . validity. not_after) ) ;
63+ log_info (
64+ LogServiceType :: Register ,
65+ format ! ( "certificate validity: {:?}" , res_x509. 1 . validity. not_after) ,
66+ ) ;
4967
5068 let expiry: & ASN1Time = & res_x509. 1 . validity . not_after ;
5169 let utc_time: DateTime < Utc > = Utc :: now ( ) + Duration :: days ( 5 ) ;
5270
53- let expiry_date: DateTime < Utc > = DateTime :: < Utc > :: from_timestamp ( expiry. timestamp ( ) , 0 ) . expect ( "invalid timestamp" ) ;
54- if expiry_date > utc_time {
55- log_info ( LogServiceType :: Register , format ! ( "Certificate valid : {:?} > {:?}" , expiry_date, utc_time) ) ;
56- return Ok ( ( get_server_file_path ( PUBLIC_FILENAME ) . await ?, get_server_file_path ( PRIVATE_FILENAME ) . await ?) ) ;
57- } else {
71+ let expiry_date: DateTime < Utc > =
72+ DateTime :: < Utc > :: from_timestamp ( expiry. timestamp ( ) , 0 ) . expect ( "invalid timestamp" ) ;
73+ if expiry_date > utc_time {
74+ log_info (
75+ LogServiceType :: Register ,
76+ format ! ( "Certificate valid : {:?} > {:?}" , expiry_date, utc_time) ,
77+ ) ;
78+ return Ok ( (
79+ get_server_file_path ( PUBLIC_FILENAME ) . await ?,
80+ get_server_file_path ( PRIVATE_FILENAME ) . await ?,
81+ ) ) ;
82+ } else {
5883 log_info ( LogServiceType :: Register , "Certificate expired" . to_string ( ) ) ;
59- }
84+ }
6085 }
61- log_info ( LogServiceType :: Register , "No certificates found, requesting new one" . to_string ( ) ) ;
86+ log_info (
87+ LogServiceType :: Register ,
88+ "No certificates found, requesting new one" . to_string ( ) ,
89+ ) ;
6290
6391 let ( account, _) = {
6492 if let Some ( existing_credentials) = get_server_file_string ( ACCOUNT_FILENAME ) . await ? {
65- let credentials: AccountCredentials = serde_json:: from_str ( & existing_credentials) . unwrap ( ) ;
93+ let credentials: AccountCredentials =
94+ serde_json:: from_str ( & existing_credentials) . unwrap ( ) ;
6695 let account: Account = Account :: from_credentials ( credentials) . await . unwrap ( ) ;
67- let credentials: AccountCredentials = serde_json:: from_str ( & existing_credentials) . unwrap ( ) ;
96+ let credentials: AccountCredentials =
97+ serde_json:: from_str ( & existing_credentials) . unwrap ( ) ;
6898 ( account, credentials)
6999 } else {
70- log_info ( LogServiceType :: Register , "Create new ACME accounts" . to_string ( ) ) ;
100+ log_info (
101+ LogServiceType :: Register ,
102+ "Create new ACME accounts" . to_string ( ) ,
103+ ) ;
71104
72105 let ( account, credentials) = Account :: create (
73106 & NewAccount {
@@ -79,17 +112,21 @@ pub async fn dns_certify() -> Result<(PathBuf, PathBuf)> {
79112 //LetsEncrypt::Production.url(),
80113 None ,
81114 )
82- . await . map_err ( |_| Error :: ServerMalformatedConfigFile ) ?;
115+ . await
116+ . map_err ( |_| Error :: ServerMalformatedConfigFile ) ?;
83117
84- let serialized_credentials = serde_json:: to_string ( & credentials) . map_err ( |_| Error :: ServerFileNotFound ) ?;
118+ let serialized_credentials =
119+ serde_json:: to_string ( & credentials) . map_err ( |_| Error :: ServerFileNotFound ) ?;
85120
86- write_server_file ( "letsencrypt_account.json" , serialized_credentials. as_bytes ( ) ) . await ?;
121+ write_server_file (
122+ "letsencrypt_account.json" ,
123+ serialized_credentials. as_bytes ( ) ,
124+ )
125+ . await ?;
87126 ( account, credentials)
88127 }
89128 } ;
90129
91-
92-
93130 let domain = format ! ( "{}-srv.redseat.cloud" , id) ;
94131 let subdomain = format ! ( "*.{}-srv.redseat.cloud" , id) ;
95132 let identifier = Identifier :: Dns ( domain. clone ( ) ) ;
@@ -107,7 +144,7 @@ pub async fn dns_certify() -> Result<(PathBuf, PathBuf)> {
107144
108145 let authorizations = order. authorizations ( ) . await . unwrap ( ) ;
109146 let mut challenges = Vec :: with_capacity ( authorizations. len ( ) ) ;
110- let mut challenges_txt = Vec :: with_capacity ( authorizations. len ( ) ) ;
147+ let mut challenges_txt = Vec :: with_capacity ( authorizations. len ( ) ) ;
111148 for authz in & authorizations {
112149 //println!("{:?}", authz);
113150 //match authz.status {
@@ -124,16 +161,18 @@ pub async fn dns_certify() -> Result<(PathBuf, PathBuf)> {
124161
125162 let Identifier :: Dns ( identifier) = & authz. identifier ;
126163
127- log_info ( LogServiceType :: Register , format ! (
128- "_acme-challenge.{} IN TXT {}" ,
129- identifier,
130- order. key_authorization( challenge) . dns_value( )
131- ) ) ;
164+ log_info (
165+ LogServiceType :: Register ,
166+ format ! (
167+ "_acme-challenge.{} IN TXT {}" ,
168+ identifier,
169+ order. key_authorization( challenge) . dns_value( )
170+ ) ,
171+ ) ;
132172
133173 challenges_txt. push ( order. key_authorization ( challenge) . dns_value ( ) ) ;
134-
135-
136- /*
174+
175+ /*
137176 println!("Please set the following DNS record then press the Return key:");
138177 println!(
139178 "_acme-challenge.{} IN TXT {}",
@@ -145,29 +184,37 @@ pub async fn dns_certify() -> Result<(PathBuf, PathBuf)> {
145184 challenges. push ( ( identifier, & challenge. url ) ) ;
146185 }
147186
148- let request = TxtRecord { txt : challenges_txt} ;
187+ let request = TxtRecord {
188+ txt : challenges_txt,
189+ } ;
149190 let client = reqwest:: Client :: new ( ) ;
150191
151- let result = client. patch ( format ! ( "https://{}/servers/{}/register/txt" , config. redseat_home, id) )
192+ let result = client
193+ . patch ( format ! (
194+ "https://{}/servers/{}/register/txt" ,
195+ config. redseat_home, id
196+ ) )
152197 . header ( "Authorization" , format ! ( "Token {}" , token) )
153198 . json ( & request)
154199 . send ( )
155200 . await ?;
156201 let json = result. text ( ) . await ?;
157- log_info ( LogServiceType :: Register , format ! (
158- "retour {:?}" ,
159- json
160- ) ) ;
161-
162-
163- log_info ( LogServiceType :: Register , format ! (
164- "Waiting 180 seconds for DNS propagation https://{}/servers/{}/register/txt {:?}" ,
165- config. redseat_home, id, request
166- ) ) ;
202+ log_info ( LogServiceType :: Register , format ! ( "retour {:?}" , json) ) ;
203+
204+ log_info (
205+ LogServiceType :: Register ,
206+ format ! (
207+ "Waiting 180 seconds for DNS propagation https://{}/servers/{}/register/txt {:?}" ,
208+ config. redseat_home, id, request
209+ ) ,
210+ ) ;
167211 sleep ( std:: time:: Duration :: from_secs ( 180 ) ) . await ;
168212
169213 for ( _, url) in & challenges {
170- order. set_challenge_ready ( url) . await . map_err ( |_| Error :: Error ( format ! ( "Unable to set challenge ready for {}" , url) ) ) ?;
214+ order
215+ . set_challenge_ready ( url)
216+ . await
217+ . map_err ( |_| Error :: Error ( format ! ( "Unable to set challenge ready for {}" , url) ) ) ?;
171218 }
172219
173220 // Exponentially back off until the order becomes ready or invalid.
@@ -176,7 +223,10 @@ pub async fn dns_certify() -> Result<(PathBuf, PathBuf)> {
176223 let mut delay = tokio:: time:: Duration :: from_millis ( 250 ) ;
177224 loop {
178225 sleep ( delay) . await ;
179- let state = order. refresh ( ) . await . map_err ( |_| Error :: Error ( "Unable to refresh order rstatus" . to_string ( ) ) ) ?;
226+ let state = order
227+ . refresh ( )
228+ . await
229+ . map_err ( |_| Error :: Error ( "Unable to refresh order rstatus" . to_string ( ) ) ) ?;
180230 if let OrderStatus :: Ready | OrderStatus :: Invalid = state. status {
181231 //println!("order state: {:#?}", state);
182232 break ;
@@ -185,7 +235,10 @@ pub async fn dns_certify() -> Result<(PathBuf, PathBuf)> {
185235 delay *= 2 ;
186236 tries += 1 ;
187237 match tries < 10 {
188- true => log_info ( LogServiceType :: Register , format ! ( "order is not ready, waiting {:?}" , tries) ) ,
238+ true => log_info (
239+ LogServiceType :: Register ,
240+ format ! ( "order is not ready, waiting {:?}" , tries) ,
241+ ) ,
189242 false => {
190243 //println!("order is not ready: {:#?}", state);
191244 return Err ( Error :: Error ( "order is not ready" . to_string ( ) ) ) ;
@@ -197,8 +250,7 @@ pub async fn dns_certify() -> Result<(PathBuf, PathBuf)> {
197250 if state. status != OrderStatus :: Ready {
198251 return Err ( Error :: Error ( "unexpected order status:" . to_string ( ) ) ) ;
199252 }
200-
201-
253+
202254 let mut names = Vec :: with_capacity ( challenges. len ( ) ) ;
203255 /*for (identifier, _) in &challenges {
204256 names.push(identifier.to_owned().to_string());
@@ -208,22 +260,32 @@ pub async fn dns_certify() -> Result<(PathBuf, PathBuf)> {
208260
209261 // If the order is ready, we can provision the certificate.
210262 // Use the rcgen library to create a Certificate Signing Request.
211-
212- log_info ( LogServiceType :: Register , format ! (
213- "Certificate names {:?}" ,
214- names
215- ) ) ;
263+
264+ log_info (
265+ LogServiceType :: Register ,
266+ format ! ( "Certificate names {:?}" , names ) ,
267+ ) ;
216268
217269 let mut params = CertificateParams :: new ( names. clone ( ) ) ;
218270 params. distinguished_name = DistinguishedName :: new ( ) ;
219- let cert = Certificate :: from_params ( params) . map_err ( |_| Error :: Error ( "Unable to create certificate from params" . to_string ( ) ) ) ?;
220- let csr = cert. serialize_request_der ( ) . map_err ( |_| Error :: Error ( "Unable to serialiaze certificate" . to_string ( ) ) ) ?;
271+ let cert = Certificate :: from_params ( params)
272+ . map_err ( |_| Error :: Error ( "Unable to create certificate from params" . to_string ( ) ) ) ?;
273+ let csr = cert
274+ . serialize_request_der ( )
275+ . map_err ( |_| Error :: Error ( "Unable to serialiaze certificate" . to_string ( ) ) ) ?;
221276
222277 // Finalize the order and print certificate chain, private key and account credentials.
223278
224- order. finalize ( & csr) . await . map_err ( |e| Error :: Error ( format ! ( "Unable to finalize CSR {:?}" , e) ) ) ?;
279+ order
280+ . finalize ( & csr)
281+ . await
282+ . map_err ( |e| Error :: Error ( format ! ( "Unable to finalize CSR {:?}" , e) ) ) ?;
225283 let cert_chain_pem: String = loop {
226- match order. certificate ( ) . await . map_err ( |_| Error :: Error ( "Unable to get finale certificate" . to_string ( ) ) ) ? {
284+ match order
285+ . certificate ( )
286+ . await
287+ . map_err ( |_| Error :: Error ( "Unable to get finale certificate" . to_string ( ) ) ) ?
288+ {
227289 Some ( cert_chain_pem) => break cert_chain_pem,
228290 None => sleep ( tokio:: time:: Duration :: from_secs ( 1 ) ) . await ,
229291 }
@@ -233,15 +295,25 @@ pub async fn dns_certify() -> Result<(PathBuf, PathBuf)> {
233295 //println!("private key:\n\n{}", cert.serialize_private_key_pem());
234296
235297 write_server_file ( PUBLIC_FILENAME , cert_chain_pem. as_bytes ( ) ) . await ?;
236- write_server_file ( "cert_private.pem" , cert. serialize_private_key_pem ( ) . as_bytes ( ) ) . await ?;
237-
238- log_info ( LogServiceType :: Register , "Certificates created and saved" . to_string ( ) ) ;
239-
240- Ok ( ( get_server_file_path ( PUBLIC_FILENAME ) . await ?, get_server_file_path ( PRIVATE_FILENAME ) . await ?) )
298+ write_server_file (
299+ "cert_private.pem" ,
300+ cert. serialize_private_key_pem ( ) . as_bytes ( ) ,
301+ )
302+ . await ?;
303+
304+ log_info (
305+ LogServiceType :: Register ,
306+ "Certificates created and saved" . to_string ( ) ,
307+ ) ;
308+
309+ Ok ( (
310+ get_server_file_path ( PUBLIC_FILENAME ) . await ?,
311+ get_server_file_path ( PRIVATE_FILENAME ) . await ?,
312+ ) )
241313 //Ok((cert_chain_pem, cert.serialize_private_key_pem()))
242314}
243315
244- /*
316+ /*
245317#[cfg(test)]
246318mod tests {
247319 use serial_test::serial;
@@ -251,4 +323,4 @@ mod tests {
251323 async fn test_letsencrypt() {
252324 //certifacte().await;
253325 }
254- }*/
326+ }*/
0 commit comments