feat(moq-native): add --tls-system-roots to trust custom and system roots together#1711
Conversation
…oots together The client TLS `root` field was an override: system roots loaded only when no `--tls-root` was given. That made it impossible to trust a local self-signed CA and the public CAs at once, so you couldn't dial both a local relay and a remote one from the same client. Make root loading additive. New `system_roots: Option<bool>` flag, defaulting to enabled only when no custom root is set (preserving today's behavior). Set it explicitly to trust the system roots alongside any custom root. The combination of no custom root and system roots disabled is rejected up front with `Error::NoRoots`, since WebPKI verification could never pass. Fingerprint pinning and disable_verify swap in their own verifier, so an empty store stays valid there. Typed as `Option<bool>` per the config-flag convention so the TOML->CLI merge can't clobber a TOML-set value; added a regression test in moq-relay. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
WalkthroughThis PR adds configurable 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches✨ Simplify code
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. Comment |
Summary
The client TLS
rootfield was an override: intls::Client::build(), system roots loaded only when--tls-rootwas empty. So passing a custom root replaced the system trust store entirely, and there was no way to trust a local self-signed CA and the public CAs at the same time. That breaks the common case of dialing both a local relay (private CA) and a remote one (public CA) from the same client.This makes client root loading additive and adds a flag to control whether the system roots come along.
What changed
New field
system_roots: Option<bool>ontls::Client(--tls-system-roots/MOQ_CLIENT_TLS_SYSTEM_ROOTS).build()is now additive: effective value issystem_roots.unwrap_or(root.is_empty()). System roots (when enabled) and every--tls-rootgo into the same store.--tls-root local.pem--tls-root local.pem --tls-system-roots--tls-system-roots=false, no root, no fingerprint/disable-verifyError::NoRoots, fails fastNew
Error::NoRootsvariant. The empty-store guard is scoped to when default WebPKI verification is actually in play;--tls-fingerprintand--tls-disable-verifyswap in their own verifier, so an empty store is fine there. The error message points at exactly those escape hatches.Typed as
Option<bool>per the config-flag convention so the TOML→CLI merge can't clobber a TOML-set value.Compatibility
Additive and non-breaking — every existing invocation behaves identically. Client-side
moq-native, so it targetsmain.Public API changes
moq_native::tls::Client: new fieldsystem_roots: Option<bool>(struct is#[non_exhaustive], so additive).moq_native::tls::Error: new variantNoRoots(enum is#[non_exhaustive], so additive).Neither is breaking.
Cross-package sync
doc/bin/relay/config.md: documentedtls.system_rootsin the[client]section.Test plan
tls::tests::build_rejects_no_roots— system roots disabled + no root + no alternate verifier →NoRoots.tls::tests::build_allows_no_roots_when_verification_overridden— empty store is fine underdisable_verify/ fingerprint pinning.config::tests::cli_does_not_clobber_toml_system_roots— TOMLclient.tls.system_roots = truesurvives the CLI re-parse.cargo fmt/clippyclean via the pinned Nix toolchain.(Written by Claude)