Help us shape the future of Go! Take the 2026 Go Developer Survey

pki

package
v0.11.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 25, 2026 License: Apache-2.0 Imports: 18 Imported by: 0

README

Management PKI and mutual-TLS contract

This package supplies a dedicated certificate issuer and Go TLS reference configuration. It is not a public enrollment route, a guest listener or authority to execute processes. The Rust guest still needs its TLS integration.

Issuance and identity

An operator provisions a dedicated management CA certificate and private signer; the package never auto-generates a production root or uses session/display keys. The issuer must receive enrollment authorization from a one-use server-side credential reservation and a fresh workspace incarnation lookup. Existing desktop enrollment tokens consumed locally are not accepted as such authority. Guest private keys remain on the guest; issuance receives a signed CSR only.

CSRs prove possession of an Ed25519 or P-256 key and must not request a subject, SAN or extensions. Issuance rejects requested identities rather than trusting or silently copying them. The server selects the identity from current provisioning state. A CA key cannot also be issued as a guest/API leaf key.

Guest leaves have a single URI SAN:

spiffe://kubeworkspaces.io/management/v1/workspaces/{namespace}/{name}/{uid}/{generation}/{revocation_epoch}

They have server-auth purpose only and the fixed DNS SAN management.workspace.internal. That verification name is not a dial address; the API still discovers/dials the workspace endpoint independently. Go's normal CA, DNS, expiry and signature verification remains enabled, followed by exact URI identity matching. The URI scheme is an identity convention, not a dependency on a SPIFFE control plane or proof of SPIFFE deployment.

API leaves have client-auth purpose only and one URI SAN:

spiffe://kubeworkspaces.io/management/v1/apis/{replica_id}

Identity components are bounded ASCII identifiers (letters/digits/dot/underscore/ hyphen), never URI-escaped paths, queries or fragments. Epochs are canonical unsigned decimal. The lifetime is explicitly selected between one minute and one hour, with at most 30 seconds of issuance backdating and no extension beyond the issuer expiry. Provisioning and policy revocation remain necessary even while a certificate is cryptographically valid.

Transport verification

Both reference configurations require TLS 1.3 and ALPN kw-management/1, an explicit management CA bundle and purpose-correct local credentials. System/web trust roots, anonymous clients, desktop protocol fallback and TLS resumption are not used. A missing current-authorization callback is a configuration error. Root rotation can explicitly overlap old/new CAs; removing a root denies its certificates on the next full handshake.

Each successful handshake additionally invokes current authorization: the API must resolve the guest UID/generation/epoch and the guest must validate the API replica's current authority. Lookups must use bounded deadlines and fail on outage. A fixed allow callback is appropriate only in synthetic tests; chain validation alone does not fence reset, deleted or revoked identities.

APIClientFingerprint and VerifiedAPIFingerprint derive the same SHA-256 of the API certificate DER. This is the value bound into management grants. The guest must derive it from its successfully verified TLS peer, not an operation field.

Handshake authentication does not authorize a process or an unlimited session. The transport integration must preserve a fresh challenge/replay verifier per connection, bound frames and deadlines, recheck grants/epochs during execution, and close/fence sessions at certificate expiry or revocation. Mandatory recording admission remains a separate gate.

Remaining enrollment integration

One-use credential provisioning/redemption must be shared across API replicas, bound to current workspace UID/generation, expiry and the guest CSR public key. Persist an issued result for same-CSR retry without issuing a second identity; reject another CSR, reset or deleted workspace. Implement rotation/renewal and guest machine-protected key storage before exposing enrollment or a listener. Keep CA/private keys in Secret/HSM references and only public roots/verification keys in image trust material. No image-wide or desktop bootstrap credential is a management issuance bypass.

go test -race ./internal/execution/pki

Tests perform real mutual-TLS exchanges and cover identity substitution, reset, epoch revocation, authorization outage, wrong CA/purpose, anonymous clients, expiry, TLS downgrade, ALPN mismatch, CSR proof/SAN injection and root rotation.

Documentation

Overview

Package pki defines management-only certificate identities and mutual TLS. Enrollment authorization and current identity resolution are caller-owned; desktop tickets and locally staged desktop tokens are not issuance authority.

Index

Constants

View Source
const (
	RoleGuest  = "guest"
	RoleAPI    = "api"
	ServerName = "management.workspace.internal"
	ALPN       = "kw-management/1"
)
View Source
const (
	MaxLeafLifetime = time.Hour
)

Variables

View Source
var (
	ErrIdentity      = errors.New("invalid management certificate identity")
	ErrCertificate   = errors.New("invalid management certificate")
	ErrTrust         = errors.New("management certificate trust unavailable")
	ErrAuthorization = errors.New("management peer authorization unavailable or denied")
)

Functions

func APIClientFingerprint

func APIClientFingerprint(cert tls.Certificate) (string, error)

APIClientFingerprint supplies the local certificate digest bound into an issued management grant. The guest derives the same digest from its verified TLS peer, rather than trusting a fingerprint supplied in an operation request.

func ClientTLS

func ClientTLS(cert tls.Certificate, roots *x509.CertPool, expected Identity, authorize AuthorizePeer) (*tls.Config, error)

ClientTLS verifies both the CA/DNS chain through Go's built-in TLS verifier and the exact enrolled guest URI identity, including provisioning and epoch. No InsecureSkipVerify/custom-chain bypass or session-resumption path exists.

func ServerTLS

func ServerTLS(cert tls.Certificate, roots *x509.CertPool, enrolled Identity, authorize AuthorizePeer) (*tls.Config, error)

ServerTLS requires a trusted API client certificate and current replica authorization. It validates the local certificate against enrolled identity.

func TrustRoots

func TrustRoots(bundle []byte) (*x509.CertPool, error)

TrustRoots accepts only an explicit, bounded management CA bundle. It never falls back to machine/web PKI roots. Both old and new roots may overlap during an operator-coordinated trust rotation.

func VerifiedAPIFingerprint

func VerifiedAPIFingerprint(state tls.ConnectionState) (string, error)

VerifiedAPIFingerprint is valid only after a successful management handshake. It refuses unverified chains, foreign protocols and server-purpose identities.

Types

type Authority

type Authority struct {
	// contains filtered or unexported fields
}

Authority uses a separately provisioned management CA; it never auto-generates production roots and never accepts desktop/session secrets as CA credentials.

func NewAuthority

func NewAuthority(caDER []byte, signer crypto.Signer) (*Authority, error)

func (*Authority) GoString

func (a *Authority) GoString() string

func (*Authority) Issue

func (a *Authority) Issue(csrDER []byte, identity Identity, now time.Time, lifetime time.Duration) ([]byte, error)

Issue signs an independently authorized identity after CSR proof of possession. The caller must validate/reserve a one-use enrollment credential and current workspace incarnation before calling, and persist the issued result for retry. No private guest key is received or generated here. CSR identity/extensions are rejected rather than copied into the certificate.

func (*Authority) String

func (a *Authority) String() string

type AuthorizePeer

type AuthorizePeer func(Identity) error

AuthorizePeer must read current authoritative identity/revocation state. A CA signature alone does not authorize a reset/deleted workspace or retired API replica. The callback must fail on lookup outages and bound its own deadline.

type Identity

type Identity struct {
	Role            string
	Namespace       string
	WorkspaceName   string
	WorkspaceUID    string
	Generation      string
	RevocationEpoch uint64
	ReplicaID       string
}

Identity is selected from authoritative provisioning state, never from CSR subject/SAN requests. API and guest identities have disjoint fields/purposes.

func CertificateIdentity

func CertificateIdentity(cert *x509.Certificate) (Identity, error)

CertificateIdentity checks the management leaf shape and extracts identity. It does not verify trust or time; peers must first pass normal TLS chain verification and the current-authorization callback.

func (Identity) URI

func (i Identity) URI() (*url.URL, error)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL