Go API Documentation

github.com/caddyserver/caddy/v2/modules/caddytls/distributedstek

Package distributedstek provides TLS session ticket ephemeral keys (STEKs) in a distributed fashion by utilizing configured storage for locking and key sharing. This allows a cluster of machines to optimally resume TLS sessions in a load-balanced environment without any hassle. This is similar to what Twitter does, but without needing to rely on SSH, as it is built into the web server this way: https://blog.twitter.com/engineering/en_us/a/2013/forward-secrecy-at-twitter.html

Package

Files: 1. Third party imports: 0. Imports from organisation: 1. Tests: 0. Benchmarks: 0.

Constants

const (
	stekLockName	= "stek_check"
	stekFileName	= "stek/stek.bin"
)

Vars

Interface guard

var _ caddytls.STEKProvider = (*Provider)(nil)

Types

Provider

Provider implements a distributed STEK provider. This module will obtain STEKs from a storage module instead of generating STEKs internally. This allows STEKs to be coordinated, improving TLS session resumption in a cluster.

type Provider struct {
	// The storage module wherein to store and obtain session
	// ticket keys. If unset, Caddy's default/global-configured
	// storage module will be used.
	Storage	json.RawMessage	`json:"storage,omitempty" caddy:"namespace=caddy.storage inline_key=module"`

	storage		certmagic.Storage
	stekConfig	*caddytls.SessionTicketService
	timer		*time.Timer
	ctx		caddy.Context
}

distributedSTEK

This type doesn't have documentation.

type distributedSTEK struct {
	Keys				[][32]byte
	LastRotation, NextRotation	time.Time
}

Functions

func (*Provider) Initialize

Initialize sets the configuration for s and returns the starting keys.

func (s *Provider) Initialize(config *caddytls.SessionTicketService) ([][32]byte, error) {
	// keep a reference to the config; we'll need it when rotating keys
	s.stekConfig = config

	dstek, err := s.getSTEK()
	if err != nil {
		return nil, err
	}

	// create timer for the remaining time on the interval;
	// this timer is cleaned up only when rotate() returns
	s.timer = time.NewTimer(time.Until(dstek.NextRotation))

	return dstek.Keys, nil
}

Cognitive complexity: 2, Cyclomatic complexity: 2

Uses: time.NewTimer, time.Until.

func (*Provider) Next

Next returns a channel which transmits the latest session ticket keys.

func (s *Provider) Next(doneChan <-chan struct{}) <-chan [][32]byte {
	keysChan := make(chan [][32]byte)
	go s.rotate(doneChan, keysChan)
	return keysChan
}

Cognitive complexity: 1, Cyclomatic complexity: 1

func (*Provider) Provision

Provision provisions s.

func (s *Provider) Provision(ctx caddy.Context) error {
	s.ctx = ctx

	// unpack the storage module to use, if different from the default
	if s.Storage != nil {
		val, err := ctx.LoadModule(s, "Storage")
		if err != nil {
			return fmt.Errorf("loading TLS storage module: %s", err)
		}
		cmStorage, err := val.(caddy.StorageConverter).CertMagicStorage()
		if err != nil {
			return fmt.Errorf("creating TLS storage configuration: %v", err)
		}
		s.storage = cmStorage
	}

	// otherwise, use default storage
	if s.storage == nil {
		s.storage = ctx.Storage()
	}

	return nil
}

Cognitive complexity: 8, Cyclomatic complexity: 5

Uses: fmt.Errorf.

func (Provider) CaddyModule

CaddyModule returns the Caddy module information.

func (Provider) CaddyModule() caddy.ModuleInfo {
	return caddy.ModuleInfo{
		ID:	"tls.stek.distributed",
		New:	func() caddy.Module { return new(Provider) },
	}
}

Cognitive complexity: 2, Cyclomatic complexity: 1

Private functions

func init

init ()

func getSTEK

getSTEK locks and loads the current STEK from storage. If none currently exists, a new STEK is created and persisted. If the current STEK is outdated (NextRotation time is in the past), then it is rotated and persisted. The resulting STEK is returned.

getSTEK () (distributedSTEK, error)
References: errors.Is, fmt.Errorf, fs.ErrNotExist, time.Now.

func loadSTEK

loadSTEK () (distributedSTEK, error)
References: bytes.NewReader, fmt.Errorf, gob.NewDecoder.

func rotate

rotate rotates keys on a regular basis, sending each updated set of keys down keysChan, until doneChan is closed.

rotate (doneChan <-chan struct{}, keysChan chan<- [][32]byte)
References: debug.Stack, log.Printf, time.Until.

func rotateKeys

rotateKeys rotates the keys of oldSTEK and returns the new distributedSTEK with updated keys and timestamps. It stores the returned STEK in storage, so this function must only be called in a storage-provided lock.

rotateKeys (oldSTEK distributedSTEK) (distributedSTEK, error)
References: time.Duration, time.Now.

func storeSTEK

storeSTEK (dstek distributedSTEK) error
References: bytes.Buffer, fmt.Errorf, gob.NewEncoder.