feat(mtls): implement mTLS/CA + bootstrap token framework [tsk_FUQws_DMIcXa]
ECDSA P-256 self-signed CA with disk persistence (load-or-generate),
CSR signing (CN=nodeUUID, 90d validity, EKU=ClientAuth), one-time
bootstrap tokens via Redis GETDEL (15min TTL), CRL revocation with
Redis SET + DB interface, gRPC unary+stream interceptors that extract
CN from verified TLS chains (Enroll whitelisted, others require cert),
and NewServerTLSConfig (VerifyClientCertIfGiven + TLS 1.3 + CRL hook).
Frozen API: SignCSR / CAPEM / IssueToken / ConsumeToken / Revoke /
NewServerTLSConfig / UnaryServerInterceptor / NodeUUIDFromContext
Tests cover: CA sign+verify, token one-time guarantee, TTL expiry,
revocation rejection, interceptor whitelist (5 categories).
Redis layer backed by miniredis in tests.
Run setup.sh from server/ to fetch deps and verify tests pass.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
package mtls
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
)
|
||||
|
||||
// NewServerTLSConfig builds the *tls.Config for the Pangolin gRPC server.
|
||||
//
|
||||
// Single-port strategy:
|
||||
// - ClientAuth = tls.VerifyClientCertIfGiven: agents that have not yet enrolled
|
||||
// complete the TLS handshake without a client cert; the identity interceptor
|
||||
// enforces cert presence for all non-Enroll RPCs at the application layer.
|
||||
// - ClientCAs is set to a pool containing only the Pangolin Node CA, so the TLS
|
||||
// stack will verify any presented certificate against it.
|
||||
// - VerifyPeerCertificate is wired to CRL.VerifyPeerCertificate: if the leaf cert
|
||||
// CN is revoked the handshake fails immediately, before any RPC handler runs.
|
||||
// - Minimum TLS version is 1.3.
|
||||
//
|
||||
// The caller must set cfg.Certificates with the server's own TLS certificate
|
||||
// (typically from Let's Encrypt) before using this config.
|
||||
func NewServerTLSConfig(ca *CA, crl *CRL) *tls.Config {
|
||||
pool := x509.NewCertPool()
|
||||
pool.AddCert(ca.CACert())
|
||||
|
||||
return &tls.Config{
|
||||
ClientAuth: tls.VerifyClientCertIfGiven,
|
||||
ClientCAs: pool,
|
||||
MinVersion: tls.VersionTLS13,
|
||||
VerifyPeerCertificate: crl.VerifyPeerCertificate,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user