Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Please document how to dynamically use TLS and NoTLS connections #31

Closed
fritshoogland-yugabyte opened this issue Apr 30, 2022 · 8 comments

Comments

@fritshoogland-yugabyte
Copy link

I am not sure if this is the correct place for this question, if not please let me know, and I close it, because clearly this is also my personal learning path. However, I can imagine this is something that others will or might run into.

I want to create a (r2d2, postgres) connection pool that can be dynamically NoTls or Tls (MakeTlsConnector).
Currently, I swap function and function arguments, but I would like to make it generic.

So far I have created the following contruction:

pub fn create_pool<T>(url: &str, pool_size: i32, cacert_file: &str) -> T {
   if url.contains("sslmode=require") {
       println!(">> creating ssl pool");

       let mut builder = SslConnector::builder(SslMethod::tls()).expect("unable to create sslconnector builder");
       builder.set_ca_file(cacert_file).expect("unable to load ca.cert");
       builder.set_verify(SslVerifyMode::NONE);
       let connector = MakeTlsConnector::new(builder.build());
       let manager = PostgresConnectionManager::new( url.parse().unwrap(), connector);

       r2d2::Pool::builder()
           .max_size(pool_size as u32)
           .connection_timeout(Duration::from_secs(120))
           .build(manager)
           .unwrap()
   } else {
       println!(">> creating nossl pool");
       let manager = PostgresConnectionManager::new( url.parse().unwrap(), NoTls);

       r2d2::Pool::builder()
           .max_size(pool_size as u32)
           .connection_timeout(Duration::from_secs(120))
           .build(manager)
           .unwrap()
   }
}

However, when I create the pool, the compiler tells me it can't derive the type:

const FULL_PATH_CA_CERT: &str = "/tmp/ca.cert";
const PG_URL: &str = "host=192.168.66.80 port=5434 sslmode=disable user=yugabyte password=yugabyte";


let connection_pool = create_pool(PG_URL, threads, FULL_PATH_CA_CERT);

let connection = connection_pool.get().unwrap();

Error:

error[E0282]: type annotations needed
  --> src/lib.rs:66:22
   |
64 |     let connection_pool = create_pool(PG_URL, threads, FULL_PATH_CA_CERT);
   |         --------------- consider giving `connection_pool` a type
65 | 
66 |     let connection = connection_pool.get().unwrap();
   |                      ^^^^^^^^^^^^^^^ cannot infer type
   |
   = note: type must be known at this point

I do understand what the compiler tells me, but how I create a connection pool that can be dynamically NoTls or Tls?

@sfackler
Copy link
Owner

Always include the MakeTlsConnector. It will internally decide if TLS is necessary or not.

@fritshoogland-yugabyte
Copy link
Author

Thank you for your answer!

Can you expand on that? I try to learn (and I'll blog about it once I understand this!)

I have changed the create_pool function to return Pool<PostgresConnectionManager>, but now the no ssl pool creation makes the compiler complain that it found the 'NoTls' struct, but expected 'MakeTlsConnector':

error[E0308]: mismatched types
   --> src/lib.rs:623:8
    |
601 |   pub fn create_pool(url: &str, pool_size: i32, cacert_file: &str) -> Pool<PostgresConnectionManager<MakeTlsConnector>> {
    |                                                                       ------------------------------------------------- expected `Pool<PostgresConnectionManager<MakeTlsConnector>>` because of return type
...
623 | /        r2d2::Pool::builder()
624 | |            .max_size(pool_size as u32)
625 | |            .connection_timeout(Duration::from_secs(120))
626 | |            .build(manager)
627 | |            .unwrap()
    | |____________________^ expected struct `MakeTlsConnector`, found struct `NoTls`
    |
    = note: expected struct `Pool<PostgresConnectionManager<MakeTlsConnector>>`
               found struct `Pool<PostgresConnectionManager<NoTls>>`

Which makes sense on itself: these are two different structs.
However, how can I make it use MakeTlsConnector, and create a non-tls connection then?

@sfackler
Copy link
Owner

You shouldn't need to do any of that. Just always make a pool configuration using a manager with MakeTlsConnector.

@SamTV12345
Copy link

How would that look like?

@sfackler
Copy link
Owner

How would what look like?

@SamTV12345
Copy link

SamTV12345 commented May 24, 2023

How would that MakeTLS look like? I also don't really know if I need this crate or not. I use diesel as ORM and have in my main.rs this code so I can switch between the databases quickly. If I use this crate I get another type and an error in LoadQuery dsl.

Can I put this together with:

#[cfg(postgresql)]
async fn init_db_pool(database_url: &str)-> Result<Pool<ConnectionManager<PgConnection>>,
    String> {
    let manager = ConnectionManager::<PgConnection>::new(database_url);
    let pool = Pool::builder()
        .max_size(1)
        .build(manager)
        .expect("Failed to create pool.");
    Ok(pool)
}
#[cfg(sqlite)]
type DbPool = Pool<ConnectionManager<SqliteConnection>>;
#[cfg(sqlite)]
type DbConnection = SqliteConnection;
#[cfg(postgresql)]
type DbPool = Pool<ConnectionManager<PgConnection>>;
#[cfg(postgresql)]
type DbConnection = PgConnection;

#[cfg(postgresql)]
type QueryBuilder = PgQueryBuilder;

#[cfg(mysql)]
type DbPool = Pool<ConnectionManager<MysqlConnection>>;
#[cfg(mysql)]
type DbConnection = MysqlConnection;

@sfackler
Copy link
Owner

This crate provides a connection manager for the postgres crate. If you're using Diesel then you'd need something else.

@SamTV12345
Copy link

Thanks understood. I was just confused because it said postgres.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants