Skip to content

SECURESIGN-4993: Add TLS profile resolver for cluster-wide TLS policy - #2040

Merged
osmman merged 1 commit into
mainfrom
SECURESIGN-4993-tls-profile-resolver
Jul 22, 2026
Merged

SECURESIGN-4993: Add TLS profile resolver for cluster-wide TLS policy#2040
osmman merged 1 commit into
mainfrom
SECURESIGN-4993-tls-profile-resolver

Conversation

@anithapriyanatarajan

@anithapriyanatarajan anithapriyanatarajan commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Summary

Resolves the cluster-wide TLS profile at operator startup and applies it to the
operator's own serving endpoints (metrics / webhooks), so the operator honors the
platform TLS policy configured on OpenShift.

Jira: SECURESIGN-4993

What this does

  • On OpenShift, at startup the operator resolves the effective TLS profile from
    the cluster APIServer config using
    openshift/controller-runtime-common/pkg/tls
    (FetchAPIServerTLSProfile / FetchAPIServerTLSAdherencePolicy), and builds the
    serving tls.Config via NewTLSConfigFromProfile.
  • The resolution runs under a cancellable context bounded by APIServerTimeout
    (flag --apiserver-timeout / env APISERVER_TIMEOUT, default 30s), so a slow or
    unreachable API server aborts startup instead of hanging.
  • A new opt-out flag --disable-cluster-tls-profile / env
    DISABLE_CLUSTER_TLS_PROFILE (default false) lets operators fall back to the
    built-in Intermediate profile. Non-OpenShift clusters and IsNotFound /
    NoMatch cases also fall back gracefully.
  • ostls.SecurityProfileWatcher is wired in so the operator restarts when the
    cluster TLS profile changes, picking up the new policy on the next boot.
  • The informer cache is scoped: field selectors pin the APIServer and Ingress
    informers to metadata.name=cluster, and operator-owned objects are filtered by
    the app.kubernetes.io/part-of label.

RBAC

Adds a config.openshift.io/apiservers get;list;watch rule (scoped to
resourceNames=cluster) backed by a +kubebuilder:rbac marker in
internal/controller/types.go so make manifests regenerates it deterministically.

Dependencies / security

  • Adds github.com/openshift/controller-runtime-common.
  • Pins github.com/distribution/distribution/v3 to v3.1.1 via a replace
    directive (durable against go mod tidy downgrades) and bumps docker/cli to
    address transitive CVEs pulled in by the new dependency.

Tests

  • 6 unit tests for resolveClusterTLSProfile covering OpenShift, non-OpenShift,
    disabled-flag, profile-fetch fallback, and adherence-fetch-error paths
    (100% function coverage of the resolver).

Note on patch coverage

The overall patch-coverage number is dominated by cmd/main.go, which is operator
bootstrap/wiring (manager construction, cache options, signal handling) that is
exercised by e2e rather than unit tests. The genuinely testable unit —
resolveClusterTLSProfile — is fully covered.

Follow-up / out of scope

@anithapriyanatarajan
anithapriyanatarajan force-pushed the SECURESIGN-4993-tls-profile-resolver branch from 9dd1985 to cf82b05 Compare July 15, 2026 16:47
@anithapriyanatarajan
anithapriyanatarajan marked this pull request as draft July 15, 2026 17:15
@anithapriyanatarajan
anithapriyanatarajan force-pushed the SECURESIGN-4993-tls-profile-resolver branch from cf82b05 to c14ef18 Compare July 15, 2026 17:21
@codecov-commenter

codecov-commenter commented Jul 15, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 50.68493% with 36 lines in your changes missing coverage. Please review.
✅ Project coverage is 56.37%. Comparing base (54ea626) to head (a5e73c2).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
cmd/main.go 50.68% 31 Missing and 5 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2040      +/-   ##
==========================================
- Coverage   56.40%   56.37%   -0.03%     
==========================================
  Files         269      269              
  Lines       15267    15339      +72     
==========================================
+ Hits         8611     8648      +37     
- Misses       5772     5803      +31     
- Partials      884      888       +4     
Flag Coverage Δ
e2e 71.03% <26.02%> (-0.47%) ⬇️
unit 33.93% <32.87%> (+0.04%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@anithapriyanatarajan
anithapriyanatarajan force-pushed the SECURESIGN-4993-tls-profile-resolver branch 2 times, most recently from 96f64f4 to 17edac8 Compare July 15, 2026 17:40
@anithapriyanatarajan
anithapriyanatarajan force-pushed the SECURESIGN-4993-tls-profile-resolver branch from 17edac8 to 7e7b4ed Compare July 16, 2026 08:31
@anithapriyanatarajan
anithapriyanatarajan marked this pull request as ready for review July 16, 2026 10:02

@osmman osmman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for putting this together — before we merge, I'd like this reworked to build on existing OpenShift tooling instead of re-implementing TLS profile resolution and crypto/cipher mapping from scratch.

There are already prepared libraries and examples from OpenShift that cover this ground:

We're a controller-runtime based operator, so controller-runtime-common's pkg/tls package is directly applicable — for example, it already watches the cluster TLS profile config and terminates the operator to reload the new config on change, which overlaps with the bootstrap wiring in "Feature 2" here. library-go/pkg/crypto also already has the profile-to-cipher-suite mappings this PR re-derives in internal/utils/tls/profile.

Please rework this PR to build on top of these libraries rather than the custom resolver, and let's sync if any gaps remain that genuinely need net-new code.

@anithapriyanatarajan

Copy link
Copy Markdown
Contributor Author

@osmman Thank you for the direction. Marking this as draft. will iterate and open for review again.

@anithapriyanatarajan
anithapriyanatarajan marked this pull request as draft July 17, 2026 09:39
@anithapriyanatarajan
anithapriyanatarajan force-pushed the SECURESIGN-4993-tls-profile-resolver branch 4 times, most recently from 14365af to 7286829 Compare July 17, 2026 13:36
@anithapriyanatarajan
anithapriyanatarajan force-pushed the SECURESIGN-4993-tls-profile-resolver branch from 7286829 to 4d36e34 Compare July 21, 2026 08:54
@anithapriyanatarajan
anithapriyanatarajan marked this pull request as ready for review July 21, 2026 11:29
@anithapriyanatarajan
anithapriyanatarajan force-pushed the SECURESIGN-4993-tls-profile-resolver branch from 3fb6385 to b53bbe7 Compare July 22, 2026 07:44
@anithapriyanatarajan

Copy link
Copy Markdown
Contributor Author

Thanks for putting this together — before we merge, I'd like this reworked to build on existing OpenShift tooling instead of re-implementing TLS profile resolution and crypto/cipher mapping from scratch.

There are already prepared libraries and examples from OpenShift that cover this ground:

We're a controller-runtime based operator, so controller-runtime-common's pkg/tls package is directly applicable — for example, it already watches the cluster TLS profile config and terminates the operator to reload the new config on change, which overlaps with the bootstrap wiring in "Feature 2" here. library-go/pkg/crypto also already has the profile-to-cipher-suite mappings this PR re-derives in internal/utils/tls/profile.

Please rework this PR to build on top of these libraries rather than the custom resolver, and let's sync if any gaps remain that genuinely need net-new code.

@osmman Thank you. The PR is reworked and ready for review now. Please consider the following points:

Why distribution/distribution/v3 is pinned to v3.1.1? the version selected transitively resolves to a release carrying a known CVE. Pinning to v3.1.1 pulls in the fixed release. It's kept as an explicit pin (rather than letting MVS pick) because go mod tidy would otherwise silently downgrade it back to the vulnerable version.

Snyk failure go-ntlmssp (Azure auth path via library-go): the flagged package (github.com/Azure/go-ntlmssp) is pulled in transitively through github.com/openshift/library-go's Azure authentication path. It is not reachable from our code. confirmed via go mod why ("main module does not need package") and it does not appear in the built binary (go version -m). There is no upstream fix version available, so it can't be resolved by bumping. Recommend suppressing it via a Snyk ignore rather than a dependency change, since a pin would have no effect on a non-reachable, no-fix-available transitive dependency.

Comment thread cmd/main.go Outdated

@osmman osmman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please squash commits into single feat commit.

SECURESIGN-4993

On OpenShift, resolve the effective cluster TLS profile at startup from the
APIServer config using openshift/controller-runtime-common/pkg/tls
(FetchAPIServerTLSProfile / FetchAPIServerTLSAdherencePolicy) and apply it to the
operator's own serving endpoints via NewTLSConfigFromProfile.

- Run resolution under a cancellable context bounded by APIServerTimeout so a slow
  or unreachable API server aborts startup instead of hanging.
- Add opt-out flag --disable-cluster-tls-profile / env DISABLE_CLUSTER_TLS_PROFILE
  (default false); non-OpenShift and IsNotFound/NoMatch cases fall back to the
  built-in Intermediate profile.
- Wire ostls.SecurityProfileWatcher so the operator restarts and picks up cluster
  TLS profile changes.
- Scope the informer cache: pin APIServer/Ingress informers to
  metadata.name=cluster and filter operator-owned objects by
  app.kubernetes.io/part-of.
- Add config.openshift.io/apiservers get;list;watch RBAC (resourceNames=cluster)
  backed by a +kubebuilder:rbac marker.
- Pin distribution/distribution/v3 to v3.1.1 via a replace directive so go mod
  tidy cannot downgrade back to the vulnerable version; bump docker/cli.
- Add unit tests for resolveClusterTLSProfile.
@anithapriyanatarajan
anithapriyanatarajan force-pushed the SECURESIGN-4993-tls-profile-resolver branch from b53bbe7 to a5e73c2 Compare July 22, 2026 09:19
@osmman
osmman merged commit 2f04fdd into main Jul 22, 2026
22 of 23 checks passed
@osmman
osmman deleted the SECURESIGN-4993-tls-profile-resolver branch July 22, 2026 10:26
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