Skip to content

[cherry-pick: release-v0.80.x] feat: add ML-KEM group to nginx for PQC readiness#3726

Merged
tekton-robot merged 1 commit into
release-v0.80.xfrom
cherry-pick-3713-to-release-v0.80.x
Jul 14, 2026
Merged

[cherry-pick: release-v0.80.x] feat: add ML-KEM group to nginx for PQC readiness#3726
tekton-robot merged 1 commit into
release-v0.80.xfrom
cherry-pick-3713-to-release-v0.80.x

Conversation

@tekton-robot

Copy link
Copy Markdown
Contributor

This is a cherry-pick of #3713


Summary

  • The OpenShift TLS FAQ mandates TLS 1.3 servers negotiate ML-KEM if the client supports it (pqc_capable=true is a mandatory requirement)
  • nginx/OpenSSL requires an explicit ssl_ecdh_curve directive to advertise post-quantum groups; Go-based components get this for free via Go 1.24+ but nginx does not
  • Added tlsECDHGroups() that always emits ssl_ecdh_curve, with a FIPS gate to prevent nginx crashes

What changes

console_plugin_reconciler.go:

  • tlsECDHGroups() — returns X25519MLKEM768:X25519:secp256r1:secp384r1 on non-FIPS clusters, X25519:secp256r1:secp384r1 on FIPS clusters
  • isFIPSEnabled() — reads /proc/sys/crypto/fips_enabled (kernel file, readable from containers without privileges)
  • fipsEnabledPath — package-level var so tests can override it with a temp file

Why FIPS gating is needed:
X25519MLKEM768 is not FIPS-approved. OpenSSL's FIPS provider rejects it with a fatal error that crashes nginx:

nginx: [emerg] SSL_CONF_cmd("Groups","X25519MLKEM768:X25519") failed

Why hardcoded (not from APIServer):
library-go's ObserveTLSSecurityProfile does not yet expose the groups field from the APIServer TLS profile. The tracking PR is openshift/library-go#2347 (open). Once merged, the hardcoded list will be replaced by dynamic propagation from the APIServer profile.

Test plan

  • TestIsFIPSEnabled — verifies all three states: missing file, 0, 1
  • TestTLSECDHGroups — verifies ML-KEM included on non-FIPS, excluded on FIPS (using temp file override)
  • TestBuildNginxTLSDirectives — all cases assert ssl_ecdh_curve X25519MLKEM768:X25519:secp256r1:secp384r1
  • TestGenerateNginxConfWithTLS — end-to-end nginx.conf generation
  • TestNginxTLSIntegration — full reconciler integration
  • Manual: deploy on non-FIPS cluster, run TLS scanner → expect pqc_capable=true
  • Manual: deploy on FIPS cluster → expect no crash, pqc_capable=false (acceptable per crypto team guidance)

Made with Cursor

The OpenShift TLS FAQ mandates that every TLS 1.3 server negotiate
ML-KEM if the client supports it. nginx/OpenSSL requires an explicit
ssl_ecdh_curve directive to advertise post-quantum groups; without
it the TLS scanner reports pqc_capable=false.

tlsECDHGroups() emits ssl_ecdh_curve based on FIPS mode:
  Non-FIPS: X25519MLKEM768:X25519:P-256:P-384:P-521
  FIPS:     P-256:P-384:P-521

X25519MLKEM768 and X25519 are not FIPS 140-approved: OpenSSL's FIPS
provider rejects them with a fatal error that crashes nginx. Only the
NIST prime curves (P-256, P-384, P-521) are accepted in FIPS mode.
isFIPSEnabled() detects FIPS by reading /proc/sys/crypto/fips_enabled,
which is accessible from containers via the shared host kernel.

The group list is hardcoded until library-go's
ObserveTLSSecurityProfile exposes the groups field from the APIServer
TLS profile (openshift/library-go#2347, currently open). At that
point the hardcoded list will be replaced by dynamic propagation.

Verified on a live FIPS cluster: pipelines-console-plugin 1/1 Running,
no nginx crash.

Signed-off-by: Jawed khelil <jkhelil@redhat.com>
Assisted-by: Claude Sonnet 4.6 (via Cursor)
Co-authored-by: Cursor <cursoragent@cursor.com>
@tekton-robot tekton-robot added do-not-merge/release-note-label-needed Indicates that a PR should not merge because it's missing one of the release note labels. size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels Jul 14, 2026
@pramodbindal

Copy link
Copy Markdown
Member

/release-note-none

@tekton-robot tekton-robot added release-note-none Denotes a PR that doesnt merit a release note. and removed do-not-merge/release-note-label-needed Indicates that a PR should not merge because it's missing one of the release note labels. labels Jul 14, 2026
@pramodbindal

Copy link
Copy Markdown
Member

/approve
/lgtm

@tekton-robot tekton-robot added lgtm Indicates that a PR is ready to be merged. approved Indicates a PR has been approved by an approver from all required OWNERS files. labels Jul 14, 2026
@tekton-robot

Copy link
Copy Markdown
Contributor Author

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: pramodbindal

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@tekton-robot tekton-robot merged commit 87c8d82 into release-v0.80.x Jul 14, 2026
13 of 14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. lgtm Indicates that a PR is ready to be merged. release-note-none Denotes a PR that doesnt merit a release note. size/L Denotes a PR that changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants