eztls

package
v0.0.1-beta.2 Latest Latest
Warning

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

Go to latest
Published: Jan 20, 2024 License: BSD-3-Clause, BSD-3-Clause, BSD-3-Clause Imports: 24 Imported by: 0

README

EZTLS

Small wrapper around acme/autocert which makes it somewhat easier to start a TLS server with a certificate provisioned with Let's Encrypt in simple configurations.

Examples

In the simplest case, it's not much different than net.Listen plus a domain and whether or not to use Let's Encrypt's staging environment:

l, err := eztls.Listen("tcp", "0.0.0.0:443", "example.com", true)

ListenConfig allows for a bit more control but less fuss than an autocert.Manager:

/* Use ALL the options. */
l, err := Config{
	Staging: true,
	TLSConfig: &tls.Config{
		NextProtos: append(
			slices.Clone(HTTPSNextProtos),
			"sneakiness",
		),
	},
	CacheDir: "/opt/certs/staging",
	Domains: []string{
		"example.com",
		"*.example.com",
		"example-*.de", /* example-1.de, example-2.de, etc. */
	},
	SelfSignedDomains: []string{
		"*.internal",
		"*.testnet",
	},
	Email: "admin@example.com",
}.Listen("tcp", "0.0.0.0:443")
if nil != err {
	log.Fatalf("Listen error: %s", err)
}

/* Accept and handle TLS clients. */
c, err := l.Accept()
go handle(c)

Most fields are optional:

	l, err := ListenConfig("tcp", "0.0.0.0:443", Config{
		Domains: []string{"example.com", "*.example.com"},
	})

Self-Signed Certificates

Self-signed certificate generation is possible with GenerateSelfSignedCertificate, SelfSignedGetter, and Config.SelfSignedDomains. All of the above generate a certificate with a singe DNS SAN: *, This is intended for simple test cases not worth fiddling about with a domain.

Documentation

Overview

Package eztls - Easy TLS listener with Let's Encrypt

Use of this package implies acceptance of Let's Encrypts Terms of Service.

Index

Examples

Constants

View Source
const CacheDirBase = "eztls-cache"

CacheDirBase is the base part of the directory returned by DefaultCacheDir.

View Source
const StagingACMEDirectory = "https://acme-staging-v02.api.letsencrypt.org/directory"

StagingACMEDirectory is the staging ACME Directory URL used by this package.

Variables

View Source
var DefaultSelfSignedCertLifespan = time.Until(time.Now().AddDate(10, 0, 0))

DefaultSelfSignedCertLifespan is the amount of time self-signed certificates are valid, by default. It is 10 years.

View Source
var HTTPSNextProtos = []string{"h2", "http/1.1", acme.ALPNProto}

HTTPSNextProtos are the ALPNs to use with tls.Config.NextProtos to serve HTTPS.

View Source
var SelfSignedSubject = "eztls"

SelfSignedSubject is the subject name we use for self-signed certificates when no other subject has been provided. This is settable at compile-time.

Functions

func DefaultCacheDir

func DefaultCacheDir() (string, error)

DefaultCacheDir returns the default directory in which are cached previously-obtained certs and other state.

func GenerateSelfSignedCertificate

func GenerateSelfSignedCertificate(subject string, dnsNames []string, ipAddresses []net.IP, lifespan time.Duration) (*tls.Certificate, error)

GenerateSelfSignedCertificate generates a bare-bones self-signed certificate with the given subject, DNS and IP Address SANs, and lifespan. The certificate's Leaf will be set.

func HostWhitelist

func HostWhitelist(patterns []string) (autocert.HostPolicy, error)

HostWhitelist returns an autocert.HostPolicy where only the specified hostname patterns are allowed. Unlike autocert.HostWhitelist, patterns are taken as globs as matched by filepath.Match. HostWhitelist does not retain patterns. Hosts checked against the whitelist will be converted to Punycode with idna.Lookup.ToASCII. The patterns will all be lowercased.

func Listen

func Listen(network, laddr, domain string, staging bool) (net.Listener, error)

Listen creates a TLS listener accepting connections on the given network address. It will obtain and refresh a TLS certificates for the given domain pattern (see HostWhitelist) using tls-alpn-01 automatically from Let's Encrypt. It uses Let's Encrypt's production environment unless staging is true, in which case it uses Let's Encrypt's staging environment.

Example
/* Listen on port 443 on all interfaces for a TLS connection for
example.com.  Equivalent to
	l, err := ListenConfig("tcp", "0.0.0.0:443", Config{
		Domains: []string{"example.com"},
	})
*/
l, err := Listen("tcp", "0.0.0.0:443", "example.com", true)
if nil != err {
	log.Fatalf("Listen error: %s", err)
}

/* Accept and handle connections as usual. */
handle(l)
Output:

func MarshalCertificate

func MarshalCertificate(c *tls.Certificate) ([]byte, error)

MarshalCertificate marshals the certificate c; it is the inverse of UnmarshalCertificate.

func SelfSignedGetter

func SelfSignedGetter(domains []string, lifespan time.Duration, cacheDir string) (func(*tls.ClientHelloInfo) (*tls.Certificate, error), error)

SelfSignedGetter returns a function suitable for use in tls.Config.Certificate which returns a self-signed certificates for the domain patterns (see HostWhitelist) allowed by domains. A single certificate with a wildcard DNS SAN is created for the given lifespan and cached in the given directory, or in memory if cacheDir is the empty string.

Example
/* Self-signed certificate generator generation, handy for testing. */
ssg, err := SelfSignedGetter([]string{"*"}, 0, "")
if nil != err {
	log.Fatalf("Faild to generate certificate generator: %s", err)
}

/* Listen for and handshake with a TLS connection. */
l, err := tls.Listen("tcp", "127.0.0.1:0", &tls.Config{
	GetCertificate: ssg,
})
if nil != err {
	log.Fatalf("Listen: %s", err)
}
go func() {
	c, err := l.Accept()
	if nil != err {
		log.Fatalf("Accept: %s", err)
	}
	if err := c.(*tls.Conn).Handshake(); nil != err {
		log.Fatalf("Handhake: %s", err)
	}
}()
defer l.Close()

/* Connect to our fancy new server. */
c, err := tls.Dial("tcp", l.Addr().String(), &tls.Config{
	ServerName:         "kittens.test",
	InsecureSkipVerify: true, /* Because self-signed. */
})
if nil != err {
	log.Fatalf("Dial: %s", err)
}
defer c.Close()

/* What's the cert like? */
svr := c.ConnectionState().PeerCertificates[0]
fmt.Printf(
	"--Certificate info--\n"+
		" Subject: %s\n"+
		"DNS SANs: %s\n",
	svr.Subject,
	svr.DNSNames,
)
Output:

--Certificate info--
 Subject: CN=eztls
DNS SANs: [*]

func UnmarshalCertificate

func UnmarshalCertificate(b []byte) (*tls.Certificate, error)

UnmarshalCertificate unmarshals the certificate in b; it is the inverse of MarshalCertificate.

Types

type BadPatternError

type BadPatternError struct {
	Pattern string
	Err     error
}

BadPatternError is returned by HostWhitelist to indicate a malformed or otherwise unusable pattern.

func (BadPatternError) Error

func (err BadPatternError) Error() string

Error implements the error interface.

func (BadPatternError) Unwrap

func (err BadPatternError) Unwrap() error

Unwrap returns err.Err.

type Config

type Config struct {
	// Staging, if true, causes the Let's Encrypt staging environment to
	// be used.
	Staging bool

	// TLSConfig, if non-nil, will be passed by ListenConfig to tls.Dial
	// after setting its GetCertificate field.  Supplying a custom TLS
	// config is useful for configuring ALPNs (NextProtos).  Don't forget
	// to add acme.ALPNProto.
	TLSConfig *tls.Config

	// CacheDir is the directory in which are cached previously-obtained
	// certificates and other state.  If no directory is given, the
	// directory returned by DefalutCacheDir will be used if Staging isn't
	// true and an in-memory cache will be used if Staging is true.
	// Multiple instances of this library as well as multiple
	// autcert.Managers may use the same cache directory.
	CacheDir string

	// Domains is the list of domain SNI patterns for which TLS certificates
	// will be obtained.  This will be passed directly to HostWhitelist.
	// Domains may be nil or empty to disable usage of Let's Encrypt.
	Domains []string

	// SelfSignedDomains is an optional list of domain SNI patterns for
	// which self-signed TLS certificates will be generated if one can't be
	// obtained from Let's Encrypt or isn't allowed by Domains.
	// SelfSignedDomains may be nil or empty to disable self-signed
	// certificate generation.  The self-signed certificate itself will
	// have a single * DNS SAN and SelfSignedNames may contain "*" to
	// allow all SNIs, even empty ones.
	SelfSignedDomains []string

	// Email specifies an optional contact email address.  Please see
	// autocert.Manager.Email for more information.
	Email string
}

Config is the configuration passed to ListenConfig. It is roughly analogous to autocert.Manager but simplified.

func (Config) CertificateGetter

func (c Config) CertificateGetter() (func(*tls.ClientHelloInfo) (*tls.Certificate, error), error)

CertificateGetter returns a function suitable for use in tls.Config.GetCertificate. Don't forget to add acme.ALPNProto to the NetxProtos slice in the tls.Config.

func (Config) Listen

func (c Config) Listen(network, laddr string) (net.Listener, error)

Listen creates a TLS listener using tls.Listen and autocert.Manager according to the config. Please see Listen for more details.

type MemCache

type MemCache struct {
	// contains filtered or unexported fields
}

MemCache is an in-memory implementation of autocert.Cache.

func NewMemCache

func NewMemCache() *MemCache

NewMemCache returns a new MemCache, ready for use.

func (*MemCache) Delete

func (m *MemCache) Delete(_ context.Context, key string) 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 will always return nil.

func (*MemCache) Get

func (m *MemCache) Get(_ context.Context, key string) ([]byte, error)

Get returns a certificate data for the specified key. If there's no such key, Get returns ErrCacheMiss.

func (*MemCache) Put

func (m *MemCache) Put(_ context.Context, key string, data []byte) error

Put stores the data in the cache under the specified key. Underlying implementations may use any data storage format, as long as the reverse operation, Get, results in the original data. Put always returns nil.

type NotWhitelistedError

type NotWhitelistedError struct {
	Host string
}

NotWhitelistedError is returned by the autocert.HostPolicy returned by HostWhitelist if the requested host doesn't match a whitelisted pattern.

func (NotWhitelistedError) Error

func (err NotWhitelistedError) Error() string

Error implements the error interface.

Directories

Path Synopsis
examples
fserv
Program fserv - Simple HTTPS fileserver
Program fserv - Simple HTTPS fileserver

Jump to

Keyboard shortcuts

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