Documentation
¶
Overview ¶
Package mtls builds mutual-TLS configs for Panel↔Agent gRPC. The CA is the trust anchor: the Agent (server) requires a Panel client cert signed by the CA, and the Panel (client) verifies the Agent's server cert against the CA using a fixed logical ServerName, so trust is decoupled from each node's network address.
Index ¶
- Constants
- func AgentIdentityFromCert(cert *x509.Certificate) string
- func AgentIdentityURI(id string) string
- func CAFingerprintPEM(pemBytes []byte) (string, error)
- func ClientTLS(certFile, keyFile, caFile, serverName string) (*tls.Config, error)
- func ClientTLSFromBytes(certPEM, keyPEM, caPEM []byte, serverName string) (*tls.Config, error)
- func FingerprintCert(cert *x509.Certificate) string
- func FingerprintPEM(pemBytes []byte) string
- func GenerateCA() (certPEM, keyPEM []byte, err error)
- func IssuePanelClientCert(caCertPEM, caKeyPEM []byte, ttl time.Duration) (certPEM, keyPEM []byte, err error)
- func IssuePanelServerCert(caCertPEM, caKeyPEM []byte, ttl time.Duration) (certPEM, keyPEM []byte, err error)
- func NewAgentKeyAndCSR(hosts []string) (keyPEM, csrPEM []byte, err error)
- func RequirePeerCN(wantCN string) func(tls.ConnectionState) error
- func SANHosts(pemBytes []byte) []string
- func ServerTLS(certFile, keyFile, caFile string) (*tls.Config, error)
- func ServerTLSFromBytes(certPEM, keyPEM, caPEM []byte) (*tls.Config, error)
- func SignAgentCSR(caCertPEM, caKeyPEM, csrPEM []byte, ttl time.Duration) ([]byte, error)
- func SignAgentCSRWithIdentity(caCertPEM, caKeyPEM, csrPEM []byte, ttl time.Duration, identity string) ([]byte, error)
- func SummarizeCert(cert *x509.Certificate) string
- func SummarizePEM(pemBytes []byte) string
- func VerifyCAFingerprint(pemBytes []byte, pinned string) error
- func VerifyPEM(certPEM, caPEM []byte) error
Constants ¶
const ( AgentServerName = "kraken-agent" PanelServerName = "kraken-panel" CAName = "kraken-ca" )
Logical certificate identities (SANs) baked into issued certs. The Panel pins AgentServerName when dialing, regardless of the node's host:port.
const DefaultAgentCertTTL = 90 * 24 * time.Hour
DefaultAgentCertTTL is how long an enrolled Agent certificate is valid.
const DefaultPanelClientCertTTL = 5 * 365 * 24 * time.Hour
DefaultPanelClientCertTTL is how long an auto-issued Panel client cert is valid. Long-lived because the Panel binds its own lifecycle to it and rotates on restart when the file is deleted, not on any external schedule.
Variables ¶
This section is empty.
Functions ¶
func AgentIdentityFromCert ¶ added in v0.21.0
func AgentIdentityFromCert(cert *x509.Certificate) string
AgentIdentityFromCert extracts the Panel-minted identity from an agent cert's URI SANs. Empty when the cert predates per-agent identities.
func AgentIdentityURI ¶ added in v0.21.0
AgentIdentityURI renders a Panel-minted agent identity as the URI SAN string embedded in issued agent certs.
func CAFingerprintPEM ¶ added in v0.16.0
CAFingerprintPEM returns the full SHA-256 fingerprint (64 hex chars) of the first certificate in pemBytes. This is the pinning identity embedded in Panel-generated deploy commands and checked by the Agent's remote-enroll path, so unlike FingerprintPEM it must carry the whole digest.
func ClientTLS ¶
ClientTLS builds the Panel's client-side config: it presents certFile/keyFile and verifies the server's cert against caFile using serverName (typically AgentServerName).
func ClientTLSFromBytes ¶ added in v0.5.1
ClientTLSFromBytes is the byte-slice counterpart to ClientTLS. Used when the Panel auto-issues its client cert against its own CA at startup and keeps the bundle in memory rather than round-tripping through a filesystem the distroless-nonroot process may not have write access to.
func FingerprintCert ¶ added in v0.21.0
func FingerprintCert(cert *x509.Certificate) string
FingerprintCert is FingerprintPEM for an already-parsed certificate.
func FingerprintPEM ¶ added in v0.6.0
FingerprintPEM returns a short SHA-256 fingerprint of the first certificate in pemBytes — enough hex to compare identities across Panel and Agent logs.
func GenerateCA ¶
GenerateCA creates a self-signed CA keypair and returns the cert and key as PEM. The Panel holds these to sign Agent enrollment requests.
func IssuePanelClientCert ¶ added in v0.5.0
func IssuePanelClientCert(caCertPEM, caKeyPEM []byte, ttl time.Duration) (certPEM, keyPEM []byte, err error)
IssuePanelClientCert generates a fresh ECDSA keypair for the Panel and returns a client certificate signed by the given CA. The cert carries the PanelServerName CN + ClientAuth EKU so an Agent (which trusts the same CA and requires client auth) accepts the Panel's outbound mTLS handshake.
This is the symmetric counterpart to SignAgentCSR: an Agent cert is server- auth + client-auth (Agent listens and Panel connects), a Panel cert is client-auth only (Panel connects out).
func IssuePanelServerCert ¶ added in v0.21.0
func IssuePanelServerCert(caCertPEM, caKeyPEM []byte, ttl time.Duration) (certPEM, keyPEM []byte, err error)
IssuePanelServerCert generates a keypair for the Panel's reverse-tunnel listener and returns a server certificate signed by the CA. Agents dialing the tunnel verify it against the same CA with ServerName=PanelServerName, so trust stays decoupled from the Panel's network address — the mirror image of how the Panel pins AgentServerName when dialing out.
func NewAgentKeyAndCSR ¶
NewAgentKeyAndCSR generates an ECDSA P-256 key and a certificate-signing request for an Agent server cert. The CSR always requests the logical AgentServerName plus loopback, and any extra hosts (DNS names or IPs) given.
func RequirePeerCN ¶ added in v0.26.1
func RequirePeerCN(wantCN string) func(tls.ConnectionState) error
RequirePeerCN returns a tls.Config.VerifyConnection hook that, on top of the CA-chain verification RequireAndVerifyClientCert already did, insists the verified client leaf's Subject CommonName equals wantCN.
This is the load-bearing authorization for the Agent's gRPC listener. The CA is a *shared* trust anchor: it signs the Panel's client cert AND every Agent's server cert, and Agent certs carry ClientAuth EKU (they need it to dial the reverse tunnel). Chain-validation alone therefore accepts any Agent's own cert as a client — so a single stolen/enrolled Agent cert could drive the full NodeService (UpdateAgent → arbitrary binary → RCE) on every other node. The CN is authoritative because the signer sets it (SignAgentCSR* hardcodes it and never copies the CSR subject), so an enrollee cannot forge PanelServerName.
func SANHosts ¶ added in v0.6.0
SANHosts returns the DNS + IP SANs of the first certificate in pemBytes, in cert order (DNS names first). Empty on parse failure.
func ServerTLS ¶
ServerTLS builds the Agent's direct-listener server config: it presents certFile/keyFile, requires a client cert signed by caFile, AND authorizes the client by identity — only the Panel (CN=PanelServerName) may connect. Without that last check any peer Agent's cert would authenticate (see RequirePeerCN).
func ServerTLSFromBytes ¶ added in v0.21.0
ServerTLSFromBytes is the byte-slice counterpart to ServerTLS — used for the Panel's reverse-tunnel listener, whose server cert is auto-issued in memory at startup (same rationale as ClientTLSFromBytes).
func SignAgentCSR ¶
SignAgentCSR verifies csrPEM and issues an Agent server certificate signed by the CA (caCertPEM/caKeyPEM), valid for ttl. The issued cert always carries the AgentServerName SAN (the Panel pins it when dialing) and server+client-auth EKUs. This is the core of the bootstrap/enrollment + rotation flow.
func SignAgentCSRWithIdentity ¶ added in v0.21.0
func SignAgentCSRWithIdentity(caCertPEM, caKeyPEM, csrPEM []byte, ttl time.Duration, identity string) ([]byte, error)
SignAgentCSRWithIdentity is SignAgentCSR plus a Panel-minted per-agent identity, embedded as a URI SAN (see AgentIdentityURI). The identity is authoritative on the Panel side — it is never taken from the CSR — and is what a reverse-tunnel handshake later maps back to a node record. An empty identity issues a legacy cert with no URI SAN.
func SummarizeCert ¶ added in v0.6.0
func SummarizeCert(cert *x509.Certificate) string
SummarizeCert renders the identity of a certificate on one log-friendly line: CN, issuer, serial, fingerprint, validity window, and SANs.
func SummarizePEM ¶ added in v0.6.0
SummarizePEM is SummarizeCert for raw PEM input.
func VerifyCAFingerprint ¶ added in v0.16.0
VerifyCAFingerprint checks pemBytes against a pinned fingerprint as produced by CAFingerprintPEM. The comparison is case-insensitive and tolerates a "sha256:" prefix so operators can paste either spelling.
Types ¶
This section is empty.