Psgl auth db (#1095)

* feat(cdk-mintd): add dedicated auth database configuration support
This commit is contained in:
thesimplekid
2025-09-21 16:56:12 +01:00
committed by GitHub
parent 075e25682e
commit df2f9d1c2a
9 changed files with 137 additions and 10 deletions

View File

@@ -295,6 +295,7 @@ fn create_ldk_settings(
fake_wallet: None,
grpc_processor: None,
database: cdk_mintd::config::Database::default(),
auth_database: None,
mint_management_rpc: None,
prometheus: None,
auth: None,

View File

@@ -219,6 +219,7 @@ pub fn create_fake_wallet_settings(
engine: DatabaseEngine::from_str(database).expect("valid database"),
postgres: None,
},
auth_database: None,
mint_management_rpc: None,
auth: None,
prometheus: Some(Default::default()),
@@ -268,6 +269,7 @@ pub fn create_cln_settings(
fake_wallet: None,
grpc_processor: None,
database: cdk_mintd::config::Database::default(),
auth_database: None,
mint_management_rpc: None,
auth: None,
prometheus: Some(Default::default()),
@@ -315,6 +317,7 @@ pub fn create_lnd_settings(
fake_wallet: None,
grpc_processor: None,
database: cdk_mintd::config::Database::default(),
auth_database: None,
mint_management_rpc: None,
auth: None,
prometheus: Some(Default::default()),

View File

@@ -74,6 +74,19 @@ max_connections = 20
# Connection timeout in seconds (optional, defaults to 10)
connection_timeout_seconds = 10
# Auth database configuration (optional, only used when auth is enabled)
[auth_database.postgres]
# PostgreSQL connection URL for authentication database
# Can also be set via CDK_MINTD_AUTH_POSTGRES_URL environment variable
# Environment variables take precedence over config file settings
url = "postgresql://user:password@localhost:5432/cdk_mint_auth"
# TLS mode: "disable", "prefer", "require" (optional, defaults to "disable")
tls_mode = "disable"
# Maximum number of connections in the pool (optional, defaults to 20)
max_connections = 20
# Connection timeout in seconds (optional, defaults to 10)
connection_timeout_seconds = 10
[ln]
# Required ln backend `cln`, `lnd`, `fakewallet`, 'lnbits', 'ldknode'
ln_backend = "fakewallet"

View File

@@ -367,6 +367,30 @@ pub struct Database {
pub postgres: Option<PostgresConfig>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct AuthDatabase {
pub postgres: Option<PostgresAuthConfig>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PostgresAuthConfig {
pub url: String,
pub tls_mode: Option<String>,
pub max_connections: Option<usize>,
pub connection_timeout_seconds: Option<u64>,
}
impl Default for PostgresAuthConfig {
fn default() -> Self {
Self {
url: String::new(),
tls_mode: Some("disable".to_string()),
max_connections: Some(20),
connection_timeout_seconds: Some(10),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PostgresConfig {
pub url: String,
@@ -457,6 +481,8 @@ pub struct Settings {
pub fake_wallet: Option<FakeWallet>,
pub grpc_processor: Option<GrpcProcessor>,
pub database: Database,
#[cfg(feature = "auth")]
pub auth_database: Option<AuthDatabase>,
#[cfg(feature = "management-rpc")]
pub mint_management_rpc: Option<MintManagementRpc>,
pub auth: Option<Auth>,

View File

@@ -2,13 +2,19 @@
use std::env;
use crate::config::PostgresConfig;
use crate::config::{PostgresAuthConfig, PostgresConfig};
pub const ENV_POSTGRES_URL: &str = "CDK_MINTD_POSTGRES_URL";
pub const ENV_POSTGRES_TLS_MODE: &str = "CDK_MINTD_POSTGRES_TLS_MODE";
pub const ENV_POSTGRES_MAX_CONNECTIONS: &str = "CDK_MINTD_POSTGRES_MAX_CONNECTIONS";
pub const ENV_POSTGRES_CONNECTION_TIMEOUT: &str = "CDK_MINTD_POSTGRES_CONNECTION_TIMEOUT_SECONDS";
pub const ENV_AUTH_POSTGRES_URL: &str = "CDK_MINTD_AUTH_POSTGRES_URL";
pub const ENV_AUTH_POSTGRES_TLS_MODE: &str = "CDK_MINTD_AUTH_POSTGRES_TLS_MODE";
pub const ENV_AUTH_POSTGRES_MAX_CONNECTIONS: &str = "CDK_MINTD_AUTH_POSTGRES_MAX_CONNECTIONS";
pub const ENV_AUTH_POSTGRES_CONNECTION_TIMEOUT: &str =
"CDK_MINTD_AUTH_POSTGRES_CONNECTION_TIMEOUT_SECONDS";
impl PostgresConfig {
pub fn from_env(mut self) -> Self {
// Check for new PostgreSQL URL env var first, then fallback to legacy DATABASE_URL
@@ -38,3 +44,29 @@ impl PostgresConfig {
self
}
}
impl PostgresAuthConfig {
pub fn from_env(mut self) -> Self {
if let Ok(url) = env::var(ENV_AUTH_POSTGRES_URL) {
self.url = url;
}
if let Ok(tls_mode) = env::var(ENV_AUTH_POSTGRES_TLS_MODE) {
self.tls_mode = Some(tls_mode);
}
if let Ok(max_connections) = env::var(ENV_AUTH_POSTGRES_MAX_CONNECTIONS) {
if let Ok(parsed) = max_connections.parse::<usize>() {
self.max_connections = Some(parsed);
}
}
if let Ok(timeout) = env::var(ENV_AUTH_POSTGRES_CONNECTION_TIMEOUT) {
if let Ok(parsed) = timeout.parse::<u64>() {
self.connection_timeout_seconds = Some(parsed);
}
}
self
}
}

View File

@@ -75,6 +75,21 @@ impl Settings {
);
}
// Parse auth database configuration from environment variables (when auth is enabled)
#[cfg(feature = "auth")]
{
self.auth_database = Some(crate::config::AuthDatabase {
postgres: Some(
self.auth_database
.clone()
.unwrap_or_default()
.postgres
.unwrap_or_default()
.from_env(),
),
});
}
self.info = self.info.clone().from_env();
self.mint_info = self.mint_info.clone().from_env();
self.ln = self.ln.clone().from_env();

View File

@@ -43,7 +43,7 @@ use cdk_common::database::DynMintDatabase;
#[cfg(feature = "prometheus")]
use cdk_common::payment::MetricsMintPayment;
use cdk_common::payment::MintPayment;
#[cfg(feature = "auth")]
#[cfg(all(feature = "auth", feature = "postgres"))]
use cdk_postgres::MintPgAuthDatabase;
#[cfg(feature = "postgres")]
use cdk_postgres::MintPgDatabase;
@@ -663,16 +663,20 @@ async fn setup_authentication(
DatabaseEngine::Postgres => {
#[cfg(feature = "postgres")]
{
// Get the PostgreSQL configuration, ensuring it exists
let pg_config = settings.database.postgres.as_ref().ok_or_else(|| {
anyhow!("PostgreSQL configuration is required when using PostgreSQL engine")
// Require dedicated auth database configuration - no fallback to main database
let auth_db_config = settings.auth_database.as_ref().ok_or_else(|| {
anyhow!("Auth database configuration is required when using PostgreSQL with authentication. Set [auth_database] section in config file or CDK_MINTD_AUTH_POSTGRES_URL environment variable")
})?;
if pg_config.url.is_empty() {
bail!("PostgreSQL URL is required for auth database. Set it in config file [database.postgres] section or via CDK_MINTD_POSTGRES_URL/CDK_MINTD_DATABASE_URL environment variable");
let auth_pg_config = auth_db_config.postgres.as_ref().ok_or_else(|| {
anyhow!("PostgreSQL auth database configuration is required when using PostgreSQL with authentication. Set [auth_database.postgres] section in config file or CDK_MINTD_AUTH_POSTGRES_URL environment variable")
})?;
if auth_pg_config.url.is_empty() {
bail!("Auth database PostgreSQL URL is required and cannot be empty. Set it in config file [auth_database.postgres] section or via CDK_MINTD_AUTH_POSTGRES_URL environment variable");
}
Arc::new(MintPgAuthDatabase::new(pg_config.url.as_str()).await?)
Arc::new(MintPgAuthDatabase::new(auth_pg_config.url.as_str()).await?)
}
#[cfg(not(feature = "postgres"))]
{
@@ -1188,3 +1192,27 @@ pub async fn run_mintd_with_shutdown(
)
.await
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_postgres_auth_url_validation() {
// Test that the auth database config requires explicit configuration
// Test empty URL
let auth_config = config::PostgresAuthConfig {
url: "".to_string(),
..Default::default()
};
assert!(auth_config.url.is_empty());
// Test non-empty URL
let auth_config = config::PostgresAuthConfig {
url: "postgresql://user:password@localhost:5432/auth_db".to_string(),
..Default::default()
};
assert!(!auth_config.url.is_empty());
}
}

View File

@@ -27,4 +27,11 @@ docker exec -e PGPASSWORD="${DB_PASS}" "${CONTAINER_NAME}" \
docker exec -e PGPASSWORD="${DB_PASS}" "${CONTAINER_NAME}" \
psql -U "${DB_USER}" -d "${DB_NAME}" -c "CREATE DATABASE mintdb_auth;"
# Export environment variables for both main and auth databases
export DATABASE_URL="host=localhost user=${DB_USER} password=${DB_PASS} dbname=${DB_NAME} port=${DB_PORT}"
export CDK_MINTD_POSTGRES_URL="postgresql://${DB_USER}:${DB_PASS}@localhost:${DB_PORT}/mintdb"
export CDK_MINTD_AUTH_POSTGRES_URL="postgresql://${DB_USER}:${DB_PASS}@localhost:${DB_PORT}/mintdb_auth"
echo "Database URLs configured:"
echo "Main database: ${CDK_MINTD_POSTGRES_URL}"
echo "Auth database: ${CDK_MINTD_AUTH_POSTGRES_URL}"

View File

@@ -198,9 +198,11 @@ where
for (endpoint, auth) in protected_endpoints.iter() {
if let Err(err) = query(
r#"
INSERT OR REPLACE INTO protected_endpoints
INSERT INTO protected_endpoints
(endpoint, auth)
VALUES (:endpoint, :auth);
VALUES (:endpoint, :auth)
ON CONFLICT (endpoint) DO UPDATE SET
auth = EXCLUDED.auth;
"#,
)?
.bind("endpoint", serde_json::to_string(endpoint)?)