Compare commits

...

1 commit

Author SHA1 Message Date
Rafael Caricio e1b294a2a5
Support database connection via SSL
This is required to use managed Postgres databases. It is necessary to
use SSL connection to the remote host as the connection goes through the
open internet.
2023-04-26 10:38:25 +02:00
4 changed files with 54 additions and 14 deletions

View file

@ -33,6 +33,8 @@ pub struct Config {
// Core settings
pub database_url: String,
#[serde(default)]
pub tls_ca_file: Option<PathBuf>,
pub storage_dir: PathBuf,
pub web_client_dir: Option<PathBuf>,

View file

@ -27,6 +27,8 @@ thiserror = "1.0.37"
# Async runtime
tokio = { version = "1.20.4", features = [] }
# Used for working with Postgresql database
openssl = { version = "0.10", features = ["vendored"] }
postgres-openssl = "0.5.0"
tokio-postgres = { version = "0.7.6", features = ["with-chrono-0_4", "with-uuid-1", "with-serde_json-1"] }
postgres-types = { version = "0.2.3", features = ["derive", "with-chrono-0_4", "with-uuid-1", "with-serde_json-1"] }
postgres-protocol = "0.6.4"
@ -38,7 +40,6 @@ uuid = { version = "1.1.2", features = ["serde", "v4"] }
[dev-dependencies]
fedimovies-utils = { path = "../fedimovies-utils", features = ["test-utils"] }
serial_test = "0.7.0"
[features]

View file

@ -1,3 +1,7 @@
use deadpool_postgres::SslMode;
use openssl::ssl::{SslConnector, SslMethod};
use postgres_openssl::MakeTlsConnector;
use std::path::Path;
use tokio_postgres::config::Config as DatabaseConfig;
use tokio_postgres::error::{Error as PgError, SqlState};
@ -11,6 +15,7 @@ pub mod test_utils;
pub type DbPool = deadpool_postgres::Pool;
pub use tokio_postgres::GenericClient as DatabaseClient;
use tokio_postgres::NoTls;
#[derive(thiserror::Error, Debug)]
#[error("database type error")]
@ -37,21 +42,49 @@ pub enum DatabaseError {
AlreadyExists(&'static str), // object type
}
pub async fn create_database_client(db_config: &DatabaseConfig) -> tokio_postgres::Client {
let (client, connection) = db_config.connect(tokio_postgres::NoTls).await.unwrap();
tokio::spawn(async move {
if let Err(err) = connection.await {
log::error!("connection error: {}", err);
};
});
pub async fn create_database_client(
db_config: &DatabaseConfig,
ca_file_path: Option<&Path>,
) -> tokio_postgres::Client {
let client = if let Some(ca_file_path) = ca_file_path {
let mut builder = SslConnector::builder(SslMethod::tls()).unwrap();
log::debug!("Using TLS CA file: {}", ca_file_path.display());
builder.set_ca_file(ca_file_path).unwrap();
let connector = MakeTlsConnector::new(builder.build());
let (client, connection) = db_config.connect(connector).await.unwrap();
tokio::spawn(async move {
if let Err(err) = connection.await {
log::error!("connection with tls error: {}", err);
};
});
client
} else {
let (client, connection) = db_config.connect(tokio_postgres::NoTls).await.unwrap();
tokio::spawn(async move {
if let Err(err) = connection.await {
log::error!("connection error: {}", err);
};
});
client
};
client
}
pub fn create_pool(database_url: &str, pool_size: usize) -> DbPool {
let manager = deadpool_postgres::Manager::new(
database_url.parse().expect("invalid database URL"),
tokio_postgres::NoTls,
);
pub fn create_pool(database_url: &str, ca_file_path: Option<&Path>, pool_size: usize) -> DbPool {
let manager = if let Some(ca_file_path) = ca_file_path {
let mut builder = SslConnector::builder(SslMethod::tls()).unwrap();
log::info!("Using TLS CA file: {}", ca_file_path.display());
builder.set_ca_file(ca_file_path).unwrap();
let connector = MakeTlsConnector::new(builder.build());
deadpool_postgres::Manager::new(
database_url.parse().expect("invalid database URL"),
connector,
)
} else {
deadpool_postgres::Manager::new(database_url.parse().expect("invalid database URL"), NoTls)
};
DbPool::builder(manager)
.max_size(pool_size)
.build()

View file

@ -44,7 +44,11 @@ async fn main() -> std::io::Result<()> {
// https://wiki.postgresql.org/wiki/Number_Of_Database_Connections
let db_pool_size = num_cpus::get() * 2;
let db_pool = create_pool(&config.database_url, db_pool_size);
let db_pool = create_pool(
&config.database_url,
config.tls_ca_file.as_ref().map(|s| s.as_path()),
db_pool_size,
);
let mut db_client = get_database_client(&db_pool).await.unwrap();
apply_migrations(&mut db_client).await;