Skip to content

Make database TLS settings take effect in the PHP Server and Helm chart #540

Closed

Description

@rmcdaniel

Problem

Operators can't reliably require or verify TLS between the PHP Server and its database.

  • The Helm chart's externalDatabase.sslMode renders DB_SSL_MODE, but nothing in the Server reads that variable.
  • PostgreSQL is hard-coded to sslmode=prefer. That mode doesn't verify the certificate and can fall back to an unencrypted connection.
  • MySQL TLS works only through an undocumented MYSQL_ATTR_SSL_CA.
  • The Rust runtime reads different names (DB_SSLMODE, DB_SSLROOTCERT), so a later cutover would change behavior again.

A deployment configured for verified database TLS silently runs unverified.

Acceptance criteria

  • The PHP Server reads documented settings to require TLS and to verify the CA and hostname for MySQL/MariaDB and PostgreSQL, using the same names as the Rust runtime.
  • The chart's TLS values reach those settings and can mount a CA bundle from a Secret, and a chart test shows they take effect.
  • In a verifying mode, an untrusted certificate or a wrong hostname fails bootstrap and readiness with a named reason, with no plaintext fallback. Readiness reports whether the active connection is encrypted and verified.
  • CI against the published image connects over real TLS to both databases and rejects a bad CA and a wrong hostname.
  • The config reference, deployment guide and Helm upgrade notes document database TLS, the default and its risk, and the previously ignored chart value.

Activity

  1. added
    bugSomething isn't working
    kind:defectA public product behavior is incorrect
    priority:P1High-priority product or release risk
    on Oct 20, 2026
  2. rmcdaniel commented on Oct 20, 2026

    @rmcdaniel
    MemberAuthor

    Accepted as a P1 product correctness/security boundary, not a documentation-only fix. Current PHP source confirms that the chart emits DB_SSL_MODE while PostgreSQL uses literal prefer, and MySQL exposes only the legacy CA variable. This is source confirmation; a live customer incident or a native runtime defect is not inferred.

    General will own the PHP configuration/readiness, Helm Secret/CA wiring, regression and published-image qualification. Canonical settings must align with the already published native configuration (DB_SSLMODE, DB_SSLROOTCERT, and applicable client certificate/key settings), with explicit compatibility handling for the chart's previously ignored spelling and the legacy MySQL CA setting. No native implementation or frozen actor edit is included; the shared environment contract will be coordinated through Server#325 before later adoption.

    Acceptance requires real encrypted connections on PostgreSQL and MySQL/MariaDB, bad-CA and wrong-host refusals without plaintext fallback, truthful readiness verification scope (including pooler legs), and the normal chart/config/upgrade instructions. An unset legacy default must be described honestly. Existing P1 entry-safety qualification continues independently; no failed original, certificate check or transport result will be relabeled as passed.

  3. rmcdaniel commented on Oct 20, 2026

    @rmcdaniel
    MemberAuthor

    PHP database TLS correction underway

    General owns a separate PHP-only correction for #540 on qualified PHP main 64c696884e. The existing chart's externalDatabase.sslMode / DB_SSL_MODE must affect the actual connection. PostgreSQL currently hard-codes prefer; MySQL/MariaDB expose only the legacy CA option. No customer or Cloud impact is inferred from that source defect.

    Use the existing native-style names DB_SSLMODE and DB_SSLROOTCERT as the canonical PHP/chart inputs. Preserve the chart's existing DB_SSL_MODE and accept DB_SSL_ROOT_CERT as aliases, along with the existing MySQL CA input. Explicit conflicting settings or URL settings must not silently downgrade verification. Native configuration and catalogs are unchanged; coordinate any future native adoption separately.

    Actual handshake controls must cover trusted CA plus hostname, wrong CA, wrong hostname, missing/unreadable CA, and refusal of a plaintext database when TLS is required. Keep normal PostgreSQL bound parameters and ownership guards. Readiness may report the outcome of its own configured connection; a PostgreSQL backend's pg_stat_ssl alone does not establish the separate client-to-pooler TLS leg.

    Official libpq guidance distinguishes encryption from certificate/hostname verification. PHP's PDO MySQL options and actual mysqlnd implementation determine supported MySQL modes; an unsupported requested mode must refuse explicitly rather than advertise verification it cannot enforce.

    Source, focused tests, chart CA wiring and operator documentation stay in this PHP scope. No native/shared/runner/frozen, Composer dependency, OpenAPI or package change. This is independent of entry-safety release #541 and is not a stopped security-probe retry.

  4. rmcdaniel commented on Oct 20, 2026

    @rmcdaniel
    MemberAuthor

    Source checkpoint: #545 merged normally at 3785364cbee7785bd7907b1c516544f49994a33f, whole tree 1d4cd63c05c9839c8d65e7dde565154535b83fe3, identical to reviewed candidate b4c8bb37d589b93a51b1a4c15cd91501da727f52. The Rust subtree remains 258e8d4b31d4f4e20f880e4120b01c14d0aac616; no native/shared/frozen adoption.

    The required PHP feature suite passed, including actual required-TLS and certificate-refusal qualification. Candidate Sonar, chart lint/kind install, rolling database upgrade, HTTP topology, polling-growth and boundary checks also passed. The final optional candidate workflow aggregate remains queued, so a terminal full-workflow pass is not claimed. Existing strict branch protection and required checks were preserved.

    Fresh-main feature 39491510884, Sonar 39491510863, performance 39491510876, HTTP topology 39491510887, rolling upgrade 39491510902, boundary 39491510799 and chart 39491510929 are independent and pending. Server 2.9.10 / Helm 0.2.0 publication, immutable image/chart proof and normally installed TLS business acceptance remain to be completed. The existing published 2.9.9 identity is separate.

  5. rmcdaniel commented on Oct 20, 2026

    @rmcdaniel
    MemberAuthor

    Server 2.9.10 / Helm 0.2.0 publication source is the merged security head 870eb3be36bf4e191cb3e06e52e2b4e88f38039b, whole tree acc127e88865b6b9acf35cdd8744bf40528812e5.

    The PHP runtime, Composer dependencies, TLS configuration, release metadata, chart and image inputs are byte-identical to TLS merge 3785364c, whose independent main feature, HTTP, performance, rolling-upgrade, chart, Sonar and boundary workflows all pass. The only subsequent changes are seven reviewed certifi pins/hashes. Their exact candidate tree matches merged 870eb3be; required feature, repository, Sonar and boundary checks pass, all seven actual locked installations and HTTPS/trust checks pass, and GitHub now reports zero open Dependabot alerts. The optional cancelled parity/performance jobs were not acceptance evidence.

    I am publishing that exact immutable source through the normal protected release workflow. New main repeats remain independent and are not claimed complete. This is the TLS/security release on the existing Core 2.7.2 reference. It does not adopt the forthcoming Core 2.8 consumer or any native change. The Core consumer owner can use the following ordinary Server/Helm versions after its own exact qualification. Registry image, chart and installed TLS acceptance remain required before closing #540.

  6. rmcdaniel commented on Oct 20, 2026

    @rmcdaniel
    MemberAuthor

    The runtime correction is now accepted on published Server 2.9.11 / chart 0.2.1, exact source 987b07e1088293d9e5a8c5530a7f5ff563952968 and image index sha256:c4f304da0176ac8b6c3e391b7f541307294b5838140ceb3c85ba1e8c31998726. The installed-artifact receipt distinguishes registry identity, chart installation, source checks and the actual image tests.

    All 18 installed-image PostgreSQL 17.11 / MySQL 8.0.46 / MariaDB 10.11.19 probes pass: verified CA+hostname and required-encryption positives, wrong-CA/hostname/configuration refusals, refusal to downgrade a mandatory-TLS connection to plaintext, and explicit plaintext controls. The test uses installed /app by immutable digest, with no product-source/vendor mounts or Composer mutation. It verifies both readiness guarantees and the backend session's actual TLS. The protected publisher and anonymous chart installation also pass. Exact release documentation covers the mode/alias/default-risk contract and CA Secret mounts in the Server reference, Helm deployment guide and upgrade notes. This does not claim HTTPS ingress, client-certificate, proxy-to-database or Cloud rollout coverage.

    The automatic published-digest TLS gate is now merged in PR #560 at 66595ebf94277e1036f0817355460def7e537aa6, whole tree b5431dac5aa05a4bfbcac654863a1c1d8a65b56e, identical to candidate 765e8be9. It adds the existing probes to both new publication and verification of an existing immutable release. Native, shared and frozen paths match preceding main 3fc05dad4a0b6fba1e275b5dda3558b5c57c800d. Both chart paths require a successful TLS result. The focused recovery verifier passes two tests / 51 assertions, all 27 chart-release controls, five cleanup/input controls and 72 Docker isolation controls pass. Fresh exact-head feature/Nexus/regression, database TLS, repository, Helm lint/install and boundary jobs pass. The independent Sonar read shows gate OK, zero open/confirmed findings, zero new violations and 0.0% new duplication. The final source aggregate remains queued; it is not described as completed. The normal protected merge occurred without bypass.

    The first recovery integration failed its normal isolation check because the reusable script lacked its own GitHub job binding. A new counterexample on that source reached the fixture launcher with another job's scope. The corrected script refuses that scope before files or Docker, while the valid original scope still reaches the launcher. All three workflow callers already supply the full run/attempt/job suffix. The original failure remains; no isolation policy or expectation was relaxed.

    The earlier proposed repeat through the main publisher was incorrect: it intentionally refuses an already-published image. Published verification recovery 39528729898 now finishes SUCCESS from exact main 66595ebf, requesting tag 2.9.11 and source 987b07e1. Its immutable-artifact verification, actual published-image TLS step and scoped cleanup PASS in job 118989416594. The matching immutable chart job 118994363452 also PASSES: it verifies unchanged content under the existing version, anonymous OCI pull and installation into a clean cluster. It correctly skips republishing the existing chart. Nothing was rebuilt, retagged or replaced.

    All #540 acceptance criteria are now delivered: documented unified PHP/native configuration names, effective chart values and CA Secret mount, fail-closed bootstrap/readiness diagnostics, actual TLS/certificate refusals on the immutable published image, and continuing protected CI coverage. The earlier local 18-probe result and successful hosted jobs remain separate evidence; the timed-out raw-log fetch is not claimed as an independent log audit. Closing #540 as completed. Cloud rollout and other TLS layers remain outside this delivery.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingkind:defectA public product behavior is incorrectpriority:P1High-priority product or release risk

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions