Documentation
¶
Overview ¶
Package audit is the gateway's durable security log: one JSON record per request decision, administrator action and log event, appended to rotating files and synced to disk.
An admitted request is acknowledged only after its record is on disk; a record that cannot be written fails the log and protected admission stops, and records refused meanwhile are counted, never dropped silently. Records never hold credentials. The writer never deletes a file: when the file limit is reached it fails instead. It imports only fault. The request pipeline, the controller and the operator commands write to it.
Index ¶
- Constants
- Variables
- func NewRequestID() string
- type AuditLog
- func (a *AuditLog) Close(ctx context.Context) error
- func (a *AuditLog) Closed() bool
- func (a *AuditLog) Commit(ctx context.Context, e Event) error
- func (a *AuditLog) Fail(err error)
- func (a *AuditLog) Failed() bool
- func (a *AuditLog) Lost() uint64
- func (a *AuditLog) OpenErr() error
- func (a *AuditLog) Path() string
- func (a *AuditLog) Record(e Event)
- func (a *AuditLog) Unconfirmed() (events, lost uint64)
- func (a *AuditLog) Usage() (activeBytes, activeLimit, files, filesLimit int64)
- type Event
Constants ¶
const ( AuditQueueSize = 1024 MaxLoggedPath = 256 // MaxRecordBytes bounds one record, so an incomplete last record is // always found within this many bytes of the end of the file. MaxRecordBytes = 64 << 10 // AuditDrainWait bounds how long a graceful stop waits for the writer to // write what was queued before the log closed. AuditDrainWait = 5 * time.Second )
const ( StageIngress = iota StageCapture StageCanonical StageRoute StageAccess StageJWT StageRBAC StageRate StageBody StageValidation StageAudit StageBind StageForward )
Request stages in evaluation order. BODY covers framing, size, media type and JSON decoding; VALIDATION covers the header and body schemas.
const ( StagePass = "PASS" StageReject = "REJECT" StageFail = "FAIL" StageNotRun = "NE" StageNotApplicable = "NA" )
Stage results. A stage without a result was not evaluated; a stage the operation does not require, such as authentication of a public operation, is not applicable.
const ( DefaultAuditBytes = 64 << 20 DefaultAuditFiles = 8 )
Default size of the active audit file and number of files kept.
const EventSchema = 7
EventSchema is the version of the event envelope below.
Variables ¶
var StageNames = [stageCount]string{
"INGRESS", "CAPTURE", "CANONICAL", "ROUTE", "ACCESS", "JWT", "RBAC",
"RATE", "BODY", "VALIDATION", "AUDIT", "BIND", "FORWARD",
}
Functions ¶
func NewRequestID ¶
func NewRequestID() string
Types ¶
type AuditLog ¶
type AuditLog struct {
// contains filtered or unexported fields
}
AuditLog appends events to a local file. Events that gate a decision wait until the batch containing them has been synced to disk; other events are queued without blocking and counted when they cannot be queued.
An event is accepted when enqueue puts it in the queue. Every accepted event is written in order by the one writer, which ends only once close has closed the queue and every event in it has been written; so a close that returns nil means every accepted event, and the count of every refused one, is in the file and synced.
The active file is rotated to "<path>.<n>" before it would exceed maxBytes. The writer never deletes records: once maxFiles files exist it fails, and protected admission stops until an operator archives files and restarts.
func OpenAudit ¶
OpenAudit never fails: an unusable file yields a log in the failed state, which refuses every acknowledgement and therefore every admission.
func (*AuditLog) Close ¶
Close ends the log. From the moment it begins no event can be queued: Record counts it as lost and Commit refuses it. It then waits, until ctx is done, for the writer to write every event queued before, then the pending loss count, and to close the file. It returns nil only when all of that was written and synced; otherwise it reports what is not confirmed written. A writer blocked in the file system cannot be interrupted: when ctx ends first, the writer keeps the file and may still finish. Each later call reports the state it then finds.
func (*AuditLog) Commit ¶
Commit records an event and waits for durable acknowledgement. A failed or closing log, or a full queue, refuses it at once.
func (*AuditLog) Record ¶
Record queues an event without waiting. An event that cannot be queued, because the log has failed, its queue is full or it is closing, is counted; the writer writes the count with its next batch, or as it ends.
func (*AuditLog) Unconfirmed ¶
Unconfirmed returns the number of accepted events not yet written and synced, and the count of refused events not yet in the file.
type Event ¶
type Event struct {
Schema int `json:"schema"`
ID string `json:"event_id"`
Time time.Time `json:"time"`
Seq uint64 `json:"seq"`
Kind string `json:"kind"`
RequestID string `json:"request_id,omitempty"`
Stage string `json:"stage,omitempty"` // terminal stage of a request event
Stages stages `json:"stages,omitzero"`
// Modules holds the result of each compiled-in module other than the
// built-ins, keyed by module ID, with the stage result values.
Modules map[string]string `json:"modules,omitempty"`
Decision string `json:"decision,omitempty"`
Status int `json:"status,omitempty"`
Error string `json:"error,omitempty"`
Method string `json:"method,omitempty"`
Path string `json:"path,omitempty"`
Truncated bool `json:"path_truncated,omitempty"` // Path or ForwardedPath was cut to MaxLoggedPath
ForwardedPath string `json:"forwarded_path,omitempty"` // set only when the forward rule changed the path
Operation string `json:"operation,omitempty"`
API string `json:"api,omitempty"`
Subject string `json:"subject,omitempty"`
Roles []string `json:"roles,omitempty"`
IgnoredRoles []string `json:"ignored_roles,omitempty"`
ClientAddress string `json:"client_address,omitempty"`
DurationMS float64 `json:"duration_ms,omitempty"`
Actor string `json:"actor,omitempty"`
Session string `json:"session,omitempty"`
Generation string `json:"generation,omitempty"`
Profile string `json:"profile,omitempty"`
Upstream string `json:"upstream,omitempty"`
Transition string `json:"transition,omitempty"`
Revision int64 `json:"revision,omitempty"`
Candidate int64 `json:"candidate,omitempty"`
// A provisional base's events name its revision, the confirmed revision
// it returns to on rollback and its deadline.
Provisional int64 `json:"provisional,omitempty"`
RollbackTarget int64 `json:"rollback_target,omitempty"`
Deadline time.Time `json:"deadline,omitzero"`
// A temporary override's events name it, the control and target it
// governs and its expiry time.
Override int64 `json:"override,omitempty"`
Target string `json:"target,omitempty"`
Expires time.Time `json:"expires_at,omitzero"`
Reason string `json:"reason,omitempty"`
Lost uint64 `json:"lost,omitempty"`
File string `json:"file,omitempty"` // audit file named by audit.* events
Offset int64 `json:"offset,omitempty"` // start of an incomplete record
// contains filtered or unexported fields
}
Event is one security record. Client-controlled strings are bounded and JSON-encoded, so they cannot forge additional records. Credentials, bodies and query strings are never recorded. Subject is set only once a token has been verified; Actor only once an administrator has been authenticated, and Session is a non-secret reference to that administrator's session.
func (*Event) IdentityKnown ¶
IdentityKnown reports whether the request's identity is known.
func (*Event) SetIdentityKnown ¶
SetIdentityKnown records whether the request's identity is known.