fix(relay-run): agent-TLS ca must be full chain (intermediate+root), not intermediate-only

Node/OpenSSL rejects an agent client leaf whose only trust anchor is a non-self-signed
intermediate (no PARTIAL_CHAIN flag) → every agent was reset at the TLS layer before attach(),
surfacing as a silent 1006. Pass the full agent-ca bundle and stop swallowing tlsClientError.
This commit is contained in:
Yaojia Wang
2026-07-07 04:49:38 +02:00
parent 7af4a68ef5
commit 89678c7949
2 changed files with 10 additions and 1 deletions

View File

@@ -205,7 +205,11 @@ async function main(): Promise<void> {
resolver,
mtls: mtlsBridge.sync,
now,
caBundle: [readFileSync(agentCaCertPath)],
// Agent-TLS trust store for validating the agent's CLIENT leaf (requestCert+rejectUnauthorized).
// MUST be the FULL chain (intermediate + self-signed root): Node/OpenSSL rejects a leaf whose only
// anchor is a non-self-signed intermediate (no PARTIAL_CHAIN flag). Intermediate-only ⇒ every agent
// is reset at the TLS layer before attach() runs.
caBundle: [readFileSync(agentCaChainPath)],
onError: (e) => console.error('[data-plane]', errText(e)),
tlsServerFactory: mtlsBridge.wrap(agentTlsFactory),
})

View File

@@ -37,6 +37,11 @@ export function makeAgentTlsServerFactory(opts: AgentTlsOptions): TlsServerFacto
const der = peer && peer.raw ? new Uint8Array(peer.raw) : new Uint8Array()
onPeer(wsToWebSocketLike(ws), der)
})
wss.on('error', (e) => opts.onError?.(e))
// Surface TLS-layer client failures (e.g. a client leaf that doesn't chain to `ca`). Node
// otherwise SWALLOWS 'tlsClientError' — the peer just sees an abrupt reset with no server signal,
// which is exactly what masked the intermediate-only-CA bug.
server.on('tlsClientError', (e) => opts.onError?.(e))
server.on('error', (e) => opts.onError?.(e))
server.listen(opts.bindPort, opts.bindHost, () => opts.onListening?.())
return {