netguard

package
v0.2.1 Latest Latest
Warning

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

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

Documentation

Overview

Package netguard implements the design-13 security-group firewall plane. This G1 slice is read-only: it materializes the design-13 view (security group + node binding + resolved builtin zones) of a node's legacy NFTInputs baseline without mutating the store or any apply path. The G2 slice adds the compiler with a byte-parity gate against network.GenerateNFTPlan before the legacy path retires.

Index

Constants

View Source
const (
	// FindingLockoutRiskSSH fires when no compiled rule can accept traffic on
	// the management port from anywhere.
	FindingLockoutRiskSSH = "lockout_risk_ssh"
	// FindingUnverifiedApply fires when the server has no public URL, so the
	// node-side apply cannot run a control-plane selfcheck after committing.
	FindingUnverifiedApply = "unverified_apply"

	SeverityBlock = "block"
	SeverityWarn  = "warn"

	// ManagementPort is the port the lockout lint protects. Until reality
	// reporting lands (design-13 G3 surfaces the node's real sshd listener),
	// tcp/22 is the safe universal assumption.
	ManagementPort = 22
)
View Source
const (
	// LegacyGroupPrefix namespaces the node-private security groups derived
	// from legacy NFTInputs baselines (design-13 §7.1).
	LegacyGroupPrefix = "sg-legacy-"
)
View Source
const MaxExpandedPortsPerRule = 1024

MaxExpandedPortsPerRule bounds range expansion. The current renderer emits explicit port lists, so a very wide range would produce an unreadable, unreviewable ruleset. Native `from-to` nft range emission is a later renderer upgrade (design-13 L2); until then wide ranges fail closed with a named error rather than silently exploding the plan.

Variables

View Source
var ErrNodeUnmanaged = errors.New("node guard binding is observe-only; adopt the node before planning")

ErrNodeUnmanaged is returned when a plan is requested for an observe-only binding. Converted legacy baselines start unmanaged: an operator must adopt a node before its firewall can be planned from the new model.

Functions

func Blocking

func Blocking(findings []Finding) bool

Blocking reports whether any finding blocks the plan.

func Compile

func Compile(in CompileInput) (network.NFTPlan, error)

Compile lowers zones, trusted-zone accepts, per-node overrides, and attached security groups into a single network.NFTPlan.

func CompileRuleset

func CompileRuleset(in CompileInput) (string, error)

CompileRuleset renders the final lattice_guard ruleset for a node.

func ExpandPortRanges

func ExpandPortRanges(ranges []model.GuardPortRange) ([]int, error)

ExpandPortRanges flattens inclusive ranges into the explicit port list the current renderer emits, fail-closed on invalid or excessively wide ranges.

func PortRanges

func PortRanges(ports []int) []model.GuardPortRange

PortRanges compresses a port list into sorted, deduplicated inclusive ranges: [9009,9010,9011,9013] becomes 9009-9011 and 9013. Out-of-range values are dropped rather than widened (fail-closed).

func ZoneMap

func ZoneMap(zones []model.GuardZone) map[string]model.GuardZone

ZoneMap indexes zones by id for CompileInput.

Types

type CompileInput

type CompileInput struct {
	Binding model.NodeGuardBinding
	// Groups in binding order. The caller resolves Binding.GroupIDs.
	Groups []model.SecurityGroup
	// Zones by id, including the builtin zones resolved for this node.
	Zones   map[string]model.GuardZone
	Resolve NodeResolver
}

CompileInput is the fully-resolved authoring state for one node.

type Finding

type Finding struct {
	Code     string `json:"code"`
	Severity string `json:"severity"`
	Message  string `json:"message"`
}

Finding is one lint result. Blocking findings refuse the plan unless the operator explicitly accepts the risk, which is audited.

func Lint

func Lint(plan network.NFTPlan, opts LintOptions) []Finding

Lint inspects a compiled plan for the failure modes that make a guard apply unsafe. It never mutates the plan.

type LegacyView

type LegacyView struct {
	Group   model.SecurityGroup
	Binding model.NodeGuardBinding
	Zones   []model.GuardZone
}

LegacyView is the read-only design-13 rendering of one node's legacy NFTInputs baseline.

func LegacyBaseline

func LegacyBaseline(inputs model.NFTInputs) LegacyView

LegacyBaseline converts a legacy NFTInputs record into the design-13 shape: one node-private security group whose rules reference the builtin public and wireguard zones, a binding attaching that group, and the node-resolved zone definitions. Semantics are preserved exactly: legacy "wireguard ports" were port-scoped source-CIDR allows, so the wireguard zone appears as a rule remote, never as a trusted zone in Binding.ZoneIDs. Managed is false: the node stays observe-only until an operator explicitly adopts it (G2).

type LintOptions

type LintOptions struct {
	// PublicURLConfigured reports whether the node-side apply will be able to
	// run `lattice-agent --selfcheck-controlplane` after committing.
	PublicURLConfigured bool
}

LintOptions carries the plan-time context the compiled ruleset cannot know.

type NodeResolver

type NodeResolver func(nodeID string) (model.Node, bool)

NodeResolver mirrors netpolicy.NodeResolver so node remotes resolve against current fleet state at compile time.

Jump to

Keyboard shortcuts

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