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
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
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.