@@ -23,7 +23,27 @@ pub trait ClientFactory: Default + Send + Sync + 'static {
2323 /// The type of client produced by `get_client`.
2424 type Client : Client ;
2525 /// Gets a client from the factory.
26- async fn get_client ( & self , address : & str , root_ca : Option < & String > ) -> Result < Self :: Client > ;
26+ async fn get_client (
27+ & self ,
28+ address : & str ,
29+ root_ca : Option < HashableCertificate > ,
30+ ) -> Result < Self :: Client > ;
31+ }
32+
33+ #[ derive( Clone ) ]
34+ pub struct HashableCertificate {
35+ certificate : native_tls:: Certificate ,
36+ hash : String ,
37+ }
38+
39+ impl HashableCertificate {
40+ pub fn from_pem ( text : & str ) -> anyhow:: Result < Self > {
41+ let cert_bytes = text. as_bytes ( ) ;
42+ let hash = spin_common:: sha256:: hex_digest_from_bytes ( cert_bytes) ;
43+ let certificate =
44+ native_tls:: Certificate :: from_pem ( cert_bytes) . context ( "invalid root certificate" ) ?;
45+ Ok ( Self { certificate, hash } )
46+ }
2747}
2848
2949/// A `ClientFactory` that uses a connection pool per address.
@@ -43,8 +63,16 @@ impl Default for PooledTokioClientFactory {
4363impl ClientFactory for PooledTokioClientFactory {
4464 type Client = deadpool_postgres:: Object ;
4565
46- async fn get_client ( & self , address : & str , root_ca : Option < & String > ) -> Result < Self :: Client > {
47- let pool_key = ( address. to_string ( ) , root_ca. cloned ( ) ) ;
66+ async fn get_client (
67+ & self ,
68+ address : & str ,
69+ root_ca : Option < HashableCertificate > ,
70+ ) -> Result < Self :: Client > {
71+ let ( root_ca, root_ca_hash) = match root_ca {
72+ None => ( None , None ) ,
73+ Some ( HashableCertificate { certificate, hash } ) => ( Some ( certificate) , Some ( hash) ) ,
74+ } ;
75+ let pool_key = ( address. to_string ( ) , root_ca_hash) ;
4876 let pool = self
4977 . pools
5078 . try_get_with_by_ref ( & pool_key, || create_connection_pool ( address, root_ca) )
@@ -58,7 +86,7 @@ impl ClientFactory for PooledTokioClientFactory {
5886/// Creates a Postgres connection pool for the given address.
5987fn create_connection_pool (
6088 address : & str ,
61- root_ca : Option < & String > ,
89+ root_ca : Option < native_tls :: Certificate > ,
6290) -> Result < deadpool_postgres:: Pool > {
6391 let config = address
6492 . parse :: < tokio_postgres:: Config > ( )
@@ -75,8 +103,7 @@ fn create_connection_pool(
75103 } else {
76104 let mut builder = TlsConnector :: builder ( ) ;
77105 if let Some ( root_ca) = root_ca {
78- let cert_bytes = root_ca. as_bytes ( ) ;
79- builder. add_root_certificate ( native_tls:: Certificate :: from_pem ( cert_bytes) ?) ;
106+ builder. add_root_certificate ( root_ca) ;
80107 }
81108 let connector = MakeTlsConnector :: new ( builder. build ( ) ?) ;
82109 deadpool_postgres:: Manager :: from_config ( config, connector, mgr_config)
0 commit comments