-
Notifications
You must be signed in to change notification settings - Fork 1
Description
Summary
When connecting to PostgreSQL databases that use self-signed or private CA certificates (such as DigitalOcean Managed Databases), Spin's allowed_outbound_hosts validation rejects connection strings that include SSL parameters like sslrootcert. This prevents Spin applications from connecting to these databases with proper TLS certificate verification.
Problem
I'm trying to connect a Spin application deployed on Fermyon Cloud to a DigitalOcean Managed PostgreSQL database. DigitalOcean uses a private CA to sign their database certificates, which means:
-
Without specifying
sslrootcert, TLS handshake fails:error performing TLS handshake: certificate verify failed (self-signed certificate in certificate chain) -
When I add
sslrootcertto the connection string (URL format), the connection is rejected:address postgres://...?sslmode=verify-full&sslrootcert=/do-ca.crt is not permitted -
When I use the libpq key/value format, the entire connection string is treated as the "address" and rejected:
address host=db.example.com port=25060 ... sslrootcert=/do-ca.crt is not permitted
Environment
- Spin CLI: 3.5.1
- spin-sdk (Rust): 5.1
- Fermyon Cloud: latest
- Database: DigitalOcean Managed PostgreSQL (uses private CA)
What I've Tried
-
URL format with
sslrootcert: Rejected because the/in the path breaks URL parsing forallowed_outbound_hostsvalidation -
URL format with percent-encoded path (
sslrootcert=%2Fdo-ca.crt): Still rejected -
Key/value connection string format: The entire string is treated as the address rather than extracting the host for validation
-
Mounting the CA certificate via
files = ["do-ca.crt"]: File is mounted correctly, but can't use it in the connection string -
Various
allowed_outbound_hostspatterns: Includingpostgres://*:*, explicit hostname with and without port
Proposed Solution
Based on documentation I found (possibly from an unreleased version), it appears the intended behavior is:
- For key/value connection strings: Parse the
host=value and validate it againstallowed_outbound_hostsseparately, allowing other parameters likesslmodeandsslrootcertto pass through to the driver
Example from documentation I found:
// allowed_outbound_hosts = ["postgres://db.example.com:5432"]
let db = Connection::open(
"host=db.example.com port=5432 user=app dbname=appdb sslmode=verify-full sslrootcert=/ca.crt",
)?;Impact
This limitation prevents Spin applications from connecting to:
- DigitalOcean Managed Databases
- AWS RDS with private CA certificates
- Azure Database for PostgreSQL with private endpoints
- Any PostgreSQL instance using self-signed or private CA certificates
These are common production database configurations, and the workaround of using sslmode=require (which skips certificate verification) is not secure as it leaves connections vulnerable to MITM attacks.
Workaround Attempts
sslmode=requirestill fails with certificate verification errors- Cannot use a database provider with publicly-trusted certificates for this project
Request
Please add support for:
- Parsing key/value PostgreSQL connection strings to extract the host for
allowed_outbound_hostsvalidation - Allowing SSL-related query parameters in URL-style connection strings without breaking the host validation
This would enable secure connections to PostgreSQL databases using private CA certificates, which is a common enterprise and cloud database configuration.