Documentation
¶
Overview ¶
Package firewall implements the node-agnostic `solo-provisioner network firewall` scope: the `inet host` nftables table that protects the bare-metal host (SSH/mgmt allowlist, ICMP policy, in-cluster host-service ports).
It is a generic primitive — it knows nothing about block/consensus/mirror/ relay nodes. Orchestration (wiring create into `kube cluster install`, teardown into `kube cluster uninstall`) is owned by the host/cluster layer (#777 → #778/#791); this package only implements the verbs.
The `inet host` table is kept deliberately separate from `inet weaver` (the BN workload plane). The two tables have opposite lifecycles: `inet host` is set once and rarely changes, while `inet weaver` churns continuously as the daemon rewrites set elements.
Index ¶
- Constants
- Variables
- type Config
- type Manager
- func (m *Manager) AddMgmtCIDR(ctx context.Context, cidr string) error
- func (m *Manager) AddPort(ctx context.Context, port int) error
- func (m *Manager) Create(ctx context.Context, t *Table, force bool) (bool, error)
- func (m *Manager) Delete(ctx context.Context) error
- func (m *Manager) RemoveMgmtCIDR(ctx context.Context, cidr string) error
- func (m *Manager) RemovePort(ctx context.Context, port int) error
- func (m *Manager) Set(ctx context.Context, mgmtCIDRs []string, ports []int) error
- func (m *Manager) Show(ctx context.Context) (string, error)
- type Runner
- type Table
- func (t *Table) AddMgmtCIDR(cidr string) error
- func (t *Table) AddPort(port int) error
- func (t *Table) RemoveMgmtCIDR(cidr string)
- func (t *Table) RemovePort(port int)
- func (t *Table) Render() (string, error)
- func (t *Table) SetMgmtCIDRs(cidrs []string) error
- func (t *Table) SetPorts(ports []int) error
- func (t *Table) Validate() error
Constants ¶
const ( // TableName is the nftables table this package owns. TableName = "inet host" // HostNftPath is the on-disk artifact replayed at boot by the shared // solo-provisioner-network-nft.service oneshot (authored by #780). It lives // under /etc (host OS config on the root filesystem) — not /opt/solo/weaver, // which may be a late mount and would leave the firewall unloaded early at // boot. HostNftPath = "/etc/solo-provisioner/network-host.nft" // WeaverNftPath is the inet weaver artifact, owned by `block node install` // (TS_2 #743). This package never writes it; it only checks for its presence // to decide whether the shared oneshot may be disabled (teardown is #791). WeaverNftPath = "/etc/solo-provisioner/network-weaver.nft" // NetworkNftService is the oneshot unit that loads network-host.nft at boot // and is restarted on every live mutation so the kernel and the on-disk file // are always in sync. This package authors, installs, and enables the unit; // it never disables it — that is orchestrated by `kube cluster uninstall` // (#791). The unit is extended by #780 to also load network-weaver.nft. NetworkNftService = "solo-provisioner-network-nft.service" // NetworkNftServiceUnitPath is the absolute path where the unit file is // installed so systemd can discover it. NetworkNftServiceUnitPath = "/usr/lib/systemd/system/" + NetworkNftService // NftablesDropInDir is where the nftables.service drop-in is installed. // Drop-ins in /etc/systemd/system/ take precedence and survive package // upgrades of the nftables package itself. NftablesDropInDir = "/etc/systemd/system/nftables.service.d" // NftablesDropInPath is the drop-in file that makes nftables.service pull // in solo-provisioner-network-nft.service whenever it activates — so a // mid-run nftables flush (e.g. triggered by kube cluster install's preflight) // is always followed by a re-apply of our inet host rules. NftablesDropInPath = NftablesDropInDir + "/solo-provisioner.conf" // LockDir holds the cross-command apply lock. It lives on tmpfs (/run) so it // is auto-cleared on reboot and leaves nothing behind on uninstall. LockDir = "/run/solo-provisioner/network" // LockPath is the flock acquired (LOCK_EX) for the duration of any mutating // verb, so a hand-run operator command and the daemon poll loop (#754) can // never interleave nft transactions. LockPath = "/run/solo-provisioner/network/.applying" )
const (
DefaultSSHPort = 22
)
Default flag values per design §8.4.1.
Variables ¶
var DefaultInClusterPorts = []int{6443, 4244, 7472, 10250}
DefaultInClusterPorts is the "stack set" of host-service ports opened to the in-cluster (pod) CIDR by default: the kube-apiserver (6443), the Cilium cluster-mesh / health port (4244), the kubelet read-only/metrics port (10250), and the MetalLB metrics/memberlist port (7472). Operators override with --in-cluster-ports.
Functions ¶
This section is empty.
Types ¶
type Config ¶
type Config struct {
Runner Runner
NftPath string
LockPath string
ApplyViaService func(ctx context.Context) error
}
Config customises a Manager. The zero value is not useful; prefer NewManager. Tests inject a fake Runner, temp paths, and a no-op service func so the package builds and runs on any platform.
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
Manager implements the `network firewall` verbs against the `inet host` table. Every mutating verb takes the shared apply lock, atomically rewrites the on-disk artifact, and then restarts the systemd service via DBus so the kernel is updated in one consistent operation — no separate nft apply exec.
func NewManager ¶
func NewManager() *Manager
NewManager returns a Manager wired to the live kernel and the production paths.
func NewManagerWithConfig ¶
NewManagerWithConfig returns a Manager, filling any unset Config field with its production default.
func (*Manager) AddMgmtCIDR ¶
AddMgmtCIDR adds one CIDR to the management allowlist and re-renders.
func (*Manager) Create ¶
Create is create-if-missing: when the table already exists and force is false, it makes no changes and returns (false, nil). force re-renders the table from the supplied flags and returns (true, nil).
func (*Manager) Delete ¶
Delete removes the inet host table and its on-disk artifact. It is idempotent. It deliberately does NOT disable the shared solo-provisioner-network-nft.service (shared with inet weaver) — that is orchestrated by `kube cluster uninstall` (#791).
func (*Manager) RemoveMgmtCIDR ¶
RemoveMgmtCIDR removes one CIDR from the management allowlist and re-renders.
func (*Manager) RemovePort ¶
RemovePort removes one in-cluster host-service port and re-renders.
type Runner ¶
type Runner interface {
// List returns the rendered ruleset for the inet host table
// (`nft list table inet host`).
List(ctx context.Context) (string, error)
// Delete removes the inet host table (`nft delete table inet host`).
Delete(ctx context.Context) error
// Exists reports whether the inet host table is present in the kernel.
Exists(ctx context.Context) (bool, error)
}
Runner is the seam over the system `nft` binary for read and delete operations. Live rule application is done by writing the on-disk artifact and restarting the systemd service via DBus — so Apply is not part of this interface. Tests substitute a fake so the package builds and unit-tests on any platform (including macOS) without touching the kernel.
func NewExecRunner ¶
func NewExecRunner() Runner
NewExecRunner resolves the nft binary path and returns a Runner that applies changes to the live kernel.
type Table ¶
type Table struct {
// MgmtCIDRs is the management/SSH allowlist (set @mgmt_addrs).
MgmtCIDRs []string
// InClusterPorts are host-service ports reachable from PodCIDR (set
// @in_cluster_ports). Per design there is deliberately no --service-ports:
// BN ports live only in `network policy --ports`.
InClusterPorts []int
// SSHPort is the TCP port accepted from @mgmt_addrs for management access.
SSHPort int
// PodCIDR is the source range allowed to reach @in_cluster_ports. Empty
// means no in-cluster port rule is rendered.
PodCIDR string
}
Table is the in-memory model of the `inet host` nftables table. It is the single source of truth that both the kernel apply (via `nft -f`) and the on-disk artifact are rendered from, so the two can never diverge.
func NewTable ¶
func NewTable() *Table
NewTable returns a Table populated with the design defaults. Callers override fields from CLI flags before rendering.
func Parse ¶
Parse reconstructs a Table from the on-disk network-host.nft artifact. It understands only the exact format this package renders (see the embedded template) — it is not a general nft parser. A render→parse→render round-trip is the identity, which is pinned by TestRoundTrip. Element verbs (add/remove/ set) use this to load prior state so they don't need the full flag set re-spec.
func (*Table) AddMgmtCIDR ¶
AddMgmtCIDR adds a single CIDR to the management allowlist (idempotent).
func (*Table) RemoveMgmtCIDR ¶
RemoveMgmtCIDR removes a single CIDR from the management allowlist (idempotent; removing an absent CIDR is a no-op).
func (*Table) RemovePort ¶
RemovePort removes a single in-cluster host-service port (idempotent).
func (*Table) Render ¶
Render produces the full `inet host` nft document for this table. The same output feeds both the kernel apply (`nft -f`) and the on-disk artifact, so the live table and the persisted file can never diverge.
func (*Table) SetMgmtCIDRs ¶
SetMgmtCIDRs atomically replaces the full management allowlist.