certify

package module
v1.9.0 Latest Latest
Warning

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

Go to latest
Published: Aug 22, 2021 License: MIT Imports: 20 Imported by: 31

README

Certify

CircleCI GoDoc Go Report Card Code Coverage Releases License

Certify

Certify allows easy automatic certificate distribution and maintenance. Certificates are requested as TLS connections are made, courtesy of the GetCertificate and GetClientCertificate tls.Config hooks. Certificates are optionally cached. Simultaneous requests are deduplicated to minimize pressure on issuers.

Vault walkthrough

My presentation from GolangPiter 2019 contains a walkthrough of how to configure your Vault instance to securely issue certificates for your Go clients and servers.

Certify presentation

Users

Are you using Certify and want to be visible here? Open an issue!

Issuers

Certify exposes an Issuer interface which is used to allow switching between issuer backends.

Currently implemented issuers:

Usage

Create an issuer:

issuer := &vault.Issuer{
    URL: &url.URL{
        Scheme: "https",
        Host: "my-local-vault-instance.com",
    },
    Token:     "myVaultToken",
    Role:      "myVaultRole",
}

Create a Certify:

c := &certify.Certify{
    // Used when request client-side certificates and
    // added to SANs or IPSANs depending on format.
    CommonName: "MyServer.com",
    Issuer: issuer,
    // It is recommended to use a cache.
    Cache: certify.NewMemCache(),
    // It is recommended to set RenewBefore.
    // Refresh cached certificates when < 24H left before expiry.
    RenewBefore: 24*time.Hour,
}

Use in your TLS Config:

tlsConfig := &tls.Config{
    GetCertificate: c.GetCertificate,
}

That's it! Both server-side and client-side certificates can be generated:

tlsConfig := &tls.Config{
    GetClientCertificate: c.GetClientCertificate,
}

For an end-to-end example using gRPC with mutual TLS authentication, see the Vault tests.

Docker image (sidecar model)

If you really want to use Certify but you are not able to use Go, there is now a Docker image available!

Simply configure this image as the access point for your Kubernetes pod and let it proxy traffic to your server.

How does it work?

How it works

Certify hooks into the GetCertificate and GetClientCertificate methods of the Go TLS stack Config struct. These get called when the server/client respectively is required to present its certificate. If possible, this is fetched from the cache, based on the requested server name. If not, a new certificate is issued with the requested server name present. For client requests, the configured CommonName is used.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrCacheMiss = errors.New("no matching certificate found")

ErrCacheMiss should be returned by Cache implementations when a certificate could not be found.

Functions

This section is empty.

Types

type Cache

type Cache interface {
	// Get returns a certificate data for the specified key.
	// If there's no such key, Get returns ErrCacheMiss.
	Get(context.Context, string) (*tls.Certificate, error)

	// Put stores the data in the cache under the specified key.
	Put(context.Context, string, *tls.Certificate) error

	// Delete removes a certificate data from the cache under the specified key.
	// If there's no such key in the cache, Delete returns nil.
	Delete(context.Context, string) error
}

Cache describes the interface that certificate caches must implement. Cache implementations must be thread safe.

func NewMemCache

func NewMemCache() Cache

NewMemCache creates an in-memory cache that implements the Cache interface.

type CertConfig

type CertConfig struct {
	SubjectAlternativeNames    []string
	IPSubjectAlternativeNames  []net.IP
	URISubjectAlternativeNames []*url.URL
	// KeyGenerator is used to create new private keys
	// for CSR requests. If not defined, defaults to ECDSA P256.
	// Only ECDSA and RSA keys are supported.
	// This is guaranteed to be provided in Issue calls.
	KeyGenerator KeyGenerator
}

CertConfig configures the specifics of the certificate requested from the Issuer.

func (*CertConfig) Clone

func (cc *CertConfig) Clone() *CertConfig

Clone makes a deep copy of the CertConfig.

type Certify

type Certify struct {
	// CommonName is the Certificate Common Name
	// that will be used when issuing certificates.
	// This can be a DNS record or a regular name.
	CommonName string

	// Issuer is the certificate issuer to use.
	Issuer Issuer

	// RenewBefore configures how long before
	// expiry a certificate should be considered too
	// old to use when fetched from the cache.
	RenewBefore time.Duration

	// Cache is the Cache implementation to use.
	Cache Cache

	// CertConfig is the certificate configuration that
	// should be used. It can be specified to set explicit
	// requirements of certificates issued.
	CertConfig *CertConfig

	// IssueTimeout is the upper bound of time allowed
	// per certificate call. Defaults to 1 minute.
	IssueTimeout time.Duration

	// Logger configures logging of events such as renewals.
	// Defaults to no logging. Use one of the adapters in
	// https://logur.dev/logur to use with specific
	// logging libraries, or implement the interface yourself.
	Logger Logger
	// contains filtered or unexported fields
}

Certify implements automatic certificate acquisition via the configured Issuer.

CommonName and Issuer are required. It is recommended that you specify a Cache to prevent requesting a new certificate for every incoming connection.

func (*Certify) GetCertificate

func (c *Certify) GetCertificate(hello *tls.ClientHelloInfo) (cert *tls.Certificate, err error)

GetCertificate implements the GetCertificate TLS config hook.

func (*Certify) GetClientCertificate

func (c *Certify) GetClientCertificate(cri *tls.CertificateRequestInfo) (cert *tls.Certificate, err error)

GetClientCertificate implements the GetClientCertificate TLS config hook.

type DirCache

type DirCache string

DirCache implements Cache using a directory on the local filesystem. If the directory does not exist, it will be created with 0700 permissions.

It is strongly based on the acme/autocert DirCache type. https://github.com/golang/crypto/blob/88942b9c40a4c9d203b82b3731787b672d6e809b/acme/autocert/cache.go#L40

func (DirCache) Delete

func (d DirCache) Delete(ctx context.Context, name string) error

Delete removes the specified file name.

func (DirCache) Get

func (d DirCache) Get(ctx context.Context, name string) (*tls.Certificate, error)

Get reads a certificate data from the specified file name.

func (DirCache) Put

func (d DirCache) Put(ctx context.Context, name string, cert *tls.Certificate) error

Put writes the certificate data to the specified file name. The file will be created with 0600 permissions.

type Issuer

type Issuer interface {
	Issue(context.Context, string, *CertConfig) (*tls.Certificate, error)
}

Issuer is the interface that must be implemented by certificate issuers.

type KeyGenerator added in v1.0.0

type KeyGenerator interface {
	Generate() (crypto.PrivateKey, error)
}

KeyGenerator defines an interface used to generate a private key.

type Logger added in v1.4.0

type Logger interface {
	Trace(msg string, fields ...map[string]interface{})
	Debug(msg string, fields ...map[string]interface{})
	Info(msg string, fields ...map[string]interface{})
	Warn(msg string, fields ...map[string]interface{})
	Error(msg string, fields ...map[string]interface{})
}

Logger must be implemented to log events. See https://logur.dev/logur for some adapters for popular logging libraries.

Directories

Path Synopsis
cmd
internal
csr
issuers
aws

Jump to

Keyboard shortcuts

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