Skip to content

feat(database): Optional TLS for DB connections#6

Merged
markshust merged 11 commits intomarko-php:developfrom
samsteele:feature/tls-for-db-connections
Apr 15, 2026
Merged

feat(database): Optional TLS for DB connections#6
markshust merged 11 commits intomarko-php:developfrom
samsteele:feature/tls-for-db-connections

Conversation

@samsteele
Copy link
Copy Markdown
Contributor

Probably getting waaaaaaay ahead of myself here but I ran into this face first while playing around with hooking Marko up to Amazon RDS so thought I'd have a crack at it.

Added 5 new optional config keys to database.php to facilitate one-way or mutual TLS for database connections.

  • ssl_cert = Path to client certificate for mutual TLS
  • ssl_key = Path to client private key for mutual TLS
  • ssl_ca = Path to the CA certificate
  • sslmode = Postgres ssl mode flags (disable, require, verify-ca, verify-full)
  • ssl_verify_server_cert = Bool flag to control whether Mysql verifies the CA cert. Doesn't strictly need to exist, but it's here for more granular control. Could just force it to true if a cert is provided.

Functionality enabled by those flags is implemented in Mysql and Postgres drivers. If the new flags are not present no behaviour changes.

Includes test coverage for new stuff + a small phpcs fix.

Example config blocks...

MySQL:

  return [
      'driver' => 'mysql',
      'host' => '127.0.0.1',
      'port' => 3306,
      'database' => 'myapp',
      'username' => 'root',
      'password' => 'secret',
      'ssl_ca' => '/path/to/ca-cert.pem',
      'ssl_verify_server_cert' => true,
      'ssl_cert' => '/path/to/client-cert.pem',
      'ssl_key' => '/path/to/client-key.pem',
  ];

PostgreSQL:

  return [
      'driver' => 'pgsql',
      'host' => '127.0.0.1',
      'port' => 5432,
      'database' => 'myapp',
      'username' => 'postgres',
      'password' => 'secret',
      'sslmode' => 'verify-full',
      'ssl_ca' => '/path/to/ca-cert.pem',
      'ssl_cert' => '/path/to/client-cert.pem',
      'ssl_key' => '/path/to/client-key.pem',
  ];

@github-actions github-actions Bot added the enhancement New feature or request label Apr 1, 2026
@samsteele samsteele changed the title feat(database): TLS for DB connections feat(database): Optional TLS for DB connections Apr 1, 2026
@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Apr 1, 2026
@markshust
Copy link
Copy Markdown
Collaborator

Very very cool, appreciate the update! Can I ask what you used to build this out?! I can provide you with my internal workflow that I've been using, but would love to also hear what you are using.

I'm still on vacation but am heading back today. Hope to get a chance to check it out and merge this in asap!

You're not getting ahead of yourself at all -- this is exactly what I'd like to see come in 😄

@samsteele
Copy link
Copy Markdown
Contributor Author

Used Claude as a test writer and research assistant (eg, "where is the postgres dsn built?") but hand wrote the business logic myself, can't let it have all of the fun.

I did get Claude to write a bash script that spins up mysql & postgres containers with/without SSL enforced, hot swap the DB config between them and run some pseudo integration tests to verify connections work as they should with and without TLS which I thought was pretty cool.

markshust and others added 2 commits April 15, 2026 11:39
…-php#6

Extract connectAndCapturePdoOptions() helper in MySQL SSL tests to
reduce duplicated anonymous class boilerplate. Fix trailing whitespace
in PgSqlConnection::bindValues() signature.

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

Hey @samsteele, thanks for this contribution! SSL/TLS support is a real need for anyone connecting to cloud-managed databases (RDS, Cloud SQL, etc.), so this is a great addition.

The architecture here is solid — shared SSL config in the base database package with driver-specific behavior in database-mysql and database-pgsql. The MySQL/PostgreSQL asymmetry (sslmode for PG, ssl_verify_server_cert for MySQL) correctly reflects how the drivers actually work. Keypair validation and secure defaults (sslVerifyServerCert defaulting to true when a CA cert is provided) are nice touches.

I merged latest from develop and made two small cleanup changes:

  1. Fixed trailing whitespace in PgSqlConnection::bindValues() signature (would fail phpcs)
  2. Extracted connectAndCapturePdoOptions() helper in the MySQL SSL tests — the 7 SSL tests each had an identical ~25-line anonymous class definition, so I pulled it into a shared helper. Same test coverage, ~127 fewer lines.

All 837 database tests pass. Merging this in — thanks again! 🎉

@markshust markshust merged commit e4966ef into marko-php:develop Apr 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants