policy

package
v0.0.1-dev.137 Latest Latest
Warning

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

Go to latest
Published: Jul 11, 2026 License: MIT Imports: 7 Imported by: 0

Documentation

Overview

Package policy implements compilation and evaluation of ServiceNetworkPolicy for the per-node agent (RUNE-064).

The agent embeds an evaluator inside the userspace proxy. When a connection lands on a service VIP listener the evaluator answers "is this peer allowed to talk to this service on this port?" using a pre-compiled rule set built from the destination service's spec.

Default-deny semantics (locked):

  • A service with **any** ingress rule defined → traffic that does not match an allow rule is denied (Kubernetes NetworkPolicy parity).
  • A service with no policy → all traffic allowed.

Source identity:

  • Same-node peers are resolved via the LocalInstances table (containerIP → service+namespace) maintained by RUNE-063.
  • Cross-node peers cannot be resolved to a service identity in v1 (no mTLS yet); only CIDR / namespace selectors match.

Egress:

  • Evaluated when a local instance dials a service VIP. The destination service+namespace is known from the dial target.

All policy state is derived from the destination Service spec. No dedicated `policy/` orderedlog keyspace is used in v1 — the spec travels with the Service. The `policy/` prefix remains reserved for a future denormalized compiled-policy index.

Index

Constants

This section is empty.

Variables

View Source
var ErrInvalidPolicy = errors.New("invalid network policy")

ErrInvalidPolicy wraps validator errors.

Functions

func Validate

func Validate(pol *types.ServiceNetworkPolicy) error

Validate runs the public ServiceNetworkPolicy validator and surfaces any compilation-time issues (currently just CIDR parse errors that Compile silently drops). The validator is the formal gate; this is a softer secondary check used by the CLI dry-run path so operators see CIDR typos.

Types

type Compiled

type Compiled struct {
	// ServiceID identifies the destination service this policy
	// belongs to. Used in logs and metrics.
	ServiceID string
	// Namespace is the destination service's namespace.
	Namespace string
	// PolicyName is a stable label for log/metric attribution. We
	// don't have a separate Policy resource yet, so this is just
	// the service ID.
	PolicyName string
	// contains filtered or unexported fields
}

Compiled is the evaluator-friendly form of a ServiceNetworkPolicy. It is small (one per service), immutable, and safe for concurrent reads. Build it once with Compile and replace atomically when the underlying spec changes.

func Compile

func Compile(svc *types.Service) *Compiled

Compile builds an evaluator for svc. svc may be nil (returns nil). Spec validation errors are surfaced via Validate; Compile is a pure transform and never returns an error — invalid peers are dropped from the rule set so a misconfigured spec fails closed.

func (*Compiled) EgressRuleCount

func (c *Compiled) EgressRuleCount() int

EgressRuleCount returns the number of compiled egress rules.

func (*Compiled) EvaluateEgress

func (c *Compiled) EvaluateEgress(target EgressTarget, proto string) Result

EvaluateEgress decides whether the service this Compiled belongs to may dial target on (port, proto).

func (*Compiled) EvaluateIngress

func (c *Compiled) EvaluateIngress(peer PeerInfo, port int, proto string) Result

EvaluateIngress decides whether peer is allowed to reach the service this Compiled belongs to on (port, proto). proto is "tcp" or "udp".

A nil Compiled means "no policy" → DecisionNoPolicy / Allow.

func (*Compiled) Explain

func (c *Compiled) Explain() ExplainOutput

Explain returns a human-readable summary of the compiled policy suitable for `rune policy explain <service>`. The output is deterministic given the same input policy.

func (*Compiled) HasEgressRules

func (c *Compiled) HasEgressRules() bool

HasEgressRules reports whether default-deny egress is in effect.

func (*Compiled) HasIngressRules

func (c *Compiled) HasIngressRules() bool

HasIngressRules reports whether default-deny ingress is in effect.

func (*Compiled) IngressRuleCount

func (c *Compiled) IngressRuleCount() int

IngressRuleCount returns the number of compiled ingress rules. Used by metrics (rune_policy_rules gauge).

type Decision

type Decision int

Decision is the outcome of evaluating a connection against a compiled policy.

const (
	// DecisionAllow means the connection is permitted.
	DecisionAllow Decision = iota
	// DecisionDeny means the connection is rejected by an explicit
	// or default-deny rule.
	DecisionDeny
	// DecisionNoPolicy means the destination service has no policy
	// at all (open service). Callers treat this as Allow but may
	// account for it separately in metrics.
	DecisionNoPolicy
)

func (Decision) String

func (d Decision) String() string

type EgressTarget

type EgressTarget struct {
	Service   string
	Namespace string
	Port      int
}

EgressTarget describes the destination of an outbound connection initiated by a local instance.

type ExplainOutput

type ExplainOutput struct {
	ServiceID          string        `json:"serviceId,omitempty"`
	Namespace          string        `json:"namespace,omitempty"`
	PolicyName         string        `json:"policy,omitempty"`
	Open               bool          `json:"open,omitempty"`
	DefaultDenyIngress bool          `json:"defaultDenyIngress,omitempty"`
	DefaultDenyEgress  bool          `json:"defaultDenyEgress,omitempty"`
	Ingress            []ExplainRule `json:"ingress,omitempty"`
	Egress             []ExplainRule `json:"egress,omitempty"`
}

ExplainOutput is the JSON-friendly form rendered by the CLI.

type ExplainRule

type ExplainRule struct {
	Peers []string `json:"peers"`
	Ports []string `json:"ports"`
}

ExplainRule is a single human-readable rule entry.

type LocalInstancesTable

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

LocalInstancesTable is a concurrent IP -> InstanceIdentity index.

Records are partitioned by node ID to make Apply / Remove cheap: when a node's local-instances record changes, the table replaces only that node's entries. The query path flattens the partitions behind the lock.

func NewLocalInstancesTable

func NewLocalInstancesTable(localNodeID string) *LocalInstancesTable

NewLocalInstancesTable returns an empty table. localNodeID is the agent's node identity; SameNode(ip) returns true only for IPs owned by that node.

func (*LocalInstancesTable) Apply

Apply replaces the entries for li.NodeID with li.Instances. An empty li.Instances clears the node's entries. Returns the new total entry count for diagnostics.

func (*LocalInstancesTable) Lookup

Lookup returns the identity for ip (and whether it was found). ip is matched as a string — callers should pass ip.String().

func (*LocalInstancesTable) PeerInfoFor

func (t *LocalInstancesTable) PeerInfoFor(ip net.IP) PeerInfo

PeerInfoFor builds a PeerInfo for an inbound source IP, attaching identity + same-node flag from the table.

func (*LocalInstancesTable) Remove

func (t *LocalInstancesTable) Remove(nodeID string) int

Remove drops all entries for nodeID. Idempotent.

func (*LocalInstancesTable) SameNode

func (t *LocalInstancesTable) SameNode(ip net.IP) bool

SameNode reports whether ip belongs to a container hosted on this agent's node.

func (*LocalInstancesTable) Size

func (t *LocalInstancesTable) Size() int

Size returns the total number of entries across all nodes. For metrics.

type PeerInfo

type PeerInfo struct {
	// IP is the source IP of the connection. Always present.
	IP net.IP
	// Identity is the (service, namespace) of the source when the
	// peer is a same-node container. Nil for cross-node peers or
	// when the agent has no local-instances entry for IP.
	Identity *types.InstanceIdentity
	// SameNode indicates whether IP belongs to a container on this
	// agent's node. Used to gate service-name selectors that cannot
	// match cross-node peers in v1.
	SameNode bool
}

PeerInfo describes the source of an inbound connection. Same-node peers carry an Identity; cross-node peers only have an IP.

type Reason

type Reason string

Reason is a short, machine-friendly tag summarising why a Decision was reached. It feeds the Prometheus drop counter and the per-drop log line.

const (
	ReasonNoPolicy             Reason = "no_policy"
	ReasonAllowedBySvc         Reason = "allow_service"
	ReasonAllowedByNamespace   Reason = "allow_namespace"
	ReasonAllowedBySelector    Reason = "allow_selector"
	ReasonAllowedByCIDR        Reason = "allow_cidr"
	ReasonDeniedNoMatch        Reason = "no_matching_rule"
	ReasonDeniedPort           Reason = "port_not_allowed"
	ReasonDeniedCrossNodeIdent Reason = "cross_node_identity_unresolved"
)

type Result

type Result struct {
	Decision Decision
	Reason   Reason
	// MatchedRule is the index into the ingress/egress slice that
	// produced an Allow decision. -1 when not applicable.
	MatchedRule int
}

Result captures both the binary Decision and a Reason for logs + metrics + `rune policy explain` output.

Jump to

Keyboard shortcuts

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