Skip to content

[PM-22023] fix: enforce TLS validation for DB connections#1104

Merged
m2ux merged 14 commits into
mainfrom
fix/PM-22023-enforce-tls-validation-db
Apr 29, 2026
Merged

[PM-22023] fix: enforce TLS validation for DB connections#1104
m2ux merged 14 commits into
mainfrom
fix/PM-22023-enforce-tls-validation-db

Conversation

@m2ux

@m2ux m2ux commented Mar 27, 2026

Copy link
Copy Markdown
Contributor

Summary

Enforce TLS validation for PostgreSQL connections and eliminate the plaintext connection path, addressing Least Authority audit finding Issue C (PM-22023).

🎫 Ticket 📐 Engineering


Motivation

See engineering plan


Changes

Node runtime — TLS enforcement

  • Main chain follower (node/src/main_chain_follower.rs) — Extracted build_ssl_connect_options for testable SSL mode selection; removed allow_non_ssl parameter from get_connection and all 10 call sites; added deprecation warning when allow_non_ssl=true is configured
  • Configuration (node/src/cfg/midnight_cfg/mod.rs) — Updated doc comments marking allow_non_ssl as deprecated; added #[validate(custom)] path-exists check for ssl_root_cert
  • Tests — 4 new unit tests covering VerifyFull with cert, Require fallback without cert, Disable-never, and invalid connection string

Local environment — self-signed TLS for PostgreSQL

  • PostgreSQL entrypoint (local-env/configurations/postgres/entrypoint.sh) — Generate a self-signed TLS certificate at container startup; store certs outside PGDATA (/etc/ssl/postgres) to avoid conflicting with initdb; chown certs to postgres user so the server can read them after privilege drop
  • Docker Compose (local-env/docker-compose.yml) — Enable ssl=on with generated cert/key paths; set custom entrypoint to run cert generation before docker-entrypoint.sh
  • Cardano entrypoint (local-env/configurations/cardano/entrypoint.sh) — Remove ALLOW_NON_SSL=true env var (flag is now ignored)
  • Well-known configs (node-dev-01, qanet, testnet-02) — Remove ALLOW_NON_SSL from all network YAML files
  • README (local-environment/README.md) — Update note from "ALLOW_NON_SSL=true" to "self-signed TLS certificate"

Release notes

  • Change file — Added audit-enforce-tls-validation-db.md

📌 Submission Checklist

  • Changes are backward-compatible (or flagged if breaking)
  • Pull request description explains why the change is needed
  • Self-reviewed the diff
  • I have included a change file, or skipped for this reason: included audit-enforce-tls-validation-db.md
  • If the changes introduce a new feature, I have bumped the node minor version
  • Update documentation (if relevant)
  • Updated AGENTS.md if build commands, architecture, or workflows changed
  • No new todos introduced

🔱 Fork Strategy

  • Node Runtime Update
  • Node Client Update
  • Other
  • N/A

🗹 TODO before merging

  • Implementation complete
  • Tests pass
  • Ready for review

@m2ux m2ux self-assigned this Mar 27, 2026
@m2ux m2ux force-pushed the fix/PM-22023-enforce-tls-validation-db branch from 9775ef7 to bab14fb Compare March 27, 2026 10:42
@m2ux m2ux marked this pull request as ready for review April 13, 2026 09:38
@m2ux m2ux requested a review from a team as a code owner April 13, 2026 09:38
@m2ux m2ux force-pushed the fix/PM-22023-enforce-tls-validation-db branch from b9d1773 to 0faea37 Compare April 13, 2026 09:42
@m2ux m2ux enabled auto-merge April 13, 2026 09:46
m2ux and others added 5 commits April 13, 2026 15:57
Initial change file for Least Authority audit finding Issue C —
enforce strict TLS validation for PostgreSQL connections.

Signed-off-by: Mike Clay <mike.clay@shielded.io>
Signed-off-by: Mike Clay <mike.clay@shielded.io>
Remove PgSslMode::Disable path — plaintext DB connections are no
longer permitted regardless of allow_non_ssl setting. The flag is
deprecated with a startup warning.

When ssl_root_cert is configured, connections use VerifyFull (cert +
hostname validation). Without ssl_root_cert, connections fall back to
Require (encrypted, no cert validation) with a warning.

Add config validation for ssl_root_cert path and unit tests for SSL
mode selection logic.

Addresses: Least Authority Node DIFF Audit Issue C (High severity)
JIRA: PM-22023
Signed-off-by: Mike Clay <mike.clay@shielded.io>
The previous commit removed PgSslMode::Disable entirely, but the
node-dev-01 local environment sets ALLOW_NON_SSL=true to connect to
a PostgreSQL without SSL. This caused the e2e Local Environment Tests
to fail in CI.

Restore the Disable path when allow_non_ssl=true with a deprecation
warning. The security improvement (VerifyFull when ssl_root_cert is
configured, Require as fallback) remains intact for production.

Made-with: Cursor
Signed-off-by: Mike Clay <mike.clay@shielded.io>
Signed-off-by: Mike Clay <mike.clay@shielded.io>
@m2ux m2ux force-pushed the fix/PM-22023-enforce-tls-validation-db branch from 4d69b0d to 525cb44 Compare April 13, 2026 14:57
Comment thread node/src/main_chain_follower.rs Outdated
m2ux added a commit that referenced this pull request Apr 17, 2026
…n path

The doc comment on allow_non_ssl says 'This flag is ignored — all
connections use TLS', but the code still used it to set
PgSslMode::Disable (plaintext). This removes the allow_non_ssl
parameter from build_ssl_connect_options and get_connection entirely,
and adds a runtime warning when the deprecated flag is set in config.

Addresses PR #1104 review comment from @LGLO.

Signed-off-by: Mike Clay <mike.clay@shielded.io>
…n path

The doc comment on allow_non_ssl says 'This flag is ignored — all
connections use TLS', but the code still used it to set
PgSslMode::Disable (plaintext). This removes the allow_non_ssl
parameter from build_ssl_connect_options and get_connection entirely,
and adds a runtime warning when the deprecated flag is set in config.

Addresses PR #1104 review comment from @LGLO.

Signed-off-by: Mike Clay <mike.clay@shielded.io>
@m2ux m2ux force-pushed the fix/PM-22023-enforce-tls-validation-db branch from d62994f to e8801a2 Compare April 17, 2026 15:25
m2ux added a commit that referenced this pull request Apr 17, 2026
The midnight-node now requires PgSslMode::Require at minimum (the
allow_non_ssl flag is truly ignored). The local-environment PostgreSQL
container was running without TLS, causing all e2e tests to fail with
'error occurred while attempting to establish a TLS connection: server
does not support TLS'.

Changes:
- Generate a self-signed TLS certificate in the postgres entrypoint
- Configure PostgreSQL with ssl=on and the generated cert/key
- Set the custom entrypoint in docker-compose so cert generation runs
- Remove ALLOW_NON_SSL from cardano entrypoint and well-known configs
- Update README to reflect self-signed TLS instead of ALLOW_NON_SSL

Fixes e2e test failures on PR #1104.

Signed-off-by: Mike Clay <mike.clay@shielded.io>
The midnight-node now requires PgSslMode::Require at minimum (the
allow_non_ssl flag is truly ignored). The local-environment PostgreSQL
container was running without TLS, causing all e2e tests to fail with
'error occurred while attempting to establish a TLS connection: server
does not support TLS'.

Changes:
- Generate a self-signed TLS certificate in the postgres entrypoint
- Configure PostgreSQL with ssl=on and the generated cert/key
- Set the custom entrypoint in docker-compose so cert generation runs
- Remove ALLOW_NON_SSL from cardano entrypoint and well-known configs
- Update README to reflect self-signed TLS instead of ALLOW_NON_SSL

Fixes e2e test failures on PR #1104.

Signed-off-by: Mike Clay <mike.clay@shielded.io>
@m2ux m2ux force-pushed the fix/PM-22023-enforce-tls-validation-db branch from 27167d6 to 5c1979f Compare April 17, 2026 16:41
@m2ux m2ux disabled auto-merge April 17, 2026 16:41
@m2ux m2ux marked this pull request as draft April 17, 2026 16:42
m2ux added 2 commits April 18, 2026 08:14
The custom entrypoint generates self-signed TLS certificates before
calling docker-entrypoint.sh. Previously these were written to
${PGDATA}/ssl (/pgdata/ssl), but the official PostgreSQL entrypoint
runs initdb which requires PGDATA to be empty on first start. The
presence of the ssl/ subdirectory caused initdb to fail with:

  initdb: error: directory "/pgdata" exists but is not empty

Move SSL certificate storage to /etc/ssl/postgres (outside PGDATA) so
initdb sees an empty data directory on first initialization.

Signed-off-by: Mike Clay <mike.clay@shielded.io>
The custom entrypoint runs as root and generates SSL certificates, but
docker-entrypoint.sh drops privileges to the postgres user. The key file
had root-only permissions (chmod 600 owned by root), causing:

  FATAL: could not load private key file "/etc/ssl/postgres/server.key":
  Permission denied

Add chown postgres:postgres for both the key and cert files so the
postgres process can read them after the privilege drop.

Signed-off-by: Mike Clay <mike.clay@shielded.io>
@m2ux m2ux marked this pull request as ready for review April 18, 2026 08:30
@m2ux m2ux requested a review from LGLO April 18, 2026 08:30
@m2ux m2ux enabled auto-merge April 22, 2026 15:18
Signed-off-by: Mike Clay <mike.clay@shielded.io>
Made-with: Cursor
@m2ux m2ux requested a review from gilescope April 22, 2026 15:26
@m2ux m2ux changed the title fix: enforce TLS validation for DB connections [PM-22023] [PM-22023] fix: enforce TLS validation for DB connections Apr 29, 2026
Signed-off-by: Squirrel <giles.cope@shielded.io>
@m2ux m2ux added this pull request to the merge queue Apr 29, 2026
Merged via the queue into main with commit b363093 Apr 29, 2026
33 checks passed
@m2ux m2ux deleted the fix/PM-22023-enforce-tls-validation-db branch April 29, 2026 15:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants