tlsconfig

package module
v0.0.0-...-0956853 Latest Latest
Warning

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

Go to latest
Published: Nov 1, 2022 License: MIT Imports: 13 Imported by: 1

README

Go TLS configuration module

Go Doc Build Status

This module eases configuration of TLS for clients and servers written in Go.

Features:

  • The Config struct has YAML and JSON struct tags.
  • It can be used for both clients and servers.
  • A Manager can generate a corresponding tls.Config.
  • On-disk certificates can be automatically reloaded without downtime.

The main idea behind it is that you can integrate it in your code once and then automatically gain support for any new certificate management features in the future.

YAML configuration examples

Note that depending on the application, the configuration can also be in JSON or another format.

The examples below group all TLS options under a tls key, but this name depends on the name used in the program.

Servers

Load certificate from file:

tls:
  cert_file: path/to/cert.pem
  key_file: path/to/key.pem

With automatic reloading:

tls:
  cert_file: path/to/cert.pem
  key_file: path/to/key.pem
  watch_certs: true
  watch_certs_poll_interval: 5s

Same with a custom CA and client certificate support:

tls:
  ca_file: path/to/ca.pem
  cert_file: path/to/cert.pem
  key_file: path/to/key.pem
  watch_certs: true
  watch_certs_poll_interval: 5s
  require_client_cert: true
Clients

Clients that just want to use OS provides CAs can leave the configuration empty.

To use custom CA certs to verify the connection:

tls:
  ca_file: path/to/ca.pem

To allow both custom CA certs and system CA certs to verify the connection:

tls:
  ca_file: path/to/ca.pem
  add_system_ca_pool: true

To use a client certificate:

tls:
  ca_file: path/to/ca.pem
  cert_file: path/to/cert.pem
  key_file: path/to/key.pem

INSECURE - to disable certificate validation:

tls:
  insecure_skip_verify: true
General options

The ca_file, cert_file and key_file options have corresponding ca, cert and key options that allow you to inline the PEM certificate into the config file:

tls:
  cert: |
    -----BEGIN CERTIFICATE-----
    ...

Note that there is no way to do automatic reloading this way.

The insecure_key_log_file option can be set to a log file path for the use of tools like Wireshark to decode encrypted traffic in development. See this Mozilla page for more information.

Usage in Go code

You can use the Config struct in you existing configuration structures:

import "github.com/PowerDNS/go-tlsconfig"

type MyConfig struct {
	Server Server `yaml:"server"`
	// ...
}

type Server struct {
	TLS tlsconfig.Config `yaml:"tls"`
}

After you have loaded your configration, you can the use a Manager to generate a tls.Config (error handling omitted):

manager, err := tlsconfig.NewManager(ctx, config.Server.TLS, tlsconfig.Options{
	IsServer: true,
})

tlsConfig, err := manager.TLSConfig()

hs := http.Server{
	TLSConfig: tlsConfig,
}
err = hs.ListenAndServeTLS("", "") // Certificates are handled by the TLSConfig

Example of how to use a custom TLS config with an HTTP client:

manager, err := tlsconfig.NewManager(ctx, config.Client.TLS, tlsconfig.Options{
	IsClient: true,
})

tlsConfig, err := manager.TLSConfig()

transport := &http.Transport{
	TLSClientConfig: tlsConfig,
    ForceAttemptHTTP2: true, // not attempted by default when TLSClientConfig is set
}
client := &http.Client{Transport: transport}
resp, err := client.Get("https://some.example/")

Or you can use this convenience method for a more opinionated HTTP client with various timeouts set, but do read the source code for this method so that you understand the implications:

manager, err := tlsconfig.NewManager(ctx, config.Client.TLS, tlsconfig.Options{
	IsClient: true,
})

client, err := manager.HTTPClient()

resp, err := client.Get("https://some.example/")

The testca/testca_test.go file contains an example that uses client certificates.

The Manager performs certificate reloads in the background. To keep track of what it is doing and see error messages, you can provide a logr.Logger interface in Options.Logr. The genericr module makes it easy to use custom logging logic here.

Stability

At this point we do not guarantee any API and config file format stability between versions. If you want to use it in your own project, pin it at a speciifc version. Once we are confident that our approach is sane, we will release a 1.0.0 version that will have these guarantees.

Documentation

Overview

Package tlsconfig provide YAML and JSON configuration options for both clients and servers.

Index

Constants

View Source
const (
	DefaultWatchCertsPollInterval = 5 * time.Second
)

Variables

View Source
var (
	ErrNoCertificate = errors.New("no certificate found")
	ErrNotClient     = errors.New("this is not a client config")
)

Functions

This section is empty.

Types

type Config

type Config struct {
	// Optional CA file to use (PEM)
	CAFile string `yaml:"ca_file" json:"ca_file"`
	CA     string `yaml:"ca" json:"ca"`

	// AddSystemCAPool adds the system CA pool if private CAs are enabled, when set.
	// By default we do not load system CAs when a private CA cert was loaded.
	AddSystemCAPool bool `yaml:"add_system_ca_pool" json:"add_system_ca_pool"`

	// These are required for the server and optional for clients.
	// They must be in PEM format.
	CertFile string `yaml:"cert_file" json:"cert_file"`
	Cert     string `yaml:"cert" json:"cert"`
	KeyFile  string `yaml:"key_file" json:"key_file"`
	Key      string `yaml:"key" json:"key"`

	// WatchCerts enables background reloading of certificate files.
	// This only affects certificates loaded from files.
	// By default certificates are only loaded on startup.
	WatchCerts bool `yaml:"watch_certs" json:"watch_certs"`
	// By default, we check for changes every 5 seconds
	WatchCertsPollInterval time.Duration `yaml:"watch_certs_poll_interval" json:"watch_certs_poll_interval"`

	// RequireClientCert can be set on servers to require a client certificate.
	// If enabled, the CA must be set.
	RequireClientCert bool `yaml:"require_client_cert" json:"require_client_cert"`

	// InsecureSkipVerify controls whether a client verifies the
	// server's certificate chain and host name.
	// If InsecureSkipVerify is true, TLS 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.
	InsecureSkipVerify bool `yaml:"insecure_skip_verify" json:"insecure_skip_verify"`

	// InsecureKeyLogFile optionally specifies a destination for TLS master secrets
	// in NSS key log format that can be used to allow external programs
	// such as Wireshark to decrypt TLS connections.
	// See https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format.
	// Use of InsecureKeyLogFile compromises security and should only be
	// used for debugging.
	InsecureKeyLogFile string `yaml:"insecure_key_log_file" json:"insecure_key_log_file"`
}

func (Config) HasCA

func (c Config) HasCA() bool

HasCA returns true if a custom CA was defined in the config

func (Config) HasCertWithKey

func (c Config) HasCertWithKey() bool

HasCertWithKey returns true if a Cert and Key was defined in the config

type Manager

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

Manager performs Config validation, certificate loading, and provides convenience methods for using the TLS configuration and automated certificate refreshing.

func NewManager

func NewManager(ctx context.Context, config Config, options Options) (*Manager, error)

NewManager creates a new Manager. This also starts any needed background worker goroutines. These can be cancelled through the provided context.

func (*Manager) HTTPClient

func (m *Manager) HTTPClient() (*http.Client, error)

HTTPClient creates an http.Client with the custom TLS config and some opinionated defaults. This is mostly here for convenience, you are recommended to create your own based on this. For example, this is not suitable for huge downloads, because it will timeout a connection after 15 minutes. These opinionated defaults may also change in future releases.

func (*Manager) TLSConfig

func (m *Manager) TLSConfig() (*tls.Config, error)

TLSConfig creates a tls.Config from the current config. This works for both clients and servers, depending on the Options. This config uses the default Go security settings. If you have different needs, you can override the ciphers and versions on the returned object.

type Options

type Options struct {
	// IsServer indicates this is a server config (cert required)
	IsServer bool

	// IsClient indicates this is a client config
	IsClient bool

	// RequireClientCert requires the use of a client cert for clients
	RequireClientCert bool

	// Logr allows custom handling of logging. By default nothing is logged.
	Logr logr.Logger
}

Options configure how the Manager works and performs Config validation

type Secret

type Secret string

Secret is a string that has "***" as its default string representation.

func (*Secret) MarshalText

func (s *Secret) MarshalText() (text []byte, err error)

func (*Secret) String

func (s *Secret) String() string

func (*Secret) UnmarshalText

func (s *Secret) UnmarshalText(text []byte) error

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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