Documentation
¶
Overview ¶
Package monitor finds what needs an admin – expiring certificates, CA certificates and CRLs, a sealed server, silent agents, failed deployments – keeps it as alerts in system.db and (step 23) tells someone about it (docs/PHASE3.md §9). Everything here works while the server is sealed: it reads pki.db and the keyring state and decrypts nothing.
Index ¶
- Constants
- type Agents
- type Alert
- type Changes
- type DigestOptions
- type EndpointSource
- type EndpointState
- type Endpoints
- func (e *Endpoints) Create(ctx context.Context, who keys.Who, req tlsscan.Request) (*tlsscan.Endpoint, error)
- func (e *Endpoints) Delete(ctx context.Context, who keys.Who, id string) error
- func (e *Endpoints) List(ctx context.Context, who keys.Who) ([]EndpointState, error)
- func (e *Endpoints) ScanNow(ctx context.Context, who keys.Who, id string) error
- func (e *Endpoints) Settings() tlsscan.Settings
- type Engine
- type Evaluator
- type Finding
- type Rules
- type Store
- func (s *Store) Digest(ctx context.Context, now time.Time, opt DigestOptions) (notify.Digest, error)
- func (s *Store) List(ctx context.Context, who keys.Who, now time.Time) (open, resolved []Alert, err error)
- func (s *Store) Open(ctx context.Context) ([]Alert, error)
- func (s *Store) Prune(ctx context.Context, cutoff time.Time) (int64, error)
- func (s *Store) Since(ctx context.Context, since time.Time) ([]Alert, error)
- func (s *Store) Sync(ctx context.Context, now time.Time, findings []Finding) (Changes, error)
Constants ¶
const ( Warning = "warning" Critical = "critical" )
Severities of an alert.
const ( KindCertExpiry = "cert_expiry" KindCAExpiry = "ca_expiry" KindCRL = "crl" KindSealed = "sealed" KindAgentSilent = "agent_silent" KindAgentCertificate = "agent_certificate" KindDeployFailed = "deploy_failed" // The TLS scan (docs/PHASE3.md §10.2, v0.3.4). KindScanMismatch = "scan_mismatch" KindScanExpiry = "scan_expiry" KindScanUnreachable = "scan_unreachable" KindScanChain = "scan_chain" )
Kinds of alerts (docs/PHASE3.md §9.2).
const ResolvedWindow = 7 * 24 * time.Hour
ResolvedWindow is how long a resolved alert stays on the Alerts page and in the API (it is kept 30 days, see internal/server/monitor.go).
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Agents ¶
type Agents interface {
ListAgents(ctx context.Context, who keys.Who) ([]agents.Agent, error)
GetAgent(ctx context.Context, who keys.Who, id string) (*agents.Agent, error)
}
Agents is what the evaluation reads about agents; nil when the agent listener is off.
type Alert ¶
type Alert struct {
ID, Key, Kind, Subject, Severity, Detail, Href string
FirstSeen, LastSeen time.Time
Resolved time.Time // zero while open
NotifiedSeverity string // "" = not reported yet
Notified time.Time
}
Alert is one row of the alerts table.
type Changes ¶
type Changes struct {
Opened, Raised, Lowered, Resolved []Alert
}
Changes is what one Sync changed – for the log; notifications read the notified_* columns, so a lost Changes value loses no message.
type DigestOptions ¶
type DigestOptions struct {
Server string // host name in the subject
RepeatEvery time.Duration // reminder for an alert still open
Link func(string) string // UI path → absolute link; nil = none
Channels []string // queue one message per channel
}
DigestOptions shape the digest of one evaluation.
type EndpointSource ¶ added in v0.3.4
type EndpointSource interface {
List(ctx context.Context, who keys.Who) ([]tlsscan.Endpoint, error)
}
EndpointSource is what the evaluation reads about TLS endpoints (*tlsscan.Service).
type EndpointState ¶ added in v0.3.4
type EndpointState struct {
Endpoint tlsscan.Endpoint
Assessment tlsscan.Assessment
// Input is the expected set and the served leaf as the PKI knows it (the
// serial of the newest certificate, for the page).
Input tlsscan.Input
// ServedID is the ID of the served leaf if the PKI issued it, else "".
ServedID string
}
EndpointState is an endpoint with what the PKI says about it and the assessment of the two – the state the page, the API and the alerts all show.
func Created ¶ added in v0.3.4
func Created(ep tlsscan.Endpoint) EndpointState
Created is the state of an endpoint that was just added: nothing is known about it before its first scan.
type Endpoints ¶ added in v0.3.4
Endpoints is the TLS scan as the REST API and the UI use it (docs/PHASE3.md §10): the endpoint service, which checks the roles and audits, plus the assessment the alerts follow, so that the page, the API and the alerts show the same state.
func (*Endpoints) Create ¶ added in v0.3.4
func (e *Endpoints) Create(ctx context.Context, who keys.Who, req tlsscan.Request) (*tlsscan.Endpoint, error)
Create adds an endpoint (permission endpoint.manage, audited by the service).
func (*Endpoints) Delete ¶ added in v0.3.4
Delete removes an endpoint (permission endpoint.manage, audited).
func (*Endpoints) List ¶ added in v0.3.4
List returns every endpoint with its assessed state, by host. The endpoint service decides whether who may read (tenant-wide pki.read); the assessment itself is computed with the evaluator's system principal and only for what the service returned.
type Engine ¶
type Engine interface {
Certificates(ctx context.Context, who keys.Who, f ca.CertificateFilter) (*ca.CertificatePage, error)
Certificate(ctx context.Context, who keys.Who, id string) (*ca.CertificateInfo, error)
CAs(ctx context.Context, who keys.Who) ([]ca.CAInfo, error)
// CertificateByFingerprint finds the certificate a TLS endpoint serves.
CertificateByFingerprint(ctx context.Context, who keys.Who, fingerprint string) (*ca.CertificateInfo, error)
}
Engine is what the evaluation reads from the CA engine.
type Evaluator ¶
type Evaluator struct {
Engine Engine
Agents Agents // nil = no agent rules
Seal func() keys.Status
Rules Rules
Who keys.Who // a system principal that may read the whole tenant
// Scan gives the TLS endpoints and their last scans; nil = no scan rules
// (docs/PHASE3.md §10.2).
Scan EndpointSource
// ScanOff: scanning is switched off (monitor.scan_interval: off). The scan
// alerts are not produced, so they resolve – there is no fresh result –
// but EndpointStates still tells the last known state.
ScanOff bool
}
Evaluator finds the conditions of docs/PHASE3.md §9.2.
func (*Evaluator) EndpointStates ¶ added in v0.3.4
EndpointStates assesses every endpoint at now, in the order of the source. It reads like the evaluation and changes nothing; with no endpoint source it returns nothing.
type Finding ¶
type Finding struct {
Key, Kind, Subject, Severity, Detail, Href string
}
Finding is one condition the evaluation found. Key is stable across runs (kind and the ID of what it is about), so the store can tell new, changed and gone conditions apart.
type Rules ¶
type Rules struct {
// End-entity certificates: warning and critical before they expire.
ExpiryWarn, ExpiryCrit time.Duration
// CA certificates.
CAWarn, CACrit time.Duration
// A sealed server: warning after SealedAfter; critical once a CRL's
// next update is closer than CRLHorizon (a sealed server can't sign).
SealedAfter, CRLHorizon time.Duration
// Agents: warning and critical after this long without a report.
AgentSilentWarn, AgentSilentCrit time.Duration
// An active agent's own certificate: critical below this.
AgentCertificate time.Duration
// ExpiredFor: an expired, not superseded certificate stays an alert this
// long after its end, then the alert is closed.
ExpiredFor time.Duration
// RepeatEvery: a reminder for an open alert (step 23).
RepeatEvery time.Duration
// The TLS scan (docs/PHASE3.md §10.2): failed scans in a row before an
// endpoint is unreachable, and how old the newest certificate for a name
// must be before an older one that is still served is an alert.
ScanUnreachableAfter int
ScanMismatchAfter time.Duration
}
Rules are the thresholds of the evaluation (configuration `monitor:`).
func DefaultRules ¶
func DefaultRules() Rules
DefaultRules are the owner-approved defaults (Q7, 2026-10-29).
type Store ¶
type Store struct {
DB *sql.DB // system.db, the write connection
Tenant string
Rand io.Reader // nil = crypto/rand (IDs)
}
Store keeps the alerts of one tenant in system.db.
func (*Store) Digest ¶
func (s *Store) Digest(ctx context.Context, now time.Time, opt DigestOptions) (notify.Digest, error)
Digest collects what to report since the last digest – new alerts, alerts that became critical, reminders, resolved alerts whose opening was reported – marks them and queues one message per channel, all in one transaction. It returns the digest (no events = nothing queued). Without channels nothing is marked: once a channel is configured, the first message lists every open alert.
func (*Store) List ¶
func (s *Store) List(ctx context.Context, who keys.Who, now time.Time) (open, resolved []Alert, err error)
List is what the Alerts page and GET /alerts show to who: the open alerts (critical first, then the oldest) and those resolved within ResolvedWindow (newest first). Alerts name certificates, CAs and hosts of the whole tenant, so it needs the tenant-wide read role (viewer); a role limited to one CA does not see them.