Documentation
¶
Overview ¶
Package est provides an EST client and server as defined by RFC7030.
Index ¶
- func NewRouter(cfg *ServerConfig) (http.Handler, error)
- func SRPUsernameFromContext(ctx context.Context) string
- func WithSRPUsername(ctx context.Context, username string) context.Context
- type Attribute
- type AttributeValueSET
- type CA
- type CSRAttrs
- type Client
- func (c *Client) CACerts(ctx context.Context) ([]*x509.Certificate, error)
- func (c *Client) CSRAttrs(ctx context.Context) (CSRAttrs, error)
- func (c *Client) Enroll(ctx context.Context, r *x509.CertificateRequest) (*x509.Certificate, error)
- func (c *Client) Reenroll(ctx context.Context, r *x509.CertificateRequest) (*x509.Certificate, error)
- func (c *Client) ServerKeyGen(ctx context.Context, r *x509.CertificateRequest) (*x509.Certificate, []byte, error)
- func (c *Client) TPMEnroll(ctx context.Context, r *x509.CertificateRequest, ekCerts []*x509.Certificate, ...) ([]byte, []byte, []byte, error)
- type Error
- type Logger
- type Refusal
- type RefusalRecorder
- type ServerConfig
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func NewRouter ¶
func NewRouter(cfg *ServerConfig) (http.Handler, error)
NewRouter creates a new EST server mux. The additional path segment of a request may be at most 255 bytes, a longer one answers 414. The CA certificates of at most 1024 segments are kept for client certificate checks.
func SRPUsernameFromContext ¶
SRPUsernameFromContext returns the username set by WithSRPUsername, or an empty string if the request did not sign in with TLS-SRP.
func WithSRPUsername ¶
WithSRPUsername returns a copy of ctx that carries the username a client proved in a TLS-SRP handshake (RFC 5054). A server that terminates TLS-SRP sets it on each request before the router handles it. The router then accepts /simplereenroll without a client certificate, as libest does. An empty username returns ctx unchanged.
Types ¶
type Attribute ¶
type Attribute struct {
Type asn1.ObjectIdentifier
Values AttributeValueSET
}
Attribute is a CSR Attribute type, as defined by RFC7030 4.5.2.
type AttributeValueSET ¶
type AttributeValueSET []interface{}
AttributeValueSET is an ASN.1 SET of CSR attribute values.
type CA ¶
type CA interface {
// CACerts requests a copy of the current CA certificates. See RFC7030 4.1.
CACerts(ctx context.Context, aps string, r *http.Request) ([]*x509.Certificate, error)
// CSRAttrs requests a list of CA-desired CSR attributes. The returned list
// may be empty. See RFC7030 4.5.
CSRAttrs(ctx context.Context, aps string, r *http.Request) (CSRAttrs, error)
// Enroll requests a new certificate. See RFC7030 4.2.
Enroll(ctx context.Context, csr *x509.CertificateRequest, aps string, r *http.Request) (*x509.Certificate, error)
// Reenroll requests renewal/rekey of an existing certificate. See RFC7030
// 4.2. cert is the TLS client certificate being renewed. The server has
// checked that it chains to the certificates CACerts returned, is within
// its validity period and allows client authentication or has let
// ServerConfig.VerifyClientCertificate decide. It does not check
// revocation, so a CA that revokes certificates must refuse a revoked
// one here. cert is nil when the client sent no certificate and signed
// in with TLS-SRP or, with ServerConfig.PasswordRenewal, with HTTP Basic
// credentials or a bearer token. Then the CA decides which certificate
// is renewed and must choose it by the signed-in identity, not by the
// Subject of csr, which any user could name. SRPUsernameFromContext
// returns the TLS-SRP username, r.BasicAuth the HTTP Basic one and the
// Authorization header the bearer token.
Reenroll(ctx context.Context, cert *x509.Certificate, csr *x509.CertificateRequest, aps string, r *http.Request) (*x509.Certificate, error)
// ServerKeyGen requests a new certificate and a private key. The key must
// be returned as a DER-encoded PKCS8 PrivateKeyInfo structure if additional
// encryption is not being employed, or returned inside a CMS SignedData
// structure which itself is inside a CMS EnvelopedData structure. See
// RFC7030 4.4.
ServerKeyGen(ctx context.Context, csr *x509.CertificateRequest, aps string, r *http.Request) (*x509.Certificate, []byte, error)
// TPMEnroll requests a new certificate using the TPM 2.0 privacy-preserving
// protocol. An EK certificate chain with a length of at least one must be
// provided, along with the EK and AK public areas. The return values are an
// encrypted credential blob, an encrypted seed, and the certificate itself
// inside a CMS EnvelopedData encrypted with the credential as a pre-shared
// key.
TPMEnroll(ctx context.Context, csr *x509.CertificateRequest, ekcerts []*x509.Certificate, ekPub, akPub []byte, aps string, r *http.Request) ([]byte, []byte, []byte, error)
}
CA is a Certificate Authority backing an EST server. The server can be connected to any backing CA by providing an implementation of this interface.
All operations receive:
- a context, from which the EST server logger can be retrieved by calling LoggerFromContext
- the optional URI additional path segment (RFC7030 3.2.2)
- the HTTP request object from the server, from which the HTTP headers passed by the client (including the Host header, to support virtual servers) can be obtained
Any error object returned from these functions which implements Error will be used by the EST server to determine the HTTP response code, human-readable error description, and Retry-After header value, if applicable. Any other error will be treated as an internal server error.
type CSRAttrs ¶
type CSRAttrs struct {
OIDs []asn1.ObjectIdentifier
Attributes []Attribute
}
CSRAttrs contains CSR attributes as defined by RFC7030 4.5.
CSR attributes are defined by RFC7030 as a sequence of AttrOrOID, where AttrOrOID is a CHOICE of Object Identifier or Attribute. For ease of use, CRSAttrs provides separately a list of Object Identifiers, and a list of Attributes.
When the EST client retrieves and parses CSR attributes from an EST server, attribute values of the ASN.1 types: - OBJECT IDENTIFIER - BOOLEAN - INTEGER - most STRING types
will be unmarshalled into the Attribute.Values field as standard Go asn1.ObjectIdentifier, bool, *big.Int and string types where possible, and they can be retrieved via a type assertion. Other types will be unmarshalled into an asn1.RawValue structure and must be interpreted by the caller.
func (*CSRAttrs) Unmarshal ¶
Unmarshal parses an DER-encoded ASN.1 data structure and stores the result in the object. Attribute values of the ASN.1 types: - OBJECT IDENTIFIER - BOOLEAN - INTEGER - most STRING types
will be unmarshalled into standard Go asn1.ObjectIdentifier, bool, *big.Int and string types where possible, and can be retrieved via a type assertion. Other types will be unmarshalled into an asn1.RawValue structure and must be interpreted by the caller.
type Client ¶
type Client struct {
// Host is the host:path of the EST server excluding any URL path
// component, e.g. est.server.com:8443
Host string
// AdditionalPathSegment is an optional label for EST servers to provide
// service for multiple CAs. See RFC7030 3.2.2.
AdditionalPathSegment string
// ExplicitAnchor is the optional Explicit TA database. See RFC7030 3.6.1.
ExplicitAnchor *x509.CertPool
// ImplicitAnchor is an optional Implicit TA database. If nil, the system
// certificate pool will be used. See RFC7030 3.6.2.
ImplicitAnchor *x509.CertPool
// Certificates are the client certificates to present to the EST server
// during the handshake. If more than one certificate is provided, they
// should be provided in order, with the end-entity certificate first, and
// the root CA (or last intermediate CA) certificate last.
Certificates []*x509.Certificate
// PrivateKey is the private key associated with the end-entity TLS
// certificate. Any object implementing crypto.Signer may be used, to
// support private keys resident on a hardware security module (HSM),
// Trusted Platform Module (TPM) or other hardware device.
PrivateKey interface{}
// SigningKey is an optional private key to use for signing CSRs during initial enrollment.
//
// If not set, the challenge password field will not be included in the CSR.
SigningKey interface{}
// AdditionalHeaders are additional HTTP headers to include with the
// request to the EST server.
AdditionalHeaders map[string]string
// HostHeader overrides the default Host header for the HTTP request to the
// EST server, and is mostly useful for testing.
HostHeader string
// Username is an optional HTTP Basic Authentication username.
Username string
// Password is an optional HTTP Basic Authentication password.
Password string
// BearerToken is an optional HTTP Bearer authentication token (RFC
// 6750). It is sent as "Authorization: Bearer <token>" when Username is
// empty, so Basic authentication takes precedence.
BearerToken string
// DisableKeepAlives disables HTTP keep-alives if set.
DisableKeepAlives bool
// Proxy returns the proxy for the connection to the EST server, as
// http.Transport.Proxy does, or nil for a direct connection. If Proxy
// is nil, http.ProxyFromEnvironment applies, so the HTTPS_PROXY and
// NO_PROXY environment variables choose the proxy. The client reaches
// the server through an http or https proxy with a CONNECT tunnel, so
// the TLS handshake, OnConnect and the tls-unique value work as without
// a proxy. The user information of the proxy URL is sent as Basic
// Proxy-Authorization. An https proxy is checked against the system
// roots.
Proxy func(*http.Request) (*url.URL, error)
// InsecureSkipVerify controls whether the client verifies the EST server's
// certificate chain and host name. If true, the client accepts any
// certificate presented by the server and any host name in that certificate.
// In this mode, TLS is susceptible to man-in-the-middle attacks. This should
// be used only for testing. If used to obtain the CA certificates from an
// otherwise untrusted EST server, those certificates must be manually
// verified in some out-of-band manner before any further EST operations with
// that server are performed.
InsecureSkipVerify bool
// WrapTransport, if set, wraps the HTTP transport of every request. The
// wrapper sees each request and response, for example to record a
// protocol trace, and must pass every request on to the transport it
// wraps. The transport it wraps already bounds response bodies with
// MaxResponseBody.
WrapTransport func(http.RoundTripper) http.RoundTripper
// OnConnect, if set, is called with the connection of each operation
// after the TLS handshake and before the request is sent. The connection
// is a *tls.Conn, or a *srptls.Conn with TLS-SRP. OnConnect must not read
// from, write to or close it.
OnConnect func(net.Conn)
// AllowCertificateChain accepts an enroll, reenroll or serverkeygen
// response that carries CA certificates besides the issued certificate.
// RFC 7030 section 4.2.3 allows only the issued certificate, but some
// servers add its chain. The client then returns the one certificate
// that issued none of the others.
AllowCertificateChain bool
// MaxResponseBody bounds the size of a response body in bytes, including
// an error message and all parts of a multipart response. A larger
// response fails the operation. If zero, 1 MiB is used. A chain of large
// post-quantum CA certificates can exceed that, such as SLH-DSA-SHA2-256f
// certificates at about 50 KB each in base64. A negative value fails
// every operation.
MaxResponseBody int64
// SRPUsername, if set, signs in with TLS-SRP (RFC 5054) as this user
// with SRPPassword, as RFC 7030 section 3.3.3 allows. The password also
// authenticates the server, so ExplicitAnchor, ImplicitAnchor,
// InsecureSkipVerify and Certificates are not used. TLS-SRP runs over
// TLS 1.2 only. OnConnect then receives a *srptls.Conn from
// github.com/misiektoja/go-tls-srp.
SRPUsername string
// SRPPassword is the TLS-SRP password of SRPUsername.
SRPPassword string
// SRPMinGroupBits is the size of the smallest SRP group the client
// accepts from the server. If zero, 2048 bits.
SRPMinGroupBits int
}
Client is an EST client implementing the Enrollment over Secure Transport protocol as defined in RFC7030.
All EST client operations will return an error object implementing Error when the EST server returns any status other than 200 OK. The status code, description and, if applicable, retry-after seconds can be extracted from that object. In order to make the retry-after seconds available through this mechanism, note that a 202 Accepted response to enroll and reenroll operations is returned as an error for this purpose, even though 2** status codes indicate success.
func (*Client) Enroll ¶
func (c *Client) Enroll(ctx context.Context, r *x509.CertificateRequest) (*x509.Certificate, error)
Enroll requests a new certificate.
func (*Client) Reenroll ¶
func (c *Client) Reenroll(ctx context.Context, r *x509.CertificateRequest) (*x509.Certificate, error)
Reenroll renews an existing certificate.
func (*Client) ServerKeyGen ¶
func (c *Client) ServerKeyGen(ctx context.Context, r *x509.CertificateRequest) (*x509.Certificate, []byte, error)
ServerKeyGen requests a new certificate and a server-generated private key.
func (*Client) TPMEnroll ¶
func (c *Client) TPMEnroll( ctx context.Context, r *x509.CertificateRequest, ekCerts []*x509.Certificate, ekPub []byte, akPub []byte, ) ([]byte, []byte, []byte, error)
TPMEnroll requests a certificate using the TPM 2.0 privacy preserving protocol for distributing credentials for keys on a TPM.
type Error ¶
type Error interface {
// StatusCode returns the HTTP status code.
StatusCode() int
// Error returns a human-readable description of the error.
Error() string
// RetryAfter returns the value in seconds after which the client should
// retry the request.
RetryAfter() int
}
Error represents an error which can be translated into an HTTP status code and message, and optionally specify a Retry-After period.
type Logger ¶
type Logger interface {
// Errorf uses fmt.Sprintf to log a formatted message.
Errorf(format string, args ...interface{})
// Errorw logs a message with some additional context. The variadic
// key-value pairs are treated as they are in With.
Errorw(format string, keysAndValues ...interface{})
// Infof uses fmt.Sprintf to log a formatted message.
Infof(format string, args ...interface{})
// Infow logs a message with some additional context. The variadic
// key-value pairs are treated as they are in With.
Infow(format string, keysAndValues ...interface{})
// With adds a variadic number of key-values pairs to the logging context.
// The first element of the pair is used as the field key and should be a
// string. Passing a non-string key or passing an orphaned key panics.
With(keysAndValues ...interface{}) Logger
}
Logger is an interface for an EST server logger.
func LoggerFromContext ¶
LoggerFromContext returns a logger included in a context.
type Refusal ¶
type Refusal struct {
// Operation is the last segment of the request path, such as
// "simpleenroll" or "simplereenroll".
Operation string
// AdditionalPathSegment is the optional label from the request path.
AdditionalPathSegment string
// Status is the HTTP status code sent to the client.
Status int
// Reason is the error text sent to the client.
Reason string
// Request is the refused request. Its body may already have been read.
Request *http.Request
}
Refusal describes a request the server refused without asking the CA.
type RefusalRecorder ¶
RefusalRecorder records the requests the server refuses without asking the CA, such as a malformed request, an unsupported content type or a renewal whose subject changed. Authentication failures from CheckBasicAuth and errors returned by the CA are not reported, because the host made those decisions. Server faults are not reported either.
RecordRefusal runs before the response is written, with a context that is not cancelled when the client disconnects, so it must bound its own work. A returned error is logged and does not change the response.
type ServerConfig ¶
type ServerConfig struct {
// CA is an interface to the Certificate Authority backing the EST server.
CA CA
// Logger is an optional logger. The logger can be retrieved by the backing
// CA from the HTTP request context using LoggerFromContext.
Logger Logger
// Timeout sets a request timeout. If zero, a reasonable default will be
// used.
Timeout time.Duration
// AllowedHosts is an optional list of fully-qualified domain names
// representing hosts which are allowed to serve the EST service.
AllowedHosts []string
// RateLimit is an optional rate limit expressed in requests per second.
// If zero, no rate limit will be applied. NewRouter refuses a negative
// value.
RateLimit int
// CheckBasicAuth is an optional callback function to check HTTP Basic
// Authentication credentials. It runs for every enrollment request that
// CheckBearerToken does not check, with empty credentials when the
// request carries no HTTP Basic credentials, so it can also accept a TLS
// client certificate from the request. A nil error means that
// authentication was successful. An error that implements Error with a
// status other than 401, such as 403 or 429, is sent as is with its
// Retry-After value. Any other error answers 401 with a Basic challenge.
// On a TLS-SRP connection, SRPUsernameFromContext(ctx) returns the
// username the client signed in with. If CheckBasicAuth is nil, then HTTP
// Basic Authentication is not required for any EST operation. The
// /healthcheck endpoint then only answers a request CheckBearerToken
// accepts.
CheckBasicAuth func(ctx context.Context, r *http.Request, aps, username, password string) error
// CheckBearerToken is an optional callback function to check the token of
// an "Authorization: Bearer" header (RFC 6750). It runs in place of
// CheckBasicAuth for every request that carries one. Its errors are
// handled like those of CheckBasicAuth. The 401 answer also carries a
// Bearer challenge. If CheckBearerToken is nil, a bearer token is not
// checked: CheckBasicAuth runs with empty credentials, as for a request
// without an Authorization header. The token then does not sign the
// client in for PasswordRenewal.
CheckBearerToken func(ctx context.Context, r *http.Request, aps, token string) error
// PasswordRenewal lets /simplereenroll accept a request without a TLS
// client certificate when it carries HTTP Basic credentials with a
// username that CheckBasicAuth accepted or a bearer token that
// CheckBearerToken accepted. RFC 7030 section 2.3 allows this when the
// certificate being renewed cannot be used for TLS client authentication,
// such as a composite ML-DSA certificate. The CA receives a nil
// certificate and decides which certificate is renewed. NewRouter refuses
// it without CheckBasicAuth or CheckBearerToken. It defaults to false.
PasswordRenewal bool
// CheckCSRSignature optionally verifies the signature of each PKCS#10
// request to /simpleenroll and /simplereenroll. /serverkeygen ignores the
// signature, as RFC 7030 section 4.4.1 requires. If nil, the server uses
// (*x509.CertificateRequest).CheckSignature, which refuses algorithms
// crypto/x509 cannot verify, such as composite ML-DSA. crypto/x509 leaves
// PublicKey nil for keys it does not know. An error that implements Error
// is sent as is. Any other error answers 400.
CheckCSRSignature func(csr *x509.CertificateRequest) error
// VerifyClientCertificate optionally checks the TLS client certificate of
// a /simplereenroll request in place of the built-in check, which verifies
// it with crypto/x509 against the certificates CACerts returns. crypto/x509
// cannot verify a certificate signed by some post-quantum CAs, such as an
// SLH-DSA or composite ML-DSA CA. The Subject and SubjectAltName
// comparison with the request runs first. A nil error accepts the
// certificate. An error that implements Error is sent as is. Any other
// error answers 403. The TLS listener must request the certificate
// without verifying it, for example with tls.RequestClientCert, because
// crypto/tls would otherwise refuse the handshake first.
VerifyClientCertificate func(ctx context.Context, r *http.Request, aps string, cert *x509.Certificate) error
// Refusals optionally receives the requests the server refuses itself,
// before or instead of calling the CA.
Refusals RefusalRecorder
// OmitTransferEncoding leaves the Content-Transfer-Encoding header out of
// responses and their multipart parts. Bodies stay base64 encoded. RFC 8951
// tells receivers to ignore the header. Some clients fail when it is
// present.
OmitTransferEncoding bool
// OmitStrictTransportSecurity leaves the Strict-Transport-Security header
// out of responses, so the host can send its own value or none. A browser
// that has stored the header refuses certificate warnings for the host
// name on every port. It defaults to false, which sends max-age=31536000.
OmitStrictTransportSecurity bool
// MaxRequestBody bounds the size of a request body in bytes. Larger
// requests are refused with 413. If zero, 64 KiB is used. A CSR for a
// large post-quantum key can exceed that, such as an SLH-DSA-SHA2-256f
// request at about 67 KB in base64. NewRouter refuses a negative value.
// Keep it below 4 MiB: /tpmenroll decodes its PKCS#7 part with a parser
// that recurses once per nested structure. A structure nested about
// 10 MB deep exhausts the stack and ends the process.
MaxRequestBody int64
// TrustProxyHeaders sets the request's RemoteAddr from the X-Real-IP or
// X-Forwarded-For header. It defaults to false. Enable it only when every
// request passes through a trusted proxy that removes or overwrites both
// headers. Proxy source addresses are not checked.
TrustProxyHeaders bool
}
ServerConfig contains EST server configuration options.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
estclient
command
Application estclient is an EST client.
|
Application estclient is an EST client. |
|
estserver
command
Application estserver is a basic EST server for testing purposes.
|
Application estserver is a basic EST server for testing purposes. |
|
internal
|
|
|
basiclogger
Package basiclogger provides a basic logger implementing est.Logger, for demonstration and testing purposes.
|
Package basiclogger provides a basic logger implementing est.Logger, for demonstration and testing purposes. |
|
mockca
Package mockca provides a mock certificate authority for testing purposes.
|
Package mockca provides a mock certificate authority for testing purposes. |
|
tpm
Package tpm provides TPM 2.0 credential-related functionality.
|
Package tpm provides TPM 2.0 credential-related functionality. |