Documentation
¶
Overview ¶
Package mailcert checks, validates and installs the TLS certificate the instance-owned mail server serves (ADR 062). It holds no transport of its own: the API supplies the volume, the restart and the probe.
Index ¶
Constants ¶
const ( OutcomeInstalled = "installed" OutcomeRolledBack = "rolled_back" OutcomeRollbackFailed = "rollback_failed" OutcomeFailed = "failed" )
Outcome values for Result.Outcome.
const ( PhaseStaging = "staging" PhaseSwapping = "swapping" )
Journal phases: while staging the live pair is untouched, from swapping on it may hold the new pair.
const ( CertPath = "certs/managed.pem" KeyPath = "certs/managed.key" PrevCertPath = "certs/managed.prev.pem" PrevKeyPath = "certs/managed.prev.key" NewCertPath = "certs/managed.new.pem" NewKeyPath = "certs/managed.new.key" JournalPath = "certs/managed.journal" )
Paths inside the mail config volume, relative to the directory mox reads its config from.
const ( TemplateID = "mail-mox" ConfigVolume = "mail_config" )
TemplateID and ConfigVolume name the mail template and the volume holding the managed pair.
const SubmissionTLSPort = 465
SubmissionTLSPort is the implicit TLS submission port probed for the served certificate.
Variables ¶
var ErrACMENotImplemented = errors.New("mail cert: obtaining a certificate through ACME is not yet implemented, upload one instead")
ErrACMENotImplemented is the seam for issuing through the ingress ACME (ADR 062, option A).
var ErrInstallInProgress = errors.New("mail cert: another certificate install is in progress, retry when it finishes")
ErrInstallInProgress means a journal from another install is still inside its lease.
var ErrInterrupted = errors.New("mail cert: an earlier install did not finish")
ErrInterrupted is the cause recorded when an earlier install did not finish.
var ErrKeyModeTooWide = errors.New("mail cert: the node did not write the key with mode 0600, upgrade the node agent")
ErrKeyModeTooWide means the node wrote the key wider than 0600, usually an agent without the private write option.
var ErrKeyRemoveFailed = errors.New("mail cert: the node wrote the key wider than 0600 and deleting it failed, so the key may be readable by other users of the node: delete it by hand and upgrade the node agent")
ErrKeyRemoveFailed means a key landed wider than 0600 and could not be deleted again.
var ErrNotPrivateTarget = errors.New("mail cert: the probe target is not a private address")
ErrNotPrivateTarget means the probe address is not a private or loopback address.
var ErrPEMTooLarge = errors.New("mail cert: the certificate chain or the key is larger than " + envMaxPEMKB + " allows")
ErrPEMTooLarge means one uploaded PEM field is over the configured size.
Functions ¶
func BackupExcludes ¶
BackupExcludes returns the tar patterns a generic backup of this volume must leave out: the managed keys and any temp file that may hold one.
func IsProtectedPath ¶
IsProtectedPath reports whether rel, a cleaned volume path, is a managed pair file, its rollback, staging or journal, or an upload temp file beside them. Case is folded so a case-insensitive file system cannot bypass it.
Types ¶
type Config ¶
type Config struct {
Window Window
ProbeTimeout time.Duration
VerifyTimeout time.Duration
PollInterval time.Duration
MaxPEMBytes int64
// RollbackTimeout bounds a rollback on its own context, detached from the request.
RollbackTimeout time.Duration
// InstallLease is how long a journal blocks other installs before it counts as interrupted.
InstallLease time.Duration
}
Config holds the env driven knobs; defaults live here and nowhere else.
func ConfigFromEnv ¶
ConfigFromEnv reads Config through lookup, keeping the defaults for unset or invalid values.
type Info ¶
type Info struct {
Subject string
Issuer string
NotAfter time.Time
Serial string
SHA256 string
SelfSigned bool
}
Info is the public description of one certificate: never any key material.
func Probe ¶
Probe dials ip:port with implicit TLS and describes the served leaf. Only private or loopback targets are allowed and no credentials are sent.
type Journal ¶
type Journal struct {
Phase string `json:"phase"`
StartedAt time.Time `json:"started_at"`
NewSHA256 string `json:"new_sha256"`
HadPrev bool `json:"had_prev"`
Origin Origin `json:"origin"`
}
Journal is the persisted in-progress marker of one install. It holds no key material.
func ReadJournal ¶
ReadJournal returns the journal of an unfinished install, if any.
type Origin ¶
type Origin struct {
CertFile string `json:"cert_file,omitempty"`
KeyFile string `json:"key_file,omitempty"`
Set bool `json:"set"`
}
Origin is the certificate setting the mail app had before an install, so a rollback can restore it.
type Result ¶
Result reports an install. Reason is a short code, never key material.
func Install ¶
func Install(ctx context.Context, cfg Config, vol Volume, sw Switcher, certPEM, keyPEM []byte, want Info, orig Origin) (Result, error)
Install stages the pair under temporary names and checks it, keeps the previous managed pair as rollback, swaps the live pair, restarts mox and waits until it serves want. A journal marks the install until it ends, so an interrupted one is found by Recover. Rollback uses its own bounded context so a spent install deadline cannot skip it.
type Switcher ¶
type Switcher interface {
Activate(ctx context.Context) error
Revert(ctx context.Context) error
Served(ctx context.Context) (Info, error)
}
Switcher points mox at the managed files and restarts it, or undoes that.
type Volume ¶
type Volume interface {
// Read returns the file, or found false when it does not exist.
Read(ctx context.Context, path string) (data []byte, found bool, err error)
Write(ctx context.Context, path string, data []byte, private bool) error
Mode(ctx context.Context, path string) (fs.FileMode, error)
Remove(ctx context.Context, path string) error
}
Volume is the mail config volume as the installer needs it. Remove of a missing file is not an error.
type Window ¶
type Window struct {
// contains filtered or unexported fields
}
Window is a daily UTC quiet window "HH:MM-HH:MM"; the zero Window allows any time.
func ParseWindow ¶
ParseWindow parses "HH:MM-HH:MM" (UTC); an empty string is the zero Window.