From 00cdadafce85fb3f4fdf2b1982a0885406b06faf Mon Sep 17 00:00:00 2001 From: Echo Date: Wed, 6 May 2026 03:03:10 +0000 Subject: [PATCH] fix: use host() to strip CIDR mask from inet column in cert IP SANs The ip_address column is PostgreSQL inet type. When cast to text (ip_address::text), it includes the CIDR mask (e.g., 192.168.0.166/32). Rust IpAddr::parse() fails on CIDR notation, so the IP SAN was silently skipped in server certificates. Fix: use host(ip_address) in SQL queries to strip the CIDR mask, returning just the IP address (e.g., 192.168.0.166). Affected endpoints: - POST /hosts/:id/certificates (issue_client_cert) - POST /hosts/:id/certificates/reissue (reissue_host_cert) --- crates/pm-web/src/routes/ca.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/pm-web/src/routes/ca.rs b/crates/pm-web/src/routes/ca.rs index 76a837c..4a67ce5 100644 --- a/crates/pm-web/src/routes/ca.rs +++ b/crates/pm-web/src/routes/ca.rs @@ -300,7 +300,7 @@ async fn issue_client_cert( require_admin(&auth)?; // Look up the host's IP address from the database. - let ip_address: String = sqlx::query_scalar("SELECT ip_address::text FROM hosts WHERE id = $1") + let ip_address: String = sqlx::query_scalar("SELECT host(ip_address) FROM hosts WHERE id = $1") .bind(host_id) .fetch_one(&state.db) .await @@ -401,7 +401,7 @@ async fn reissue_host_cert( require_admin(&auth)?; // Look up the host's FQDN and IP address for the new certificate CN and SANs. - let row = sqlx::query("SELECT fqdn, ip_address::text AS ip_address FROM hosts WHERE id = $1") + let row = sqlx::query("SELECT fqdn, host(ip_address) AS ip_address FROM hosts WHERE id = $1") .bind(host_id) .fetch_one(&state.db) .await