Skip to content

feat: tls.peer manifest field for service-to-service mtls posture - #440

Merged
kacy merged 1 commit into
mainfrom
feat/mtls-manifest-tls-peer
Jun 16, 2026
Merged

feat: tls.peer manifest field for service-to-service mtls posture#440
kacy merged 1 commit into
mainfrom
feat/mtls-manifest-tls-peer

Conversation

@kacy

@kacy kacy commented Jun 12, 2026

Copy link
Copy Markdown
Owner

summary

first PR-5 chunk. adds the manifest tls.peer = "off" | "warn" | "require"
field so the next chunks can wire the proxy listener (server-side accept
with mTLS) and the upstream dial (client-side originate) based on it.

config-surface only — nothing reads tls.peer in this PR yet.

what's in here

  • spec.TlsConfig.PeerMode enum (off / warn / require) + label + parser
  • spec.TlsConfig.peer field defaulting to .off
  • spec.TlsConfig.domain is now optional (defaults to "") — a service
    that only wants mTLS doesn't need a public DNS name. ACME still
    requires a domain, and the loader enforces that.
  • loader parses tls.peer; an unknown value is rejected with the
    existing InvalidTlsConfig error
  • four new tests: defaults, all three modes, mtls-only (no domain),
    invalid-value reject

design notes

  • nesting peer under tls matches the original Phase 8 plan and
    keeps related config grouped. one could argue mTLS is orthogonal to
    inbound termination, but the user-facing surface is small enough
    that grouping wins.
  • making domain optional is a small breaking-change risk only for
    users who were relying on the prior "missing domain ⇒ error" behavior
    without acme set. that combination was previously invalid (the
    cert had nowhere to go), so the behavior change is a bug fix more
    than a contract break.

next chunk

  • read tls.peer from the proxy listener path and call
    acceptServerHandshake(MtlsOpts) when set
  • read tls.peer from the upstream dial path and call
    client_session.doHandshake with the cluster CA
  • handshake metrics and yoq cert service <name> CLI

still no auto-merge — security-sensitive wiring.

per-service knob in [service.<name>.tls]:
  peer = "off"     # default — no peer authentication
  peer = "warn"    # request + verify, but accept on failure
  peer = "require" # reject any peer without a valid cluster-CA leaf

a service that only wants mtls (no public-facing acme cert) can now
declare just tls.peer with no tls.domain. acme still requires a
domain — the loader keeps that constraint.

four new loader tests cover defaults, all three modes, the domain-
optional case, and the invalid-value rejection.

no behavior change yet — this PR just lands the config surface so the
listener (server-side accept) and the upstream dial (client-side
originate) can read it in the next chunk.
@kacy
kacy merged commit 010256c into main Jun 16, 2026
10 checks passed
@kacy
kacy deleted the feat/mtls-manifest-tls-peer branch June 16, 2026 01:38
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.

1 participant