policy

package
v0.5.2 Latest Latest
Warning

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

Go to latest
Published: May 2, 2026 License: Apache-2.0 Imports: 10 Imported by: 0

Documentation

Overview

Package policy implements the shared admission and runtime capability logic from ADR-0014. Both the HarnessRun validating webhook and (in M3+) the broker's runtime checks route through the same types and functions here — the admission path is a fast path, not a separate policy language.

Index

Constants

View Source
const (
	PSAEnforceLabel    = "pod-security.kubernetes.io/enforce"
	PSALevelPrivileged = "privileged"
	PSALevelBaseline   = "baseline"
	PSALevelRestricted = "restricted"
)

Pod Security Standards namespace labels (Kubernetes 1.25+). Source: https://kubernetes.io/docs/concepts/security/pod-security-admission/

Variables

This section is empty.

Functions

func AnyDiscoveryActive

func AnyDiscoveryActive(matches []*paddockv1alpha1.BrokerPolicy, now time.Time) bool

AnyDiscoveryActive reports whether at least one matching BrokerPolicy has an unexpired egressDiscovery window. Implements the any-wins merge rule resolved during Plan D brainstorming (a single policy with active discovery is sufficient to enable discovery for the run, even if sibling matching policies do not opt in).

accepted=false is treated as inactive — a defensive check, since admission rejects that shape, but the resolver should not silently flip behavior if a malformed policy reaches it.

func AnyHostMatches

func AnyHostMatches(grants []string, required string) bool

AnyHostMatches reports whether any of the grant patterns matches the required host under EgressHostMatches semantics. Whitespace is trimmed on both sides for defence against operator-typed list entries (admission rejects whitespace, but providers historically trimmed here too — preserving that behaviour avoids a silent semantic shift during the B-03 host-match consolidation).

func AppliesToTemplate

func AppliesToTemplate(selectors []string, templateName string) bool

AppliesToTemplate reports whether a BrokerPolicy's appliesToTemplates selector list matches the given template name.

Selector dialect (Phase 2h Theme 3, F-30): shell-style globs via path.Match. "*" matches any sequence of characters; "?" matches one; "[abc]" character classes are supported. Malformed patterns silently do not match — admission's ValidateAppliesToTemplate catches them at CRD-write time so a malformed selector never reaches this function in production.

func DescribeShortfall

func DescribeShortfall(result *IntersectionResult, templateName, namespace string) string

DescribeShortfall formats an admission-diagnostic string from an intersection result. Used by the HarnessRun webhook and the CLI's `policy check` command.

func EgressHostMatches

func EgressHostMatches(grant, required string) bool

EgressHostMatches is the same grant→host matching rule admission uses, exposed for runtime callers (broker ValidateEgress). Apex does not match a "*." wildcard; case-insensitive; literal equality always wins.

func FilterUnexpired

func FilterUnexpired(matches []*paddockv1alpha1.BrokerPolicy, now time.Time) []*paddockv1alpha1.BrokerPolicy

FilterUnexpired returns the subset of matches whose egressDiscovery window is either absent or unexpired. Used by the HarnessRun admission webhook to drop expired policies from the matching set before policy.IntersectMatches; spec 0003 §3.6 calls these "non-effective."

func ListMatchingPolicies

func ListMatchingPolicies(ctx context.Context, c client.Client, namespace, templateName string) ([]*paddockv1alpha1.BrokerPolicy, error)

ListMatchingPolicies returns the BrokerPolicies in namespace whose appliesToTemplates selects templateName. Kept separate from Intersect so runtime callers (e.g. the interception-mode resolver) can reuse the same appliesToTemplates filter without re-running the full requires intersection.

func MergeTemplates

MergeTemplates applies child overrides onto a parent's locked fields per ADR-0003. Locked (inherited verbatim): Image, Command, Args, EventAdapter, Workspace, Harness. Overridable (child wins when set): Defaults, Requires, PodTemplateOverlay. The controller's reconciler and this package's webhook + (in M3+) broker clients all route through this function.

func RequiresEmpty

func RequiresEmpty(r paddockv1alpha1.RequireSpec) bool

RequiresEmpty reports whether a resolved template declares no capabilities. Used by M2's admission webhook to reject any run whose template has expectations the broker is not yet present to satisfy. M3 replaces this call with the full intersection algorithm.

func ResolveTemplate

ResolveTemplate walks TemplateRef.Kind (or the default "prefer namespaced" order) and returns the fully-resolved spec — with parent inheritance already merged per ADR-0003.

M2 uses this only from the HarnessRun webhook to extract the template's Requires. The broker reuses it in M3+.

func ValidateAppliesToTemplate

func ValidateAppliesToTemplate(selector string) error

ValidateAppliesToTemplate reports a non-nil error when selector is not a syntactically valid path.Match pattern. Admission uses this to reject malformed entries on BrokerPolicy.spec.appliesToTemplates so the runtime matcher never sees ErrBadPattern.

Types

type CoveredCredential

type CoveredCredential struct {
	Policy   string
	Provider string
}

CoveredCredential names the policy + provider backing a required credential.

type CredentialShortfall

type CredentialShortfall struct {
	Name string
}

CredentialShortfall names a required credential that no policy granted.

type EgressShortfall

type EgressShortfall struct {
	Host string
	Port int32
}

EgressShortfall names a (host, port) tuple no policy covered. Port is 0 when the requirement specified no ports (meaning "any port") and no grant covered it.

type InterceptionDecision

type InterceptionDecision struct {
	Mode        paddockv1alpha1.InterceptionMode
	Unavailable bool
	Reason      string

	// AcceptanceReason carries the BrokerPolicy
	// spec.interception.cooperativeAccepted.reason when Mode is
	// cooperative; empty otherwise. Plumbed to the proxy sidecar for
	// the F-19 residual startup AuditEvent.
	AcceptanceReason string
	// MatchedPolicy is the name of the FIRST BrokerPolicy whose
	// spec.interception.cooperativeAccepted produced the cooperative
	// decision. Used for the cooperative-acceptance audit trail.
	MatchedPolicy string
}

InterceptionDecision is the outcome of merging matching BrokerPolicies' spec.interception with the namespace PSA label. When Unavailable is true the run must fail closed with a HarnessRunConditionInterceptionUnavailable condition; Mode is empty in that case. Otherwise Mode is the interception strategy the controller should wire into the Pod.

func ResolveInterceptionMode

func ResolveInterceptionMode(
	ctx context.Context,
	c client.Client,
	ns string,
	matches []*paddockv1alpha1.BrokerPolicy,
) (InterceptionDecision, error)

ResolveInterceptionMode merges the interception specs on the supplied matching BrokerPolicies with the namespace's PSA enforce label and returns the decision the reconciler should act on.

Merge rule: ALL matching policies must explicitly opt into cooperative (via spec.interception.cooperativeAccepted with accepted=true) for the decision to pick cooperative. A missing or Transparent interception field on any matching policy yields transparent. When no BrokerPolicy matches the run's template, the default is transparent — the safer posture.

PSA gate: transparent needs CAP_NET_ADMIN on the iptables init container. Baseline and Restricted both forbid NET_ADMIN; in those namespaces a transparent request flips to Unavailable rather than silently degrading to cooperative. Cooperative does not need NET_ADMIN and is therefore insensitive to PSA.

type IntersectionResult

type IntersectionResult struct {
	// Admitted is true iff the union of MatchedPolicies' grants covers
	// every requirement in the template's requires block.
	Admitted bool

	// MatchedPolicies lists the BrokerPolicy names whose
	// appliesToTemplates selected the template. Populated regardless
	// of outcome; empty when no BrokerPolicy matched.
	MatchedPolicies []string

	// MissingCredentials lists the credential requirements no matching
	// policy granted. Populated when Admitted is false.
	MissingCredentials []CredentialShortfall

	// MissingEgress lists the egress tuples no matching policy covered.
	// Populated when Admitted is false.
	MissingEgress []EgressShortfall

	// CoveredCredentials maps each covered credential name to the
	// policy + provider that granted it. Informational — for
	// diagnostics and M10's `policy check` CLI.
	CoveredCredentials map[string]CoveredCredential

	// RunsInteract is true if at least one matching policy's grants.runs
	// has Interact: true. Aggregated across matching policies.
	RunsInteract bool

	// Shell is the resolved shell capability — nil if no matching
	// policy declares one. Multi-policy merge takes the most-permissive
	// (target=agent over adapter; union of allowedPhases [empty wins
	// i.e. "any phase"]; recordTranscript=true if any sets it; first
	// non-empty Command wins).
	Shell *paddockv1alpha1.ShellCapability
}

IntersectionResult describes the outcome of the ADR-0014 admission algorithm — intersecting a template's spec.requires with the union of matching BrokerPolicy grants in the run's namespace.

func Intersect

func Intersect(ctx context.Context, c client.Client, namespace, templateName string, requires paddockv1alpha1.RequireSpec) (*IntersectionResult, error)

Intersect lists BrokerPolicies in the given namespace, filters by appliesToTemplates against templateName, unions their grants, and compares against requires. Returns (result, nil) even when !result.Admitted — callers use the shortfall lists to produce the admission diagnostic.

func IntersectMatches

func IntersectMatches(matching []*paddockv1alpha1.BrokerPolicy, requires paddockv1alpha1.RequireSpec) *IntersectionResult

IntersectMatches is the matches-already-listed variant of Intersect. Callers that need to filter the matching policy set (e.g. dropping expired discovery policies) can pass in the filtered slice and avoid re-querying. Behavior is otherwise identical to Intersect.

Jump to

Keyboard shortcuts

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