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 ¶
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 ¶
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 ¶
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.
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 ¶
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 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 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.