Documentation ¶
Overview ¶
Package acme provides an implementation of the Automatic Certificate Management Environment (ACME) spec. See https://tools.ietf.org/html/draft-ietf-acme-acme-02 for details.
Most common scenarios will want to use autocert subdirectory instead, which provides automatic access to certificates from Let's Encrypt and any other ACME-based CA.
This package is a work in progress and makes no API stability promises.
Index ¶
- Constants
- Variables
- func AcceptTOS(tosURL string) bool
- func JWKThumbprint(pub crypto.PublicKey) (string, error)
- func RateLimit(err error) (time.Duration, bool)
- type Account
- type Authorization
- type AuthorizationError
- type AuthzID
- type CRLReasonCode
- type CertOption
- type Challenge
- type Client
- func (c *Client) Accept(ctx context.Context, chal *Challenge) (*Challenge, error)
- func (c *Client) Authorize(ctx context.Context, domain string) (*Authorization, error)
- func (c *Client) CreateCert(ctx context.Context, csr []byte, exp time.Duration, bundle bool) (der [][]byte, certURL string, err error)
- func (c *Client) DNS01ChallengeRecord(token string) (string, error)
- func (c *Client) Discover(ctx context.Context) (Directory, error)
- func (c *Client) FetchCert(ctx context.Context, url string, bundle bool) ([][]byte, error)
- func (c *Client) GetAuthorization(ctx context.Context, url string) (*Authorization, error)
- func (c *Client) GetChallenge(ctx context.Context, url string) (*Challenge, error)
- func (c *Client) GetReg(ctx context.Context, url string) (*Account, error)
- func (c *Client) HTTP01ChallengePath(token string) string
- func (c *Client) HTTP01ChallengeResponse(token string) (string, error)
- func (c *Client) Register(ctx context.Context, a *Account, prompt func(tosURL string) bool) (*Account, error)
- func (c *Client) RevokeAuthorization(ctx context.Context, url string) error
- func (c *Client) RevokeCert(ctx context.Context, key crypto.Signer, cert []byte, reason CRLReasonCode) error
- func (c *Client) TLSALPN01ChallengeCert(token, domain string, opt ...CertOption) (cert tls.Certificate, err error)
- func (c *Client) TLSSNI01ChallengeCert(token string, opt ...CertOption) (cert tls.Certificate, name string, err error)
- func (c *Client) TLSSNI02ChallengeCert(token string, opt ...CertOption) (cert tls.Certificate, name string, err error)
- func (c *Client) UpdateReg(ctx context.Context, a *Account) (*Account, error)
- func (c *Client) WaitAuthorization(ctx context.Context, url string) (*Authorization, error)
- type Directory
- type Error
Constants ¶
const ( // LetsEncryptURL is the Directory endpoint of Let's Encrypt CA. LetsEncryptURL = "https://acme-v01.api.letsencrypt.org/directory" // ALPNProto is the ALPN protocol name used by a CA server when validating // tls-alpn-01 challenges. // // Package users must ensure their servers can negotiate the ACME ALPN in // order for tls-alpn-01 challenge verifications to succeed. // See the crypto/tls package's Config.NextProtos field. ALPNProto = "acme-tls/1" )
const ( StatusUnknown = "unknown" StatusPending = "pending" StatusProcessing = "processing" StatusValid = "valid" StatusInvalid = "invalid" StatusRevoked = "revoked" )
ACME server response statuses used to describe Authorization and Challenge states.
Variables ¶
var ErrUnsupportedKey = errors.New("acme: unknown key type; only RSA and ECDSA are supported")
ErrUnsupportedKey is returned when an unsupported key type is encountered.
Functions ¶
func AcceptTOS ¶
AcceptTOS always returns true to indicate the acceptance of a CA's Terms of Service during account registration. See Register method of Client for more details.
func JWKThumbprint ¶
JWKThumbprint creates a JWK thumbprint out of pub as specified in https://tools.ietf.org/html/rfc7638.
Types ¶
type Account ¶
type Account struct { // URI is the account unique ID, which is also a URL used to retrieve // account data from the CA. URI string // Contact is a slice of contact info used during registration. Contact []string // The terms user has agreed to. // A value not matching CurrentTerms indicates that the user hasn't agreed // to the actual Terms of Service of the CA. AgreedTerms string // Actual terms of a CA. CurrentTerms string // Authz is the authorization URL used to initiate a new authz flow. Authz string // Authorizations is a URI from which a list of authorizations // granted to this account can be fetched via a GET request. Authorizations string // Certificates is a URI from which a list of certificates // issued for this account can be fetched via a GET request. Certificates string }
Account is a user account. It is associated with a private key.
type Authorization ¶
type Authorization struct { // URI uniquely identifies a authorization. URI string // Status identifies the status of an authorization. Status string // Identifier is what the account is authorized to represent. Identifier AuthzID // Challenges that the client needs to fulfill in order to prove possession // of the identifier (for pending authorizations). // For final authorizations, the challenges that were used. Challenges []*Challenge // A collection of sets of challenges, each of which would be sufficient // to prove possession of the identifier. // Clients must complete a set of challenges that covers at least one set. // Challenges are identified by their indices in the challenges array. // If this field is empty, the client needs to complete all challenges. Combinations [][]int }
Authorization encodes an authorization response.
type AuthorizationError ¶
type AuthorizationError struct { // URI uniquely identifies the failed Authorization. URI string // Identifier is an AuthzID.Value of the failed Authorization. Identifier string // Errors is a collection of non-nil error values of Challenge items // of the failed Authorization. Errors []error }
AuthorizationError indicates that an authorization for an identifier did not succeed. It contains all errors from Challenge items of the failed Authorization.
func (*AuthorizationError) Error ¶
func (a *AuthorizationError) Error() string
type AuthzID ¶
type AuthzID struct { Type string // The type of identifier, e.g. "dns". Value string // The identifier itself, e.g. "example.org". }
AuthzID is an identifier that an account is authorized to represent.
type CRLReasonCode ¶
type CRLReasonCode int
CRLReasonCode identifies the reason for a certificate revocation.
const ( CRLReasonUnspecified CRLReasonCode = 0 CRLReasonKeyCompromise CRLReasonCode = 1 CRLReasonCACompromise CRLReasonCode = 2 CRLReasonAffiliationChanged CRLReasonCode = 3 CRLReasonSuperseded CRLReasonCode = 4 CRLReasonCessationOfOperation CRLReasonCode = 5 CRLReasonCertificateHold CRLReasonCode = 6 CRLReasonRemoveFromCRL CRLReasonCode = 8 CRLReasonPrivilegeWithdrawn CRLReasonCode = 9 CRLReasonAACompromise CRLReasonCode = 10 )
CRL reason codes as defined in RFC 5280.
type CertOption ¶
type CertOption interface {
// contains filtered or unexported methods
}
CertOption is an optional argument type for the TLS ChallengeCert methods for customizing a temporary certificate for TLS-based challenges.
func WithKey ¶
func WithKey(key crypto.Signer) CertOption
WithKey creates an option holding a private/public key pair. The private part signs a certificate, and the public part represents the signee.
func WithTemplate ¶
func WithTemplate(t *x509.Certificate) CertOption
WithTemplate creates an option for specifying a certificate template. See x509.CreateCertificate for template usage details.
In TLS ChallengeCert methods, the template is also used as parent, resulting in a self-signed certificate. The DNSNames field of t is always overwritten for tls-sni challenge certs.
type Challenge ¶
type Challenge struct { // Type is the challenge type, e.g. "http-01", "tls-sni-02", "dns-01". Type string // URI is where a challenge response can be posted to. URI string // Token is a random value that uniquely identifies the challenge. Token string // Status identifies the status of this challenge. Status string // Error indicates the reason for an authorization failure // when this challenge was used. // The type of a non-nil value is *Error. Error error }
Challenge encodes a returned CA challenge. Its Error field may be non-nil if the challenge is part of an Authorization with StatusInvalid.
type Client ¶
type Client struct { // Key is the account key used to register with a CA and sign requests. // Key.Public() must return a *rsa.PublicKey or *ecdsa.PublicKey. Key crypto.Signer // HTTPClient optionally specifies an HTTP client to use // instead of http.DefaultClient. HTTPClient *http.Client // DirectoryURL points to the CA directory endpoint. // If empty, LetsEncryptURL is used. // Mutating this value after a successful call of Client's Discover method // will have no effect. DirectoryURL string // RetryBackoff computes the duration after which the nth retry of a failed request // should occur. The value of n for the first call on failure is 1. // The values of r and resp are the request and response of the last failed attempt. // If the returned value is negative or zero, no more retries are done and an error // is returned to the caller of the original method. // // Requests which result in a 4xx client error are not retried, // except for 400 Bad Request due to "bad nonce" errors and 429 Too Many Requests. // // If RetryBackoff is nil, a truncated exponential backoff algorithm // with the ceiling of 10 seconds is used, where each subsequent retry n // is done after either ("Retry-After" + jitter) or (2^n seconds + jitter), // preferring the former if "Retry-After" header is found in the resp. // The jitter is a random value up to 1 second. RetryBackoff func(n int, r *http.Request, resp *http.Response) time.Duration // contains filtered or unexported fields }
Client is an ACME client. The only required field is Key. An example of creating a client with a new key is as follows:
key, err := rsa.GenerateKey(rand.Reader, 2048) if err != nil { log.Fatal(err) } client := &Client{Key: key}
func (*Client) Accept ¶
Accept informs the server that the client accepts one of its challenges previously obtained with c.Authorize.
The server will then perform the validation asynchronously.
func (*Client) Authorize ¶
Authorize performs the initial step in an authorization flow. The caller will then need to choose from and perform a set of returned challenges using c.Accept in order to successfully complete authorization.
If an authorization has been previously granted, the CA may return a valid authorization (Authorization.Status is StatusValid). If so, the caller need not fulfill any challenge and can proceed to requesting a certificate.
func (*Client) CreateCert ¶
func (c *Client) CreateCert(ctx context.Context, csr []byte, exp time.Duration, bundle bool) (der [][]byte, certURL string, err error)
CreateCert requests a new certificate using the Certificate Signing Request csr encoded in DER format. The exp argument indicates the desired certificate validity duration. CA may issue a certificate with a different duration. If the bundle argument is true, the returned value will also contain the CA (issuer) certificate chain.
In the case where CA server does not provide the issued certificate in the response, CreateCert will poll certURL using c.FetchCert, which will result in additional round-trips. In such a scenario, the caller can cancel the polling with ctx.
CreateCert returns an error if the CA's response or chain was unreasonably large. Callers are encouraged to parse the returned value to ensure the certificate is valid and has the expected features.
func (*Client) DNS01ChallengeRecord ¶
DNS01ChallengeRecord returns a DNS record value for a dns-01 challenge response. A TXT record containing the returned value must be provisioned under "_acme-challenge" name of the domain being validated.
The token argument is a Challenge.Token value.
func (*Client) Discover ¶
Discover performs ACME server discovery using c.DirectoryURL.
It caches successful result. So, subsequent calls will not result in a network round-trip. This also means mutating c.DirectoryURL after successful call of this method will have no effect.
func (*Client) FetchCert ¶
FetchCert retrieves already issued certificate from the given url, in DER format. It retries the request until the certificate is successfully retrieved, context is cancelled by the caller or an error response is received.
The returned value will also contain the CA (issuer) certificate if the bundle argument is true.
FetchCert returns an error if the CA's response or chain was unreasonably large. Callers are encouraged to parse the returned value to ensure the certificate is valid and has expected features.
func (*Client) GetAuthorization ¶
GetAuthorization retrieves an authorization identified by the given URL.
If a caller needs to poll an authorization until its status is final, see the WaitAuthorization method.
func (*Client) GetChallenge ¶
GetChallenge retrieves the current status of an challenge.
A client typically polls a challenge status using this method.
func (*Client) GetReg ¶
GetReg retrieves an existing registration. The url argument is an Account URI.
func (*Client) HTTP01ChallengePath ¶
HTTP01ChallengePath returns the URL path at which the response for an http-01 challenge should be provided by the servers. The response value can be obtained with HTTP01ChallengeResponse.
The token argument is a Challenge.Token value.
func (*Client) HTTP01ChallengeResponse ¶
HTTP01ChallengeResponse returns the response for an http-01 challenge. Servers should respond with the value to HTTP requests at the URL path provided by HTTP01ChallengePath to validate the challenge and prove control over a domain name.
The token argument is a Challenge.Token value.
func (*Client) Register ¶
func (c *Client) Register(ctx context.Context, a *Account, prompt func(tosURL string) bool) (*Account, error)
Register creates a new account registration by following the "new-reg" flow. It returns the registered account. The account is not modified.
The registration may require the caller to agree to the CA's Terms of Service (TOS). If so, and the account has not indicated the acceptance of the terms (see Account for details), Register calls prompt with a TOS URL provided by the CA. Prompt should report whether the caller agrees to the terms. To always accept the terms, the caller can use AcceptTOS.
func (*Client) RevokeAuthorization ¶
RevokeAuthorization relinquishes an existing authorization identified by the given URL. The url argument is an Authorization.URI value.
If successful, the caller will be required to obtain a new authorization using the Authorize method before being able to request a new certificate for the domain associated with the authorization.
It does not revoke existing certificates.
func (*Client) RevokeCert ¶
func (c *Client) RevokeCert(ctx context.Context, key crypto.Signer, cert []byte, reason CRLReasonCode) error
RevokeCert revokes a previously issued certificate cert, provided in DER format.
The key argument, used to sign the request, must be authorized to revoke the certificate. It's up to the CA to decide which keys are authorized. For instance, the key pair of the certificate may be authorized. If the key is nil, c.Key is used instead.
func (*Client) TLSALPN01ChallengeCert ¶
func (c *Client) TLSALPN01ChallengeCert(token, domain string, opt ...CertOption) (cert tls.Certificate, err error)
TLSALPN01ChallengeCert creates a certificate for TLS-ALPN-01 challenge response. Servers can present the certificate to validate the challenge and prove control over a domain name. For more details on TLS-ALPN-01 see https://tools.ietf.org/html/draft-shoemaker-acme-tls-alpn-00#section-3
The token argument is a Challenge.Token value. If a WithKey option is provided, its private part signs the returned cert, and the public part is used to specify the signee. If no WithKey option is provided, a new ECDSA key is generated using P-256 curve.
The returned certificate is valid for the next 24 hours and must be presented only when the server name in the TLS ClientHello matches the domain, and the special acme-tls/1 ALPN protocol has been specified.
func (*Client) TLSSNI01ChallengeCert ¶
func (c *Client) TLSSNI01ChallengeCert(token string, opt ...CertOption) (cert tls.Certificate, name string, err error)
TLSSNI01ChallengeCert creates a certificate for TLS-SNI-01 challenge response. Servers can present the certificate to validate the challenge and prove control over a domain name.
The implementation is incomplete in that the returned value is a single certificate, computed only for Z0 of the key authorization. ACME CAs are expected to update their implementations to use the newer version, TLS-SNI-02. For more details on TLS-SNI-01 see https://tools.ietf.org/html/draft-ietf-acme-acme-01#section-7.3.
The token argument is a Challenge.Token value. If a WithKey option is provided, its private part signs the returned cert, and the public part is used to specify the signee. If no WithKey option is provided, a new ECDSA key is generated using P-256 curve.
The returned certificate is valid for the next 24 hours and must be presented only when the server name of the TLS ClientHello matches exactly the returned name value.
func (*Client) TLSSNI02ChallengeCert ¶
func (c *Client) TLSSNI02ChallengeCert(token string, opt ...CertOption) (cert tls.Certificate, name string, err error)
TLSSNI02ChallengeCert creates a certificate for TLS-SNI-02 challenge response. Servers can present the certificate to validate the challenge and prove control over a domain name. For more details on TLS-SNI-02 see https://tools.ietf.org/html/draft-ietf-acme-acme-03#section-7.3.
The token argument is a Challenge.Token value. If a WithKey option is provided, its private part signs the returned cert, and the public part is used to specify the signee. If no WithKey option is provided, a new ECDSA key is generated using P-256 curve.
The returned certificate is valid for the next 24 hours and must be presented only when the server name in the TLS ClientHello matches exactly the returned name value.
func (*Client) UpdateReg ¶
UpdateReg updates an existing registration. It returns an updated account copy. The provided account is not modified.
func (*Client) WaitAuthorization ¶
WaitAuthorization polls an authorization at the given URL until it is in one of the final states, StatusValid or StatusInvalid, the ACME CA responded with a 4xx error code, or the context is done.
It returns a non-nil Authorization only if its Status is StatusValid. In all other cases WaitAuthorization returns an error. If the Status is StatusInvalid, the returned error is of type *AuthorizationError.
type Directory ¶
type Directory struct { // RegURL is an account endpoint URL, allowing for creating new // and modifying existing accounts. RegURL string // AuthzURL is used to initiate Identifier Authorization flow. AuthzURL string // CertURL is a new certificate issuance endpoint URL. CertURL string // RevokeURL is used to initiate a certificate revocation flow. RevokeURL string // Term is a URI identifying the current terms of service. Terms string // Website is an HTTP or HTTPS URL locating a website // providing more information about the ACME server. Website string // CAA consists of lowercase hostname elements, which the ACME server // recognises as referring to itself for the purposes of CAA record validation // as defined in RFC6844. CAA []string }
Directory is ACME server discovery data.
type Error ¶
type Error struct { // StatusCode is The HTTP status code generated by the origin server. StatusCode int // ProblemType is a URI reference that identifies the problem type, // typically in a "urn:acme:error:xxx" form. ProblemType string // Detail is a human-readable explanation specific to this occurrence of the problem. Detail string // Header is the original server error response headers. // It may be nil. Header http.Header }
Error is an ACME error, defined in Problem Details for HTTP APIs doc http://tools.ietf.org/html/draft-ietf-appsawg-http-problem.