fix(agent): make native cert auto-renew actually work end-to-end
Two real-deploy renew bugs (found running the live /renew):
- the /renew mTLS request pinned the enroll caChain as the server CA → TLS
'unable to get local issuer certificate' (the LE-fronted CP is publicly
trusted). Verify the server against SYSTEM roots (drop ca), keep the client
cert + rejectUnauthorized:true. (TlsClientOptions.ca now optional.)
- renewCert parsed {cert, caChain:string}, but the CP returns cert=base64(DER)
+ caChain=base64(DER)[]; normalize to PEM (shared certs/pem.ts, reused by
native enroll). Verified live: cert rotated 13:41→next-day, frpc restarted,
tunnel stayed up. 281 tests pass.
This commit is contained in:
@@ -15,6 +15,7 @@ import type { EnrollResult } from 'relay-contracts'
|
||||
import type { AgentIdentity } from '../keys/identity.js'
|
||||
import type { Keystore } from '../keys/keystore.js'
|
||||
import { buildCsr } from './csr.js'
|
||||
import { derBase64ToPem } from '../certs/pem.js'
|
||||
|
||||
/** v0.8 shared-token gate vs v0.9+ per-host Ed25519. Default is `'ed25519'` from v0.9. */
|
||||
export type EnrollMode = 'token' | 'ed25519'
|
||||
@@ -69,16 +70,6 @@ interface EnrollResponseJson {
|
||||
hostContentSecret: string // base64url over the wire
|
||||
}
|
||||
|
||||
/**
|
||||
* base64(DER) → PEM. The native /enroll returns the leaf + CA certs as base64-encoded DER; the
|
||||
* keystore + frpc need PEM files, so wrap the base64 body at 64 columns in CERTIFICATE armor.
|
||||
*/
|
||||
function derBase64ToPem(derBase64: string, label = 'CERTIFICATE'): string {
|
||||
const body = derBase64.replace(/\s+/g, '')
|
||||
const lines = body.match(/.{1,64}/g) ?? []
|
||||
return `-----BEGIN ${label}-----\n${lines.join('\n')}\n-----END ${label}-----\n`
|
||||
}
|
||||
|
||||
function parseEnrollResult(json: unknown, allowMissingContentSecret = false): EnrollResult {
|
||||
const j = json as Partial<EnrollResponseJson>
|
||||
if (typeof j.hostContentSecret !== 'string') {
|
||||
|
||||
Reference in New Issue
Block a user