acme

package
v0.0.0-...-9a6eaac Latest Latest
Warning

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

Go to latest
Published: Jan 3, 2020 License: BSD-3-Clause, MIT, Apache-2.0 Imports: 27 Imported by: 0

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

View Source
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"
)
View Source
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

View Source
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

func AcceptTOS(tosURL string) bool

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

func JWKThumbprint(pub crypto.PublicKey) (string, error)

JWKThumbprint creates a JWK thumbprint out of pub as specified in https://tools.ietf.org/html/rfc7638.

func RateLimit

func RateLimit(err error) (time.Duration, bool)

RateLimit reports whether err represents a rate limit error and any Retry-After duration returned by the server.

See the following for more details on rate limiting: https://tools.ietf.org/html/draft-ietf-acme-acme-05#section-5.6

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.
	//
	// The following algorithms are supported:
	// RS256, ES256, ES384 and ES512.
	// See RFC7518 for more details about the algorithms.
	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

func (c *Client) Accept(ctx context.Context, chal *Challenge) (*Challenge, error)

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

func (c *Client) Authorize(ctx context.Context, domain string) (*Authorization, error)

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) AuthorizeIP

func (c *Client) AuthorizeIP(ctx context.Context, ipaddr string) (*Authorization, error)

AuthorizeIP is the same as Authorize but requests IP address authorization. Clients which successfully obtain such authorization may request to issue a certificate for IP addresses.

See the ACME spec extension for more details about IP address identifiers: https://tools.ietf.org/html/draft-ietf-acme-ip.

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

func (c *Client) DNS01ChallengeRecord(token string) (string, error)

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

func (c *Client) Discover(ctx context.Context) (Directory, error)

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

func (c *Client) FetchCert(ctx context.Context, url string, bundle bool) ([][]byte, error)

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

func (c *Client) GetAuthorization(ctx context.Context, url string) (*Authorization, error)

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

func (c *Client) GetChallenge(ctx context.Context, url string) (*Challenge, error)

GetChallenge retrieves the current status of an challenge.

A client typically polls a challenge status using this method.

func (*Client) GetReg

func (c *Client) GetReg(ctx context.Context, url string) (*Account, error)

GetReg retrieves an existing registration. The url argument is an Account URI.

func (*Client) HTTP01ChallengePath

func (c *Client) HTTP01ChallengePath(token string) string

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

func (c *Client) HTTP01ChallengeResponse(token string) (string, error)

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

func (c *Client) RevokeAuthorization(ctx context.Context, url string) error

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

func (c *Client) UpdateReg(ctx context.Context, a *Account) (*Account, error)

UpdateReg updates an existing registration. It returns an updated account copy. The provided account is not modified.

func (*Client) WaitAuthorization

func (c *Client) WaitAuthorization(ctx context.Context, url string) (*Authorization, error)

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.

func (*Error) Error

func (e *Error) Error() string

Directories

Path Synopsis
Package autocert provides automatic access to certificates from Let's Encrypt and any other ACME-based CA.
Package autocert provides automatic access to certificates from Let's Encrypt and any other ACME-based CA.
internal/acmetest
Package acmetest provides types for testing acme and autocert packages.
Package acmetest provides types for testing acme and autocert packages.

Jump to

Keyboard shortcuts

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