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

edgecert

package
v0.17.1 Latest Latest
Warning

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

Go to latest
Published: Nov 1, 2026 License: AGPL-3.0 Imports: 30 Imported by: 0

Documentation

Overview

Package edgecert issues the edge's certificates when the edge cannot issue its own (R-169, R-174; notes-kubernetes-runtime-issue-72.md, "Certificates with several replicas").

On Kubernetes the edge is several Traefik replicas. Each ordering its own certificates would multiply Let's Encrypt rate-limit use and fail HTTP-01 whenever the CA's request reached another replica, and Traefik's open-source edition has no leader election for ACME. So Pando's leader is the one ACME client, in its edge pass (a cluster.Job): it orders what the routing adapter asks for, renews ahead of expiry, keeps every certificate and the account key sealed in Postgres (R-190), and hands them to the runtime, which writes them where every replica reads them. HTTP-01 challenges are answered by Pando's proxy from the database, on whichever replica the CA's request reaches.

lego is the ACME client, the library Traefik itself uses, so the DNS-01 provider codes and credential variables the Traefik adapter's settings already name mean the same thing here.

Index

Constants

View Source
const (
	// RenewBefore is how long before expiry a certificate is renewed. Let's
	// Encrypt issues for 90 days and recommends renewing at 60.
	RenewBefore = 30 * 24 * time.Hour

	// RetryAfter is how long a failed order waits before it is tried again,
	// so a hostname whose DNS is wrong does not spend the CA's limit of five
	// failed validations an hour.
	RetryAfter = time.Hour

	// LetsEncrypt is the CA used unless another directory is set.
	LetsEncrypt = "https://acme-v02.api.letsencrypt.org/directory"
)

Defaults [P].

Variables

View Source
var NamedDNSProviders = []string{"cloudflare", "route53", "digitalocean", "porkbun", "namecheap"}

NamedDNSProviders are the DNS-01 providers Pando issues through itself, the five the Traefik adapter offers by name (design 03 §4.4).

Functions

func ClientTrusting

func ClientTrusting(caFile string) (*http.Client, error)

ClientTrusting is an HTTP client for the CA that trusts the certificates in caFile beside the system's roots: a private ACME server, or a test CA such as Pebble, whose own certificate no public root signs (O-49). Empty caFile is nil, lego's default client.

func DNSProvider

func DNSProvider(code string, creds map[string]secret.Value) (challenge.Provider, error)

DNSProvider builds a DNS-01 provider from the settings' code and variables, read from the credentials given rather than from Pando's environment.

Types

type ACME

type ACME interface {
	// Obtain orders a certificate for domains with the account, proving
	// control with solver. It returns the account as the CA now knows it — a
	// new key and registration the first time — and the certificate.
	Obtain(ctx context.Context, account state.AcmeAccount, domains []string, solver Solver) (state.AcmeAccount, Issued, error)
}

ACME orders one certificate. Lego in production; a fake in tests.

type Challenges

type Challenges struct {
	Store interface {
		Challenge(ctx context.Context, token string) (string, bool, error)
	}
}

Challenges answers HTTP-01 requests from the database, for the router.

func (Challenges) KeyAuthorization

func (c Challenges) KeyAuthorization(ctx context.Context, token string) (string, bool, error)

KeyAuthorization is the answer for a pending token.

type HTTPSolver

type HTTPSolver interface {
	Present(ctx context.Context, domain, token, keyAuthorization string) error
	CleanUp(ctx context.Context, domain, token string) error
}

HTTPSolver publishes HTTP-01 answers.

type Held added in v0.17.0

type Held struct {
	Store interface {
		Certificate(ctx context.Context, name string) (state.EdgeCertificate, bool, error)
	}
	Clock clock.Clock
}

Held hands out the certificates the leader issued and orders none: what a control host that does not lead serves, so every control host's edge serves the one certificate issued for a hostname (R-417, O-68). Only the leader's Issuer talks to the CA.

func (Held) Ensure added in v0.17.0

func (h Held) Ensure(ctx context.Context, plan *api.CertificateIssue) ([]api.EdgeCertificate, error)

Ensure returns every unexpired certificate held for the plan's orders. One not issued yet is left out, and the edge serves what there is.

type Issued

type Issued struct {
	CertPEM []byte
	KeyPEM  secret.Value
}

Issued is a certificate chain and its key, in PEM.

type Issuer

type Issuer struct {
	Store  Store
	ACME   ACME
	Clock  clock.Clock
	Logger *zap.Logger

	// Directory is the ACME directory URL; LetsEncrypt when empty.
	Directory string
}

Issuer orders, renews and hands out the edge's certificates.

func (*Issuer) Ensure

func (i *Issuer) Ensure(ctx context.Context, plan *api.CertificateIssue) ([]api.EdgeCertificate, error)

Ensure orders every certificate the plan asks for that is missing, covers other names, or is within RenewBefore of expiry, and returns every certificate it holds for the plan that has not expired. An order that fails leaves the certificate it replaces in service; the failure is returned with the certificates, so the edge still serves what there is.

type Lego

type Lego struct {
	// HTTPClient reaches the CA. Nil is lego's default.
	HTTPClient *http.Client
}

Lego is the ACME client: lego, which Traefik also uses.

func (Lego) Obtain

func (l Lego) Obtain(ctx context.Context, account state.AcmeAccount, domains []string, solver Solver) (state.AcmeAccount, Issued, error)

Obtain orders one certificate.

type Solver

type Solver struct {
	Challenge string // api.ChallengeHTTP01 or api.ChallengeDNS01

	// HTTP answers HTTP-01: Present makes the key authorization available
	// at the token's path on every replica, CleanUp withdraws it.
	HTTP HTTPSolver

	DNSProvider    string
	DNSCredentials map[string]secret.Value
}

Solver is how an order proves control of its names.

type Store

type Store interface {
	Certificate(ctx context.Context, name string) (state.EdgeCertificate, bool, error)
	PutCertificate(ctx context.Context, c state.EdgeCertificate) error
	RecordFailure(ctx context.Context, name string, domains []string, message string, at time.Time) error
	Account(ctx context.Context, email, directory string) (state.AcmeAccount, bool, error)
	PutAccount(ctx context.Context, a state.AcmeAccount) error
	PutChallenge(ctx context.Context, token, keyAuthorization, domain string, expires time.Time) error
	DeleteChallenge(ctx context.Context, token string) error
	Challenge(ctx context.Context, token string) (string, bool, error)
}

Store is what the issuer keeps. *state.EdgeCertificates in production.

Jump to

Keyboard shortcuts

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