Documentation
¶
Overview ¶
Package cert provides certificate-handling adapter implementations: the self-signed identity CA and the BYOC server-certificate validator.
Index ¶
- type ACMEIssuer
- type ACMEIssuerOption
- type SelfCA
- func (c *SelfCA) GetCACertificate(ctx context.Context) (string, error)
- func (c *SelfCA) IsRevoked(serialHex string) bool
- func (c *SelfCA) IssueIdentityCertificate(ctx context.Context, csrPEM string, ansName string) (*port.IssuedCert, error)
- func (c *SelfCA) RevokeCertificate(ctx context.Context, req port.RevokeCertificateRequest) error
- type SelfCAOption
- type ServerSelfCA
- type ServerSelfCAOption
- type ValidatorOption
- type X509Validator
- func (v *X509Validator) ValidateIdentityCSR(ctx context.Context, csrPEM string, expectedAnsName string) error
- func (v *X509Validator) ValidateServerCSR(ctx context.Context, csrPEM string, expectedFQDN string) error
- func (v *X509Validator) ValidateServerCertificate(ctx context.Context, leafPEM, chainPEM, expectedFQDN string) (*port.ValidatedCert, error)
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 ¶
GetCACertificate returns the root certificate PEM.
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 ¶
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.