Skip to content

Feat: Auto-generate the tls_bridge CA when generate_ca is set - #707

Merged
huang195 merged 1 commit into
rossoctl:mainfrom
huang195:feat/tls-bridge-generate-ca
Jul 28, 2026
Merged

Feat: Auto-generate the tls_bridge CA when generate_ca is set#707
huang195 merged 1 commit into
rossoctl:mainfrom
huang195:feat/tls-bridge-generate-ca

Conversation

@huang195

@huang195 huang195 commented Jul 28, 2026

Copy link
Copy Markdown
Member

Summary

Running authbridge-proxy standalone as a forward proxy with tls_bridge required minting a signing CA by hand (openssl) into ca_dirmain.go always loaded tls.crt/tls.key via NewFileSource and log.Fatalf'd when they were absent. That openssl step is the biggest friction point in the local demo.

Change

Add tls_bridge.generate_ca (default false). When true and the ca_dir CA set is incomplete, the bridge mints a self-signed CA (reusing the existing ephemeral-CA machinery), persists tls.crt/tls.key/ca.crt into ca_dir, and logs the exact NODE_EXTRA_CA_CERTS=<ca_dir>/ca.crt line to trust. The local demo drops the whole openssl block:

tls_bridge:
  mode: enabled
  ca_dir: /tmp/ab/ca
  generate_ca: true      # replaces the manual `openssl req ...`

then HTTPS_PROXY=http://localhost:8081 NODE_EXTRA_CA_CERTS=/tmp/ab/ca/ca.crt claude.

Safety — in-cluster behavior unchanged

generate_ca defaults to false, so the operator/cluster path is untouched:

  • generate_ca=false → always NewFileSource; a missing or invalid CA still Fatals (fail-loud on a missing cert-manager Secret).
  • generate_ca=true + a complete set present → loads it; a complete-but-invalid set is never overwritten (fails loud, so a real Secret is protected).

Robustness against partial writes

generate_ca=true self-heals an incomplete on-disk set — any of tls.crt/tls.key/ca.crt missing → regenerate all three. This closes two partial-write failure modes:

  • orphaned tls.key (killed/errored after the key write, before the cert) that would otherwise wedge every subsequent boot — NewFileSource fatals on the missing cert forever, reintroducing the manual rm this feature removes;
  • missing ca.crt trust anchor that loads fine yet leaves clients unable to verify the forged leaves (no WARN, opaque client-side TLS errors).

The three files are also written atomically (temp + rename), so a reader never sees a half-written cert/key.

Implementation

  • config: TLSBridgeConfig.GenerateCA (generate_ca); doc notes ca_dir must persist across restarts (ephemeral storage re-mints each boot → clients re-trust).
  • tlsbridge: factored genSelfSignedCA (now also emits the PKCS#8 key PEM); NewEphemeralSource delegates to it. NewGeneratedFileSource writes key 0600, cert + ca.crt 0644 via an atomic temp+rename helper. EnsureFileSource loads a complete set, or self-heals an incomplete one.
  • cmd/authbridge-proxy: call EnsureFileSource; WARN with the trust-cert hint when generated.

Discoverability is via the generate_ca doc comment and the startup WARN (which prints the exact NODE_EXTRA_CA_CERTS path) — no separate demo doc exists to update.

Testing Instructions

go test ./...                          # full authlib module — pass
go vet ./tlsbridge/... ./config/...    # clean
go build ./cmd/authbridge-proxy        # builds

Tests cover: generated CA reloads via NewFileSource and is a valid signing CA; key not group/other-readable; generate-when-absent; fail-loud when generate=false; load-without-overwrite when the set is complete; complete-but-invalid not overwritten; self-heal of incomplete sets (orphaned key, orphaned cert, missing ca.crt); missing parent dirs created.

Assisted-By: Claude (Anthropic AI) noreply@anthropic.com

@huang195
huang195 requested a review from a team as a code owner July 28, 2026 15:12
@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Changes

TLS bridge configuration now supports optional self-signed CA generation. CA creation is centralized, persisted with defined permissions, validated through new tests, and integrated into proxy startup with generation warnings and client trust guidance.

TLS bridge CA provisioning

Layer / File(s) Summary
Self-signed CA generation
authbridge/authlib/config/config.go, authbridge/authlib/tlsbridge/ca.go
Adds the GenerateCA setting and centralizes ECDSA-P256 self-signed CA creation for ephemeral and file-backed sources.
Generated file source and validation
authbridge/authlib/tlsbridge/ca.go, authbridge/authlib/tlsbridge/ca_test.go
Writes certificate, key, and trust-store files with defined permissions; ensures missing files are generated while existing or invalid material is not overwritten.
Proxy startup integration
authbridge/cmd/authbridge-proxy/main.go
Uses EnsureFileSource during TLS bridge initialization and logs generation warnings with a client trust hint.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Proxy
  participant EnsureFileSource
  participant FileSystem
  participant TLSBridge
  Proxy->>EnsureFileSource: initialize CA source
  EnsureFileSource->>FileSystem: check tls.crt and tls.key
  EnsureFileSource->>FileSystem: generate and persist CA when configured
  EnsureFileSource-->>Proxy: return CA source and generated status
  Proxy->>TLSBridge: construct bridge with CA source
Loading

Suggested reviewers: alan-cha

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: optional automatic CA generation when generate_ca is enabled.
✨ 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.

@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 `@authbridge/authlib/tlsbridge/ca.go`:
- Around line 158-181: Update EnsureFileSource so the generate=true load path
also checks ca.crt; when tls.crt and tls.key exist but the trust file is
missing, repair or regenerate ca.crt and surface any failure instead of
returning generated=false silently. Preserve NewFileSource behavior for complete
material and for present-but-invalid or partially present CA files, without
overwriting existing CA material.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 3b5e4f4f-b9e0-4af1-bbe0-d6b300db91e0

📥 Commits

Reviewing files that changed from the base of the PR and between 3568d69 and 5d3f6f4.

📒 Files selected for processing (4)
  • authbridge/authlib/config/config.go
  • authbridge/authlib/tlsbridge/ca.go
  • authbridge/authlib/tlsbridge/ca_test.go
  • authbridge/cmd/authbridge-proxy/main.go

Comment thread authbridge/authlib/tlsbridge/ca.go Outdated
@huang195
huang195 force-pushed the feat/tls-bridge-generate-ca branch from 5d3f6f4 to 4deea9b Compare July 28, 2026 15:30
@huang195 huang195 added this to the Release v0.8.0 milestone Jul 28, 2026

@mrsabath mrsabath left a comment

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.

Summary

Clean, security-conscious change. I verified the safety-critical claims against the code (not just the PR body):

  • Key perms — signing key persisted 0600, cert + ca.crt 0644 (NewGeneratedFileSource); the test asserts mode & 0o077 == 0.
  • Generation gateEnsureFileSource mints only when generate && !fileExists(tls.crt) && !fileExists(tls.key). Any presence (even partial) falls through to NewFileSource.
  • Never overwrites present-but-invalid — garbage/partial material returns the loud NewFileSource error and is left on disk untouched (tested).
  • In-cluster path untouchedgenerate_ca defaults to false (bool zero value), so a missing cert-manager Secret still log.Fatalfs. Fail-loud preserved.
  • Refactor is behavior-preservinggenSelfSignedCA keeps the exact cert template (NotBefore -1m, NotAfter +365d, IsCA, CertSign|DigitalSignature); NewEphemeralSource's output is unchanged, it just delegates now. slog was already imported.
  • Tests are assertive and cover the corners — write+reload-as-valid-CA, key perms, generate-when-absent, fail-loud-when-generate=false, load-without-overwrite, no-overwrite-when-present-but-invalid, and nested-parent-dir creation.

All Go CI (authlib, authbridge-proxy, authbridge-envoy), CodeQL(go), and Trivy are green.

一举两得 (yī jǔ liǎng dé, "one action, two gains"): it removes the manual openssl friction from the standalone demo and hardens the missing/invalid-cert path in the same stroke.

One non-blocking thought (no change needed): if a user ends up with exactly one of tls.crt/tls.key present, they correctly get a fail-loud load error rather than a regenerate — the safe choice — but the error may not obviously hint "remove the stray file to regenerate." Fine to leave to the startup logs.

Areas reviewed: Go (config / tlsbridge / cmd), Security, Tests, commit conventions
Commits: 1, signed-off (DCO passes)
CI status: green
Verdict: APPROVE

Running authbridge-proxy standalone as a forward proxy with tls_bridge
required minting a signing CA by hand (openssl) into ca_dir: main.go
always loaded tls.crt/tls.key via NewFileSource and fatally exited when
they were absent.

Add tls_bridge.generate_ca (default false). When true AND the ca_dir CA
set is incomplete, the bridge mints a self-signed CA (reusing the existing
ephemeral-CA machinery), persists tls.crt/tls.key/ca.crt into ca_dir, and
logs the exact NODE_EXTRA_CA_CERTS=<ca_dir>/ca.crt line for clients to
trust. The manual openssl step disappears from the local demo.

Default (generate_ca=false) is unchanged: a missing/invalid ca_dir CA
still fails loudly, preserving the in-cluster contract where the CA is a
mounted cert-manager Secret.

Robust against partial writes: the three files are written atomically
(temp + rename), and EnsureFileSource regenerates when generate=true and
the on-disk set is INCOMPLETE (any of tls.crt/tls.key/ca.crt missing).
This self-heals two partial-write failure modes — an orphaned tls.key that
would otherwise wedge every subsequent boot (NewFileSource fatal on the
missing cert), and a missing ca.crt trust anchor that loads fine yet
leaves clients unable to verify forged leaves. A COMPLETE-but-invalid set
is never overwritten (still fails loud, so a real Secret is protected).

Implementation:
- config: TLSBridgeConfig.GenerateCA (generate_ca); note that ca_dir must
  persist across restarts (ephemeral storage re-mints each boot).
- tlsbridge: extract genSelfSignedCA (adds PKCS#8 key PEM); NewEphemeralSource
  delegates to it. NewGeneratedFileSource writes key 0600, cert+ca.crt 0644
  via an atomic temp+rename helper. EnsureFileSource loads a complete set or
  self-heals an incomplete one.
- cmd/authbridge-proxy: call EnsureFileSource; warn with the trust-cert hint
  when generated.

Tests: generated CA reloads and is a valid signing CA; key not
group/other-readable; generate-when-absent; fail-loud when generate=false;
load-without-overwrite when complete; complete-but-invalid not overwritten;
self-heal of incomplete sets (orphaned key, orphaned cert, missing ca.crt);
missing parent dirs created.

Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: Hai Huang <huang195@gmail.com>
@huang195
huang195 force-pushed the feat/tls-bridge-generate-ca branch from 4deea9b to e6d4853 Compare July 28, 2026 18:02
@huang195 huang195 changed the title Feat: auto-generate the tls_bridge CA when generate_ca is set Feat: Auto-generate the tls_bridge CA when generate_ca is set Jul 28, 2026
@huang195
huang195 merged commit ad1bf3e into rossoctl:main Jul 28, 2026
20 checks passed
@huang195
huang195 deleted the feat/tls-bridge-generate-ca branch July 28, 2026 18:06
@github-project-automation github-project-automation Bot moved this from New/ToDo to Done in Rossoctl Issue Prioritization Jul 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants