Files
windmill/backend/windmill-common/src/db_params.rs
T
hugocasa 6a5cfbc159 feat: add Entra ID (Azure Workload Identity) database auth (#8526)
* feat: add Entra ID (Azure Workload Identity) support for database auth

Add support for Azure Workload Identity to authenticate to Azure Database
for PostgreSQL using short-lived Entra ID tokens. Mirrors the existing
AWS IAM RDS auth pattern.

- Extract shared DatabaseParams to db_params.rs for reuse across providers
- Add DatabaseUrl::EntraId variant with token refresh
- Detect "entraid" magic password in DATABASE_URL
- Unified background refresh task for both IAM RDS and Entra ID
- Support sovereign clouds via AZURE_AUTHORITY_HOST env var

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: restore needs_refresh() check in background token refresh task

The unified refresh task was missing the needs_refresh() gate, causing
it to refresh tokens every 10 seconds instead of only when near expiry.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: update ee-repo-ref.txt for Entra ID branch

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: move entraid env var reads inside cfg(private) block

Fixes unused variable warnings in OSS and EE-without-private builds
where -D warnings is enabled.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: update ee-repo-ref to 0e001bab643e449b3310b0692dd3598ee0902ecc

This commit updates the EE repository reference after PR #483 was merged in windmill-ee-private.

Previous ee-repo-ref: 44199013ed0c96680672e718f35124aa34a5d010

New ee-repo-ref: 0e001bab643e449b3310b0692dd3598ee0902ecc

Automated by sync-ee-ref workflow.

* refactor: add needs_refresh() and refresh_if_needed() to DatabaseUrl

Simplify duplicated refresh logic per Claude review suggestion.
Background task and get_database_url() now use shared methods
instead of matching on each variant individually.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
2026-04-02 16:00:33 +02:00

46 lines
1.3 KiB
Rust

use anyhow::Result;
/// Parsed database connection parameters, shared across DB auth providers (IAM RDS, Entra ID, etc.)
#[derive(Debug, Clone)]
pub struct DatabaseParams {
pub hostname: String,
pub port: u64,
pub username: String,
pub database: String,
}
/// Extract database connection parameters from a PostgreSQL URL
pub fn extract_database_params(database_url: &str) -> Result<DatabaseParams> {
let url = url::Url::parse(database_url)
.map_err(|e| anyhow::anyhow!("Failed to parse database URL: {}", e))?;
let hostname = url
.host_str()
.ok_or_else(|| anyhow::anyhow!("Database URL missing hostname"))?
.to_string();
let port = url.port().unwrap_or(5432) as u64;
let username = if url.username().is_empty() {
return Err(anyhow::anyhow!("Database URL missing username"));
} else {
urlencoding::decode(url.username())?.to_string()
};
let database = url
.path()
.trim_start_matches('/')
.split('/')
.next()
.filter(|s| !s.is_empty())
.ok_or_else(|| anyhow::anyhow!("Database URL missing database name"))?
.to_string();
Ok(DatabaseParams {
hostname,
port,
username,
database: urlencoding::decode(&database)?.to_string(),
})
}