api¶
Package api defines the load-bearing interfaces and DTOs that Portal modules communicate through. It is the only package depended on by every other internal package; nothing in api may import from internal/admission, internal/audit, internal/network, internal/actions, internal/engine, internal/expr, internal/sink, internal/lookup, or internal/rule.
The only external dependencies allowed are k8s.io/apimachinery (for GVK and Unstructured, which travel through Context) and Go's standard library.
Index¶
- func ContextBuilders() map[string]func() ContextBuilder
- func RegisterAction(typ string, ctor func() Action)
- func RegisterContextBuilder(name string, ctor func() ContextBuilder)
- func RegisterEngine(name string, ctor func() ExpressionEngine)
- func RegisterSink(name string, ctor func() OutputSink)
- func Sinks() map[string]func() OutputSink
- type Action
- func ActionFor(typ string) Action
- type ActionDispatcher
- type ActionSpec
- type AdmissionRequest
- type Context
- type ContextBuilder
- type Decision
- type DepEntry
- type DepRecorder
- type EnforcementAction
- type EventMeta
- type EventSource
- type ExpressionEngine
- func Engine(name string) ExpressionEngine
- type IdempotencyStore
- type Lookup
- type Matcher
- type Mode
- type NamespaceSelector
- type ObjectRef
- type OutputSink
- type Program
- type RateLimiter
- type Rule
- func (r Rule) HasMode(m Mode) bool
- type RuleEngine
- type RuleIndex
- type RuleLoader
- type RuleSource
- type Severity
- type UserInfo
- type Violation
- type ViolationSource
func ContextBuilders¶
ContextBuilders returns a snapshot of every registered builder factory, in no particular order. The engine queries each in turn via Supports(gvk).
func RegisterAction¶
RegisterAction adds an Action factory.
func RegisterContextBuilder¶
RegisterContextBuilder adds a ContextBuilder factory.
func RegisterEngine¶
RegisterEngine adds an ExpressionEngine factory. Last writer wins.
func RegisterSink¶
RegisterSink adds an OutputSink factory.
func Sinks¶
Sinks returns a snapshot of every registered sink factory.
type Action¶
Action is one response capability — label, annotate, evict, patch-NP, revoke-SA-token, alertmanager. Adding a new action type is one struct + one Register call.
type Action interface {
Type() string
Execute(ctx context.Context, v Violation, params map[string]any) error
Idempotent() bool
DefaultRateLimit() time.Duration
}
func ActionFor¶
ActionFor returns a constructed Action by type, or nil if absent.
type ActionDispatcher¶
ActionDispatcher routes Violations to enabled Actions. It is non-blocking, applies rate-limiting per (rule, target) tuple, and consults an IdempotencyStore so re-emissions within the action's idempotency window are dropped rather than re-executed.
type ActionDispatcher interface {
Dispatch(ctx context.Context, v Violation)
// Drain blocks until in-flight dispatches finish or ctx is cancelled.
Drain(ctx context.Context) error
}
type ActionSpec¶
ActionSpec is one entry in Rule.Actions.
type ActionSpec struct {
Type string `json:"type" yaml:"type"`
On []Mode `json:"on,omitempty" yaml:"on,omitempty"`
RateLimit string `json:"rateLimit,omitempty" yaml:"rateLimit,omitempty"`
Params map[string]any `json:"params,omitempty" yaml:",inline"`
}
type AdmissionRequest¶
AdmissionRequest is the subset of AdmissionReview.Request that rules can read.
type AdmissionRequest struct {
Operation string
UserInfo UserInfo
DryRun bool
OldObject *unstructured.Unstructured
}
type Context¶
Context is the evaluation environment a rule sees. It carries three layers:
- Object: always populated. The raw resource as *unstructured.Unstructured, exposed to expr-lang as nested maps. Anything reachable in the K8s schema is reachable here — this is the universal escape hatch.
- Env: the rendered expr-lang environment (a map[string]any). Pod-shaped sugar lives here under the keys "container", "spec", "securityContext", "metadata", "object", "request". Non-pod GVKs get only "object", "metadata", "request".
- Request: admission-only request metadata (Operation, UserInfo, DryRun, OldObject).
type Context struct {
GVK schema.GroupVersionKind
Object *unstructured.Unstructured
Env map[string]any
Request *AdmissionRequest
}
type ContextBuilder¶
ContextBuilder converts a raw unstructured resource into an evaluation Context. One ContextBuilder is responsible for one GVK family — the pod-shaped builder covers Pod plus any GVK whose spec embeds PodTemplateSpec; a fallback builder handles everything else with only Object/Env(object,metadata,request).
type ContextBuilder interface {
Supports(gvk schema.GroupVersionKind) bool
Build(obj *unstructured.Unstructured) (Context, error)
}
type Decision¶
Decision is the admission-time aggregate response across all rules that fired for one AdmissionReview request.
type Decision struct {
Allowed bool
Message string
Warnings []string
// Violations is the full list this request produced, for PolicyReport + metrics.
Violations []Violation
}
type DepEntry¶
DepEntry is an (rule, observed-object) pair recorded as depending on some referenced object.
type DepRecorder¶
DepRecorder is the write side of the reverse-dependency index. The lookup implementation records (rule, object) → (referenced) edges; the audit loop queries the inverse on resource-change events to enqueue re-evaluation.
type DepRecorder interface {
Record(rule string, observed, referenced ObjectRef)
Dependents(referenced ObjectRef) []DepEntry
}
type EnforcementAction¶
EnforcementAction controls how admission responds to a violation.
const (
EnforceDeny EnforcementAction = "deny"
EnforceWarn EnforcementAction = "warn"
EnforceDryRun EnforcementAction = "dryrun"
)
type EventMeta¶
EventMeta describes one event flowing through the engine. It is what EventSource produces and what ActionDispatcher / OutputSink consume alongside Violations.
type EventMeta struct {
Source string // "admission", "audit", "network", "api-audit-log" (v2)
EventID string // unique per event; used as the idempotency seed
At time.Time
DryRun bool
Operation string // create/update/delete; "audit" or "network" outside admission
}
type EventSource¶
EventSource produces evaluation events. The admission webhook, the audit informer loop, and the NetworkPolicy analyser each implement EventSource and feed the same RuleEngine + ActionDispatcher pipeline.
type EventSource interface {
Name() string
// Start blocks until ctx is cancelled or the source errors fatally. onEvent
// is invoked for each event; the source is responsible for any internal
// goroutines (informers, HTTP handlers).
Start(ctx context.Context, onEvent func(Context, EventMeta)) error
Stop(ctx context.Context) error
}
type ExpressionEngine¶
ExpressionEngine compiles rule expressions into evaluable Programs. expr-lang is the default implementation; CEL/Rego/starlark can be added in v3 without touching the rule schema.
type ExpressionEngine interface {
// Name is "expr", "cel", "rego" — used in metrics and the Rule's selector.
Name() string
// Compile parses one rule expression. Diagnostics include line/column when
// available so PortalClusterRule.status.parseError is human-readable.
Compile(expression string) (Program, error)
}
func Engine¶
Engine returns a constructed ExpressionEngine by name, or nil if absent.
type IdempotencyStore¶
IdempotencyStore remembers recently-dispatched (rule,gvk,ns,name,actionType) tuples. Default impl is an in-memory LRU; v2 may swap in a persistent store.
type IdempotencyStore interface {
// Seen returns true if the key has been observed within ttl, otherwise
// records it and returns false.
Seen(key string, ttl time.Duration) bool
}
type Lookup¶
Lookup is exposed to rule expressions as `cluster.\<gvk>.byName(ns, name)` and `cluster.\<gvk>.list(ns, selector)`. Backed by audit's shared informer caches at runtime; pluggable for tests.
type Lookup interface {
// ByName fetches a single object from the cache. Returns nil if absent.
ByName(gvk schema.GroupVersionKind, namespace, name string) (*unstructured.Unstructured, error)
// List returns every object of gvk in namespace matching selector. Empty
// namespace means cluster-wide.
List(gvk schema.GroupVersionKind, namespace string, selector map[string]string) ([]*unstructured.Unstructured, error)
// Watched reports the set of GVKs this Lookup currently has informers for.
Watched() []schema.GroupVersionKind
}
type Matcher¶
Matcher narrows the set of resources a rule applies to.
type Matcher struct {
GVK []schema.GroupVersionKind `json:"gvk" yaml:"gvk"`
Namespaces NamespaceSelector `json:"namespaces,omitempty" yaml:"namespaces,omitempty"`
}
type Mode¶
Mode names a rule-evaluation loop. A rule may opt in to multiple modes.
const (
ModeAdmission Mode = "admission"
ModeAudit Mode = "audit"
ModeNetwork Mode = "network"
ModeRuntime Mode = "runtime" // v2
)
type NamespaceSelector¶
NamespaceSelector is the include/exclude shape used by Rule.Match.Namespaces.
type NamespaceSelector struct {
Include []string `json:"include,omitempty" yaml:"include,omitempty"`
Exclude []string `json:"exclude,omitempty" yaml:"exclude,omitempty"`
}
type ObjectRef¶
ObjectRef identifies one cluster object for the dep index.
type OutputSink¶
OutputSink writes violations somewhere visible. AlertManager, PolicyReport, Prometheus, stdout/JSON all implement this. Each sink is independently enable-able and must be safe for concurrent Emit calls.
type OutputSink interface {
Name() string
Emit(ctx context.Context, v Violation) error
Close() error
}
type Program¶
Program is a compiled, reusable rule expression. It MUST be safe for concurrent Eval calls.
type RateLimiter¶
RateLimiter limits dispatch frequency per opaque key. Returning false means "drop"; the dispatcher counts these into portal_actions_total{result="ratelimited"}.
type Rule¶
Rule is the canonical parsed shape of a Portal rule, regardless of whether it originated from a folder YAML file or a PortalClusterRule / PortalRule CR.
type Rule struct {
Name string `json:"name" yaml:"name"`
Enabled bool `json:"enabled" yaml:"enabled"`
Severity Severity `json:"severity,omitempty" yaml:"severity,omitempty"`
Mode []Mode `json:"mode,omitempty" yaml:"mode,omitempty"`
EnforcementAction EnforcementAction `json:"enforcementAction,omitempty" yaml:"enforcementAction,omitempty"`
Match Matcher `json:"match" yaml:"match"`
Expression string `json:"rule" yaml:"rule"`
Alert string `json:"alert,omitempty" yaml:"alert,omitempty"`
Actions []ActionSpec `json:"actions,omitempty" yaml:"actions,omitempty"`
// Source identifies where this rule came from; used by status reporting and tests.
Source RuleSource `json:"-" yaml:"-"`
}
func (Rule) HasMode¶
HasMode reports whether the rule opts into the given evaluation mode.
type RuleEngine¶
RuleEngine dispatches a Context to every rule indexed under that GVK and returns the produced Violations.
type RuleIndex¶
RuleIndex is the read-only view of the rule store that the engine consults. Loaders (folder, CR) write into a concrete index that implements this.
type RuleIndex interface {
// ForGVK returns the rules whose Match.GVK includes gvk, filtered by enabled.
ForGVK(gvk schema.GroupVersionKind) []Rule
// All returns every enabled rule. Used for static dependency extraction.
All() []Rule
}
type RuleLoader¶
RuleLoader feeds parsed Rules into a central index. The folder loader walks a directory and watches it via fsnotify; the CR loader watches the two PortalClusterRule / PortalRule CRDs. Both produce the same Rule shape.
type RuleLoader interface {
Name() string
Start(ctx context.Context, onUpdate func(snapshot []Rule)) error
Stop(ctx context.Context) error
}
type RuleSource¶
RuleSource records the origin of a Rule for diagnostics.
type RuleSource struct {
Origin string // "folder", "PortalClusterRule", "PortalRule"
Path string // file path or CR name/namespace
UID string // CR UID when applicable
Generated bool // true if produced by migrate-rules
}
type Severity¶
Severity classifies a rule for downstream routing and alerting.
const (
SeverityInfo Severity = "info"
SeverityLow Severity = "low"
SeverityMedium Severity = "medium"
SeverityHigh Severity = "high"
SeverityCritical Severity = "critical"
)
type UserInfo¶
UserInfo identifies the requester at admission.
type Violation¶
Violation is the cross-cutting DTO emitted by rule evaluation. Every output channel (admission response, PolicyReport, AlertManager, Prometheus, action dispatcher) consumes Violations.
type Violation struct {
Rule string // Rule.Name
Severity Severity // copied from Rule
GVK schema.GroupVersionKind // resource that violated
Namespace string
Name string
Mode Mode // which loop produced this violation (admission/audit/network)
Message string // human-readable reason
At time.Time // creation timestamp
// EnforcementAction tells admission how to respond. Empty outside admission.
EnforcementAction EnforcementAction
// Actions is the rule's action list, copied verbatim so the dispatcher
// doesn't need to re-read the rule store. Pre-merged with the `alert:`
// shorthand.
Actions []ActionSpec
// Source carries enough metadata for sinks to render context-rich messages
// without re-fetching the object.
Source ViolationSource
}
type ViolationSource¶
ViolationSource captures the originating event for downstream rendering.
type ViolationSource struct {
EventID string // unique per emission, used for idempotency
Operation string // admission operation, if any
Username string // admission requester, if any
Container string // when the violating context was a specific container in a multi-container Pod
}
Generated by gomarkdoc