@@ -34,8 +34,28 @@ pub struct AdminClient {
3434impl AdminClient {
3535 /// Create a new AdminClient from an Alias
3636 pub fn new ( alias : & Alias ) -> Result < Self > {
37- let http_client = Client :: builder ( )
37+ let mut builder = Client :: builder ( )
3838 . danger_accept_invalid_certs ( alias. insecure )
39+ . tls_built_in_native_certs ( true )
40+ . tls_built_in_webpki_certs ( true ) ;
41+
42+ if let Some ( bundle_path) = alias. ca_bundle . as_deref ( ) {
43+ let pem = std:: fs:: read ( bundle_path) . map_err ( |e| {
44+ Error :: Network ( format ! ( "Failed to read CA bundle '{bundle_path}': {e}" ) )
45+ } ) ?;
46+ let certs = reqwest:: Certificate :: from_pem_bundle ( & pem)
47+ . map_err ( |e| Error :: Network ( format ! ( "Invalid CA bundle '{bundle_path}': {e}" ) ) ) ?;
48+ if certs. is_empty ( ) {
49+ return Err ( Error :: Network ( format ! (
50+ "Invalid CA bundle '{bundle_path}': no certificates found"
51+ ) ) ) ;
52+ }
53+ for cert in certs {
54+ builder = builder. add_root_certificate ( cert) ;
55+ }
56+ }
57+
58+ let http_client = builder
3959 . build ( )
4060 . map_err ( |e| Error :: Network ( format ! ( "Failed to create HTTP client: {e}" ) ) ) ?;
4161
@@ -700,6 +720,7 @@ impl AdminApi for AdminClient {
700720#[ cfg( test) ]
701721mod tests {
702722 use super :: * ;
723+ use tempfile:: tempdir;
703724
704725 #[ test]
705726 fn test_admin_url_construction ( ) {
@@ -748,4 +769,48 @@ mod tests {
748769 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
749770 ) ;
750771 }
772+
773+ #[ test]
774+ fn test_admin_client_invalid_ca_bundle_path_surfaces_error ( ) {
775+ let mut alias = Alias :: new ( "test" , "https://localhost:9000" , "access" , "secret" ) ;
776+ alias. ca_bundle = Some ( "/definitely-not-here/ca.pem" . to_string ( ) ) ;
777+
778+ let result = AdminClient :: new ( & alias) ;
779+ match result {
780+ Err ( Error :: Network ( msg) ) => {
781+ assert ! (
782+ msg. contains( "Failed to read CA bundle" ) ,
783+ "Unexpected error message: {msg}"
784+ ) ;
785+ }
786+ Ok ( _) => panic ! ( "Expected Error::Network for invalid path, got Ok(_)" ) ,
787+ Err ( e) => panic ! ( "Expected Error::Network for invalid path, got Err({e})" ) ,
788+ }
789+ }
790+
791+ #[ test]
792+ fn test_admin_client_invalid_ca_bundle_pem_surfaces_error ( ) {
793+ let temp_dir = tempdir ( ) . expect ( "create temp dir" ) ;
794+ let bad_pem_path = temp_dir. path ( ) . join ( "bad-ca.pem" ) ;
795+ std:: fs:: write (
796+ & bad_pem_path,
797+ b"-----BEGIN CERTIFICATE-----\n invalid-base64\n -----END CERTIFICATE-----\n " ,
798+ )
799+ . expect ( "write invalid PEM" ) ;
800+
801+ let mut alias = Alias :: new ( "test" , "https://localhost:9000" , "access" , "secret" ) ;
802+ alias. ca_bundle = Some ( bad_pem_path. display ( ) . to_string ( ) ) ;
803+
804+ let result = AdminClient :: new ( & alias) ;
805+ match result {
806+ Err ( Error :: Network ( msg) ) => {
807+ assert ! (
808+ msg. contains( "Invalid CA bundle" ) && msg. contains( "bad-ca.pem" ) ,
809+ "Unexpected error message for invalid PEM CA bundle: {msg}"
810+ ) ;
811+ }
812+ Ok ( _) => panic ! ( "Expected Error::Network for invalid PEM, got Ok(_)" ) ,
813+ Err ( e) => panic ! ( "Expected Error::Network for invalid PEM, got Err({e})" ) ,
814+ }
815+ }
751816}
0 commit comments