Documentation
¶
Overview ¶
Package acme is a pure-Go (CGO-free), MRI-faithful reimplementation of the surface of Ruby's acme-client gem — the ACME / Let's Encrypt protocol client.
It mirrors the ergonomics of Acme::Client while delegating the ACME/JWS protocol itself to the standard, pure-Go golang.org/x/crypto/acme client, so no part of the RFC 8555 wire protocol is reimplemented here.
The Ruby object graph is reproduced with idiomatic Go types:
client, _ := acme.NewClient(accountKey, directoryURL)
account, _ := client.NewAccount(ctx, []string{"mailto:me@example.com"}, true)
order, _ := client.NewOrder(ctx, []string{"example.com"})
authzs, _ := order.Authorizations(ctx)
chal := authzs[0].HTTP01()
ka, _ := chal.KeyAuthorization() // token.thumbprint to serve
_ = chal.RequestValidation(ctx) // ask the CA to validate
csr, _ := acme.NewCSR(certKey, "example.com")
_ = order.Finalize(ctx, csr)
pem, _ := order.Certificate(ctx) // PEM certificate chain
The ACME transport is a host seam: an *http.Client can be injected with WithHTTPClient, and the retry policy with WithRetryBackoff, so the whole flow runs against an in-process mock ACME server with no live network and no real Let's Encrypt.
Problem documents returned by the CA are mapped onto an error tree rooted at *Error, with *Unauthorized, *RateLimited, *BadNonce and *Malformed mirroring the Acme::Client::Error subclasses.
Index ¶
- Constants
- func NewCSR(key crypto.Signer, names ...string) ([]byte, error)
- type Account
- type Authorization
- func (a *Authorization) Challenges() []*Challenge
- func (a *Authorization) DNS01() *Challenge
- func (a *Authorization) Domain() string
- func (a *Authorization) HTTP01() *Challenge
- func (a *Authorization) Status() string
- func (a *Authorization) TLSALPN01() *Challenge
- func (a *Authorization) URL() string
- func (a *Authorization) Wildcard() bool
- type BadNonce
- type Challenge
- func (ch *Challenge) Error() error
- func (ch *Challenge) KeyAuthorization() (string, error)
- func (ch *Challenge) Reload(ctx context.Context) error
- func (ch *Challenge) RequestValidation(ctx context.Context) error
- func (ch *Challenge) Status() string
- func (ch *Challenge) Token() string
- func (ch *Challenge) Type() string
- func (ch *Challenge) URL() string
- type Client
- type Error
- type Malformed
- type Option
- type Order
- func (o *Order) Authorizations(ctx context.Context) ([]*Authorization, error)
- func (o *Order) Certificate(ctx context.Context) (string, error)
- func (o *Order) Finalize(ctx context.Context, csr []byte) error
- func (o *Order) Identifiers() []string
- func (o *Order) Reload(ctx context.Context) error
- func (o *Order) Status() string
- func (o *Order) URL() string
- type RateLimited
- type Unauthorized
Constants ¶
const ( ChallengeHTTP01 = "http-01" ChallengeDNS01 = "dns-01" ChallengeTLSALPN01 = "tls-alpn-01" )
ACME challenge type identifiers.
Variables ¶
This section is empty.
Functions ¶
func NewCSR ¶
NewCSR builds a DER-encoded PKCS#10 certificate signing request for the given key and DNS names, suitable for Order.Finalize. The first name becomes the subject common name and every name is included as a DNS SAN, mirroring the CSR that Acme::Client::CertificateRequest produces.
Types ¶
type Account ¶
type Account struct {
// URL is the account resource URL (the KID used to sign later requests).
URL string
// Status is the account status, e.g. "valid".
Status string
// Contact is the list of contact URIs registered for the account.
Contact []string
}
Account is a registered ACME account, mirroring the account object returned by Acme::Client#new_account.
type Authorization ¶
type Authorization struct {
// contains filtered or unexported fields
}
Authorization is an authorization for a single identifier, mirroring the Acme::Client authorization object.
func (*Authorization) Challenges ¶
func (a *Authorization) Challenges() []*Challenge
Challenges returns every challenge offered for the authorization, mirroring Authorization#challenges.
func (*Authorization) DNS01 ¶
func (a *Authorization) DNS01() *Challenge
DNS01 returns the dns-01 challenge, or nil if the CA did not offer one. Mirrors Authorization#dns01.
func (*Authorization) Domain ¶
func (a *Authorization) Domain() string
Domain returns the identifier value this authorization is for.
func (*Authorization) HTTP01 ¶
func (a *Authorization) HTTP01() *Challenge
HTTP01 returns the http-01 challenge, or nil if the CA did not offer one. Mirrors Authorization#http01.
func (*Authorization) Status ¶
func (a *Authorization) Status() string
Status returns the authorization status, e.g. "pending" or "valid".
func (*Authorization) TLSALPN01 ¶
func (a *Authorization) TLSALPN01() *Challenge
TLSALPN01 returns the tls-alpn-01 challenge, or nil if the CA did not offer one. Mirrors Authorization#tls_alpn01.
func (*Authorization) URL ¶
func (a *Authorization) URL() string
URL returns the authorization resource URL.
func (*Authorization) Wildcard ¶
func (a *Authorization) Wildcard() bool
Wildcard reports whether the authorization is for a wildcard identifier.
type BadNonce ¶
type BadNonce struct{ Problem *Error }
BadNonce maps urn:ietf:params:acme:error:badNonce — the client sent an unacceptable anti-replay nonce. Mirrors Acme::Client::Error::BadNonce.
type Challenge ¶
type Challenge struct {
// contains filtered or unexported fields
}
Challenge is a single ACME challenge, mirroring the Acme::Client challenge object.
func (*Challenge) Error ¶
Error returns the reason the challenge failed, or nil, mirroring Challenge#error. The value is mapped onto the acme error tree.
func (*Challenge) KeyAuthorization ¶
KeyAuthorization returns the key authorization ("token.thumbprint") to be served for the challenge, mirroring Challenge#key_authorization.
func (*Challenge) Reload ¶
Reload re-fetches the challenge from the CA, refreshing its status and error, mirroring Challenge#reload.
func (*Challenge) RequestValidation ¶
RequestValidation tells the CA the client is ready to answer the challenge, mirroring Challenge#request_validation. The challenge's status is refreshed from the CA's response.
func (*Challenge) Status ¶
Status returns the challenge status, e.g. "pending" or "valid", mirroring Challenge#status.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is a pure-Go ACME client, mirroring Ruby's Acme::Client.
It is constructed from an account private key and the CA's directory URL and is the entry point for account registration and order creation.
func NewClient ¶
NewClient builds a Client from an account private key and a directory URL, mirroring Acme::Client.new(private_key:, directory:).
privateKey must be an RSA or ECDSA key (per RFC 7518); directory is the CA's ACME directory endpoint.
func (*Client) Account ¶
Account looks up the account already associated with the client's key, mirroring account lookup on an existing Acme::Client.
func (*Client) NewAccount ¶
func (c *Client) NewAccount(ctx context.Context, contact []string, termsOfServiceAgreed bool) (*Account, error)
NewAccount registers a new account with the CA, mirroring Acme::Client#new_account(contact:, terms_of_service_agreed:).
contact is a list of contact URIs (e.g. "mailto:me@example.com"); when termsOfServiceAgreed is true the client agrees to the CA's terms of service.
type Error ¶
type Error struct {
// ProblemType is the RFC 8555 problem type URN.
ProblemType string
// Detail is the human-readable explanation from the CA.
Detail string
// StatusCode is the HTTP status code the CA responded with.
StatusCode int
}
Error is the root of the ACME error tree, mirroring Acme::Client::Error.
It wraps an ACME problem document (RFC 8555 §6.7): ProblemType is the problem URN (e.g. "urn:ietf:params:acme:error:unauthorized"), Detail is the human-readable explanation and StatusCode is the HTTP status the CA returned.
type Malformed ¶
type Malformed struct{ Problem *Error }
Malformed maps urn:ietf:params:acme:error:malformed — the request message was malformed. Mirrors Acme::Client::Error::Malformed.
type Option ¶
type Option func(*Client)
Option configures a Client at construction time.
func WithHTTPClient ¶
WithHTTPClient injects the HTTP client used for every ACME request. This is the transport seam: tests point it at an in-process mock ACME server.
func WithRetryBackoff ¶
WithRetryBackoff installs a custom retry-backoff policy. Returning a non-positive duration disables further retries of a failed request. Mirrors the tunable retry behaviour exposed by the underlying transport.
type Order ¶
type Order struct {
// contains filtered or unexported fields
}
Order is a certificate order, mirroring the Acme::Client order object.
func (*Order) Authorizations ¶
func (o *Order) Authorizations(ctx context.Context) ([]*Authorization, error)
Authorizations fetches the authorization objects for the order, mirroring Order#authorizations.
func (*Order) Certificate ¶
Certificate returns the issued certificate chain as a PEM string, mirroring Order#certificate. If the chain was already downloaded by Order.Finalize it is returned directly; otherwise the order is reloaded and the chain fetched from the CA.
func (*Order) Finalize ¶
Finalize submits the certificate signing request to the CA, waits for the order to become valid and downloads the issued chain, mirroring Order#finalize(csr:). csr is the DER-encoded PKCS#10 request; use NewCSR to build one.
func (*Order) Identifiers ¶
Identifiers returns the DNS identifiers this order covers.
func (*Order) Reload ¶
Reload re-fetches the order from the CA, refreshing its status and URLs, mirroring Order#reload.
type RateLimited ¶
type RateLimited struct {
Problem *Error
// RetryAfter is the delay advertised by the CA's Retry-After header, if any.
RetryAfter time.Duration
}
RateLimited maps urn:ietf:params:acme:error:rateLimited — the request exceeds a rate limit. RetryAfter carries the parsed Retry-After hint when present. Mirrors Acme::Client::Error::RateLimited.
func (*RateLimited) Error ¶
func (e *RateLimited) Error() string
Error implements the error interface.
func (*RateLimited) Unwrap ¶
func (e *RateLimited) Unwrap() error
Unwrap exposes the underlying *Error.
type Unauthorized ¶
Unauthorized maps urn:ietf:params:acme:error:unauthorized — the client lacks authorization to act on a resource. Mirrors Acme::Client::Error::Unauthorized.
func (*Unauthorized) Error ¶
func (e *Unauthorized) Error() string
Error implements the error interface.
func (*Unauthorized) Unwrap ¶
func (e *Unauthorized) Unwrap() error
Unwrap exposes the underlying *Error so errors.As(err, new(*Error)) matches.
