client

package
v0.0.2 Latest Latest
Warning

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

Go to latest
Published: Nov 22, 2020 License: MPL-2.0 Imports: 20 Imported by: 0

Documentation

Overview

Package client provides a low-level ACME v2 client.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type B64CSR

type B64CSR string

B64CSR is the Base64URLSafe encoding of an x509 Certificate Signing Request (CSR)

type Client

type Client struct {
	// A parsed *url.URL pointer for the ACME server's directory URL.
	DirectoryURL *url.URL
	// A pointer to the Account object that is considered currently active for
	// signing JWS for ACME requests.
	ActiveAccount *resources.Account
	// A map of key identifiers to Signers. These keys are used for signing
	// operations that shouldn't use an Account's associated key.
	Keys map[string]crypto.Signer
	// A slice of Account object pointers. The ActiveAccount is selected from this
	// list of available accounts.
	Accounts []*resources.Account
	// Options controlling the Client's output.
	Output OutputOptions
	// Use POST-as-GET requests instead of GET
	PostAsGet bool
	// contains filtered or unexported fields
}

Client allows interaction with an ACME server. A client may have many Accounts, each associated with a keypair and corresponding server-side Account resource. Each client uses the ActiveAccount to authenticate requests to the ACME server. In addition to Accounts a client maintains a map of Keys holding private keys that can be used for signing CSRs when finalizing orders. Internally the Client uses the https://godoc.org/cpu/acmeshell/net package to perform HTTP requests to the ACME server.

The Client's DirectoryURL field is a parsed *url.URL for the ACME server's directory. The client configures itself with the correct URLs for ACME operations using the directory resource accessed at this URL. See https://ietf-wg-acme.github.io/acme/draft-ietf-acme-acme.html#rfc.section.7.1.1

The Client's ActiveAccount field is a pointer to an Account that should be used for authenticating ACME requests with JSON Web Signatures (JWS). Switching the ActiveAccount between entries from the Accounts array allows performing complex multi-user tests (e.g. verifying access control restrictions on resources) with an ACME server.

The Client's Keys field is a map of crypto.Signer's that can be used for signing operations that should not use the ActiveAccount's keypair. One example of this being helpful is for certificate signing requests (CSRs) used during order finalization which SHOULD NOT be the account keypair (see https://ietf-wg-acme.github.io/acme/draft-ietf-acme-acme.html#rfc.section.11.1). Each signer is indexed in the Keys map by a string key identifier which will often be a human readable name (e.g. "example-key", "cpu-throwaway"). The key identifier for the Keys entry has no relation to ACME JWS key identifiers.

The Client's Accounts field is a slice of Account object pointers. These are the available Accounts that have been registered by the client with the ACME server, or loaded from a previous session.

func NewClient

func NewClient(config ClientConfig) (*Client, error)

NewClient creates a Client instance from the given ClientConfig. If the config is not valid or if another error occurs it will be returned along with a nil Client.

TODO(@cpu): This function is way too long/messy. Refactor ASAP!

func (*Client) ActiveAccountID

func (c *Client) ActiveAccountID() string

ActiveAccountID returns the ID of the ActiveAccount. If the ActiveAccount is nil, an empty string is returned. If the ActiveAccount has not yet been created with the ACME server an empty string is returned.

func (*Client) AuthzByIdentifier

func (c *Client) AuthzByIdentifier(order *resources.Order, identifier string) (*resources.Authorization, error)

func (*Client) CSR

func (c *Client) CSR(commonName string, names []string, keyID string) (B64CSR, PEMCSR, error)

CSR produces a CertificateSigningRequest for the provided commonName and SAN names. The keyID will be used to look up a client Keys entry to sign the CSR. The CSR will use the public component of this key as the CSR public key. If no commonName is provided the first of the names will be used. CSR returns the PEM encoding of the CSR as well as the Base64URL encoding of the CSR.

func (*Client) CreateAccount

func (c *Client) CreateAccount(acct *resources.Account) error

CreateAccount creates the given Account resource with the ACME server. The Account is updated with the ID returned in the server's response's Location header if the operation is successful, otherwise an error is returned.

Important: This function always unconditionally agrees to the server's terms of service (e.g. it sends "termsOfServiceAgreed:"true" in all account creation requests). This is one of MANY reasons why you should not be using ACME Shell for anything except development and testing!

For more information on account creation see https://tools.ietf.org/html/rfc8555#section-7.3

func (*Client) CreateOrder

func (c *Client) CreateOrder(order *resources.Order) error

CreateOrder creates the given Order resource with the ACME server. If the operation is successful, the order is mutated in place with the response from the server's reply. Otherwise a non-nil error is returned.

For more information on Order creation see "Applying for Certificate Issuance" in RFC 8555: https://tools.ietf.org/html/rfc8555#section-7.4

func (*Client) Directory

func (c *Client) Directory() (map[string]interface{}, error)

Directory fetches the ACME Directory resource from the ACME server and returns it deserialized as a map.

See https://tools.ietf.org/html/rfc8555#section-7.1.1

func (*Client) GetEndpointURL

func (c *Client) GetEndpointURL(name string) (string, bool)

GetEndpintURL gets a URL for a specific ACME endpoint URL by first fetching the ACME server's directory and then checking that directory resource for the a key with the given name. If the key is found its value is returned along with a true bool. If the key is not found an empty string is returned with a false bool.

func (*Client) GetURL

func (c *Client) GetURL(url string) (*net.NetResponse, error)

func (*Client) Nonce

func (c *Client) Nonce() (string, error)

Nonce satisfies the JWS "NonceSource" interface by using a nonce stored by the client from previous responses. That nonce value will be returned after first getting a replacement nonce to store from the ACME server's NewNonce endpoint. This ensures a constant supply of fresh nonces by always fetching a replacement at the same time we use the old nonce.

func (*Client) OrderByIndex

func (c *Client) OrderByIndex(index int) (*resources.Order, error)

func (*Client) PostAsGetURL

func (c *Client) PostAsGetURL(url string) (*net.NetResponse, error)

func (*Client) PostURL

func (c *Client) PostURL(url string, body []byte) (*net.NetResponse, error)

func (*Client) Printf

func (c *Client) Printf(format string, vals ...interface{})

TODO(@cpu): This is stupid

func (*Client) RefreshNonce

func (c *Client) RefreshNonce() error

RefreshNonce fetches a new nonce from the ACME server's NewNonce endpoint and stores it in the client's memory to be used in subsequent Nonce calls.

See https://tools.ietf.org/html/rfc8555#section-7.2

func (*Client) Rollover added in v0.0.2

func (c *Client) Rollover(newKey crypto.Signer) error

func (*Client) Sign

func (c *Client) Sign(url string, data []byte, opts *SigningOptions) (*SignResult, error)

Sign produces a SignResult by Signing the provided data (with a protected URL header) according to the SigningOptions provided. If no Signer is specified in the SigningOptions then the ActiveAccount's Signer is used. If the SigningOptions specify not to embed a JWK but do not specify a Key ID to use then the ActiveAccount's ID is used as the JWS Key ID. If the SigningOptions do not specify an explicit NonceSource the Client is used as the NonceSource.

func (*Client) UpdateAuthz

func (c *Client) UpdateAuthz(authz *resources.Authorization) error

UpdateAuthz refreshes a given Authz by fetching its ID URL from the ACME server. If this is successful the Authz is updated in place. Otherwise an error is returned.

Calling UpdateAuthz is required to refresh an Authz's Status field to synchronize the resource with the server-side representation.

func (*Client) UpdateChallenge

func (c *Client) UpdateChallenge(chall *resources.Challenge) error

UpdateChallenge refreshes a given Challenge by fetching its URL from the ACME server. If this is successful the Challenge is updated in place. Otherwise an error is returned.

func (*Client) UpdateDirectory

func (c *Client) UpdateDirectory() error

UpdateDirectory updates the Client's cached directory used when referencing the endpoints for updating nonces, creating accounts, and creating orders.

TODO(@cpu): I don't think it makes sense for both Directory and UpdateDirectory to be exported/defined on the client.

func (*Client) UpdateOrder

func (c *Client) UpdateOrder(order *resources.Order) error

UpdateOrder refreshes a given Order by fetching its ID URL from the ACME server. If this is successful the Order is mutated in place. Otherwise a nil Order and a non-nil error are returned.

Calling UpdateOrder is required to refresh an Order's Status field to synchronize the resource with the server-side representation.

type ClientConfig

type ClientConfig struct {
	// A fully qualified URL for the ACME server's directory resource. Must
	// include an HTTP/HTTPS protocol prefix.
	DirectoryURL string
	// An optional file path to one or more PEM encoded CA certificates to be used
	// as trust roots for HTTPS requests to the ACME server.
	CACert string
	// An optional email address to use if AutoRegister is true and an Account is
	// created with the ACME server. It should not have a protocol prefix,
	// acmeshell will automatically add a "mailto://" prefix. This field only
	// supports one email address.
	ContactEmail string
	// An optional file path to a previously saved ACME Shell account. It will be
	// loaded and used as the ActiveAccount. If provided this field takes
	// precedence over AutoRegister and will prevent an account from being
	// auto-registered even if AutoRegister is true.
	AccountPath string
	// If AutoRegister is true NewClient will automatically create a new Account
	// with the ACME server and use it as the ActiveAccount. If ContactEmail is
	// specified it will be used as the new ACME account's Contact mailto address.
	AutoRegister bool
	// If POSTAsGET is true then GET requests to Orders, Authorizations,
	// Challenges and Certificates will be made as POST-as-GET requests. Using false
	// is suggested when interacting with legacy pre RFC 8555 ACME servers. It
	// will cause most requests to fail with modern RFC 8555 compatible servers.
	POSTAsGET bool
	// Initial OutputOptions settings
	InitialOutput OutputOptions
}

ClientConfig contains configuration options provided to NewClient when creating a Client instance.

The DirectoryURL field is a string containing the URL for the ACME server's directory endpoint. This field is mandatory and must not be empty. It should be a fully qualified URL with a HTTP/HTTPS protocol prefix ("http://" or "https://"). See https://ietf-wg-acme.github.io/acme/draft-ietf-acme-acme.html#rfc.section.7.1.1 for more information about the ACME directory resource.

The CACert field is an optional string containing a file path to a file containing one or more PEM encoded CA certificate that should be used as trust roots for HTTPS requests to the ACME server. If empty the default system roots are used. For example, if you are using Pebble as the ACME server, it should be the file path to the "test/certs/pebble.minica.pem" file from the Pebble source directory. If you are using a public ACME server with a trusted HTTPS certificate you should provide the path to a file containing the combination of all of the PEM encoded system trusted root CA certificates. Often this is something like "/etc/ssl/certs.pem".

The ContactEmail field is a string expected to contain a single email address or to be empty. It will be used as a "mailto://" contact address when auto-registering an ACME account. Because this field is only referenced during auto-registering an Account it is only used when AutoRegister is true. You can not include multiple email addresses in the ContactEmail field. For more complex account creation set AutoRegister to false and use the "newAccount" shell command.

The AccountPath field is a string expected to contain a file path for a previously saved Account, or to be empty. If the AccountPath field is populated NewClient will not auto-register an account (even when AutoRegister is true) and will instead load the Account serialized in the provided filepath. It will be the ActiveAccount once loaded.

type OutputOptions

type OutputOptions struct {
	// Print all HTTP requests made to the ACME server.
	PrintRequests bool
	// Print all HTTP responses from the ACME server.
	PrintResponses bool
	// Print all the input to JWS produced.
	PrintSignedData bool
	// Print the JSON serialization of all JWS produced.
	PrintJWS bool
	// Print HEAD requests to newNonce and the updated Replay-Nonce value.
	PrintNonceUpdates bool
}

OutputOptions holds runtime output settings for a client.

type PEMCSR

type PEMCSR string

PEMCSR is the PEM encoding of an x509 Certificate Signing Request (CSR)

type SignResult

type SignResult struct {
	// The url argument given to Sign.
	InputURL string
	// The data argument given to sign.
	InputData []byte
	// The JWS produced by signing the given data.
	JWS *jose.JSONWebSignature
	// The JWS in serialized form.
	SerializedJWS []byte
}

SignResult holds the input and output from a Sign operation.

type SigningOptions

type SigningOptions struct {
	// If true, embed the Account's public key as a JWK in the signed JWS instead
	// of using a KeyID header. This is useful for endpoints like NewAccount.
	// Setting EmbedKey to true is mutually exclusive with a non-empty KeyID.
	EmbedKey bool
	// If not-empty, a KeyID value to use for the JWS Key ID header to identify the ACME
	// account. If empty the Account's ID field will be used. Providing a KeyID is
	// mutually exclusive with setting EmbedKey to true.
	KeyID string
	// A Signer to use to sign the JWS. The associated public key
	// will be computed and used for the embedded JWK if EmbedKey is true.
	Signer crypto.Signer
	// NonceSource is a jose.NonceSource implementation that provides the
	// Replay-Nonce header value for the produced JWS. Often this will be a Client
	// instance.
	NonceSource jose.NonceSource
}

SigningOptions allows specifying signature related options when calling an Account's Sign function.

Jump to

Keyboard shortcuts

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