33//! checks if certificates are not outdated, 
44//! persists files on disk. 
55
6+ use  crate :: errors:: AtomicServerResult ; 
7+ use  actix_web:: { dev:: ServerHandle ,  App ,  HttpServer } ; 
68use  std:: { 
79    fs:: { self ,  File } , 
810    io:: BufReader , 
911    path:: PathBuf , 
1012} ; 
13+ use  tracing:: { info,  warn} ; 
1114
12- use  crate :: errors:: AtomicServerResult ; 
1315/// Create RUSTLS server config from certificates in config dir 
1416pub  fn  get_https_config ( 
1517    config :  & crate :: config:: Config , 
@@ -18,7 +20,6 @@ pub fn get_https_config(
1820    let  https_config = rustls:: ServerConfig :: builder ( ) 
1921        . with_safe_defaults ( ) 
2022        . with_no_client_auth ( ) ; 
21-     // rustls::NoClientAuth::new() 
2223    let  cert_file =
2324        & mut  BufReader :: new ( File :: open ( config. cert_path . clone ( ) ) . expect ( "No HTTPS TLS key found." ) ) ; 
2425    let  key_file =
@@ -65,7 +66,7 @@ fn set_certs_created_at_file(config: &crate::config::Config) {
6566/// Will be true if there are no certs yet. 
6667pub  fn  should_renew_certs_check ( config :  & crate :: config:: Config )  -> AtomicServerResult < bool >  { 
6768    if  std:: fs:: File :: open ( & config. cert_path ) . is_err ( )  { 
68-         warn ! ( 
69+         info ! ( 
6970            "No HTTPS certificates found in {:?}, requesting new ones..." , 
7071            & config. https_path
7172        ) ; 
@@ -87,17 +88,12 @@ pub fn should_renew_certs_check(config: &crate::config::Config) -> AtomicServerR
8788    Ok ( expired) 
8889} 
8990
90- use  actix_web:: { dev:: ServerHandle ,  App ,  HttpServer } ; 
91- use  instant_acme:: { KeyAuthorization ,  OrderStatus } ; 
92- use  tracing:: { info,  log:: warn} ; 
93- 
94- use  std:: sync:: mpsc; 
95- 
96- /// Starts an HTTP Actix server for HTTPS certificate initialization 
91+ /// Starts an HTTP Actix server for HTTPS certificate initialization. 
92+ /// Hosts `.well-known/acme-challenge` folder and the challenge file. 
9793async  fn  cert_init_server ( 
9894    config :  & crate :: config:: Config , 
9995    challenge :  & instant_acme:: Challenge , 
100-     key_auth :  & KeyAuthorization , 
96+     key_auth :  & instant_acme :: KeyAuthorization , 
10197)  -> AtomicServerResult < ServerHandle >  { 
10298    let  address = format ! ( "{}:{}" ,  config. opts. ip,  config. opts. port) ; 
10399    warn ! ( "Server temporarily running in HTTP mode at {}, running Let's Encrypt Certificate initialization..." ,  address) ; 
@@ -117,10 +113,10 @@ async fn cert_init_server(
117113    challenge_path. push ( "acme-challenge" ) ; 
118114    fs:: create_dir_all ( & challenge_path) ?; 
119115    challenge_path. push ( & challenge. token ) ; 
120-     // let challenge_file_content = format!("{}.{}", challenge.token, key_auth.as_str()); 
121116    fs:: write ( challenge_path,  key_auth. as_str ( ) ) ?; 
122117
123-     let  ( tx,  rx)  = mpsc:: channel ( ) ; 
118+     // Channel is used to send the server handle back to the main thread, so we can stop it later 
119+     let  ( tx,  rx)  = std:: sync:: mpsc:: channel ( ) ; 
124120
125121    std:: thread:: spawn ( move  || { 
126122        actix_web:: rt:: System :: new ( ) . block_on ( async  move  { 
@@ -153,20 +149,20 @@ async fn cert_init_server(
153149        & config. opts. domain,  & challenge. token
154150    ) ; 
155151
156-     // wait for a few secs 
157152    std:: thread:: sleep ( std:: time:: Duration :: from_secs ( 2 ) ) ; 
158153    info ! ( "Testing availability of {}" ,  & well_known_url) ; 
159154
160155    let  agent = ureq:: builder ( ) 
161156        . timeout ( std:: time:: Duration :: from_secs ( 2 ) ) 
162157        . build ( ) ; 
163-     let  resp = agent
164-         . get ( & well_known_url) 
165-         // .get("https://docs.certifytheweb.com/docs/http-validation/") 
166-         . call ( ) 
167-         . map_err ( |e| format ! ( "Unable to Test local server. {}" ,  e) ) ?; 
158+     let  resp = agent. get ( & well_known_url) . call ( ) . map_err ( |e| { 
159+         format ! ( 
160+             "Unable to test local server. Is it available at the right address? {}" , 
161+             e
162+         ) 
163+     } ) ?; 
168164    if  resp. status ( )  != 200  { 
169-         warn ! ( "Unable to Test  local server. Status: {}" ,  resp. status( ) ) ; 
165+         warn ! ( "Unable to test  local server. Status: {}" ,  resp. status( ) ) ; 
170166    }  else  { 
171167        info ! ( "Server for HTTP initialization running correctly" ) ; 
172168    } 
@@ -175,6 +171,8 @@ async fn cert_init_server(
175171
176172/// Sends a request to LetsEncrypt to create a certificate 
177173pub  async  fn  request_cert ( config :  & crate :: config:: Config )  -> AtomicServerResult < ( ) >  { 
174+     use  instant_acme:: OrderStatus ; 
175+ 
178176    let  challenge_type = if  config. opts . https_dns  { 
179177        info ! ( "Using DNS-01 challenge" ) ; 
180178        instant_acme:: ChallengeType :: Dns01 
@@ -188,6 +186,9 @@ pub async fn request_cert(config: &crate::config::Config) -> AtomicServerResult<
188186    // using `Account::from_credentials()`. 
189187
190188    let  lets_encrypt_url = if  config. opts . development  { 
189+         warn ! ( 
190+             "Using LetsEncrypt staging server, not production. This is for testing purposes only and will not provide a working certificate." 
191+         ) ; 
191192        instant_acme:: LetsEncrypt :: Staging . url ( ) 
192193    }  else  { 
193194        instant_acme:: LetsEncrypt :: Production . url ( ) 
@@ -253,7 +254,7 @@ pub async fn request_cert(config: &crate::config::Config) -> AtomicServerResult<
253254            . challenges 
254255            . iter ( ) 
255256            . find ( |c| c. r#type  == challenge_type) 
256-             . ok_or ( "no Dns01  challenge found" ) ?; 
257+             . ok_or ( format ! ( "no {:?}  challenge found" ,  challenge_type ) ) ?; 
257258
258259        let  instant_acme:: Identifier :: Dns ( identifier)  = & authz. identifier ; 
259260
@@ -278,7 +279,8 @@ pub async fn request_cert(config: &crate::config::Config) -> AtomicServerResult<
278279    } 
279280
280281    // Let the server know we're ready to accept the challenges. 
281-     for  ( _,  url)  in  & challenges { 
282+     for  ( a,  url)  in  & challenges { 
283+         info ! ( "Setting challenge ready for {} at {}" ,  a,  url) ; 
282284        order. set_challenge_ready ( url) . await . unwrap ( ) ; 
283285    } 
284286
@@ -287,17 +289,16 @@ pub async fn request_cert(config: &crate::config::Config) -> AtomicServerResult<
287289    let  mut  delay = std:: time:: Duration :: from_millis ( 250 ) ; 
288290    let  url = authorizations. get ( 0 ) . expect ( "Authorizations is empty" ) ; 
289291    let  state = loop  { 
290-         actix:: clock:: sleep ( delay) . await ; 
291292        let  state = order. state ( ) ; 
292-         if  let  instant_acme:: OrderStatus :: Ready  | instant_acme:: OrderStatus :: Invalid  = state. status 
293-         { 
294-             info ! ( "order state: {:#?}" ,  state) ; 
293+         info ! ( "Order state: {:#?}" ,  state) ; 
294+         if  let  OrderStatus :: Ready  | OrderStatus :: Invalid  | OrderStatus :: Valid  = state. status  { 
295295            break  state; 
296296        } 
297+         order. refresh ( ) . await . unwrap ( ) ; 
297298
298299        delay *= 2 ; 
299300        tries += 1 ; 
300-         match  tries < 8  { 
301+         match  tries < 10  { 
301302            true  => info ! ( "order is not ready, waiting {delay:?}" ) , 
302303            false  => { 
303304                return  Err ( format ! ( 
@@ -306,6 +307,7 @@ pub async fn request_cert(config: &crate::config::Config) -> AtomicServerResult<
306307                . into ( ) ) ; 
307308            } 
308309        } 
310+         actix:: clock:: sleep ( delay) . await ; 
309311    } ; 
310312
311313    if  state. status  == OrderStatus :: Invalid  { 
@@ -319,26 +321,35 @@ pub async fn request_cert(config: &crate::config::Config) -> AtomicServerResult<
319321
320322    // If the order is ready, we can provision the certificate. 
321323    // Use the rcgen library to create a Certificate Signing Request. 
322- 
323-     let  mut  params = rcgen:: CertificateParams :: new ( names. clone ( ) ) ; 
324+     let  mut  params = rcgen:: CertificateParams :: new ( names) ; 
324325    params. distinguished_name  = rcgen:: DistinguishedName :: new ( ) ; 
325326    let  cert = rcgen:: Certificate :: from_params ( params) . map_err ( |e| e. to_string ( ) ) ?; 
326327    let  csr = cert. serialize_request_der ( ) . map_err ( |e| e. to_string ( ) ) ?; 
327328
328329    // Finalize the order and print certificate chain, private key and account credentials. 
329- 
330330    order. finalize ( & csr) . await . map_err ( |e| e. to_string ( ) ) ?; 
331-     let  cert_chain_pem = order
332-         . certificate ( ) 
333-         . await 
334-         . map_err ( |e| format ! ( "Error getting certificate {}" ,  e) ) ?
335-         . expect ( "No cert found" ) ; 
336-     info ! ( "certficate chain:\n \n {}" ,  cert_chain_pem) ; 
337-     info ! ( "private key:\n \n {}" ,  cert. serialize_private_key_pem( ) ) ; 
338-     // info!( 
339-     //     "account credentials:\n\n{}", 
340-     //     serde_json::to_string_pretty(&account.credentials()).map_err(|e| e.to_string())? 
341-     // ); 
331+ 
332+     let  mut  tries = 1u8 ; 
333+ 
334+     let  cert_chain_pem = loop  { 
335+         match  order. certificate ( ) . await  { 
336+             Ok ( Some ( cert_chain_pem) )  => { 
337+                 info ! ( "Certificate ready!" ) ; 
338+                 break  cert_chain_pem; 
339+             } 
340+             Ok ( None )  => { 
341+                 if  tries > 10  { 
342+                     return  Err ( "Giving up: certificate is still not ready" . into ( ) ) ; 
343+                 } 
344+                 tries += 1 ; 
345+                 info ! ( "Certificate not ready yet..." ) ; 
346+                 std:: thread:: sleep ( std:: time:: Duration :: from_secs ( 1 ) ) ; 
347+                 continue ; 
348+             } 
349+             Err ( e)  => return  Err ( format ! ( "Error getting certificate {}" ,  e) . into ( ) ) , 
350+         } 
351+     } ; 
352+ 
342353    write_certs ( config,  cert_chain_pem,  cert) ?; 
343354
344355    if  let  Some ( hnd)  = handle { 
0 commit comments