Skip to content

Propagate OpenShift TLS security profile to Authorino#2091

Open
philbrookes wants to merge 1 commit into
Kuadrant:mainfrom
philbrookes:ocp5-tls-compliance
Open

Propagate OpenShift TLS security profile to Authorino#2091
philbrookes wants to merge 1 commit into
Kuadrant:mainfrom
philbrookes:ocp5-tls-compliance

Conversation

@philbrookes

@philbrookes philbrookes commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Reads the cluster's APIServer CR (apiserver.config.openshift.io/cluster) and resolves its TLS security profile
  • Propagates tlsMinVersion and tlsCipherSuites to the Authorino CR
  • On non-OpenShift clusters (no APIServer CRD), falls back to Intermediate profile defaults
  • Translates OpenSSL cipher names to IANA names; DHE ciphers silently skipped (unsupported by Go)
  • Includes RBAC for apiservers (get/list/watch) and test script covering 9 scenarios

Context

Part of OCP5 TLS profile compliance. Authorino is the only Kuadrant component serving TLS. This change ensures its TLS configuration matches the cluster-wide TLS security profile.

The operator looks up the APIServer CR named cluster — this follows the OpenShift convention where all config.openshift.io resources are singletons with a canonical instance name of "cluster". See:

Depends on: Kuadrant/authorino-operator#335

Test plan

  • Unit tests for ResolveTLSProfile() (all profile types, nil input, OpenSSL→IANA mapping)
  • No CRD → Intermediate defaults
  • CRD exists, no CR → Intermediate defaults
  • Intermediate, Modern, Old, Custom profiles
  • Profile change triggers reconciliation
  • CR deletion falls back to Intermediate
  • Multiple CRs — only "cluster" is used

Summary by CodeRabbit

  • New Features

    • Added detection and monitoring of the OpenShift APIServer resource when available.
    • Authorino TLS settings now use the configured OpenShift TLS security profile, including support for custom profiles and cipher-suite translation.
  • Bug Fixes

    • Improved TLS updates to preserve existing certificate secret and enablement settings while applying the new minimum TLS version and cipher suites.
    • Refined OIDC cookie query handling to avoid adding empty query strings.
  • Compatibility

    • Updated RBAC permissions and installation manifests to allow access to OpenShift APIServer resources.

@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The controller now detects the OpenShift APIServer CRD, watches APIServer resources, resolves their TLS profiles, and applies the resulting settings to Authorino. RBAC, fake-manager compatibility, dependency versions, generated metadata, and an OIDC policy test expectation are also updated.

Changes

OpenShift TLS profile propagation

Layer / File(s) Summary
TLS profile helpers and tests
internal/openshift/tls_profile.go, internal/openshift/tls_profile_test.go
Adds APIServer identifiers and topology links, translates OpenShift TLS versions and cipher suites, and tests profile mappings.
Controller bootstrap and RBAC
internal/controller/state_of_the_world.go, internal/controller/fake/manager.go, config/rbac/role.yaml, charts/kuadrant-operator/templates/manifests.yaml, bundle/manifests/...
Detects APIServer CRD availability, registers watchers and links, passes availability into Authorino reconciliation, extends fake manager methods, and grants APIServer read access.
Authorino TLS wiring
internal/controller/authorino_reconciler.go
Conditionally subscribes to APIServer events, resolves TLS settings, preserves existing TLS fields during patches, and populates TLS settings for new resources.

OIDC policy test adjustment

Layer / File(s) Summary
Query-string expression assertion
cmd/extensions/oidc-policy/internal/controller/oidcpolicy_reconciler_test.go
Updates the expected CEL expression to require both a present and non-empty query string.

Build and release metadata

Layer / File(s) Summary
Go toolchain and dependency updates
go.mod
Sets Go 1.26.4 and refreshes direct and indirect module versions, including YAML and structured-merge-diff modules.
Release metadata timestamp
bundle/manifests/kuadrant-operator.clusterserviceversion.yaml
Updates the ClusterServiceVersion creation timestamp.

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

Sequence Diagram(s)

sequenceDiagram
  participant ControllerBootstrap
  participant RESTMapper
  participant APIServerWatcher
  participant AuthorinoReconciler
  participant APIServer
  participant Authorino

  ControllerBootstrap->>RESTMapper: check APIServer CRD
  RESTMapper-->>ControllerBootstrap: availability
  ControllerBootstrap->>APIServerWatcher: register watcher when available
  APIServerWatcher->>AuthorinoReconciler: deliver APIServer topology event
  AuthorinoReconciler->>APIServer: read selected TLS profile
  APIServer-->>AuthorinoReconciler: return TLSSecurityProfile
  AuthorinoReconciler->>Authorino: apply TLS version and cipher suites
Loading

Poem

A rabbit hops through TLS bright,
APIServer profiles guide the night.
Ciphers twinkle, watchers run,
Authorino blooms beneath the sun.
“Binky!” says Bun, “the patch is done.”

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 6.90% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarises the main change: propagating the OpenShift TLS security profile to Authorino.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

Comment thread internal/controller/authorino_reconciler.go Outdated
Comment thread internal/controller/authorino_reconciler.go Outdated
@philbrookes philbrookes force-pushed the ocp5-tls-compliance branch from 59ae86f to e7b63a5 Compare July 7, 2026 15:01

@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

🧹 Nitpick comments (1)
internal/openshift/tls_profile.go (1)

45-77: 📐 Maintainability & Code Quality | 🔵 Trivial

Consider a completeness test for the cipher translation table.

opensslToIANA is a manually maintained map. If OpenShift renames/adds ciphers to a predefined profile (Old/Intermediate/Modern) in a future openshift/api bump, ciphers not yet added here will silently disappear from ResolveTLSProfile's output with no compile-time or test signal. Consider a test that iterates configv1.TLSProfiles[...].Ciphers for all built-in profile types and asserts every cipher is either mapped or explicitly documented/allow-listed as an intentionally-skipped DHE cipher.

Also applies to: 99-103

🤖 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/openshift/tls_profile.go` around lines 45 - 77, Add a completeness
test around the opensslToIANA translation table in tls_profile.go so future
openshift/api profile cipher changes are caught. In the test, iterate all
built-in entries from configv1.TLSProfiles and verify every cipher in each
profile’s Ciphers list is either present in opensslToIANA or explicitly
allow-listed as an intentionally skipped DHE cipher. Use ResolveTLSProfile and
opensslToIANA as the primary symbols to locate the behavior, and fail the test
when a new cipher would otherwise be silently dropped.
🤖 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/controller/authorino_reconciler.go`:
- Around line 239-254: The chained type assertion in
resolveTLSProfileFromTopology can panic if the child’s underlying object is not
the expected APIServer type. Update the lookup in
AuthorinoReconciler.resolveTLSProfileFromTopology to use safe type assertions
when casting child to controller.RuntimeObject and then to configv1.APIServer,
and if either cast fails, skip that child and fall back to
openshift.ResolveTLSProfile(nil) instead of panicking.

---

Nitpick comments:
In `@internal/openshift/tls_profile.go`:
- Around line 45-77: Add a completeness test around the opensslToIANA
translation table in tls_profile.go so future openshift/api profile cipher
changes are caught. In the test, iterate all built-in entries from
configv1.TLSProfiles and verify every cipher in each profile’s Ciphers list is
either present in opensslToIANA or explicitly allow-listed as an intentionally
skipped DHE cipher. Use ResolveTLSProfile and opensslToIANA as the primary
symbols to locate the behavior, and fail the test when a new cipher would
otherwise be silently dropped.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: bac19e49-aea4-4f10-93ca-7b6332c251b4

📥 Commits

Reviewing files that changed from the base of the PR and between f601936 and e7b63a5.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (9)
  • Dockerfile
  • config/rbac/role.yaml
  • go.mod
  • hack/test-tls-profile.sh
  • internal/controller/authorino_reconciler.go
  • internal/controller/fake/manager.go
  • internal/controller/state_of_the_world.go
  • internal/openshift/tls_profile.go
  • internal/openshift/tls_profile_test.go

Comment thread internal/controller/authorino_reconciler.go
@philbrookes philbrookes changed the title Propagate OpenShift TLS security profile to Authorino [WIP] Propagate OpenShift TLS security profile to Authorino Jul 8, 2026
@maksymvavilov maksymvavilov moved this to In Review in Kuadrant Jul 9, 2026
@philbrookes philbrookes force-pushed the ocp5-tls-compliance branch from b6ff143 to ecdcd4f Compare July 9, 2026 12:37

@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

🧹 Nitpick comments (5)
hack/test-tls-profile.sh (4)

180-204: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Use mktemp instead of hardcoded /tmp paths for TLS key and certificate.

Hardcoded /tmp/tls.key and /tmp/tls.crt are vulnerable to symlink/TOCTOU attacks and can collide with concurrent runs. mktemp is trivially safer and avoids stale-file issues.

🛡️ Suggested fix
 setup_tls() {
   log "Setting up TLS for deployment args verification"
-  openssl req -x509 -newkey rsa:2048 -keyout /tmp/tls.key -out /tmp/tls.crt \
+  local tls_key tls_crt
+  tls_key="$(mktemp)"
+  tls_crt="$(mktemp)"
+  openssl req -x509 -newkey rsa:2048 -keyout "$tls_key" -out "$tls_crt" \
     -days 1 -nodes -subj '/CN=authorino' 2>/dev/null
   kubectl create secret tls "$TLS_SECRET_NAME" -n "$AUTHORINO_NS" \
-    --cert=/tmp/tls.crt --key=/tmp/tls.key 2>/dev/null || true
+    --cert="$tls_crt" --key="$tls_key" 2>/dev/null || true

And in teardown_tls:

 teardown_tls() {
   log "Tearing down TLS"
   kubectl patch "$AUTHORINO_GVR" "$AUTHORINO_NAME" -n "$AUTHORINO_NS" \
     --type=merge -p '{"spec":{
       "listener":{"tls":{"enabled":false,"certSecretRef":null}},
       "oidcServer":{"tls":{"enabled":false,"certSecretRef":null}}
     }}' 2>/dev/null || true
   kubectl delete secret "$TLS_SECRET_NAME" -n "$AUTHORINO_NS" 2>/dev/null || true
-  rm -f /tmp/tls.key /tmp/tls.crt
 }

Note: with mktemp, cleanup should ideally use a trap or store the paths in variables accessible to teardown_tls. Alternatively, use mktemp -d to create a temporary directory and remove it on exit.

🤖 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 `@hack/test-tls-profile.sh` around lines 180 - 204, Use mktemp for the TLS key
and certificate in setup_tls instead of hardcoded /tmp/tls.key and /tmp/tls.crt,
and store the generated paths in variables that teardown_tls can access for
cleanup. Update the openssl req and kubectl create secret tls calls to use those
variables, and ensure teardown_tls removes the same temporary files or a
temporary directory created with mktemp -d.

121-137: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Guard against missing python3.

The script silently depends on python3 for JSON arg parsing but never checks for its availability. On minimal environments (e.g., some CI images), this will produce a confusing error.

🛡️ Suggested pre-flight check
 if ! wait_for_authorino 5; then
   echo "Authorino CR not found in $AUTHORINO_NS. Run 'make local-setup' first."
   exit 1
 fi

+if ! command -v python3 &>/dev/null; then
+  echo "python3 is required but not found in PATH."
+  exit 1
+fi
+
🤖 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 `@hack/test-tls-profile.sh` around lines 121 - 137, The
get_deployment_arg_value helper currently assumes python3 is installed, which
can fail on minimal CI or local environments. Add a pre-flight dependency check
near the top of the script or before get_deployment_arg_value is used, and make
it fail fast with a clear message if python3 is unavailable. Keep the change
scoped to the TLS profile test script and the functions
get_deployment_args/get_deployment_arg_value so the dependency is validated
before JSON parsing starts.

17-21: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Rename the fail function to avoid shadowing the fail counter variable.

While bash resolves fail as a command (function) vs $fail (variable) in separate namespaces, the identical name is confusing and fragile — a future contributor might easily break the arithmetic or introduce a recursive call.

♻️ Suggested rename
 pass=0
-fail=0
+fail_count=0

 log()  { echo -e "${YELLOW}--- $1${NC}"; }
 ok()   { echo -e "${GREEN}PASS: $1${NC}"; pass=$((pass + 1)); }
-fail() { echo -e "${RED}FAIL: $1${NC}"; fail=$((fail + 1)); }
+fail_test() { echo -e "${RED}FAIL: $1${NC}"; fail_count=$((fail_count + 1)); }

Note: all call sites and the final exit "$fail" on line 450 would need updating accordingly.

🤖 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 `@hack/test-tls-profile.sh` around lines 17 - 21, The `fail` helper function in
`test-tls-profile.sh` is named the same as the `fail` counter variable, which is
confusing and fragile. Rename the function to a distinct name (for example, a
failure-reporting helper) and update every call site in the script, including
the final `exit "$fail"`-related references if they rely on the old name, so the
counter and helper are clearly separated.

4-4: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

The hardcoded openshift/api version in the GOMODCACHE path is fragile.

If go.mod is updated to a different github.com/openshift/api version, this path silently points to a non-existent file and the script fails at runtime with a confusing error. Consider deriving the version from go.mod or at minimum adding a guard:

🛡️ Suggested guard
 APISERVER_CRD="$(go env GOMODCACHE)/github.com/openshift/api@v0.0.0-20240926211938-f89ab92f1597/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_apiservers.crd.yaml"
+if [[ ! -f "$APISERVER_CRD" ]]; then
+  echo "APIServer CRD manifest not found at: $APISERVER_CRD" >&2
+  echo "Verify that github.com/openshift/api is in go.mod and downloaded to GOMODCACHE." >&2
+  exit 1
+fi
cmd/extensions/oidc-policy/internal/controller/oidcpolicy_reconciler_test.go (1)

483-564: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

notExpectedInRule field is declared but never populated.

The test struct includes notExpectedInRule []string and the test loop iterates over it (lines 555-559), but none of the three test cases populate it. Consider adding negative assertions — e.g., in case 2 verify that baseURL does not appear in location 2 — or remove the field if not needed.

🤖 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 `@cmd/extensions/oidc-policy/internal/controller/oidcpolicy_reconciler_test.go`
around lines 483 - 564, The test table in
TestBuildOpaAuthorizationRule_UsesCorrectBaseURL declares notExpectedInRule but
never uses it, so either add real negative assertions for
buildOpaAuthorizationRule (for example, verify the custom baseURL is not used
where igwURL should be) or remove the unused field and loop entirely. Keep the
fix localized to the test cases and the assertion block so the struct shape
matches the actual checks being performed.
🤖 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
`@cmd/extensions/oidc-policy/internal/controller/oidcpolicy_reconciler_test.go`:
- Around line 226-343: `TestBuildTargetCookieExpression_Examples` is asserting
the wrong CEL substring for the query-string branch. Update the expected pattern
in that test to match the actual output from `buildTargetCookieExpression`,
including the `has(request.query) && request.query != ""` guard used elsewhere
in the same test file. Keep the check aligned with the expression built for
`request.url_path` so the subtests compare against the exact generated form.

---

Nitpick comments:
In
`@cmd/extensions/oidc-policy/internal/controller/oidcpolicy_reconciler_test.go`:
- Around line 483-564: The test table in
TestBuildOpaAuthorizationRule_UsesCorrectBaseURL declares notExpectedInRule but
never uses it, so either add real negative assertions for
buildOpaAuthorizationRule (for example, verify the custom baseURL is not used
where igwURL should be) or remove the unused field and loop entirely. Keep the
fix localized to the test cases and the assertion block so the struct shape
matches the actual checks being performed.

In `@hack/test-tls-profile.sh`:
- Around line 180-204: Use mktemp for the TLS key and certificate in setup_tls
instead of hardcoded /tmp/tls.key and /tmp/tls.crt, and store the generated
paths in variables that teardown_tls can access for cleanup. Update the openssl
req and kubectl create secret tls calls to use those variables, and ensure
teardown_tls removes the same temporary files or a temporary directory created
with mktemp -d.
- Around line 121-137: The get_deployment_arg_value helper currently assumes
python3 is installed, which can fail on minimal CI or local environments. Add a
pre-flight dependency check near the top of the script or before
get_deployment_arg_value is used, and make it fail fast with a clear message if
python3 is unavailable. Keep the change scoped to the TLS profile test script
and the functions get_deployment_args/get_deployment_arg_value so the dependency
is validated before JSON parsing starts.
- Around line 17-21: The `fail` helper function in `test-tls-profile.sh` is
named the same as the `fail` counter variable, which is confusing and fragile.
Rename the function to a distinct name (for example, a failure-reporting helper)
and update every call site in the script, including the final `exit
"$fail"`-related references if they rely on the old name, so the counter and
helper are clearly separated.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f6d140ce-5af6-4d95-b634-e87351d4094e

📥 Commits

Reviewing files that changed from the base of the PR and between e7b63a5 and ecdcd4f.

⛔ Files ignored due to path filters (8)
  • go.sum is excluded by !**/*.sum
  • pkg/extension/grpc/v1/common.pb.go is excluded by !**/*.pb.go
  • pkg/extension/grpc/v1/descriptor_service.pb.go is excluded by !**/*.pb.go
  • pkg/extension/grpc/v1/descriptor_service_grpc.pb.go is excluded by !**/*.pb.go
  • pkg/extension/grpc/v1/gateway_api.pb.go is excluded by !**/*.pb.go
  • pkg/extension/grpc/v1/kuadrant.pb.go is excluded by !**/*.pb.go
  • pkg/extension/grpc/v1/kuadrant_grpc.pb.go is excluded by !**/*.pb.go
  • pkg/extension/grpc/v1/policy.pb.go is excluded by !**/*.pb.go
📒 Files selected for processing (15)
  • Dockerfile
  • cmd/extensions/oidc-policy/api/v1alpha1/oidcpolicy_types.go
  • cmd/extensions/oidc-policy/api/v1alpha1/oidcpolicy_types_test.go
  • cmd/extensions/oidc-policy/internal/controller/oidcpolicy_reconciler.go
  • cmd/extensions/oidc-policy/internal/controller/oidcpolicy_reconciler_test.go
  • config/rbac/role.yaml
  • go.mod
  • hack/test-tls-profile.sh
  • internal/controller/authorino_reconciler.go
  • internal/controller/fake/manager.go
  • internal/controller/state_of_the_world.go
  • internal/extension/reconciler.go
  • internal/openshift/tls_profile.go
  • internal/openshift/tls_profile_test.go
  • pkg/extension/grpc/v1/gateway_api.proto
🚧 Files skipped from review as they are similar to previous changes (8)
  • config/rbac/role.yaml
  • Dockerfile
  • internal/openshift/tls_profile_test.go
  • internal/controller/fake/manager.go
  • internal/openshift/tls_profile.go
  • internal/controller/state_of_the_world.go
  • go.mod
  • internal/controller/authorino_reconciler.go

@philbrookes philbrookes force-pushed the ocp5-tls-compliance branch 2 times, most recently from 248f3d4 to e7949a7 Compare July 13, 2026 12:28

@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

🧹 Nitpick comments (2)
hack/test-tls-profile.sh (1)

4-4: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Hardcoded openshift/api pseudo-version may drift from go.mod.

APISERVER_CRD pins an exact pseudo-version of github.com/openshift/api independently of go.mod. If that dependency is bumped elsewhere in this PR/stack, this path will stop resolving and kubectl apply -f "$APISERVER_CRD" (line 256) will fail, aborting the whole script under set -e.

♻️ Suggested approach
-APISERVER_CRD="$(go env GOMODCACHE)/github.com/openshift/api@v0.0.0-20240926211938-f89ab92f1597/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_apiservers.crd.yaml"
+APISERVER_API_DIR="$(go list -m -f '{{.Dir}}' github.com/openshift/api)"
+APISERVER_CRD="${APISERVER_API_DIR}/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_apiservers.crd.yaml"

Please confirm whether the openshift/api version pinned in go.mod matches v0.0.0-20240926211938-f89ab92f1597, as this script will silently break otherwise.

🤖 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 `@hack/test-tls-profile.sh` at line 4, Update APISERVER_CRD in
hack/test-tls-profile.sh to derive the openshift/api module version from go.mod
or the Go module tooling instead of hardcoding
v0.0.0-20240926211938-f89ab92f1597, while preserving the existing generated CRD
path used by kubectl apply.
Dockerfile (1)

6-6: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider pinning the builder image to an exact patch/digest.

golang:1.26 is a floating tag that will silently pick up newer patch releases (e.g. currently resolves to 1.26.5) over time, which can produce non-reproducible builds across CI runs. Consider pinning to the exact patch used in go.mod (golang:1.26.4) or, better, a digest, consistent with the ratchet: pinning already used elsewhere in the repo's GitHub Actions workflows.

🤖 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 `@Dockerfile` at line 6, Pin the builder image in the Dockerfile’s FROM
declaration to the exact Go patch version required by go.mod, golang:1.26.4, or
preferably to its immutable digest; retain the existing BUILDPLATFORM and
builder stage.
🤖 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 `@hack/test-tls-profile.sh`:
- Line 242: Guard both wait_for_authorino 30 calls in the Scenario 1 and
Scenario 2 flows so a timeout does not terminate the script under set -e.
Preserve the subsequent assert/ok/fail handling by allowing each wait failure to
continue execution.

---

Nitpick comments:
In `@Dockerfile`:
- Line 6: Pin the builder image in the Dockerfile’s FROM declaration to the
exact Go patch version required by go.mod, golang:1.26.4, or preferably to its
immutable digest; retain the existing BUILDPLATFORM and builder stage.

In `@hack/test-tls-profile.sh`:
- Line 4: Update APISERVER_CRD in hack/test-tls-profile.sh to derive the
openshift/api module version from go.mod or the Go module tooling instead of
hardcoding v0.0.0-20240926211938-f89ab92f1597, while preserving the existing
generated CRD path used by kubectl apply.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 12c12f68-dfd0-47a7-8736-a43255a6291a

📥 Commits

Reviewing files that changed from the base of the PR and between ecdcd4f and 248f3d4.

⛔ Files ignored due to path filters (8)
  • go.sum is excluded by !**/*.sum
  • pkg/extension/grpc/v1/common.pb.go is excluded by !**/*.pb.go
  • pkg/extension/grpc/v1/descriptor_service.pb.go is excluded by !**/*.pb.go
  • pkg/extension/grpc/v1/descriptor_service_grpc.pb.go is excluded by !**/*.pb.go
  • pkg/extension/grpc/v1/gateway_api.pb.go is excluded by !**/*.pb.go
  • pkg/extension/grpc/v1/kuadrant.pb.go is excluded by !**/*.pb.go
  • pkg/extension/grpc/v1/kuadrant_grpc.pb.go is excluded by !**/*.pb.go
  • pkg/extension/grpc/v1/policy.pb.go is excluded by !**/*.pb.go
📒 Files selected for processing (17)
  • Dockerfile
  • bundle.Dockerfile
  • bundle/manifests/kuadrant-operator.clusterserviceversion.yaml
  • cmd/extensions/oidc-policy/api/v1alpha1/oidcpolicy_types.go
  • cmd/extensions/oidc-policy/api/v1alpha1/oidcpolicy_types_test.go
  • cmd/extensions/oidc-policy/internal/controller/oidcpolicy_reconciler.go
  • cmd/extensions/oidc-policy/internal/controller/oidcpolicy_reconciler_test.go
  • config/rbac/role.yaml
  • go.mod
  • hack/test-tls-profile.sh
  • internal/controller/authorino_reconciler.go
  • internal/controller/fake/manager.go
  • internal/controller/state_of_the_world.go
  • internal/extension/reconciler.go
  • internal/openshift/tls_profile.go
  • internal/openshift/tls_profile_test.go
  • pkg/extension/grpc/v1/gateway_api.proto
💤 Files with no reviewable changes (1)
  • bundle.Dockerfile
🚧 Files skipped from review as they are similar to previous changes (11)
  • cmd/extensions/oidc-policy/api/v1alpha1/oidcpolicy_types.go
  • pkg/extension/grpc/v1/gateway_api.proto
  • internal/openshift/tls_profile_test.go
  • cmd/extensions/oidc-policy/api/v1alpha1/oidcpolicy_types_test.go
  • config/rbac/role.yaml
  • internal/controller/fake/manager.go
  • internal/controller/state_of_the_world.go
  • cmd/extensions/oidc-policy/internal/controller/oidcpolicy_reconciler.go
  • internal/openshift/tls_profile.go
  • internal/controller/authorino_reconciler.go
  • cmd/extensions/oidc-policy/internal/controller/oidcpolicy_reconciler_test.go

Comment thread hack/test-tls-profile.sh Outdated
@philbrookes philbrookes force-pushed the ocp5-tls-compliance branch 2 times, most recently from 682b3ea to bab4a9c Compare July 13, 2026 13:59
@philbrookes philbrookes changed the title [WIP] Propagate OpenShift TLS security profile to Authorino Propagate OpenShift TLS security profile to Authorino Jul 13, 2026
@philbrookes philbrookes force-pushed the ocp5-tls-compliance branch from bab4a9c to e5eadb8 Compare July 13, 2026 15:13

@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
`@cmd/extensions/oidc-policy/internal/controller/oidcpolicy_reconciler_test.go`:
- Line 336: Update the comment describing the CEL expression in the OIDC policy
reconciler test to include the request.query != "" guard, matching the corrected
assertion and production behavior. Change only the stale comment near the
relevant assertion.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 54f86acd-ce1c-4ea5-a249-d7224a7a5011

📥 Commits

Reviewing files that changed from the base of the PR and between 248f3d4 and e5eadb8.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (10)
  • bundle/manifests/kuadrant-operator.clusterserviceversion.yaml
  • charts/kuadrant-operator/templates/manifests.yaml
  • cmd/extensions/oidc-policy/internal/controller/oidcpolicy_reconciler_test.go
  • config/rbac/role.yaml
  • go.mod
  • internal/controller/authorino_reconciler.go
  • internal/controller/fake/manager.go
  • internal/controller/state_of_the_world.go
  • internal/openshift/tls_profile.go
  • internal/openshift/tls_profile_test.go
🚧 Files skipped from review as they are similar to previous changes (8)
  • bundle/manifests/kuadrant-operator.clusterserviceversion.yaml
  • config/rbac/role.yaml
  • internal/openshift/tls_profile_test.go
  • internal/openshift/tls_profile.go
  • internal/controller/authorino_reconciler.go
  • go.mod
  • internal/controller/fake/manager.go
  • internal/controller/state_of_the_world.go

Comment thread cmd/extensions/oidc-policy/internal/controller/oidcpolicy_reconciler_test.go Outdated
@philbrookes philbrookes force-pushed the ocp5-tls-compliance branch from e5eadb8 to 0271cb4 Compare July 14, 2026 06:27
Comment thread internal/controller/state_of_the_world.go Outdated
Read the cluster's APIServer CR (apiserver.config.openshift.io/cluster)
and propagate its TLS security profile to the Authorino CR on both the
Listener and OIDCServer TLS configurations. On non-OpenShift clusters,
falls back to Intermediate profile defaults.

- Navigate the topology graph from Kuadrant CR to find the APIServer CR
  instead of filtering all objects; CR name defaults to "cluster" and
  can be overridden via APISERVER_CR_NAME env var
- Map OpenShift VersionTLS12 format to 1.2 short form to match the
  updated Authorino CLI flag format
- Add integration test script (hack/test-tls-profile.sh) covering 9
  scenarios with both Authorino CR spec and deployment args verification

Signed-off-by: Phil Brookes <pbrookes@redhat.com>

rh-pre-commit.version: 2.3.2
rh-pre-commit.check-secrets: ENABLED
@philbrookes philbrookes force-pushed the ocp5-tls-compliance branch from 0271cb4 to 6d477c3 Compare July 15, 2026 09:34
// The CEL expression uses a ternary: request.url_path + (has(request.query) && request.query != "" ? "?" + request.query : "")
// This should construct the full path with query when query is present
if !strings.Contains(expression, `request.url_path + (has(request.query) ? "?" + request.query : "")`) {
if !strings.Contains(expression, `request.url_path + (has(request.query) && request.query != "" ? "?" + request.query : "")`) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This is a "pre-existing" part, but does this test check for nothing? And the comment seems useless.

apiServer, ok := rObj.Object.(*configv1.APIServer)
if !ok {
continue
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why do we have two casts/checks?

Comment on lines +99 to +109
if profile == nil || profile.Type == "" {
spec = configv1.TLSProfiles[configv1.TLSProfileIntermediateType]
} else if profile.Type == configv1.TLSProfileCustomType && profile.Custom != nil {
spec = &profile.Custom.TLSProfileSpec
} else {
spec = configv1.TLSProfiles[profile.Type]
}

if spec == nil {
spec = configv1.TLSProfiles[configv1.TLSProfileIntermediateType]
}

@maksymvavilov maksymvavilov Jul 15, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This defines what the default profile is in two places: the first if block and this nil check. It should work the same if we remove the first if and would leave us with the single "default" source of truth 🤔

Comment on lines +78 to +101
t.Run("Custom profile with unsupported DHE cipher skips it", func(t *testing.T) {
profile := &configv1.TLSSecurityProfile{
Type: configv1.TLSProfileCustomType,
Custom: &configv1.CustomTLSProfile{
TLSProfileSpec: configv1.TLSProfileSpec{
Ciphers: []string{"DHE-RSA-AES128-GCM-SHA256", "ECDHE-RSA-AES128-GCM-SHA256"},
MinTLSVersion: configv1.VersionTLS12,
},
},
}
_, ciphers := ResolveTLSProfile(profile)
if len(ciphers) != 1 {
t.Fatalf("expected 1 cipher (DHE skipped), got %d: %v", len(ciphers), ciphers)
}
})

t.Run("Intermediate profile excludes DHE ciphers", func(t *testing.T) {
_, ciphers := ResolveTLSProfile(nil)
for _, c := range ciphers {
if c == "DHE-RSA-AES128-GCM-SHA256" || c == "DHE-RSA-AES256-GCM-SHA384" {
t.Errorf("DHE cipher should not appear in translated output: %s", c)
}
}
})

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

If someone were to add DHE ciphers to the opensslToIANA map this will not catch it. We should be looking for "TLS_DHE_*" or matching the count to what we expect

}

func apiServerCRName() string {
if name := os.Getenv("APISERVER_CR_NAME"); name != "" {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

How will people know that this envar exists?
If there is any documentation that we expect to produce, we would benefit from including this envar in there.

}
}

return minVersion, cipherSuites

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

There is a mention of a test script in the description and a few test scenarios. Are those manual testing steps?
We could have an integration test case that would register a new CRD/CR and verify this logic. Should we have it?

return name
}
return openshift.DefaultAPIServerCRName
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Wondering if this func belongs in the openshift package too 🤔

}

func LinkKuadrantToAPIServer(objs controller.Store) machinery.LinkFunc {
kuadrants := lo.Map(objs.FilterByGroupKind(kuadrantv1beta1.KuadrantGroupKind), controller.ObjectAs[machinery.Object])

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Since the cluster APIServer CR is a cluster-scoped singleton, I wonder if the link function couldn't be filtering it by name already. I.e., linking this one and only, well-known CR to the Kuadrant CR. Then, later, the reconcilers could always navigate to the first child of the Kuadrant CR of this type, with no need to filter by name again. WDYT?

}

func (b *BootOptionsBuilder) getOpenShiftServerConfigOptions() ([]controller.ControllerOption, error) {
opts := make([]controller.ControllerOption, 0, 2)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Line 504 appends 3 elements to the slice, but the capacity is preset to 2. Won't this require a realloc?

return openshift.DefaultAPIServerCRName
}

func (r *AuthorinoReconciler) resolveTLSProfileFromTopology(topology *machinery.Topology, kobj *v1beta1.Kuadrant) (string, []string) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Maybe add a unit test for this func?

for _, ex := range examples {
t.Run(ex.scenario, func(t *testing.T) {
// The CEL expression uses a ternary: request.url_path + (has(request.query) ? "?" + request.query : "")
// The CEL expression uses a ternary: request.url_path + (has(request.query) && request.query != "" ? "?" + request.query : "")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Brought from an unrelated and uncommitted local change perhaps, or was it @CodeRabbit complaining about it?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
gh pr view 2091 --repo Kuadrant/kuadrant-operator --json comments,reviews -q '.reviews[] | select(.body != "") | .body' 2>/dev/null | head -100
echo "---review comments---"
gh api repos/Kuadrant/kuadrant-operator/pulls/2091/comments --paginate -q '.[] | {user: .user.login, body: .body, path: .path, line: .line}' 2>/dev/null

Length of output: 23282


Confirmed it — I flagged this comment.

@guicassolato it was CodeRabbit: I posted the review comment on Line 336 (cr-comment:v1:4f7a4605c9a13a684743c91c) pointing out the stale comment still described the old ternary has(request.query) ? "?" + request.query : "" while the assertion on Line 338 and the actual production code already had the && request.query != "" guard. That comment was subsequently addressed in commit 0271cb4, which is the diff you're looking at now — so this fix is directly tied to my review, not an unrelated local change.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It's unrelated to the main issue addressed by this PR though. For the sake of cohesion, I personally think it would be better addressed in a separate PR.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@guicassolato, fair point — noted. Since the fix is already included in this PR's diff and is a trivial one-line comment/documentation correction (no functional impact), I'll leave it as is unless you'd like it reverted and reopened separately. Either way works from my end.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Really up to @philbrookes to decide.

Comment on lines +103 to +105
CertSecret: clusterAuthorino.Spec.Listener.Tls.CertSecret,
MinVersion: tlsMinVersion,
CipherSuites: tlsCipherSuites,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should we avoid setting these options when tls.enabled is false? Thinking about reducing the noise in the CR spec (and command-line args). WDYT?

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

Labels

None yet

Projects

Status: In Review

Development

Successfully merging this pull request may close these issues.

3 participants