1+ #[ cfg( feature = "hyper-rustls" ) ]
2+ use std:: path:: Path ;
13use std:: sync:: Arc ;
24#[ cfg( feature = "time" ) ]
35use std:: time:: { Duration , SystemTime } ;
@@ -6,6 +8,12 @@ use base64::prelude::{BASE64_URL_SAFE_NO_PAD, Engine};
68use http:: header:: LOCATION ;
79#[ cfg( feature = "time" ) ]
810use http:: { Method , Request } ;
11+ #[ cfg( feature = "hyper-rustls" ) ]
12+ use rustls:: RootCertStore ;
13+ #[ cfg( feature = "hyper-rustls" ) ]
14+ use rustls_pki_types:: CertificateDer ;
15+ #[ cfg( feature = "hyper-rustls" ) ]
16+ use rustls_pki_types:: pem:: PemObject ;
917use rustls_pki_types:: { PrivateKeyDer , PrivatePkcs8KeyDer } ;
1018use serde:: de:: DeserializeOwned ;
1119use serde:: { Deserialize , Serialize } ;
@@ -48,6 +56,26 @@ impl Account {
4856 } )
4957 }
5058
59+ /// Create an account builder with an HTTP client configured using a custom root CA
60+ ///
61+ /// This is useful if your ACME server uses a testing PKI and not a certificate
62+ /// chain issued by a publicly trusted CA.
63+ #[ cfg( feature = "hyper-rustls" ) ]
64+ pub fn builder_with_root ( pem_path : impl AsRef < Path > ) -> Result < AccountBuilder , Error > {
65+ let root_der = match CertificateDer :: from_pem_file ( pem_path) {
66+ Ok ( root_der) => root_der,
67+ Err ( err) => return Err ( Error :: Other ( err. into ( ) ) ) ,
68+ } ;
69+
70+ let mut roots = RootCertStore :: empty ( ) ;
71+ match roots. add ( root_der) {
72+ Ok ( ( ) ) => Ok ( AccountBuilder {
73+ http : Box :: new ( DefaultClient :: with_roots ( roots) ?) ,
74+ } ) ,
75+ Err ( err) => Err ( Error :: Other ( err. into ( ) ) ) ,
76+ }
77+ }
78+
5179 /// Create an account builder with the given HTTP client
5280 pub fn builder_with_http ( http : Box < dyn HttpClient > ) -> AccountBuilder {
5381 AccountBuilder { http }
0 commit comments