Documentation
¶
Index ¶
- Constants
- Variables
- func AbandonServingCandidate(ref CandidateRef) error
- func CleanupMachine() error
- func CleanupMachineBySHA256(fp [32]byte) error
- func ComputeSHA256Fingerprint(der []byte) [32]byte
- func ConfirmServingCandidate(ref CandidateRef) error
- func MachineAgentPath() (string, error)
- func MachineTLSPath() (string, error)
- func ParseSHA256Fingerprint(hexFP string) ([32]byte, error)
- type CandidateRef
- type MachineKeyDeleter
- type MachineKeyStore
- type Material
- func LoadServingCandidate(ref CandidateRef) (Material, error)
- func LoadServingMaterial() (Material, error)
- func ProvisionMachine() (Material, error)
- func ProvisionWithKeyStore(dataDir string, keyStore MachineKeyStore, trustStore TrustStore, ...) (Material, error)
- func ReloadMachine() (Material, error)
- type RenewalOutcome
- type TrustProvisioner
- type TrustState
- type TrustStore
- type TrustVerifier
Constants ¶
const ( // RenewalThreshold is how close to expiry we renew the server certificate. RenewalThreshold = 30 * 24 * time.Hour )
Variables ¶
var ( // ErrRenewalDue indicates that the persisted server certificate is due for // renewal. Neither ReloadMachine nor existing-state provisioning renews // implicitly; the caller stages a renewal with StageServerRenewal. // ReloadMachine reports it whenever the leaf is within RenewalThreshold of // expiry; existing-state provisioning reports it only once the leaf has // expired (a still-valid leaf in the renewal window is returned with a nil // error). An expired leaf also matches ErrCertificateNotValidNow. CA, key, // certificate identity and trust failures detected first are reported with // their own errors and do not match ErrRenewalDue. ErrRenewalDue = errors.New("server certificate renewal is due; stage it with StageServerRenewal") // ErrNoCandidate indicates that a CandidateRef does not describe a staged // candidate (its Outcome is not RenewalCandidateStaged). ErrNoCandidate = errors.New("candidate reference does not describe a staged candidate") // ErrCandidateNotFound indicates that no pending candidate DER exists. ErrCandidateNotFound = errors.New("pending server certificate candidate not found") // ErrCandidateMismatch indicates that the persisted pending candidate is // not the one identified by the CandidateRef. Nothing is changed. ErrCandidateMismatch = errors.New("pending server certificate candidate does not match the candidate reference") // ErrCandidateStale indicates that the persisted server certificate or CA // certificate is no longer the base the candidate was staged against. // Nothing is changed; stage again. ErrCandidateStale = errors.New("candidate reference is stale: persisted server or CA certificate changed since staging") // ErrCandidatePromoted indicates that the candidate has already been // promoted to the persisted server certificate, so it can no longer be // abandoned. Abandon never reverses a completed promotion. ErrCandidatePromoted = errors.New("candidate has already been promoted") // ErrPromotionUnconfirmed indicates that the final promotion step reported // an error whose effect is not known: the candidate may or may not have // become the persisted server certificate. Retry ConfirmServingCandidate // with the same CandidateRef to reconcile; never treat this as "not // promoted". ErrPromotionUnconfirmed = errors.New("server certificate promotion outcome unconfirmed") )
var ( // ErrCertificateNotValidNow indicates that the CA or the server // certificate is expired or not yet valid at the time of the check. ErrCertificateNotValidNow = errors.New("certificate is expired or not yet valid") // ErrLeafOutlivesCA indicates that a server certificate's validity would // extend beyond its CA certificate's NotAfter. Local-TLS never shortens // the leaf to fit and never renews or rotates the CA automatically. ErrLeafOutlivesCA = errors.New("server certificate validity extends beyond the CA certificate") // ErrTrustNotHealthy indicates that the CA trust anchor is not in the // TrustHealthy state (absent or conflicting). Loading fails closed; // manual resolution is required. ErrTrustNotHealthy = errors.New("CA trust anchor is not healthy") // ErrInconsistentMachineState indicates persisted Local-TLS state that // cannot be used or repaired automatically, for example a CA certificate // DER without a server certificate DER. Nothing is regenerated. ErrInconsistentMachineState = errors.New("inconsistent Local-TLS machine state") )
var ErrKeyDeletionUnconfirmed = errors.New("key deletion unconfirmed")
ErrKeyDeletionUnconfirmed indicates that cleanup could not confirm deletion of a Local-TLS key because the delete reported ErrKeyNotFound: the key was not found or is not accessible to the caller, so nothing was deleted and the key may still exist. Errors carrying it also match ErrKeyNotFound.
var ErrKeyNotFound = errors.New("persisted CNG key not found or not accessible")
ErrKeyNotFound indicates that the native open of the exact persisted CNG key reported the key as not found OR not accessible to the caller (NTE_NOT_FOUND or NTE_BAD_KEYSET). It does not prove that the key is absent: the Microsoft Software KSP reports NTE_BAD_KEYSET to a caller that the key's DACL does not grant. It must never by itself trigger a reset, regeneration or overwrite of a key, and cleanup never treats it as a confirmed deletion (see ErrKeyDeletionUnconfirmed). The returned error keeps the native HRESULT in its message.
var ErrTrustAnchorNotFound = errors.New("trust anchor certificate not found in LocalMachine\\Root")
ErrTrustAnchorNotFound indicates that the exact CA trust anchor is not present in the machine trust store (i.e. it is already absent). Cleanup treats this as an idempotent success, not a failure.
Functions ¶
func AbandonServingCandidate ¶ added in v0.2.0
func AbandonServingCandidate(ref CandidateRef) error
AbandonServingCandidate is not supported on non-Windows platforms.
func CleanupMachine ¶
func CleanupMachine() error
CleanupMachine is not supported on non-Windows platforms.
func CleanupMachineBySHA256 ¶
CleanupMachineBySHA256 is not supported on non-Windows platforms.
func ComputeSHA256Fingerprint ¶
ComputeSHA256Fingerprint returns the SHA-256 fingerprint of a DER certificate.
func ConfirmServingCandidate ¶ added in v0.2.0
func ConfirmServingCandidate(ref CandidateRef) error
ConfirmServingCandidate is not supported on non-Windows platforms.
func MachineAgentPath ¶
MachineAgentPath returns an error on non-Windows platforms because machine-scoped state at %ProgramData% is a Windows-only concept.
func MachineTLSPath ¶
MachineTLSPath returns an error on non-Windows platforms.
func ParseSHA256Fingerprint ¶
ParseSHA256Fingerprint parses a 64-character hex SHA-256 fingerprint into a [32]byte. It accepts surrounding whitespace and is case-insensitive.
Types ¶
type CandidateRef ¶ added in v0.2.0
type CandidateRef struct {
// Outcome reports whether a candidate was staged.
Outcome RenewalOutcome
// CandidateSHA256 is the SHA-256 of the pending candidate DER. Zero when
// Outcome is RenewalNotDue.
CandidateSHA256 [32]byte
// BaseSHA256 is the SHA-256 of the persisted server certificate DER the
// candidate was staged against.
BaseSHA256 [32]byte
// CASHA256 is the SHA-256 of the CA certificate DER.
CASHA256 [32]byte
}
CandidateRef identifies one staged renewal attempt by public digests. It is returned by StageServerRenewal and passed back unchanged to LoadServingCandidate, ConfirmServingCandidate and AbandonServingCandidate.
CandidateRef is public metadata only. It is not a secret, not an authorization, not a compare-and-swap token, and not proof that any listener activated the candidate. The caller keeps it for the whole attempt; if it is lost, the attempt is restarted (stage, load, activate, attest, confirm), and the presence of a pending file is never treated as confirmation.
func StageServerRenewal ¶ added in v0.2.0
func StageServerRenewal() (CandidateRef, error)
StageServerRenewal is not supported on non-Windows platforms.
type MachineKeyDeleter ¶
type MachineKeyDeleter interface {
// DeleteCAKey deletes the exact persisted Local-TLS CA key.
// Returns ErrKeyNotFound when the key was not found or is not
// accessible: nothing was deleted, and absence is not proven.
DeleteCAKey() error
// DeleteServerKey deletes the exact persisted Local-TLS server key.
// Returns ErrKeyNotFound when the key was not found or is not
// accessible: nothing was deleted, and absence is not proven.
DeleteServerKey() error
}
MachineKeyDeleter deletes exactly the Local-TLS-owned persisted machine keys. It must never delete keys that are not owned by this module, and it deletes only by exact persisted key name — never by wildcard or CN.
func PlatformKeyDeleter ¶
func PlatformKeyDeleter() (MachineKeyDeleter, error)
PlatformKeyDeleter returns the platform-appropriate MachineKeyDeleter. On Windows this deletes the exact persisted CNG keys via the Microsoft Software Key Storage Provider. On other platforms it returns an error.
type MachineKeyStore ¶
type MachineKeyStore interface {
// LoadOrCreateCAKey returns a signer for the local TLS CA key.
// If the key does not exist it is created as a persistent,
// non-exportable machine-scoped key.
LoadOrCreateCAKey() (crypto.Signer, error)
// LoadOrCreateServerKey returns a signer for the local TLS server key.
// If the key does not exist it is created as a persistent,
// non-exportable machine-scoped key.
LoadOrCreateServerKey() (crypto.Signer, error)
}
MachineKeyStore provides machine-scoped persistent signing keys. On Windows this is backed by CNG/KSP; on other platforms it is unsupported.
The production implementation never returns private-key bytes. Keys are identified by stable names and persist across process restarts.
func PlatformKeyStore ¶
func PlatformKeyStore() (MachineKeyStore, error)
PlatformKeyStore returns the platform-appropriate MachineKeyStore. On Windows this uses CNG/KSP with the Microsoft Software Key Storage Provider. On other platforms it returns an error — machine-scoped key storage is not supported outside Windows.
type Material ¶
type Material struct {
Certificate tls.Certificate
CACertificate *x509.Certificate
ServerCertificate *x509.Certificate
CAFingerprintSHA256 [32]byte
}
Material contains the provisioned local TLS material.
func LoadServingCandidate ¶ added in v0.2.0
func LoadServingCandidate(ref CandidateRef) (Material, error)
LoadServingCandidate is not supported on non-Windows platforms.
func LoadServingMaterial ¶
LoadServingMaterial is not supported on non-Windows platforms.
func ProvisionMachine ¶
ProvisionMachine is not supported on non-Windows platforms.
func ProvisionWithKeyStore ¶
func ProvisionWithKeyStore(dataDir string, keyStore MachineKeyStore, trustStore TrustStore, now func() time.Time) (Material, error)
ProvisionWithKeyStore provisions local TLS using a MachineKeyStore for persistent signing keys. Only public certificate DERs are written to disk; private keys remain in the machine-scoped key store.
First install is entered only when both the CA and the server certificate DER are absent. A DER whose presence cannot be determined (any stat error other than not-exist), or exactly one present DER, fails closed with ErrInconsistentMachineState: the CA certificate is never reissued for an existing state. ProvisionWithKeyStore performs no CA-key pre-check; ProvisionMachine adds the conservative pre-check and documents the single-writer caller contract that also applies here.
On existing state it verifies the persisted material with the common validator and never writes DER, renews or stages. A valid leaf is returned with a nil error even within RenewalThreshold of expiry: success means the existing state was verified, not that a renewal occurred (renewal goes through StageServerRenewal and the consumer confirmation flow). An expired leaf fails with ErrRenewalDue and ErrCertificateNotValidNow; any other validation or trust failure returns a zero Material with a classified error. Existing-state keys are acquired through keyStore (open-or-create).
func ReloadMachine ¶
ReloadMachine is not supported on non-Windows platforms.
func (*Material) Close ¶
Close releases the process-local native CNG handle backing the serving signer. It never deletes the persisted CNG key, never removes certificates or trust anchors, and never triggers CleanupMachine or CleanupMachineBySHA256. Lifecycle release is distinct from persisted-key deletion and from Local TLS uninstall/cleanup.
Close is safe to call after a successful production machine operation. It is idempotent in effect: the underlying CNG signer's Close is safe to call repeatedly and reports no error. After Close, the serving certificate must not be used for new TLS handshakes.
Material is single-owner: do not copy it by value and then reuse the copy after Close, since both copies reference the same underlying signer.
type RenewalOutcome ¶ added in v0.2.0
type RenewalOutcome int
RenewalOutcome is the result of StageServerRenewal. The zero value is not a valid outcome.
const ( // RenewalNotDue means the persisted server certificate is not within // RenewalThreshold of expiry; no candidate was staged. RenewalNotDue RenewalOutcome = iota + 1 // RenewalCandidateStaged means a validated candidate is persisted as the // pending server certificate. The persisted server certificate is // unchanged. RenewalCandidateStaged )
func (RenewalOutcome) String ¶ added in v0.2.0
func (o RenewalOutcome) String() string
String returns a human-readable representation of the outcome.
type TrustProvisioner ¶
type TrustProvisioner interface {
// InstallTrust installs the CA certificate DER into the machine
// trust store. It is idempotent: if the exact same certificate
// (matched by SHA-256 fingerprint) already exists, the call
// succeeds without creating a duplicate.
InstallTrust(certificateDER []byte) error
// RemoveTrust removes the exact CA certificate identified by DER
// from the machine trust store. Only the exact certificate
// (matched by SHA-256 fingerprint) is removed.
// Returns ErrTrustAnchorNotFound when the certificate is not present.
RemoveTrust(certificateDER []byte) error
// RemoveTrustBySHA256 removes the exact CA certificate identified by
// its SHA-256 fingerprint from the machine trust store. This is used
// when the original DER is no longer available (e.g. the state
// directory was already removed).
//
// Removal is by exact 32-byte SHA-256 identity only; no subject/CN
// matching is performed. Returns ErrTrustAnchorNotFound when the
// certificate is not present.
RemoveTrustBySHA256(fp [32]byte) error
}
TrustProvisioner performs elevated certificate trust operations. Mutating operations MUST only be called from an elevated context (installer, provisioning, cleanup). Normal runtime MUST NOT use this.
type TrustState ¶
type TrustState int
TrustState describes the result of a runtime trust verification.
const ( // TrustHealthy means the expected CA certificate (matched by its exact // SHA-256 fingerprint) is present in the machine trust store. Other // certificates with the same subject are not examined in that case, so // TrustHealthy does not prove that no other Local-TLS CA anchor exists. TrustHealthy TrustState = iota // TrustAbsent means the expected CA certificate is not present in the // machine trust store. Manual resolution is required. TrustAbsent // TrustConflict means a certificate with a matching subject name but a // different fingerprint exists. Manual resolution is required. TrustConflict // TrustError means the verification itself failed (store access, etc.). TrustError )
func (TrustState) String ¶
func (s TrustState) String() string
String returns a human-readable representation of the trust state.
type TrustStore ¶
type TrustStore interface {
TrustProvisioner
TrustVerifier
// EnsureTrusted installs the CA certificate DER into the trust store
// if it is not already present.
// Deprecated: use TrustProvisioner.InstallTrust for elevated operations,
// and TrustVerifier.VerifyTrust for runtime checks.
EnsureTrusted(certificateDER []byte) error
}
TrustStore is the combined interface for backward compatibility. New code should use TrustProvisioner and TrustVerifier separately.
func PlatformTrustStore ¶
func PlatformTrustStore() (TrustStore, error)
PlatformTrustStore returns the platform-appropriate TrustStore. Machine-scoped trust deployment targets LocalMachine\Root on Windows.
type TrustVerifier ¶
type TrustVerifier interface {
// VerifyTrust checks whether the given CA certificate DER is
// trusted in the machine trust store. It returns the trust state
// and, when TrustError, an error describing the failure.
VerifyTrust(certificateDER []byte) (TrustState, error)
// IsTrustedSHA256 reports whether a certificate with the given
// SHA-256 fingerprint is present in the trust store.
IsTrustedSHA256(fingerprint [32]byte) (bool, error)
}
TrustVerifier performs read-only trust verification. It is safe for normal (non-elevated) runtime use.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
verify
command
Command verify performs manual verification for the Local TLS module.
|
Command verify performs manual verification for the Local TLS module. |
|
examples
|
|
|
fingerprint
command
Command fingerprint demonstrates the non-destructive fingerprint / cleanup handoff utilities of Local TLS.
|
Command fingerprint demonstrates the non-destructive fingerprint / cleanup handoff utilities of Local TLS. |
|
provision
command
Command provision demonstrates the elevated first-install / verification flow using ProvisionMachine.
|
Command provision demonstrates the elevated first-install / verification flow using ProvisionMachine. |
|
serving
command
Command serving demonstrates the preferred production HTTPS serving startup flow using LoadServingMaterial.
|
Command serving demonstrates the preferred production HTTPS serving startup flow using LoadServingMaterial. |
|
internal
|
|
|
identity
Package identity centralises the product-branding constants used by the Local TLS module.
|
Package identity centralises the product-branding constants used by the Local TLS module. |