Tokio_postgres to TLS or not to TLS

Friends,

Still new to rust and still working on an AWS Lamdba that bulk uploads events into a Postgres Database (AWS RDS). I am trying to match a db_ca String that has the filename of my PEM file for the CA Bundle. If that is "" just use NoTls so I can use the same code on my local laptop test rig. My match arms have incompatible types, and I'm not sure what to do here to fix this.

    let (mut pg_client, pg_connection) = match db_ca.as_str() {
        "" => tokio_postgres::connect(db_str.as_str(), NoTls).await?,
        _  => {
            let cert_file = File::open(db_ca)?;
            let mut buf = BufReader::new(cert_file);
            let mut root_store = rustls::RootCertStore::empty();
            for cert in rustls_pemfile::certs(&mut buf) {
                root_store.add(cert?)?;
            }

            let tls_config = RustlsClientConfig::builder()
                .with_root_certificates(root_store)
                .with_no_client_auth();
            let tls = MakeRustlsConnect::new(tls_config);
            tokio_postgres::connect(db_str.as_str(), tls).await?
        },
    };

The compiler says....

    = note: expected tuple `(tokio_postgres::Client, tokio_postgres::Connection<_, NoTlsStream>)`
               found tuple `(tokio_postgres::Client, tokio_postgres::Connection<_, RustlsStream<Socket>>)`

I understand that, I'm just not sure how to make this logic work.

Jack

This suggestion is an educated guess, and not based on experience with the libraries at hand.

Does it work to conditionally initialize the connection portion?

let pg_connection;
let notls_connection;
let mut pg_client = match db_ca.as_str() {
        "" => {
            let (cli, cnxn) = tokio_postgres::connect(db_str.as_str(), NoTls).await?;
            notls_connection = cnxn;
            cli
        }
        _  => {
            let cert_file = File::open(db_ca)?;
            let mut buf = BufReader::new(cert_file);
            let mut root_store = rustls::RootCertStore::empty();
            for cert in rustls_pemfile::certs(&mut buf) {
                root_store.add(cert?)?;
            }

            let tls_config = RustlsClientConfig::builder()
                .with_root_certificates(root_store)
                .with_no_client_auth();
            let tls = MakeRustlsConnect::new(tls_config);
            let (cli, cnxn) = tokio_postgres::connect(db_str.as_str(), tls).await?;
            pg_connection = cnxn;
            cli
        },
    };
1 Like

The TLS implementation is part of the type. You can't conditionally swap it out in that way.

You don't need to though - you should just always use MakeRustlsConnect and only configure the CA list if you have one configured.