Refactor getting PostgreSQL ca certs.

This commit is contained in:
Orne Brocaar 2023-11-29 12:10:06 +00:00
parent 17f0d8c495
commit ed06de231e
2 changed files with 20 additions and 58 deletions

View File

@ -1,9 +1,7 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::fs::File;
use std::io::BufReader;
use std::str::FromStr; use std::str::FromStr;
use anyhow::{Context, Result}; use anyhow::Result;
use async_trait::async_trait; use async_trait::async_trait;
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use diesel::{ConnectionError, ConnectionResult}; use diesel::{ConnectionError, ConnectionResult};
@ -19,6 +17,7 @@ use uuid::Uuid;
use super::Integration as IntegrationTrait; use super::Integration as IntegrationTrait;
use crate::config::{self, PostgresqlIntegration as Config}; use crate::config::{self, PostgresqlIntegration as Config};
use crate::helpers::tls::get_root_certs;
use chirpstack_api::integration; use chirpstack_api::integration;
use schema::{ use schema::{
event_ack, event_integration, event_join, event_location, event_log, event_status, event_ack, event_integration, event_join, event_location, event_log, event_status,
@ -232,8 +231,14 @@ impl Integration {
// https://github.com/weiznich/diesel_async/blob/main/examples/postgres/pooled-with-rustls/src/main.rs // https://github.com/weiznich/diesel_async/blob/main/examples/postgres/pooled-with-rustls/src/main.rs
fn pg_establish_connection(config: &str) -> BoxFuture<ConnectionResult<AsyncPgConnection>> { fn pg_establish_connection(config: &str) -> BoxFuture<ConnectionResult<AsyncPgConnection>> {
let fut = async { let fut = async {
let root_certs = let conf = config::get();
pg_root_certs().map_err(|e| ConnectionError::BadConnection(e.to_string()))?;
let root_certs = get_root_certs(if conf.integration.postgresql.ca_cert.is_empty() {
None
} else {
Some(conf.integration.postgresql.ca_cert.clone())
})
.map_err(|e| ConnectionError::BadConnection(e.to_string()))?;
let rustls_config = rustls::ClientConfig::builder() let rustls_config = rustls::ClientConfig::builder()
.with_safe_defaults() .with_safe_defaults()
.with_root_certificates(root_certs) .with_root_certificates(root_certs)
@ -252,30 +257,6 @@ fn pg_establish_connection(config: &str) -> BoxFuture<ConnectionResult<AsyncPgCo
fut.boxed() fut.boxed()
} }
fn pg_root_certs() -> Result<rustls::RootCertStore> {
let conf = config::get();
let mut roots = rustls::RootCertStore::empty();
let certs = rustls_native_certs::load_native_certs()?;
let certs: Vec<_> = certs.into_iter().map(|cert| cert.0).collect();
roots.add_parsable_certificates(&certs);
if !conf.postgresql.ca_cert.is_empty() {
let f = File::open(&conf.integration.postgresql.ca_cert).context("Open ca certificate")?;
let mut reader = BufReader::new(f);
let certs = rustls_pemfile::certs(&mut reader)?;
for cert in certs
.into_iter()
.map(rustls::Certificate)
.collect::<Vec<_>>()
{
roots.add(&cert)?;
}
}
Ok(roots)
}
#[async_trait] #[async_trait]
impl IntegrationTrait for Integration { impl IntegrationTrait for Integration {
async fn uplink_event( async fn uplink_event(

View File

@ -1,8 +1,5 @@
use std::fs::File;
use std::io::BufReader;
use std::sync::RwLock; use std::sync::RwLock;
use anyhow::Context;
use anyhow::Result; use anyhow::Result;
use diesel::{ConnectionError, ConnectionResult}; use diesel::{ConnectionError, ConnectionResult};
use diesel_async::async_connection_wrapper::AsyncConnectionWrapper; use diesel_async::async_connection_wrapper::AsyncConnectionWrapper;
@ -43,6 +40,8 @@ pub mod search;
pub mod tenant; pub mod tenant;
pub mod user; pub mod user;
use crate::helpers::tls::get_root_certs;
pub type AsyncPgPool = DeadpoolPool<AsyncPgConnection>; pub type AsyncPgPool = DeadpoolPool<AsyncPgConnection>;
pub type AsyncPgPoolConnection = DeadpoolObject<AsyncPgConnection>; pub type AsyncPgPoolConnection = DeadpoolObject<AsyncPgConnection>;
@ -138,8 +137,14 @@ pub async fn setup() -> Result<()> {
// https://github.com/weiznich/diesel_async/blob/main/examples/postgres/pooled-with-rustls/src/main.rs // https://github.com/weiznich/diesel_async/blob/main/examples/postgres/pooled-with-rustls/src/main.rs
fn pg_establish_connection(config: &str) -> BoxFuture<ConnectionResult<AsyncPgConnection>> { fn pg_establish_connection(config: &str) -> BoxFuture<ConnectionResult<AsyncPgConnection>> {
let fut = async { let fut = async {
let root_certs = let conf = config::get();
pg_root_certs().map_err(|e| ConnectionError::BadConnection(e.to_string()))?;
let root_certs = get_root_certs(if conf.postgresql.ca_cert.is_empty() {
None
} else {
Some(conf.postgresql.ca_cert.clone())
})
.map_err(|e| ConnectionError::BadConnection(e.to_string()))?;
let rustls_config = rustls::ClientConfig::builder() let rustls_config = rustls::ClientConfig::builder()
.with_safe_defaults() .with_safe_defaults()
.with_root_certificates(root_certs) .with_root_certificates(root_certs)
@ -158,30 +163,6 @@ fn pg_establish_connection(config: &str) -> BoxFuture<ConnectionResult<AsyncPgCo
fut.boxed() fut.boxed()
} }
fn pg_root_certs() -> Result<rustls::RootCertStore> {
let conf = config::get();
let mut roots = rustls::RootCertStore::empty();
let certs = rustls_native_certs::load_native_certs()?;
let certs: Vec<_> = certs.into_iter().map(|cert| cert.0).collect();
roots.add_parsable_certificates(&certs);
if !conf.postgresql.ca_cert.is_empty() {
let f = File::open(&conf.postgresql.ca_cert).context("Open ca certificate")?;
let mut reader = BufReader::new(f);
let certs = rustls_pemfile::certs(&mut reader)?;
for cert in certs
.into_iter()
.map(rustls::Certificate)
.collect::<Vec<_>>()
{
roots.add(&cert)?;
}
}
Ok(roots)
}
pub fn get_async_db_pool() -> Result<AsyncPgPool> { pub fn get_async_db_pool() -> Result<AsyncPgPool> {
let pool_r = ASYNC_PG_POOL.read().unwrap(); let pool_r = ASYNC_PG_POOL.read().unwrap();
let pool: AsyncPgPool = pool_r let pool: AsyncPgPool = pool_r