Documentation
¶
Overview ¶
Package detection evaluates versioned, declarative detection rules.
The package deliberately owns no database or provider credentials. A rule receives an immutable event and organization context and returns finding drafts. Persistence, deduplication against SecurityFinding, and provider remediation remain in the ingestion worker. This keeps rule evaluation deterministic and makes the same engine usable by backtests and tests.
Index ¶
- Variables
- func DedupeMaterial(rule Rule, target string) string
- func SortedRuleIDs(rules []Rule) []string
- func VersionedDedupeHash(rule Rule, target string) string
- type BacktestMatch
- type BacktestReport
- type Condition
- type DedupeSpec
- type Engine
- func (e *Engine) AutoResolve(event Event, org OrgContext, overrides Overrides) ([]ResolutionDraft, error)
- func (e *Engine) Backtest(ruleID string, events []Event, org OrgContext, overrides Overrides) (BacktestReport, error)
- func (e *Engine) Evaluate(event Event, org OrgContext, overrides Overrides) ([]FindingDraft, error)
- func (e *Engine) Rules() []Rule
- type Event
- type FindingDraft
- type FindingSpec
- type OrgContext
- type Overrides
- type ResolutionDraft
- type Rule
- type Source
Constants ¶
This section is empty.
Variables ¶
var BuiltinFS embed.FS
BuiltinFS contains the reviewed P1 rules shipped with Aperio. Callers can use LoadPack on a filesystem for operator-supplied packs; production worker startup uses BuiltinEngine so it does not depend on the process cwd.
Functions ¶
func DedupeMaterial ¶
DedupeMaterial is provided for callers that need to inspect the exact versioned material without duplicating the hash implementation.
func SortedRuleIDs ¶
SortedRuleIDs is useful for support-matrix and diagnostics output.
func VersionedDedupeHash ¶
VersionedDedupeHash returns a stable content hash for external backtest reports and future version-aware persistence. The current worker keeps the legacy ID-plus-target persisted key so existing findings do not fork during this migration, and stores RuleVersion in finding provenance.
Types ¶
type BacktestMatch ¶
type BacktestMatch struct {
EventType string `json:"eventType"`
OccurredAt string `json:"occurredAt"`
Target string `json:"target"`
DedupeTarget string `json:"dedupeTarget"`
Severity string `json:"severity,omitempty"`
Resolution bool `json:"resolution,omitempty"`
}
BacktestMatch is a small evidence sample suitable for CLI/API rendering.
type BacktestReport ¶
type BacktestReport struct {
RuleID string `json:"ruleId"`
RuleVersion string `json:"ruleVersion"`
Events int `json:"events"`
Candidates int `json:"candidates"`
Matches int `json:"matches"`
Resolutions int `json:"resolutions"`
MatchSamples []BacktestMatch `json:"matchSamples,omitempty"`
}
BacktestReport summarizes deterministic replay over a fixture/event slice.
type Condition ¶
type Condition struct {
Expression string `yaml:"expression" json:"expression"`
}
Condition is intentionally only an expression string. CEL is compiled at pack-load time and executes without access to Go functions, I/O, or a database.
type DedupeSpec ¶
type DedupeSpec struct {
TargetTemplate string `yaml:"target_template" json:"targetTemplate"`
}
DedupeSpec defines the stable subject used by the worker's tenant-scoped dedupe key. Templates are deliberately logic-free.
type Engine ¶
type Engine struct {
// contains filtered or unexported fields
}
Engine compiles a rule pack once and evaluates it without I/O. CEL's standard environment is intentionally limited to three dynamic bindings; rules cannot call Go functions or access process state.
func NewEngine ¶
NewEngine validates and compiles rules. Compilation is the trust boundary: callers should refuse to activate a pack when this returns an error.
func (*Engine) AutoResolve ¶
func (e *Engine) AutoResolve(event Event, org OrgContext, overrides Overrides) ([]ResolutionDraft, error)
AutoResolve evaluates clean-event predicates for open finding state. It does not mutate storage; the ingestion worker must perform the scoped transition using the returned rule ID and target.
func (*Engine) Backtest ¶
func (e *Engine) Backtest(ruleID string, events []Event, org OrgContext, overrides Overrides) (BacktestReport, error)
Backtest replays events through one rule. It is intentionally in-memory so callers can use fixture events in CI or a bounded database query without granting the evaluator database access.
func (*Engine) Evaluate ¶
func (e *Engine) Evaluate(event Event, org OrgContext, overrides Overrides) ([]FindingDraft, error)
Evaluate produces one draft per matching rule. Event type filtering and tenant overrides happen before CEL evaluation. A runtime expression error is returned rather than treated as a match; callers can fail closed and preserve an error/metrics record for operators.
type Event ¶
type Event struct {
OrganizationID string
IntegrationID string
Provider string
EventType string
Source string
Actor string
OccurredAt time.Time
Payload map[string]any
}
Event is the provider-neutral input to the evaluator.
type FindingDraft ¶
type FindingDraft struct {
RuleID string
RuleVersion string
Title string
Description string
Severity string
RiskScore int
Tags []string
RemediationSteps []string
Target string
DedupeTarget string
Evidence map[string]any
}
FindingDraft is pure evaluator output. DedupeTarget is the rendered, version-stable subject; the worker adds organization/integration identity before hashing the persisted dedupe key and records RuleVersion alongside the finding for migration-safe provenance.
type FindingSpec ¶
type FindingSpec struct {
TargetTemplate string `yaml:"target_template,omitempty" json:"targetTemplate,omitempty"`
Title string `yaml:"title" json:"title"`
Description string `yaml:"description" json:"description"`
RemediationSteps []string `yaml:"remediation_steps" json:"remediationSteps"`
Evidence map[string]string `yaml:"evidence,omitempty" json:"evidence,omitempty"`
}
FindingSpec is the operator-facing output of a rule.
type OrgContext ¶
OrgContext contains non-secret tenant configuration explicitly made available to a rule. It is kept as data rather than a callback so a rule cannot perform I/O or escape the evaluator sandbox.
type Overrides ¶
Overrides are applied after a rule is selected. Disabled is the existing integration disabled_checks mechanism. SeverityOverrides is intentionally a separate map so a caller can preserve disabled-check expiry metadata while adding a severity policy in the same integration configuration JSON.
type ResolutionDraft ¶
type ResolutionDraft struct {
RuleID string
RuleVersion string
DedupeTarget string
Evidence map[string]any
}
ResolutionDraft identifies an open finding that a later clean event should resolve. The worker owns the state transition and must scope it by tenant, integration, rule ID, and rendered target.
type Rule ¶
type Rule struct {
ID string `yaml:"id" json:"id"`
Version string `yaml:"version" json:"version"`
Name string `yaml:"name" json:"name"`
Severity string `yaml:"severity" json:"severity"`
RiskScore int `yaml:"risk_score" json:"riskScore"`
Tags []string `yaml:"tags,omitempty" json:"tags,omitempty"`
Source Source `yaml:"source" json:"source"`
When Condition `yaml:"when" json:"when"`
Dedupe DedupeSpec `yaml:"dedupe" json:"dedupe"`
Finding FindingSpec `yaml:"finding" json:"finding"`
AutoResolveWhen *Condition `yaml:"auto_resolve_when,omitempty" json:"autoResolveWhen,omitempty"`
}
Rule is the YAML representation of one stateless detection rule.
Rule IDs and versions are public contracts. A rule version changes when its predicate, finding semantics, or dedupe target changes; callers can retain the old version while evaluating a new one during a controlled migration.
func LoadEmbeddedPack ¶
LoadEmbeddedPack loads YAML rules from an fs.FS, which makes the built-in rules easy to test without relying on the machine filesystem.
func LoadPack ¶
LoadPack reads and validates all YAML rule files directly in dir. Nested directories are not walked implicitly: packs are versioned directories and callers must choose the exact provider pack they intend to activate.
func ValidateRules ¶
ValidateRules validates a complete pack and rejects duplicate rule IDs. There is one active version per ID in an Engine; a version change is a replacement that must be rolled out deliberately rather than two programs competing for the same persisted finding key. Returning a fresh slice also makes a caller's subsequent append unable to mutate the loader's registry accidentally.
type Source ¶
type Source struct {
Provider string `yaml:"provider" json:"provider"`
EventTypes []string `yaml:"event_types" json:"eventTypes"`
}
Source restricts evaluation before CEL runs. Event types are normalized in the same way as ingestion worker event types, so providers can use either audit-log names (for example repository.publicized) or canonical names.