Skip to content

mount trusted CA bundle in runner pods#1258

Open
ktdreyer wants to merge 1 commit intomainfrom
feat/trusted-ca-bundle-runner-pods
Open

mount trusted CA bundle in runner pods#1258
ktdreyer wants to merge 1 commit intomainfrom
feat/trusted-ca-bundle-runner-pods

Conversation

@ktdreyer
Copy link
Copy Markdown
Contributor

@ktdreyer ktdreyer commented Apr 8, 2026

Summary

  • Runner pods now conditionally mount a trusted-ca-bundle ConfigMap at /etc/pki/tls/certs/ca-bundle.crt (the UBI9 system CA path), enabling TLS validation against private/corporate CAs
  • On OpenShift clusters with CA injection enabled, this ConfigMap is auto-populated in the session namespace; on other clusters it can be provisioned manually
  • Clusters without the ConfigMap are unaffected — the mount is conditional

Fixes #1247

Test plan

  • TestApplyTrustedCABundle_ConfigMapPresent — volume + mount added when ConfigMap exists
  • TestApplyTrustedCABundle_ConfigMapAbsent — pod unchanged when ConfigMap is missing
  • TestApplyTrustedCABundle_ExistingMountsPreserved — existing mounts not clobbered
  • TestApplyTrustedCABundle_APIError — pod unchanged on transient API errors
  • Manual: create trusted-ca-bundle ConfigMap in session namespace, start session, verify /etc/pki/tls/certs/ca-bundle.crt in runner pod contains the custom CA

Summary by CodeRabbit

  • New Features

    • Session pods will automatically mount a trusted CA bundle when a ConfigMap named "trusted-ca-bundle" is present; the certificate is mounted read-only into the session container. If the ConfigMap is missing or unreadable, pods are created unchanged and a warning is logged.
  • Tests

    • Added unit tests covering presence, absence, missing key, existing mounts, and API error scenarios for the trusted CA bundle behavior.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 8, 2026

📝 Walkthrough

Walkthrough

A new helper function conditionally mounts a trusted CA bundle ConfigMap into dynamically-created runner pods. The operator checks the session namespace for trusted-ca-bundle; if the ConfigMap contains ca-bundle.crt, it appends a ConfigMap volume and mounts it into the ambient-code-runner container at /etc/pki/tls/certs/ca-bundle.crt. Missing ConfigMap or missing key is non-fatal.

Changes

Cohort / File(s) Summary
Trusted CA Bundle Implementation
components/operator/internal/handlers/sessions.go, components/operator/internal/types/resources.go
Added applyTrustedCABundle(k8sClient kubernetes.Interface, namespace string, pod *corev1.Pod) and TrustedCABundleConfigMapName constant; integrated helper into session pod creation to conditionally add a trusted-ca-bundle ConfigMap volume and readonly mount at /etc/pki/tls/certs/ca-bundle.crt. Non-NotFound errors and missing key are logged and ignored.
Trusted CA Bundle Tests
components/operator/internal/handlers/sessions_test.go
Added unit tests (ConfigMap present with key, ConfigMap absent, existing VolumeMounts preserved, ConfigMap present but missing key, and ConfigMap GET error) using fake client reactors to validate behavior and non-fatal error handling.

Sequence Diagram(s)

sequenceDiagram
    participant Operator as Operator (session handler)
    participant K8s as Kubernetes API
    participant Pod as PodSpec (in-memory)

    Operator->>K8s: GET ConfigMap `trusted-ca-bundle` in session namespace
    alt ConfigMap Found and has ca-bundle.crt
        K8s-->>Operator: ConfigMap with ca-bundle.crt
        Operator->>Pod: append ConfigMap Volume `trusted-ca-bundle`
        Operator->>Pod: add VolumeMount to container `ambient-code-runner` at /etc/pki/tls/certs/ca-bundle.crt (subPath: ca-bundle.crt, readOnly)
    else NotFound
        K8s-->>Operator: 404 NotFound
        Operator-->>Pod: no changes
    else Other error or missing key
        K8s-->>Operator: error or missing key
        Operator-->>Pod: log warning, no changes
    end
    Operator->>K8s: create Pod from modified PodSpec
    K8s-->>Operator: Pod created / acknowledged
Loading
🚥 Pre-merge checks | ✅ 7 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Title check ⚠️ Warning Title does not follow Conventional Commits format (missing 'type(scope):' prefix required by project standards). Use Conventional Commits format. Suggested: 'feat(operator): mount trusted CA bundle in runner pods' or 'feat(sessions): mount trusted CA bundle in runner pods'.
✅ Passed checks (7 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Code changes fully satisfy issue #1247 requirements: ConfigMap check implemented, conditional mount at /etc/pki/tls/certs/ca-bundle.crt added, existing behavior preserved, tests cover all scenarios.
Out of Scope Changes check ✅ Passed All changes are scoped to trusted CA bundle mounting: new helper function, wiring into session runner creation, constant definition, and comprehensive test coverage. No unrelated modifications detected.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Performance And Algorithmic Complexity ✅ Passed Single ConfigMap.Get() call per pod creation, bounded container iteration (O(1) in practice), no N+1 pattern, and safe implementation matching existing vertex-secret logic.
Security And Secret Handling ✅ Passed Trusted CA bundle implementation uses hardcoded ConfigMap/mount paths, proper k8s authentication via operator client, no sensitive data logging, and safe namespace derivation from k8s object metadata.
Kubernetes Resource Safety ✅ Passed ConfigMap mount implementation properly handles errors and doesn't create child resources without OwnerReferences; no RBAC or security context changes needed.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/trusted-ca-bundle-runner-pods
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch feat/trusted-ca-bundle-runner-pods

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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@components/operator/internal/handlers/sessions.go`:
- Around line 2172-2200: The code currently only checks that the ConfigMap
exists via k8sClient.CoreV1().ConfigMaps(...).Get and then unconditionally adds
a Volume and a VolumeMount with SubPath "ca-bundle.crt"; you must GET the
ConfigMap object and validate that its Data (or BinaryData) contains the
"ca-bundle.crt" key before appending the pod.Spec.Volumes and before adding the
SubPath mount to pod.Spec.Containers[i].VolumeMounts (match container name
"ambient-code-runner"); if the key is missing, log a warning referencing
types.TrustedCABundleConfigMapName and skip adding the volume/mount to avoid
kubelet SubPath mount failures.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: e18eebad-be36-4572-94ec-50e41f26f95b

📥 Commits

Reviewing files that changed from the base of the PR and between 02d3d96 and b5d1c07.

📒 Files selected for processing (3)
  • components/operator/internal/handlers/sessions.go
  • components/operator/internal/handlers/sessions_test.go
  • components/operator/internal/types/resources.go

On clusters with private or corporate CAs, runner pods fail TLS
validation because they only have the default UBI9 system CA store.
The "backend-api" Deployment already supports a trusted CA bundle,
but runner pods (created dynamically by the operator) never had
matching support.

"applyTrustedCABundle" checks for a "trusted-ca-bundle" ConfigMap in
the session namespace before each pod is created. On OpenShift, this
ConfigMap is auto-populated by CA injection; on other clusters,
operators can provision it manually. When present, the ConfigMap is
mounted at "/etc/pki/tls/certs/ca-bundle.crt" (the UBI9 system CA
path) so all TLS clients in the runner container trust the corporate
CA without any application-level changes. Clusters without the
ConfigMap are unaffected.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@ktdreyer ktdreyer force-pushed the feat/trusted-ca-bundle-runner-pods branch from b5d1c07 to 32550e2 Compare April 8, 2026 20:56
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 `@components/operator/internal/handlers/sessions.go`:
- Around line 2199-2213: The current patch only mounts the trusted CA bundle
into the ambient-code-runner container; update the code to also mount the same
VolumeMount into init containers and any other containers that need it
(specifically target init container named "init-hydrate" in
pod.Spec.InitContainers and the container named "state-sync" in
pod.Spec.Containers) so they receive the trusted CA before network operations;
reuse the same corev1.VolumeMount (Name "trusted-ca-bundle", MountPath
"/etc/pki/tls/certs/ca-bundle.crt", SubPath "ca-bundle.crt", ReadOnly true) and
log using types.TrustedCABundleConfigMapName, ensuring you iterate
pod.Spec.InitContainers to patch "init-hydrate" and pod.Spec.Containers to patch
both "state-sync" and "ambient-code-runner" (avoid duplicate mounts if already
present).
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ea8d4d77-4042-4f4d-89a2-931cf6ff48cd

📥 Commits

Reviewing files that changed from the base of the PR and between b5d1c07 and 32550e2.

📒 Files selected for processing (3)
  • components/operator/internal/handlers/sessions.go
  • components/operator/internal/handlers/sessions_test.go
  • components/operator/internal/types/resources.go
✅ Files skipped from review due to trivial changes (1)
  • components/operator/internal/types/resources.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • components/operator/internal/handlers/sessions_test.go

Comment on lines +2199 to +2213
for i := range pod.Spec.Containers {
if pod.Spec.Containers[i].Name == "ambient-code-runner" {
pod.Spec.Containers[i].VolumeMounts = append(
pod.Spec.Containers[i].VolumeMounts,
corev1.VolumeMount{
Name: "trusted-ca-bundle",
MountPath: "/etc/pki/tls/certs/ca-bundle.crt",
SubPath: "ca-bundle.crt",
ReadOnly: true,
},
)
log.Printf("Mounted %s ConfigMap to /etc/pki/tls/certs/ca-bundle.crt in runner container",
types.TrustedCABundleConfigMapName)
break
}
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot Apr 8, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Mount the bundle into init-hydrate and state-sync too.

This only patches ambient-code-runner. init-hydrate lives in pod.Spec.InitContainers and is configured with repo/S3 inputs (Lines 901-946), and state-sync is configured for S3 (Lines 1230-1248). On private-CA clusters, those containers can still fail TLS before the main runner starts, so private repo hydration/state sync is still broken unless they get the same trust bundle when present.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/operator/internal/handlers/sessions.go` around lines 2199 - 2213,
The current patch only mounts the trusted CA bundle into the ambient-code-runner
container; update the code to also mount the same VolumeMount into init
containers and any other containers that need it (specifically target init
container named "init-hydrate" in pod.Spec.InitContainers and the container
named "state-sync" in pod.Spec.Containers) so they receive the trusted CA before
network operations; reuse the same corev1.VolumeMount (Name "trusted-ca-bundle",
MountPath "/etc/pki/tls/certs/ca-bundle.crt", SubPath "ca-bundle.crt", ReadOnly
true) and log using types.TrustedCABundleConfigMapName, ensuring you iterate
pod.Spec.InitContainers to patch "init-hydrate" and pod.Spec.Containers to patch
both "state-sync" and "ambient-code-runner" (avoid duplicate mounts if already
present).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@coderabbitai how can those require the CA?

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.

@ktdreyer Good challenge — it depends on the deployment:

  • init-hydrate's backend API call (BACKEND_API_URL) uses plain http:// — no TLS at all, so definitely no CA needed there.
  • S3 (s3Endpoint) — if it's internal MinIO over HTTP (the typical default here), no CA needed. But if an operator configures an internal HTTPS S3 endpoint backed by a corporate CA, init-hydrate and state-sync would fail TLS.
  • Git clones in init-hydrate — if repos are hosted on an internal Gitlab/Gitea with a private CA cert, cloning over HTTPS would fail without the bundle.

So the containers can need it, but only when:

  1. The S3 endpoint is HTTPS + corporate CA, or
  2. Git repos are on a private-CA HTTPS host

If your target environments use plain-HTTP MinIO and public-CA git hosts, the runner container is the only one making connections (to Anthropic/Claude APIs, etc.) that realistically need the bundle. In that case you can safely ignore my comment. Your call on whether the edge cases (HTTPS S3, private git) are in scope for this PR.

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.

mount trusted CA bundle in runner pods for custom TLS

1 participant