@@ -11,6 +11,7 @@ use postgres_native_tls::MakeTlsConnector;
1111use std:: str:: FromStr ;
1212use std:: sync:: Arc ;
1313use std:: time:: Duration ;
14+ use tokio:: sync:: Mutex ;
1415use tokio_postgres:: GenericClient ;
1516use tokio_postgres:: Statement ;
1617
@@ -24,21 +25,10 @@ impl Postgres {
2425
2526const CERT_URL : & str = "https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem" ;
2627
27- lazy_static:: lazy_static! {
28- static ref CERTIFICATE_PEMS : Vec <u8 > = {
29- let client = reqwest:: blocking:: Client :: new( ) ;
30- let resp = client
31- . get( CERT_URL )
32- . send( )
33- . expect( "failed to get RDS cert" ) ;
34- resp. bytes( ) . expect( "failed to get RDS cert body" ) . to_vec( )
35- } ;
36- }
37-
3828async fn make_client ( db_url : & str ) -> anyhow:: Result < tokio_postgres:: Client > {
3929 if db_url. contains ( "rds.amazonaws.com" ) {
4030 let mut builder = TlsConnector :: builder ( ) ;
41- for cert in make_certificates ( ) {
31+ for cert in make_certificates ( ) . await {
4232 builder. add_root_certificate ( cert) ;
4333 }
4434 let connector = builder. build ( ) . context ( "built TlsConnector" ) ?;
@@ -75,11 +65,28 @@ async fn make_client(db_url: &str) -> anyhow::Result<tokio_postgres::Client> {
7565 Ok ( db_client)
7666 }
7767}
78- fn make_certificates ( ) -> Vec < Certificate > {
68+ async fn make_certificates ( ) -> Vec < Certificate > {
7969 use x509_cert:: der:: pem:: LineEnding ;
8070 use x509_cert:: der:: EncodePem ;
8171
82- let certs = x509_cert:: Certificate :: load_pem_chain ( & CERTIFICATE_PEMS [ ..] ) . unwrap ( ) ;
72+ static CERTIFICATE_PEMS : Mutex < Option < Vec < u8 > > > = Mutex :: const_new ( None ) ;
73+
74+ let mut guard = CERTIFICATE_PEMS . lock ( ) . await ;
75+ if guard. is_none ( ) {
76+ let client = reqwest:: Client :: new ( ) ;
77+ let resp = client
78+ . get ( CERT_URL )
79+ . send ( )
80+ . await
81+ . expect ( "failed to get RDS cert" ) ;
82+ let certificate_pems = resp
83+ . bytes ( )
84+ . await
85+ . expect ( "failed to get RDS cert body" )
86+ . to_vec ( ) ;
87+ * guard = Some ( certificate_pems. clone ( ) ) ;
88+ }
89+ let certs = x509_cert:: Certificate :: load_pem_chain ( & guard. as_ref ( ) . unwrap ( ) [ ..] ) . unwrap ( ) ;
8390 certs
8491 . into_iter ( )
8592 . map ( |cert| Certificate :: from_pem ( cert. to_pem ( LineEnding :: LF ) . unwrap ( ) . as_bytes ( ) ) . unwrap ( ) )
@@ -1365,9 +1372,9 @@ mod tests {
13651372
13661373 // Makes sure we successfully parse the RDS certificates and load them into native-tls compatible
13671374 // format.
1368- #[ test]
1369- fn can_make_certificates ( ) {
1370- let certs = make_certificates ( ) ;
1375+ #[ tokio :: test]
1376+ async fn can_make_certificates ( ) {
1377+ let certs = make_certificates ( ) . await ;
13711378 assert ! ( !certs. is_empty( ) ) ;
13721379 }
13731380}
0 commit comments