Skip to content

Remove ModelMesh and Serverless from get_ca_bundle#1173

Merged
threcc merged 9 commits intoopendatahub-io:mainfrom
threcc:fix-get-ca-bundle
Mar 6, 2026
Merged

Remove ModelMesh and Serverless from get_ca_bundle#1173
threcc merged 9 commits intoopendatahub-io:mainfrom
threcc:fix-get-ca-bundle

Conversation

@threcc
Copy link
Copy Markdown
Contributor

@threcc threcc commented Mar 5, 2026

Pull Request

Summary

This PR simplifies certificates_utils.py by removing deployment-mode branching that is no longer needed since the test suite only targets RawDeployment mode.

Changes:

  • create_ca_bundle_file: Removed ca_type parameter and the knative/istio code path — the function now only handles the OpenShift router cert (router-certs-default).

  • get_ca_bundle: Removed deployment_mode parameter and all Serverless/ModelMesh branching. Returns empty string on managed clusters, creates the OpenShift router CA bundle on self-managed clusters.

  • Removed unused ISTIO_CA_BUNDLE_FILENAME, KServeDeploymentType, and is_self_managed_operator imports.

  • Updated all callers (tests/conftest.py, evalhub, guardrails, trustyai, llmd_utils.py) to use the simplified signatures.

How it has been tested

  • Locally
  • Jenkins

Summary by CodeRabbit

  • Refactor
    • Unified CA bundle retrieval into a single flow across cluster types; simplified behavior on managed clusters (logs/no bundle).
    • Command generation now uses the unified CA handling and falls back to insecure TLS when no bundle is available.
  • Tests
    • Updated fixtures and helpers to use the simplified CA bundle API.

@threcc threcc requested a review from a team as a code owner March 5, 2026 10:41
@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 5, 2026

The following are automatically added/executed:

  • PR size label.
  • Run pre-commit
  • Run tox
  • Add PR author as the PR assignee
  • Build image based on the PR

Available user actions:

  • To mark a PR as WIP, add /wip in a comment. To remove it from the PR comment /wip cancel to the PR.
  • To block merging of a PR, add /hold in a comment. To un-block merging of PR comment /hold cancel.
  • To mark a PR as approved, add /lgtm in a comment. To remove, add /lgtm cancel.
    lgtm label removed on each new commit push.
  • To mark PR as verified comment /verified to the PR, to un-verify comment /verified cancel to the PR.
    verified label removed on each new commit push.
  • To Cherry-pick a merged PR /cherry-pick <target_branch_name> to the PR. If <target_branch_name> is valid,
    and the current PR is merged, a cherry-picked PR would be created and linked to the current PR.
  • To build and push image to quay, add /build-push-pr-image in a comment. This would create an image with tag
    pr-<pr_number> to quay repository. This image tag, however would be deleted on PR merge or close action.
Supported labels

{'/build-push-pr-image', '/cherry-pick', '/lgtm', '/verified', '/hold', '/wip'}

mwaykole
mwaykole previously approved these changes Mar 5, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 5, 2026

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

CA bundle handling simplified: create_ca_bundle_file no longer accepts ca_type and always creates an OpenShift ingress CA bundle; get_ca_bundle now only takes client and returns empty on managed clusters. Removed is_self_managed_operator. Callers and tests updated to remove ca_type/deployment_mode args.

Changes

Cohort / File(s) Summary
Certificates util
utilities/certificates_utils.py
Removed ca_type branching and related constants; create_ca_bundle_file(client: DynamicClient) -> str always reads the OpenShift ingress secret and writes the fixed CA bundle filename; get_ca_bundle(client: DynamicClient) -> str simplified to managed vs non-managed and delegates to create_ca_bundle_file.
Infra util
utilities/infra.py
Removed is_self_managed_operator and its CatalogSource usage/import; deleted related cached check logic.
Runtime callers
utilities/inference_utils.py, utilities/llmd_utils.py
Updated calls to get_ca_bundle(client) (removed deployment_mode argument). Command-generation behavior unchanged aside from call signature.
Tests & fixtures
tests/conftest.py, tests/.../model_explainability/.../conftest.py, tests/.../model_explainability/.../trustyai_service/trustyai_service_utils.py
Fixtures and test helpers updated to call create_ca_bundle_file(client) without ca_type; preserved behavior and return usage. Minor argument removals across test files.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 70.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and concisely describes the main change: removing ModelMesh and Serverless deployment mode branching from the get_ca_bundle function.
Description check ✅ Passed PR description covers summary, changes, and testing, but is missing related issues/tickets and additional requirements sections from template.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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 and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

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

⚠️ Outside diff range comments (1)
utilities/llmd_utils.py (1)

586-592: ⚠️ Potential issue | 🔴 Critical

TLS verification is silently disabled even when secure mode is requested.

Lines 586-592 force ca_bundle = None, so insecure=False still results in --insecure. This defeats certificate validation and can hide regressions in LLMD auth/TLS flows.

🔒 Proposed fix (restore CA path and fail closed)
@@
-                # ca_bundle = get_ca_bundle(client=client)
-                ca_bundle = None
+                ca_bundle = get_ca_bundle(client=client)
                 if ca_bundle:
                     cmd += f" --cacert {ca_bundle}"
                 else:
-                    cmd += " --insecure"
-            except Exception:  # noqa: BLE001
-                cmd += " --insecure"
+                    raise InferenceResponseError(
+                        "CA bundle was not found while insecure=False; refusing insecure TLS downgrade."
+                    )
+            except Exception as e:  # noqa: BLE001
+                raise InferenceResponseError(
+                    "Failed to resolve CA bundle while insecure=False."
+                ) from e
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@utilities/llmd_utils.py` around lines 586 - 592, The code force-sets
ca_bundle = None which causes TLS verification to be disabled; restore the call
to get_ca_bundle(client=client) and use its result to decide whether to append "
--cacert {ca_bundle}" or fail closed instead of appending " --insecure". In the
block around ca_bundle, replace the hardcoded None with ca_bundle =
get_ca_bundle(client=client), and update the exception handler in the same scope
to surface/log the error and abort (or raise) when no CA bundle is available and
secure mode is requested so you never silently add "--insecure" to cmd.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@utilities/certificates_utils.py`:
- Around line 67-84: get_ca_bundle always returns the knative CA for any
self-managed cluster, which is wrong for RAW routes and causes callers to fall
back to insecure mode; update get_ca_bundle to accept a deployment_mode (or an
enum/string from utilities/inference_utils) and use that to select the correct
secret/type when calling create_ca_bundle_file instead of always passing
ca_type="knative". Locate get_ca_bundle, is_managed_cluster, and
create_ca_bundle_file and change the signature/use so callers (e.g., the caller
in utilities/inference_utils.py around the deployment_mode handling) pass
deployment_mode through to get_ca_bundle, and map deployment_mode to the
appropriate ca_type when invoking create_ca_bundle_file.

---

Outside diff comments:
In `@utilities/llmd_utils.py`:
- Around line 586-592: The code force-sets ca_bundle = None which causes TLS
verification to be disabled; restore the call to get_ca_bundle(client=client)
and use its result to decide whether to append " --cacert {ca_bundle}" or fail
closed instead of appending " --insecure". In the block around ca_bundle,
replace the hardcoded None with ca_bundle = get_ca_bundle(client=client), and
update the exception handler in the same scope to surface/log the error and
abort (or raise) when no CA bundle is available and secure mode is requested so
you never silently add "--insecure" to cmd.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: c7f0373e-2b33-4cd7-a887-8d4f6cf9170b

📥 Commits

Reviewing files that changed from the base of the PR and between 44389d6 and 4956328.

📒 Files selected for processing (3)
  • utilities/certificates_utils.py
  • utilities/inference_utils.py
  • utilities/llmd_utils.py

Comment thread utilities/certificates_utils.py Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

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)
utilities/llmd_utils.py (1)

585-590: ⚠️ Potential issue | 🔴 Critical

Restore CA bundle lookup; this change currently forces insecure TLS for all requests.

Because ca_bundle is hardcoded to None, Line 590 always appends --insecure in the non-insecure path, which disables cert verification by default. That’s a security regression from the prior behavior and from utilities/inference_utils.py.

🔧 Proposed fix
+from utilities.certificates_utils import get_ca_bundle
...
         else:
             try:
                 from ocp_resources.resource import get_client

                 client = get_client()
-                # ca_bundle = get_ca_bundle(client=client)
-                ca_bundle = None
+                ca_bundle = get_ca_bundle(client=client)
                 if ca_bundle:
                     cmd += f" --cacert {ca_bundle}"
                 else:
+                    LOGGER.warning("No CA bundle found, using insecure access")
                     cmd += " --insecure"
             except Exception:  # noqa: BLE001
                 cmd += " --insecure"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@utilities/llmd_utils.py` around lines 585 - 590, The code hardcodes ca_bundle
= None which forces appending "--insecure" to cmd; replace that line to call
get_ca_bundle(client=client) and use its return value (ca_bundle) so the
existing conditional will add "--cacert {ca_bundle}" when available and only add
"--insecure" when no bundle is found, matching the behavior in
utilities/inference_utils.py; ensure get_ca_bundle is in scope/imported and use
the same fallback semantics as the other module so TLS verification is not
disabled by default (references: ca_bundle, get_ca_bundle, cmd).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@utilities/llmd_utils.py`:
- Around line 585-590: The code hardcodes ca_bundle = None which forces
appending "--insecure" to cmd; replace that line to call
get_ca_bundle(client=client) and use its return value (ca_bundle) so the
existing conditional will add "--cacert {ca_bundle}" when available and only add
"--insecure" when no bundle is found, matching the behavior in
utilities/inference_utils.py; ensure get_ca_bundle is in scope/imported and use
the same fallback semantics as the other module so TLS verification is not
disabled by default (references: ca_bundle, get_ca_bundle, cmd).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 5e54ce8a-b753-48c8-aad4-40512a2ad0f2

📥 Commits

Reviewing files that changed from the base of the PR and between 4956328 and d0c30ec.

📒 Files selected for processing (1)
  • utilities/llmd_utils.py

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

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 the current code and only fix it if needed.

Inline comments:
In `@utilities/certificates_utils.py`:
- Around line 29-43: The code directly indexes
certs_secret.instance.data["tls.crt"] which can raise if the secret or key is
missing; update the logic around certs_secret (and the block that builds
bundle/filepath using OPENSHIFT_CA_BUNDLE_FILENAME and
py_config["tmp_base_dir"]) to first verify certs_secret.instance and
certs_secret.instance.data exist and that "tls.crt" is present, and if any of
these are missing return the documented empty string; additionally guard the
base64.b64decode/decode step in case of invalid data by catching exceptions and
returning an empty string to preserve fallback behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: e3ab4f54-7b37-41b8-a2fb-bc824caa9511

📥 Commits

Reviewing files that changed from the base of the PR and between d0c30ec and 4a3831b.

📒 Files selected for processing (6)
  • tests/conftest.py
  • tests/model_explainability/evalhub/conftest.py
  • tests/model_explainability/guardrails/conftest.py
  • tests/model_explainability/trustyai_service/trustyai_service_utils.py
  • utilities/certificates_utils.py
  • utilities/llmd_utils.py

Comment thread utilities/certificates_utils.py
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

♻️ Duplicate comments (1)
utilities/certificates_utils.py (1)

32-43: ⚠️ Potential issue | 🟠 Major

Guard missing/invalid router cert data so fallback behavior is preserved.

At Line 39, direct access to certs_secret.instance.data["tls.crt"] can raise (AttributeError/KeyError/decode errors) and bypass the empty-string contract described at Line 60, which downstream callers rely on.

Proposed fix
 def create_ca_bundle_file(client: DynamicClient) -> str:
@@
-    certs_secret = Secret(
+    certs_secret = Secret(
         client=client,
         name="router-certs-default",
         namespace="openshift-ingress",
+        ensure_exists=True,
     )
 
     filename = OPENSHIFT_CA_BUNDLE_FILENAME
-    bundle = base64.b64decode(certs_secret.instance.data["tls.crt"]).decode()
+    tls_crt_b64 = (getattr(certs_secret, "instance", None) and certs_secret.instance.data or {}).get("tls.crt")
+    if not tls_crt_b64:
+        LOGGER.warning("router-certs-default secret missing tls.crt; skipping CA bundle creation")
+        return ""
+    try:
+        bundle = base64.b64decode(tls_crt_b64).decode("utf-8")
+    except Exception as exc:  # noqa: BLE001
+        LOGGER.warning(f"Failed to decode router certificate: {exc}")
+        return ""
     filepath = os.path.join(py_config["tmp_base_dir"], filename)
 
-    with open(filepath, "w") as fd:
+    with open(filepath, "w", encoding="utf-8") as fd:
         fd.write(bundle)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@utilities/certificates_utils.py` around lines 32 - 43, Accessing
certs_secret.instance.data["tls.crt"] can raise AttributeError/KeyError or
decoding errors and must be guarded so downstream code relying on an
empty-string fallback still works; update the block around certs_secret,
OPENSHIFT_CA_BUNDLE_FILENAME, bundle and filepath to first check that
certs_secret.instance and certs_secret.instance.data exist and use
.get("tls.crt") safely, then wrap base64.b64decode(...) and .decode() in a
try/except that on any exception sets bundle = "" (or leaves it as an empty
string), and finally write that bundle (possibly empty) to the filepath so the
file is always created with a safe fallback.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@utilities/certificates_utils.py`:
- Around line 32-43: Accessing certs_secret.instance.data["tls.crt"] can raise
AttributeError/KeyError or decoding errors and must be guarded so downstream
code relying on an empty-string fallback still works; update the block around
certs_secret, OPENSHIFT_CA_BUNDLE_FILENAME, bundle and filepath to first check
that certs_secret.instance and certs_secret.instance.data exist and use
.get("tls.crt") safely, then wrap base64.b64decode(...) and .decode() in a
try/except that on any exception sets bundle = "" (or leaves it as an empty
string), and finally write that bundle (possibly empty) to the filepath so the
file is always created with a safe fallback.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 95e5abe0-7c05-4611-b9ec-2015dca1c50a

📥 Commits

Reviewing files that changed from the base of the PR and between 4a3831b and 2a8499a.

📒 Files selected for processing (7)
  • tests/conftest.py
  • tests/model_explainability/evalhub/conftest.py
  • tests/model_explainability/guardrails/conftest.py
  • tests/model_explainability/trustyai_service/trustyai_service_utils.py
  • utilities/certificates_utils.py
  • utilities/inference_utils.py
  • utilities/llmd_utils.py
🚧 Files skipped from review as they are similar to previous changes (4)
  • utilities/llmd_utils.py
  • utilities/inference_utils.py
  • tests/model_explainability/trustyai_service/trustyai_service_utils.py
  • tests/conftest.py

@coderabbitai

This comment was marked as spam.

Comment thread utilities/certificates_utils.py
@threcc threcc force-pushed the fix-get-ca-bundle branch from 4b06ee2 to 8152230 Compare March 5, 2026 16:27
Comment thread utilities/certificates_utils.py
Copy link
Copy Markdown
Contributor

@kpunwatk kpunwatk left a comment

Choose a reason for hiding this comment

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

/lgtm

@threcc threcc enabled auto-merge (squash) March 6, 2026 08:23
@threcc threcc merged commit c214dd7 into opendatahub-io:main Mar 6, 2026
8 checks passed
@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 6, 2026

Status of building tag latest: success.
Status of pushing tag latest to image registry: success.

@threcc threcc deleted the fix-get-ca-bundle branch March 11, 2026 15:59
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.

6 participants