Skip to content

feat: integrate with cluster TLS security profile - #31

Merged
openshift-merge-bot[bot] merged 1 commit into
opendatahub-io:mainfrom
jstourac:centralTlsProfile
Jul 20, 2026
Merged

openshift-merge-bot[bot] merged 1 commit into
opendatahub-io:mainfrom
jstourac:centralTlsProfile

Conversation

@jstourac

@jstourac jstourac commented Jul 10, 2026 •

Copy link
Copy Markdown
Member

https://redhat.atlassian.net/browse/RHOAIENG-76050

Summary

Integrate controller-runtime-common/pkg/tls TLS profile support into the workbenches-operator to comply with the OCP 5.0 centralized TLS profile requirement (OCPSTRAT-2611).

  • Fetch the cluster APIServer TLS profile at startup (OpenShift only, fail closed on unexpected errors)
  • Apply profile-driven cipher suites and TLS version to webhook and metrics servers
  • Set explicit MinVersion=TLS12 + Mozilla Intermediate cipher fallback for non-OpenShift clusters
  • Register SecurityProfileWatcher to trigger graceful restart on profile changes
  • Handle transient API errors (ServiceUnavailable/Timeout/TooManyRequests) with hardened defaults and watcher self-healing
  • Wire OCP 5.0 TLSAdherencePolicy into the watcher (inert on OCP 4.19, active when the FeatureGate is available)
  • Set NextProtos (ALPN) for HTTP/2 + HTTP/1.1 support on all TLS endpoints
  • Add RBAC for config.openshift.io/apiservers (get/list/watch)

Motivation

OCP 5.0 (GA October 2026) requires all components to honor the centralized TLS profile (OCPSTRAT-2611). This is modeled after the same integration done for odh-notebook-controller in opendatahub-io/kubeflow#836 and its follow-up opendatahub-io/kubeflow#847.

Ref: RHOAIENG-76050

How Has This Been Tested?

Build & manifests

  • go build ./... passes
  • make manifests regenerates RBAC cleanly (no uncommitted diff)
  • Helm chart ClusterRole includes the new apiservers permission (hack/chart-sync-rbac.sh)
  • Existing unit tests pass

OpenShift cluster (OCP 4.19+)

  1. Deploy the operator on an OpenShift cluster
  2. Verify the operator pod starts without errors
  3. Check operator logs for the TLS bootstrap message:
    • On OpenShift: expect to see the profile being fetched successfully (no "hardened defaults" message)
    • Confirm no unable to read APIServer TLS profile error
  4. Verify RBAC: oc get clusterrole <operator-role> -o yaml should include config.openshift.io / apiservers with get, list, watch verbs
  5. Create a workbench, stop and restart it -- confirm normal operation is unaffected
  6. Change the cluster TLS profile: oc edit apiserver cluster and modify spec.tlsSecurityProfile (e.g., switch from Intermediate to Old or Custom)
  7. Observe the operator log emitting "TLS profile changed, initiating graceful shutdown to reload" and the pod restarting
  8. After restart, verify the operator picks up the new profile and continues operating normally

Non-OpenShift / vanilla Kubernetes

  1. Deploy the operator on a non-OpenShift Kubernetes cluster (or envtest without OpenShift CRDs)
  2. Verify logs show "TLS profile not available, using hardened defaults (non-OpenShift cluster)"
  3. Confirm the operator starts and operates normally with TLS 1.2 + Intermediate cipher defaults

Merge criteria:

  • The commits are squashed in a cohesive manner and have meaningful messages.
  • Testing instructions have been added in the PR body (for PRs involving changes that are not immediately obvious).
  • The developer has manually tested the changes and verified that the changes work

Summary by CodeRabbit

  • New Features

    • Added automatic TLS configuration based on the cluster’s API server security profile.
    • Applied derived TLS settings consistently to metrics and webhook services.
    • Added support for optional HTTP/2 configuration and TLS adherence policy detection.
    • Automatically responds to OpenShift TLS profile changes by gracefully restarting affected services.
    • Added read-only access to OpenShift API server configuration for additional components.
  • Bug Fixes

    • Improved handling of missing, transient, and unsupported TLS configuration data with hardened secure defaults.
    • Ensures non-fatal behavior when TLS adherence cannot be determined.

@coderabbitai

coderabbitai Bot commented Jul 10, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

@jstourac, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 56 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Central YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: 2c61f706-52f6-47c4-baca-65a6db59a846

📥 Commits

Reviewing files that changed from the base of the PR and between 9f1c257 and 429bc4e.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum, !**/*.sum
📒 Files selected for processing (7)
  • charts/operator/templates/clusterrole.yaml
  • cmd/main.go
  • config/rbac/role.yaml
  • go.mod
  • internal/controller/workbenches_controller.go
  • internal/tlsconfig/tlsconfig.go
  • internal/tlsconfig/tlsconfig_test.go
📝 Walkthrough

Walkthrough

Adds TLS bootstrap logic that reads OpenShift API-server TLS profiles and adherence policies, applies derived options to metrics and webhook servers, and reloads through a security profile watcher. Adds tests for defaults, error classification, protocol selection, adherence handling, and unsupported ciphers. Grants read access to OpenShift API-server resources and updates Go dependencies.

Estimated code review effort: 4 (Complex) | ~45 minutes

🚥 Pre-merge checks | ✅ 9 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Contribution Quality And Spam Detection ⚠️ Warning FAIL: the PR body is a rigid Summary/Motivation/Test/Checklist template, and cmd/main.go contains a broken manager-creation block (syntax error / unbalanced braces). Rewrite the PR description in project-specific prose, then fix and verify the main.go edit compiles cleanly before resubmitting.
✅ Passed checks (9 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed Title clearly matches the main change: integrating cluster TLS security profile support.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
No Hardcoded Secrets ✅ Passed No hardcoded secrets, credentialed URLs, or long base64 literals were introduced in touched files; only RBAC resource names like secrets/tokenreviews appear. CWE-798 not observed.
No Weak Cryptography ✅ Passed PASS: Diff uses stdlib crypto/tls only; no MD5/SHA1/DES/RC4/3DES/ECB, no custom crypto, and no secret/token compares. New TLS ciphers are AEAD-only (no CWE-327/328/208).
No Injection Vectors ✅ Passed PASS: No CWE-89/78/94/502/79 sinks in changed production code; the new TLS/RBAC paths use Kubernetes/OpenShift client APIs and constants.
No Privileged Containers ✅ Passed PR diff only adds RBAC rules for config.openshift.io/apiservers; touched manifests contain no privileged/host*/allowPrivilegeEscalation/USER root settings (CWE-269/284).
No Sensitive Data In Logs ✅ Passed Only static startup/watcher messages and generic error logs were added; no passwords, tokens, PII, raw bodies, or credential-bearing URLs are logged. CWE-532 not evident.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codecov-commenter

codecov-commenter commented Jul 10, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 45.45455% with 48 lines in your changes missing coverage. Please review.
✅ Project coverage is 62.29%. Comparing base (7beeb0d) to head (429bc4e).

Files with missing lines Patch % Lines
cmd/main.go 0.00% 40 Missing ⚠️
internal/tlsconfig/tlsconfig.go 83.33% 8 Missing ⚠️

❌ Your patch status has failed because the patch coverage (45.45%) is below the target coverage (60.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main      #31      +/-   ##
==========================================
- Coverage   62.84%   62.29%   -0.56%     
==========================================
  Files          15       16       +1     
  Lines        1674     1753      +79     
==========================================
+ Hits         1052     1092      +40     
- Misses        490      529      +39     
  Partials      132      132              
Flag Coverage Δ
unit-tests 62.29% <45.45%> (-0.56%) ⬇️

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

Files with missing lines Coverage Δ
internal/controller/workbenches_controller.go 75.24% <ø> (ø)
internal/tlsconfig/tlsconfig.go 83.33% <83.33%> (ø)
cmd/main.go 0.00% <0.00%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@jstourac
jstourac force-pushed the centralTlsProfile branch 3 times, most recently from b7bfa9f to 4be9266 Compare July 15, 2026 13:19
@jstourac
jstourac marked this pull request as ready for review July 15, 2026 13:20
@openshift-ci
openshift-ci Bot requested review from harshad16 and thaorell July 15, 2026 13:20
@jstourac

Copy link
Copy Markdown
Member Author

I haven't tested this anyhow yet, but let's undraft to see how this goes and what coderabbitai has to say.

@jstourac
jstourac force-pushed the centralTlsProfile branch from 4be9266 to ada2934 Compare July 15, 2026 19:41

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/tlsconfig/tlsconfig.go`:
- Around line 87-91: Update isTransientAPIError to recognize client-side context
deadlines by importing the standard errors package and including an errors.Is
check for context.DeadlineExceeded alongside the existing Kubernetes
transient-error checks.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Central YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: 2fdda4a4-7f64-429a-b31e-00adc712f973

📥 Commits

Reviewing files that changed from the base of the PR and between 23cc533 and ada2934.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum, !**/*.sum
📒 Files selected for processing (7)
  • charts/operator/templates/clusterrole.yaml
  • cmd/main.go
  • config/rbac/role.yaml
  • go.mod
  • internal/controller/workbenches_controller.go
  • internal/tlsconfig/tlsconfig.go
  • internal/tlsconfig/tlsconfig_test.go

Comment thread internal/tlsconfig/tlsconfig.go

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
internal/controller/workbenches_controller.go (1)

140-146: 🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

Missing OwnerReferences for managed child resources (CWE-459).

The controller watches appsv1.Deployment via a custom event mapper instead of .Owns(). This violates the path instruction to set OwnerReferences on all child resources. Without owner references, Kubernetes garbage collection cannot track and delete child resources when the parent CR is deleted, leading to resource leaks (CWE-459). Refactor the manifest application logic to inject OwnerReferences and replace this watch with .Owns(&appsv1.Deployment{}).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/controller/workbenches_controller.go` around lines 140 - 146, The
Workbenches controller currently maps Deployment events without establishing
ownership. Update the manifest application logic to inject the owning
Workbenches resource into child Deployment OwnerReferences, then replace the
custom deployment watch in ctrlBuilder with .Owns(&appsv1.Deployment{}),
preserving the availability-change predicate if applicable.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@internal/controller/workbenches_controller.go`:
- Around line 140-146: The Workbenches controller currently maps Deployment
events without establishing ownership. Update the manifest application logic to
inject the owning Workbenches resource into child Deployment OwnerReferences,
then replace the custom deployment watch in ctrlBuilder with
.Owns(&appsv1.Deployment{}), preserving the availability-change predicate if
applicable.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Central YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: 17b15231-18f3-409e-b95a-894acf75295e

📥 Commits

Reviewing files that changed from the base of the PR and between ada2934 and 9f1c257.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum, !**/*.sum
📒 Files selected for processing (7)
  • charts/operator/templates/clusterrole.yaml
  • cmd/main.go
  • config/rbac/role.yaml
  • go.mod
  • internal/controller/workbenches_controller.go
  • internal/tlsconfig/tlsconfig.go
  • internal/tlsconfig/tlsconfig_test.go
🚧 Files skipped from review as they are similar to previous changes (5)
  • config/rbac/role.yaml
  • charts/operator/templates/clusterrole.yaml
  • cmd/main.go
  • internal/tlsconfig/tlsconfig.go
  • go.mod

Read the cluster TLS profile from apiservers.config.openshift.io/cluster
at startup. Apply MinVersion, CipherSuites, and NextProtos to webhook
and metrics server TLS configs. Fail closed on unexpected errors.
Use Mozilla Intermediate defaults on non-OpenShift clusters.

1. Transient error handling: IsServiceUnavailable/IsTimeout/IsTooManyRequests
   fall back to hardened defaults instead of crashing.
2. TLSAdherencePolicy: fetches the OCP 5.0 adherence policy and wires it
   into SecurityProfileWatcher.
3. Watcher self-healing: on transient errors, the watcher still registers
   and self-heals when the API recovers.
4. 10s context timeout for bootstrap TLS fetch.
@jstourac
jstourac force-pushed the centralTlsProfile branch from 9f1c257 to 429bc4e Compare July 17, 2026 09:44

@harshad16 harshad16 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for the TLS integration.
Great direction toward cluster-wide TLS profile compliance

/lgtm
/approve

@openshift-ci

openshift-ci Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: harshad16, jstourac

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

@openshift-merge-bot
openshift-merge-bot Bot merged commit 36ce8ae into opendatahub-io:main Jul 20, 2026
12 checks passed
@jstourac
jstourac deleted the centralTlsProfile branch July 21, 2026 06:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants