Documentation
¶
Overview ¶
Package attacksim is a SAFE, offline adversary-emulation harness. It does not exploit anything: it carries a curated set of ATT&CK-for-Containers TTPs as inert, well-bounded *descriptors* and asks the security controls under test whether they would fire (deny at admission, or detect at runtime). It is control-VALIDATION, not an exploit kit — nothing here starts a process, opens a socket, writes outside a temp dir, or touches real infrastructure.
The harness is deliberately decoupled from the controls it validates: Phase 4 (admission) and Phase 5 (runtime detection) plug in by implementing the small Control interface (see controls.go). Until those phases exist, the package ships a reference PolicyControl and a fixture-backed control so scenarios can be validated end-to-end today. Everything is deterministic (scenarios sort by ID) and gated behind an explicit authorization acknowledgement.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ErrNotAuthorized = errors.New("attacksim: run not authorized — set Options.Authorized and Options.Acknowledgement")
ErrNotAuthorized is returned when Run is called without an explicit opt-in. Adversary emulation must never run by accident.
Functions ¶
Types ¶
type Baseline ¶
type Baseline struct {
// Fired maps scenario ID -> did a control fire when this baseline was taken.
Fired map[string]bool `json:"fired"`
}
Baseline records, per scenario ID, whether a control fired at a known-good point in time. It is deliberately tiny and JSON-serializable so it can be checked into a repo and diffed like any other artifact.
func BaselineFrom ¶
BaselineFrom builds a Baseline snapshot from a completed run, so today's green run becomes tomorrow's regression yardstick.
func LoadBaseline ¶
LoadBaseline parses a Baseline from JSON.
type Control ¶
type Control interface {
// Name is a stable identifier for the control in reports.
Name() string
// Kind reports whether this is an admission or detection control.
Kind() ControlKind
// Evaluate returns the control's verdict for an inert event. It must never
// execute the action — only reason about its descriptor.
Evaluate(ctx context.Context, e Event) Verdict
}
Control is a defensive control the harness can probe. Implementations must be pure and deterministic over an Event: no wall clock, no randomness, no I/O.
type ControlKind ¶
type ControlKind string
ControlKind distinguishes the two defensive layers a scenario can exercise.
const ( // KindAdmission is a preventive control that should deny a bad request // before it is admitted (Phase 4). KindAdmission ControlKind = "admission" // KindDetection is a runtime control that should raise an alert when a bad // action occurs (Phase 5). KindDetection ControlKind = "detection" )
type ControlSet ¶
type ControlSet struct {
// contains filtered or unexported fields
}
ControlSet is an ordered collection of controls. The harness asks the set, filtered by the kind a scenario expects, whether anything fires.
func NewControlSet ¶
func NewControlSet(cs ...Control) *ControlSet
NewControlSet builds a set from the given controls, preserving order.
func (*ControlSet) Add ¶
func (s *ControlSet) Add(c Control)
Add appends a control (e.g. a real Phase 4 admission controller at wiring time).
type Event ¶
type Event struct {
Technique string // ATT&CK technique id, e.g. "T1611"
Tactic string // ATT&CK tactic name, e.g. "Privilege Escalation"
Action string // short verb phrase, e.g. "create privileged pod"
Target string // what it acts on, e.g. "pod/attacker"
Attributes map[string]string // machine-matchable properties of the action
}
Event describes, in data only, the adversary action a scenario represents. It is never executed. Attributes carry the specific bad properties (e.g. privileged=true, hostPath=/) that a control matches on — the same shape a real admission request or runtime event would expose, so a real Phase 4/5 control can evaluate it unchanged.
type FixtureControl ¶
type FixtureControl struct {
// contains filtered or unexported fields
}
FixtureControl replays recorded verdicts keyed by ATT&CK technique. It is how tests pin "this control fires for T1611" without any real control present, and how a recorded baseline of a real control can be checked into testdata. A missing technique means the control did not fire (an honest gap).
func LoadFixtureControl ¶
func LoadFixtureControl(data []byte) (*FixtureControl, error)
LoadFixtureControl parses a recorded control from JSON of the form {"name":"...","kind":"admission","fires":{"T1611":true,...}}.
func NewFixtureControl ¶
func NewFixtureControl(name string, kind ControlKind, fires map[string]bool) *FixtureControl
NewFixtureControl builds a fixture control from a technique→fired map.
func (*FixtureControl) Evaluate ¶
func (f *FixtureControl) Evaluate(_ context.Context, e Event) Verdict
Evaluate looks up the event's technique in the recorded map.
func (*FixtureControl) Kind ¶
func (f *FixtureControl) Kind() ControlKind
func (*FixtureControl) Name ¶
func (f *FixtureControl) Name() string
type Options ¶
type Options struct {
// Authorized must be true and Acknowledgement must equal AckPhrase() for a
// run to proceed. Two independent signals, so neither a stray true nor a
// copied string alone is enough.
Authorized bool
Acknowledgement string
// Only, when non-empty, restricts the run to these scenario IDs.
Only []string
}
Options gates and scopes a harness run. The zero value refuses to run (safe by default). Only include specifies a subset of scenario IDs; empty means all.
type PolicyControl ¶
type PolicyControl struct {
// contains filtered or unexported fields
}
PolicyControl is a built-in reference control. matchers maps an attribute key to the value that should trip it; presence of the key with that value (or, for "*", any non-empty value) fires the control.
func ReferenceAdmissionControl ¶
func ReferenceAdmissionControl() *PolicyControl
ReferenceAdmissionControl returns a PolicyControl that denies the pod-shaped bad properties an admission webhook would reject.
func ReferenceDetectionControl ¶
func ReferenceDetectionControl() *PolicyControl
ReferenceDetectionControl returns a PolicyControl that alerts on the runtime behaviors a detection engine would flag.
func (*PolicyControl) Evaluate ¶
func (p *PolicyControl) Evaluate(_ context.Context, e Event) Verdict
Evaluate fires when the event carries any attribute the control matches on. It is deterministic and side-effect free; matched keys are reported sorted so the reason string is stable.
func (*PolicyControl) Kind ¶
func (p *PolicyControl) Kind() ControlKind
func (*PolicyControl) Name ¶
func (p *PolicyControl) Name() string
type Regression ¶
type Regression struct {
ScenarioID string
Technique string
Name string
Severity string
WasFiring bool
NowFiring bool
}
Regression is a scenario whose defense weakened relative to the baseline: it used to fire and now does not (the dangerous direction). Newly-firing controls are improvements, not regressions, and are not reported here.
func CompareBaseline ¶
func CompareBaseline(current *Report, baseline Baseline) []Regression
CompareBaseline returns the regressions between a baseline and a current run, sorted by scenario ID. An empty result means every previously-working control still fires — the outcome you want from a scheduled validation agent.
type Report ¶
type Report struct {
Results []ScenarioResult
Total int
Validated int // scenarios where a control fired as expected
Gaps int // scenarios where no control fired (defenses did not hold)
}
Report is the full validation run: per-scenario results plus quick counts.
func Run ¶
func Run(ctx context.Context, scenarios []Scenario, controls *ControlSet, opts Options) (*Report, error)
Run validates scenarios against the control set. It returns ErrNotAuthorized unless the caller has explicitly opted in. It never executes any scenario — it only evaluates each inert Event against the controls.
type Scenario ¶
type Scenario struct {
ID string // DS-RAT-ATK-NNN
Technique string // ATT&CK technique id
TacticName string // ATT&CK tactic
Name string // short human name
Description string // what it does and why it matters
Event Event // the inert action
Expect ControlKind // which control layer must fire
Severity string // CRITICAL|HIGH|MEDIUM if the control fails to fire
References []string // ATT&CK / hardening links
}
Scenario is one curated, safe adversary technique the harness can validate. Expect names which control layer *should* stop or catch it; Severity is how serious an undetected gap would be.
type ScenarioResult ¶
type ScenarioResult struct {
Scenario Scenario
Verdicts []Verdict
Fired bool // at least one expected-kind control fired
Gap bool // no expected-kind control fired — a validation failure
}
ScenarioResult is the outcome of validating one scenario: the verdicts from every relevant control and whether the defense held (Fired) or a Gap exists.