reporter

package
v0.1.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 12, 2026 License: Apache-2.0 Imports: 22 Imported by: 0

Documentation

Overview

Package reporter writes kyverno-runtime findings to namespaced OpenReports Report resources.

It is the redaction chokepoint of the event plane: this package makes leaks structurally impossible on the way out:

  1. Finding is a CLOSED struct — typed scalar fields only. There is no header map, no body field, and no free-form properties passthrough, so an unredacted payload is not even representable at the boundary.
  2. buildResult emits a FIXED key set into ReportResult.Properties, and every emitted value passes through Sanitize (see redact.go).
  3. PodIdentity.Labels are deliberately never emitted: arbitrary user-controlled key/values have no place in a Report.

None of this is configurable — there is no option, flag, or field that disables or weakens it (DESIGN §4).

Index

Constants

View Source
const (
	ResultFail = "fail"
	ResultWarn = "warn"
)

Result values emitted by this package. Monitor findings are "fail"; "warn" is available for advisory findings. No other OpenReports result value is ever produced by kyverno-runtime.

View Source
const (
	DefaultMaxResultsPerReport = 500
	DefaultFlushInterval       = 10 * time.Second
)

Defaults for Options.

View Source
const (
	LabelManagedBy = "app.kubernetes.io/managed-by"
	LabelNode      = "runtime.nirmata.io/node"
	// LabelPodUID identifies which incarnation of the Report's named pod its
	// results describe, so a pod recreated under the same name is detected as
	// a new incarnation instead of inheriting its predecessor's findings.
	LabelPodUID = "runtime.nirmata.io/pod-uid"
)

Labels applied to every Report this package writes.

View Source
const AnnotationTruncatedResults = "runtime.nirmata.io/truncated-results"

AnnotationTruncatedResults is set to "true" on a Report whose results were capped at Options.MaxResultsPerReport. Silence must never read as safety: an operator can always tell that findings were dropped.

View Source
const Category = "Runtime Security"

Category groups every result kyverno-runtime emits.

View Source
const Redacted = "REDACTED"

Redacted replaces every credential- or payload-shaped substring found in a value on its way into a Report. It is a constant: there is no knob, flag, or option that changes or disables it.

View Source
const Source = "kyverno-runtime"

Source identifies kyverno-runtime as the engine that owns the reports it writes, both at the Report and the ReportResult level.

Variables

This section is empty.

Functions

func Sanitize added in v0.1.1

func Sanitize(v string) string

Sanitize is applied to EVERY property value emitted into a Report. It scrubs credential- and payload-shaped substrings, strips control characters, and bounds the result to maxPropertyRunes.

Types

type DNSSummary

type DNSSummary struct {
	QName string
}

DNSSummary summarizes the observed question of a dns finding.

type Finding

type Finding struct {
	PolicyName string
	PolicyUID  string
	Behavior   string // "network"|"open"|"exec"|"protocol"|"dns"
	// Target is the behavior's object: the destination, path, executed
	// binary, protocol[/alpn], or question name the message names.
	Target string
	Result string // "fail"|"warn" (observation-only findings are "warn")
	// Enforced is true when the kernel actually denied the operation (an
	// enforce-mode policy's maps blocked it); false for monitor mode's
	// "would have been denied" counterfactual findings.
	Enforced  bool
	Message   string
	Pod       runtimeevent.PodIdentity
	Net       *NetSummary
	DNS       *DNSSummary
	Process   *ProcessSummary
	Timestamp time.Time
}

Finding is a CLOSED struct: typed scalar fields only. There is no headers map, no body field, no free-form properties passthrough. This is the redaction boundary: what is not representable cannot leak.

func Redact added in v0.1.1

func Redact(f Finding) Finding

Redact returns f with every string field scrubbed and bounded, and the pod labels dropped. A Finding reaches a sink before anything in this package has touched it, still carrying the raw argv and paths the kernel observed, so a sink that transmits one instead of writing it into a Report redacts here.

The pod identity is rebuilt field by field rather than copied and patched: a field added to PodIdentity and not added here is dropped, never forwarded unscrubbed.

func (Finding) Fingerprint

func (f Finding) Fingerprint() string

Fingerprint identifies a finding across flushes so repeats merge into one Report result with a count instead of growing the report unboundedly.

It deliberately excludes the message, timestamp, and every free-text field: two occurrences of the same policy hitting the same target from the same pod are the same finding.

type NetSummary

type NetSummary struct {
	DestIP   string
	DestHost string
}

NetSummary summarizes the destination of a network finding.

type Options

type Options struct {
	// NodeName is the value of the node label on every Report this daemon
	// writes.
	NodeName string
	// MaxResultsPerReport caps results per Report (default 500). Reports at
	// the cap carry the truncated-results annotation.
	MaxResultsPerReport int
	// FlushInterval is how often buffered findings are written (default 10s).
	FlushInterval time.Duration
	// Clock is injectable for tests; defaults to time.Now.
	Clock func() time.Time
	// FlushSink receives each deduplicated finding once per flush, with its
	// merged occurrence count. The finding is raw: the sink redacts. Nil
	// disables it.
	FlushSink func(f Finding, count int)
}

Options configures a Reporter. The zero value is usable: every field has a default. Note that no option touches redaction — that is deliberate and permanent (DESIGN §4).

type ProcessSummary

type ProcessSummary struct {
	Comm string
	Argv string
}

ProcessSummary summarizes the process of an exec/open finding.

type Reporter

type Reporter struct {
	// contains filtered or unexported fields
}

Reporter buffers findings, deduplicates them by fingerprint, and flushes them into namespaced OpenReports Report resources.

func New

func New(c client.Client, log logr.Logger, m *metrics.Metrics, opts Options) *Reporter

New creates a Reporter writing through c. m may be nil.

func (*Reporter) Report

func (r *Reporter) Report(f Finding)

Report enqueues a finding. It never blocks on the API server: repeats of a fingerprint merge into the buffered entry (count, firstTimestamp, lastTimestamp) and the next flush writes the merged result.

Findings without a usable pod namespace and name are dropped: they cannot address a namespaced Report. Attribution normally guarantees both (unattributed events are dropped upstream), so this is both a safety net and — because an unvalidated value would otherwise be echoed into object metadata, bypassing Sanitize — part of the redaction boundary.

func (*Reporter) Run

func (r *Reporter) Run(ctx context.Context) error

Run flushes buffered findings every FlushInterval until ctx is done, then performs one final flush so findings observed just before shutdown are not lost. It returns nil on clean shutdown.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL