Documentation
¶
Overview ¶
Package monitor observes the gateway without deciding anything: the bounded window of recent requests and its live views, request metrics, traffic summaries, the fixed advice checks, impact previews and the security log search.
It holds no authority over admission, policy, durable audit or upstream writes; every view is built from a generation, the observations or the security log files it is given. It has no HTTP routing and checks no permission: the Admin API does both. It imports only policy, compile and audit. The request pipeline records into it; the Admin API and the metrics listener read from it.
Index ¶
- Constants
- Variables
- func EncodeCursor(c Cursor) string
- func LogFiles(active string) (files, missing []string, err error)
- func Metrics(o *Observations, gauges func() []Gauge) http.Handler
- func OptionalString(value string) *string
- func Percentiles(durations []float64) (float64, float64)
- func PreviewDecision(g *compile.Generation, event Observed) (decision, code, operation string, known bool)
- func RecentRecord(path string, span int64) (int64, time.Time, error)
- func SortFindings(items []Finding)
- func TrafficTop[T any](items []T, count func(T) int, name func(T) string, limit int) []T
- func WasAllowed(event RequestView) bool
- type Cursor
- type Finding
- type Gauge
- type LogUse
- type Observations
- func (o *Observations) Close()
- func (o *Observations) Closing() <-chan struct{}
- func (o *Observations) ConnectionRefused()
- func (o *Observations) Recent(keep func(*Observed) bool, limit int) []Observed
- func (o *Observations) Record(event audit.Event)
- func (o *Observations) Redirected()
- func (o *Observations) Retained() int
- func (o *Observations) RetainedSince() (time.Time, bool)
- func (o *Observations) Snapshot() []Observed
- func (o *Observations) Subscribe() *Viewer
- func (o *Observations) TakeDropped(viewer *Viewer) uint64
- func (o *Observations) Unsubscribe(viewer *Viewer)
- func (o *Observations) Viewers() int
- func (o *Observations) Window() int
- type Observed
- type Query
- type RequestView
- type Result
- type Summaries
- type TrafficGroup
- type UnusedReport
- type Viewer
Constants ¶
const ( AdviceRules = "checks-0.6" // The security log also raises an alert when, at the active file's recent // write rate, its remaining budget lasts less than FillingTime (medium) or // NearlyFullTime (critical). The rate is read over the file's last // RateMinBytes and counts once the file holds that much, so a few early // records cannot predict a fill and a slow start does not dilute it. FillingTime = time.Hour NearlyFullTime = 15 * time.Minute RateMinBytes = 1 << 20 // NearlyFull is the share of a store that raises an alert; Filling, the // share of the security log budget that raises an earlier one. NearlyFull = 0.9 Filling = 0.7 )
The fixed checks, rule set version "checks-0.6": static configuration warnings, unused permissions from observed traffic, and alerts. They advise only: nothing here blocks, changes or activates anything, and nothing runs on the request path. Each answer names the rule set version so findings can be traced to the rules that made them.
const ( PageScan = 16 << 20 ExportScan = 256 << 20 ExportRows = 10000 )
const MaxStreams = 8
const QueueSize = 128
const TopLimit = 10
Variables ¶
var ErrCursorGone = errors.New("the file the search stopped in is no longer present")
Functions ¶
func EncodeCursor ¶
func LogFiles ¶
LogFiles lists the audit files newest first: the active file, then the rotated files from the highest number down. missing names the numbered files below the highest that are no longer present (moved away to archive).
func Metrics ¶
func Metrics(o *Observations, gauges func() []Gauge) http.Handler
Metrics serves the metrics listener from the observations and the published gauges, which published reads from the controller.
func OptionalString ¶
func Percentiles ¶
Percentiles returns the median and the 95th percentile of durations, which it sorts in place; both are zero when there are none.
func PreviewDecision ¶
func PreviewDecision(g *compile.Generation, event Observed) (decision, code, operation string, known bool)
PreviewDecision shares canonical matching and permit evaluation with the request pipeline. It deliberately does not touch counters or validate bodies.
func RecentRecord ¶ added in v0.2.0
RecentRecord finds the first complete record that starts at or after span bytes before the file's logical end (audit.End). It returns the bytes from that record to the end and the record's time; zero time when the file holds less than span or no complete, decodable record starts there. Besides audit.End's search, it reads at most two records.
func SortFindings ¶
func SortFindings(items []Finding)
SortFindings gives the fixed order: severity, rule, object.
func TrafficTop ¶
TrafficTop keeps the groups with the most requests, at most limit of them, ties broken by name so the order is stable between readings.
func WasAllowed ¶
func WasAllowed(event RequestView) bool
traffic failures are refusals from the caller's perspective, while request events retain the distinction between refusal and an unknown upstream result.
Types ¶
type Cursor ¶
Cursor is where a search stopped: lines before offset in the file whose first record is first are still to be read. first identifies the file across a rotation, which renames the active file.
func DecodeCursor ¶
type Finding ¶
type Finding struct {
ID string `json:"id"`
Severity string `json:"severity"`
Object string `json:"object"`
Message string `json:"message"`
}
func ConfigurationWarnings ¶
func ConfigurationWarnings(g *compile.Generation, plain bool) []Finding
ConfigurationWarnings reads the compiled generation and, for HSTS, whether the gateway serves the data plane itself over plain HTTP (plain). A host program's listener may use TLS, which the gateway cannot see, so plain is false there and HSTS raises nothing.
type LogUse ¶
type LogUse struct {
Searched []string
// contains filtered or unexported fields
}
LogUse is what the security log shows about permission use: the role and endpoint pairs of allowed requests, how many request records were read and how far back they reach.
type Observations ¶
type Observations struct {
// contains filtered or unexported fields
}
Observations owns a bounded ring and bounded, nonblocking subscriptions. It has no authority over admission, policy, durable audit or upstream writes.
func New ¶
func New(window, apis int) *Observations
New keeps the last window requests; apis bounds the per-API duration metrics. Both are the resolved capacity limits.
func (*Observations) Close ¶
func (o *Observations) Close()
func (*Observations) Closing ¶
func (o *Observations) Closing() <-chan struct{}
Closing closes when the observations close.
func (*Observations) ConnectionRefused ¶ added in v0.2.0
func (o *Observations) ConnectionRefused()
ConnectionRefused counts one data connection closed at the cap.
func (*Observations) Recent ¶
func (o *Observations) Recent(keep func(*Observed) bool, limit int) []Observed
Recent returns, newest first, the retained requests that keep accepts, stopping once it has limit of them (0: no limit). Only returned requests are copied, so a reader that wants a short window or a few matches does not copy the whole ring while holding the lock the request path records under. keep runs under that lock and must not block.
func (*Observations) Record ¶
func (o *Observations) Record(event audit.Event)
func (*Observations) Redirected ¶ added in v0.2.0
func (o *Observations) Redirected()
Redirected counts one answer of the HTTP-to-HTTPS redirect listener.
func (*Observations) Retained ¶
func (o *Observations) Retained() int
Retained returns the number of requests kept in the window.
func (*Observations) RetainedSince ¶
func (o *Observations) RetainedSince() (time.Time, bool)
RetainedSince returns the time of the oldest request still kept and whether older requests have already been dropped from the ring.
func (*Observations) Snapshot ¶
func (o *Observations) Snapshot() []Observed
func (*Observations) Subscribe ¶
func (o *Observations) Subscribe() *Viewer
func (*Observations) TakeDropped ¶
func (o *Observations) TakeDropped(viewer *Viewer) uint64
func (*Observations) Unsubscribe ¶
func (o *Observations) Unsubscribe(viewer *Viewer)
func (*Observations) Viewers ¶
func (o *Observations) Viewers() int
Viewers returns the number of open live views.
func (*Observations) Window ¶ added in v0.2.0
func (o *Observations) Window() int
Window returns the number of requests the window keeps at most.
type Observed ¶
type Observed struct {
RequestView
// contains filtered or unexported fields
}
func (Observed) ClaimedRoles ¶
ClaimedRoles are the verified role assertions, including roles the active policy dropped.
type Query ¶
type Query struct {
// contains filtered or unexported fields
}
Query holds the filters of one search. Empty filters match all.
type RequestView ¶
type RequestView struct {
RequestID string `json:"request_id"`
Time time.Time `json:"time"`
Method string `json:"method"`
Path string `json:"path"`
Operation *string `json:"operation"`
API *string `json:"api"`
Subject *string `json:"subject"`
Roles []string `json:"roles"`
ClientAddress string `json:"client_address"`
Decision string `json:"decision"`
Status int `json:"status"`
Stage string `json:"stage"`
Code *string `json:"code"`
Generation string `json:"generation"`
DurationMS float64 `json:"duration_ms"`
// Modules is present only in builds with modules other than the built-ins.
Modules map[string]string `json:"modules,omitempty"`
}
RequestView is the explicit, secret-free Admin API projection. Private audit envelopes and their future fields are never serialized to viewers.
func View ¶
func View(event audit.Event) RequestView
View is the secret-free view of a request's final audit event, shared by the live views and the security log search so both show the same fields.
type Result ¶
type Result struct {
Items []RequestView
Next *Cursor
Searched []string
Unreadable int
}
func Search ¶
func Search(dir string, files []string, start *Cursor, query Query, limit int, scan int64) (Result, error)
Search reads the files in dir newest first from start, at most scan bytes, until limit records match. Only the final record of each request (request.rejected or request.forwarded) is read, as the live views do. A line still being written at the end of the active file is skipped.
type Summaries ¶ added in v0.2.0
type Summaries struct {
// contains filtered or unexported fields
}
Summaries keeps the fileUse of each rotated file read in full, keyed by its name and checked against its size and modification time; rotated files do not change. An entry goes when its file is no longer listed. The zero value is ready to use.
func (*Summaries) PermitUse ¶ added in v0.2.0
PermitUse reads the request records of the security log files, listed as LogFiles lists them (the active file first), newest first, at most scan bytes. A rotated file with a summary is not read but takes the budget its full read took, so the answer is the same as a full read's.
type TrafficGroup ¶
type TrafficGroup struct {
API string `json:"api"`
Operation string `json:"operation,omitempty"`
Total int `json:"total"`
Allowed int `json:"allowed"`
Refused int `json:"refused"`
P50 float64 `json:"p50_ms"`
P95 float64 `json:"p95_ms"`
// contains filtered or unexported fields
}
TrafficGroup counts the requests of one API or one endpoint and keeps their durations for the percentiles.
func (*TrafficGroup) Add ¶
func (g *TrafficGroup) Add(event RequestView)
func (*TrafficGroup) Settle ¶
func (g *TrafficGroup) Settle() TrafficGroup
type UnusedReport ¶
type UnusedReport struct {
Requests int `json:"requests"`
Since *string `json:"since"`
Complete bool `json:"complete"`
FilesSearched []string `json:"files_searched"`
FilesMissing []string `json:"files_missing"`
Withheld *string `json:"withheld"`
Items []Finding `json:"items"`
MinMinute int `json:"min_minutes"`
MinCount int `json:"min_requests"`
}
func UnusedPermissions ¶
func UnusedPermissions(g *compile.Generation, use LogUse, missing []string, now time.Time) UnusedReport
UnusedPermissions lists permits no allowed request in the security log used, once the records read cover enough time and requests. missing names log files moved away, which were not read.