cert

package
v0.1.6 Latest Latest
Warning

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

Go to latest
Published: Jun 26, 2026 License: MIT Imports: 22 Imported by: 0

Documentation

Overview

Package cert provides certificate-handling adapter implementations: the self-signed identity CA and the BYOC server-certificate validator.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ACMEIssuer added in v0.1.6

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

ACMEIssuer implements port.ServerCertificateIssuer against an RFC 8555 CA — Let's Encrypt being the canonical target (use the staging directory for testing, production for live issuance).

Order-lifecycle mapping:

  • CreateOrder → new-order. The provider's challenges are relayed with their account-bound key authorizations and the computed DNS-01 TXT digest, so the pending-registration response hands the domain owner exactly the artifacts to publish. ANS never publishes them — the owner does, exactly as with the self-signed issuer.
  • FinalizeOrder → answer the RA-verified challenge, wait briefly for validation + issuance, then finalize with the CSR and download the chain. Validation that outlives the in-call budget reports port.ErrOrderPending; the re-driven verify-acme picks the order back up by its URL. Orders the provider moves to `invalid` report port.ErrOrderFailed.

Account handling: the account key is generated once and persisted under dataDir; registration happens lazily on first use and auto-accepts the provider's terms of service — choosing `ca.server.type: acme` in config is the operator's ToS consent, per standard ACME automation practice.

func NewACMEIssuer added in v0.1.6

func NewACMEIssuer(directoryURL, email, dataDir string, opts ...ACMEIssuerOption) (*ACMEIssuer, error)

NewACMEIssuer opens (or creates) the ACME account key under dataDir and returns an issuer speaking to the given directory URL (e.g. Let's Encrypt staging: https://acme-staging-v02.api.letsencrypt.org/directory). The optional email becomes the account contact for expiry and incident notices. No network I/O happens here — account registration is deferred to first use so the RA can boot while the provider is unreachable.

func (*ACMEIssuer) CreateOrder added in v0.1.6

func (a *ACMEIssuer) CreateOrder(ctx context.Context, fqdn string) (*domain.CertificateOrder, error)

CreateOrder opens an RFC 8555 order for the FQDN and relays the provider's pending challenges.

A new order is not always 'pending': per RFC 8555 §7.1.3 a CA that still holds a valid authorization for this account+identifier returns the order already 'ready' (Let's Encrypt reuses authorizations for ~30 days). The RA uses a single ACME account, so a renewal or re-registration of a recently-validated FQDN hits this routinely. In that case there is nothing for the owner to publish: the order is relayed as ISSUING with no challenges, the RA's gate skips ISSUING orders, and the next verify-acme finalizes directly.

func (*ACMEIssuer) FinalizeOrder added in v0.1.6

func (a *ACMEIssuer) FinalizeOrder(ctx context.Context, req port.FinalizeOrderRequest) (*port.IssuedCert, error)

FinalizeOrder drives the order to completion: answer the challenges the RA verified, wait (bounded) for the provider's validation, then finalize with the CSR and download the chain.

func (*ACMEIssuer) GetCACertificate added in v0.1.6

func (a *ACMEIssuer) GetCACertificate(_ context.Context) (string, error)

GetCACertificate returns the top of the most recently downloaded chain. Informational for ACME providers — relying parties already trust the public root via system stores, so an error before first issuance is expected and harmless.

type ACMEIssuerOption added in v0.1.6

type ACMEIssuerOption func(*ACMEIssuer)

ACMEIssuerOption configures the issuer at construction time.

func WithFinalizeBudget added in v0.1.6

func WithFinalizeBudget(d time.Duration) ACMEIssuerOption

WithFinalizeBudget overrides how long FinalizeOrder blocks on the provider before reporting port.ErrOrderPending.

func WithLogger added in v0.1.6

func WithLogger(logger zerolog.Logger) ACMEIssuerOption

WithLogger attaches a structured logger (default: a no-op logger). Issuance against an external CA is the part of the flow operators cannot see from the wire — order open / finalize transitions are logged at INFO and upstream-provider failures at ERROR so a stuck or rejected order can be debugged from the RA logs.

type SelfCA

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

SelfCA implements port.IdentityCertificateAuthority with an in-process ECDSA P-256 root CA. The root key and certificate are persisted under <dataDir> on first run and reused on subsequent runs.

func NewSelfCA

func NewSelfCA(dataDir, org string, validityDays int, opts ...SelfCAOption) (*SelfCA, error)

NewSelfCA opens (or creates) a self-signed CA in the given directory. The root certificate has the organization name set to org and a validity of validityDays days.

func (*SelfCA) GetCACertificate

func (c *SelfCA) GetCACertificate(ctx context.Context) (string, error)

GetCACertificate returns the root certificate PEM.

func (*SelfCA) IsRevoked

func (c *SelfCA) IsRevoked(serialHex string) bool

IsRevoked reports whether the given serial has been revoked in-process.

func (*SelfCA) IssueIdentityCertificate

func (c *SelfCA) IssueIdentityCertificate(
	ctx context.Context,
	csrPEM string,
	ansName string,
) (*port.IssuedCert, error)

IssueIdentityCertificate signs the given CSR. The resulting certificate has the provided ANS name as a URI SAN and is valid for identityTTL.

func (*SelfCA) RevokeCertificate

func (c *SelfCA) RevokeCertificate(
	ctx context.Context,
	req port.RevokeCertificateRequest,
) error

RevokeCertificate marks a certificate as revoked by serial. Idempotent per the port contract. The in-process CRL is not published; revocations are tracked in memory (and authoritatively through transparency-log events) — production deployments that need CRL/OCSP distribution swap in a cloud private-CA adapter at this port.

type SelfCAOption

type SelfCAOption func(*SelfCA)

SelfCAOption configures the CA at construction time.

func WithIdentityTTL

func WithIdentityTTL(d time.Duration) SelfCAOption

WithIdentityTTL sets the validity period of issued identity certificates. Default is 90 days.

type ServerSelfCA

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

ServerSelfCA implements port.ServerCertificateIssuer with an in-process ECDSA P-256 root CA that signs TLS server-auth certificates.

This is the local / LF-submittable implementation. The reference RA delegates to an internal ACME-style cert service, and any cloud adapter (a hosted ACME CA such as Let's Encrypt, AWS Private CA, GCP CAS) can replace ServerSelfCA without touching the service layer — the port (ServerCertificateIssuer) is the stable contract.

Because this CA is its own trust root, it plays the provider role in the order lifecycle itself: CreateOrder self-issues the domain-control challenge tokens (the same tokens an external ACME provider would mint), and FinalizeOrder signs synchronously, trusting the RA's challenge-presence gate as the authoritative domain validation. Orders carry no server-side state — the order ref exists so the lifecycle is uniform across providers.

Kept distinct from SelfCA (the identity CA) so operators can rotate the two roots independently and publish the server-CA trust anchor separately from the identity-CA trust anchor. Operators that want to consolidate the two can wire the same SelfCA instance behind both ports; there's no functional difference at the x509 layer, only a key-management convention.

func NewServerSelfCA

func NewServerSelfCA(dataDir, org string, validityDays int, opts ...ServerSelfCAOption) (*ServerSelfCA, error)

NewServerSelfCA opens (or creates) a self-signed server CA in the given directory. The root certificate has the organization name set to org and a validity of validityDays days.

The CA key and certificate are persisted under <dataDir> as `server-root.key` / `server-root.crt` (note the `server-` prefix so they coexist with the identity CA's `root.key` / `root.crt`).

func (*ServerSelfCA) CreateOrder added in v0.1.6

func (c *ServerSelfCA) CreateOrder(ctx context.Context, fqdn string) (*domain.CertificateOrder, error)

CreateOrder opens a certificate order for the FQDN, self-issuing the domain-control challenge tokens. Because this CA is its own trust root there is no remote order to track — the order ref is a random handle that exists so the lifecycle (and its persistence) is identical to external providers'. Both DNS-01 and HTTP-01 challenges are offered; the owner satisfies whichever is easier to publish, exactly as with an ACME provider.

func (*ServerSelfCA) FinalizeOrder added in v0.1.6

func (c *ServerSelfCA) FinalizeOrder(
	ctx context.Context,
	req port.FinalizeOrderRequest,
) (*port.IssuedCert, error)

FinalizeOrder signs the order's server CSR. The resulting certificate has the request FQDN as a DNS SAN and the standard TLS server-auth EKU, and is valid for serverTTL. Signing is synchronous and never returns port.ErrOrderPending.

Domain validation: the RA's challenge-presence gate runs before every FinalizeOrder call and is authoritative for this CA (it IS the CA's validation — there is no separate provider to convince), so req.Verified is not re-checked here.

func (*ServerSelfCA) GetCACertificate

func (c *ServerSelfCA) GetCACertificate(ctx context.Context) (string, error)

GetCACertificate returns the server-CA root certificate PEM. Operators publish this separately from the identity-CA root so relying parties can trust server certs without also trusting identity certs (or vice versa).

type ServerSelfCAOption

type ServerSelfCAOption func(*ServerSelfCA)

ServerSelfCAOption configures the server CA at construction time.

func WithOrderTTL added in v0.1.6

func WithOrderTTL(d time.Duration) ServerSelfCAOption

WithOrderTTL sets the lifetime of certificate orders (the window the domain owner has to publish a challenge artifact). Default is 7 days, matching ACME-provider order lifetimes; the registration and renewal flows clamp their own shorter windows on top.

func WithServerCertTTL

func WithServerCertTTL(d time.Duration) ServerSelfCAOption

WithServerCertTTL sets the validity period of issued server certs. Default is 90 days — matches the reference RA's ACME-style rolling validity.

type ValidatorOption

type ValidatorOption func(*X509Validator)

ValidatorOption configures an X509Validator.

func WithSkipChainVerify

func WithSkipChainVerify() ValidatorOption

WithSkipChainVerify disables chain verification against public roots. Use only in local-dev configurations where the operator may submit self-signed BYOC certificates for testing.

type X509Validator

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

X509Validator implements port.CertificateValidator using Go crypto/x509. BYOC server certificates are validated for format, FQDN match, validity period, algorithm allowlist, and key strength. Chain validation against public roots is performed with the OS root pool; callers can opt out of chain verification for local-dev flows via WithSkipChainVerify.

func NewX509Validator

func NewX509Validator(opts ...ValidatorOption) *X509Validator

NewX509Validator constructs a validator with the given options.

func (*X509Validator) ValidateIdentityCSR

func (v *X509Validator) ValidateIdentityCSR(
	ctx context.Context,
	csrPEM string,
	expectedAnsName string,
) error

ValidateIdentityCSR implements port.CertificateValidator.

func (*X509Validator) ValidateServerCSR

func (v *X509Validator) ValidateServerCSR(
	ctx context.Context,
	csrPEM string,
	expectedFQDN string,
) error

ValidateServerCSR implements port.CertificateValidator for the server-cert issuance path. Server CSRs carry the agent's FQDN as a DNS SAN (TLS server-auth convention, distinct from the identity CSR's URI SAN).

func (*X509Validator) ValidateServerCertificate

func (v *X509Validator) ValidateServerCertificate(
	ctx context.Context,
	leafPEM, chainPEM, expectedFQDN string,
) (*port.ValidatedCert, error)

ValidateServerCertificate implements port.CertificateValidator.

Directories

Path Synopsis
Package acmetest provides an in-process fake RFC 8555 server for exercising the ACME issuer adapter without network access.
Package acmetest provides an in-process fake RFC 8555 server for exercising the ACME issuer adapter without network access.

Jump to

Keyboard shortcuts

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