Files
orca/internal/cli/nft_test.go
T
Jon Chery 8d1cdceb5c feat(P15.5): threat model (C-19) + ingress hybrid (R-017, REQ-099..102) + doctor mTLS (REQ-118)
Sub-wave 1: internal/emitter/nft.go (nftables emitter, DNAT :443→127.0.0.1:8443, rate-limit, SYN-flood filter); Traefik static config 127.0.0.1:8443 binding (D-220); orca doctor nft; orca nft CLI (show/diff/doctor/country-block/rate-limit).
Sub-wave 2: docs/threat-model.md (R-017 trust boundary, R-020 deadlock, D-234 secret exclusion, orca user blast radius, step-ca SPOF); orca doctor mTLS (chain verification + live handshake probe, C5).

---ci---
project: orca
phase: 15.5
milestone: v0.11
status: execute
---/ci---
2026-08-07 08:35:06 +00:00

253 lines
6.6 KiB
Go

package cli
import (
"bytes"
"context"
"errors"
"strings"
"testing"
"git.cloudinit.dev/coreci/orca/internal/emitter"
)
func TestNftCmd_Registered(t *testing.T) {
found := false
for _, c := range rootCmd.Commands() {
if c.Name() == "nft" {
found = true
break
}
}
if !found {
t.Fatal("nft command not registered on root")
}
}
func TestNftShowCmd(t *testing.T) {
_, cleanup := initTestEnv(t)
defer cleanup()
origTransport := nftTransportOverride
origPeer := nftLeadPeerOverride
defer func() {
nftTransportOverride = origTransport
nftLeadPeerOverride = origPeer
}()
nftLeadPeerOverride = "lead"
want := "table inet orca-ingress { dnat }"
nftTransportOverride = &mockNftTransport{
execOut: map[string][]byte{
"nft list table inet orca-ingress": []byte(want),
},
}
resetRootFlags(t)
var buf bytes.Buffer
rootCmd.SetOut(&buf)
rootCmd.SetErr(&buf)
rootCmd.SetArgs([]string{"nft", "show"})
if err := rootCmd.Execute(); err != nil {
t.Fatalf("nft show: %v", err)
}
if !strings.Contains(buf.String(), want) {
t.Errorf("nft show output missing %q:\n%s", want, buf.String())
}
}
func TestNftShowCmd_PeerFlag(t *testing.T) {
_, cleanup := initTestEnv(t)
defer cleanup()
origTransport := nftTransportOverride
defer func() { nftTransportOverride = origTransport }()
mt := &mockNftTransport{
execOut: map[string][]byte{"nft list table inet orca-ingress": []byte("ok")},
}
nftTransportOverride = mt
resetRootFlags(t)
var buf bytes.Buffer
rootCmd.SetOut(&buf)
rootCmd.SetErr(&buf)
rootCmd.SetArgs([]string{"nft", "show", "--peer", "node-2"})
if err := rootCmd.Execute(); err != nil {
t.Fatalf("nft show: %v", err)
}
}
func TestNftDiffCmd_NoDrift(t *testing.T) {
_, cleanup := initTestEnv(t)
defer cleanup()
origTransport := nftTransportOverride
origPeer := nftLeadPeerOverride
defer func() {
nftTransportOverride = origTransport
nftLeadPeerOverride = origPeer
}()
nftLeadPeerOverride = "lead"
// Use the full default nft render so the diff detects no drift
rendered, rerr := emitter.NftEmitter{}.RenderNftConfig(emitter.NftClusterConfig{})
if rerr != nil {
t.Fatalf("render: %v", rerr)
}
live := string(rendered[0].Content)
nftTransportOverride = &mockNftTransport{
execOut: map[string][]byte{
"nft list table inet orca-ingress": []byte(live),
},
}
resetRootFlags(t)
var buf bytes.Buffer
rootCmd.SetOut(&buf)
rootCmd.SetErr(&buf)
rootCmd.SetArgs([]string{"nft", "diff", "--against", "txn-123"})
if err := rootCmd.Execute(); err != nil {
t.Fatalf("nft diff: %v", err)
}
if !strings.Contains(buf.String(), "no drift") {
t.Errorf("expected no drift, got:\n%s", buf.String())
}
}
func TestNftDiffCmd_RequiresAgainst(t *testing.T) {
_, cleanup := initTestEnv(t)
defer cleanup()
resetRootFlags(t)
var buf bytes.Buffer
rootCmd.SetOut(&buf)
rootCmd.SetErr(&buf)
rootCmd.SetArgs([]string{"nft", "diff"})
if err := rootCmd.Execute(); err == nil {
t.Fatal("expected error for missing --against, got nil")
}
}
func TestNftRateLimitSetCmd(t *testing.T) {
_, cleanup := initTestEnv(t)
defer cleanup()
origTransport := nftTransportOverride
origPeer := nftLeadPeerOverride
defer func() {
nftTransportOverride = origTransport
nftLeadPeerOverride = origPeer
}()
nftLeadPeerOverride = "lead"
mt := &mockNftTransport{
execOut: map[string][]byte{},
}
nftTransportOverride = mt
resetRootFlags(t)
var buf bytes.Buffer
rootCmd.SetOut(&buf)
rootCmd.SetErr(&buf)
rootCmd.SetArgs([]string{"nft", "rate", "limit", "set", "--rate", "250"})
if err := rootCmd.Execute(); err != nil {
t.Fatalf("nft rate limit set: %v", err)
}
if !strings.Contains(buf.String(), "rate-limit set to 250/s burst 500") {
t.Errorf("unexpected output:\n%s", buf.String())
}
}
func TestNftRateLimitSetCmd_RequiresRate(t *testing.T) {
_, cleanup := initTestEnv(t)
defer cleanup()
resetRootFlags(t)
var buf bytes.Buffer
rootCmd.SetOut(&buf)
rootCmd.SetErr(&buf)
rootCmd.SetArgs([]string{"nft", "rate", "limit", "set"})
if err := rootCmd.Execute(); err == nil {
t.Fatal("expected error for missing --rate, got nil")
}
}
func TestNftCountryBlockAddCmd(t *testing.T) {
_, cleanup := initTestEnv(t)
defer cleanup()
origTransport := nftTransportOverride
origPeer := nftLeadPeerOverride
defer func() {
nftTransportOverride = origTransport
nftLeadPeerOverride = origPeer
}()
nftLeadPeerOverride = "lead"
mt := &mockNftTransport{execOut: map[string][]byte{}}
nftTransportOverride = mt
resetRootFlags(t)
var buf bytes.Buffer
rootCmd.SetOut(&buf)
rootCmd.SetErr(&buf)
rootCmd.SetArgs([]string{"nft", "country", "block", "add", "RU,CN"})
if err := rootCmd.Execute(); err != nil {
t.Fatalf("nft country block add: %v", err)
}
if !strings.Contains(buf.String(), "added 2 country code(s)") {
t.Errorf("unexpected output:\n%s", buf.String())
}
}
func TestNftCountryBlockAddCmd_BadCode(t *testing.T) {
_, cleanup := initTestEnv(t)
defer cleanup()
resetRootFlags(t)
var buf bytes.Buffer
rootCmd.SetOut(&buf)
rootCmd.SetErr(&buf)
rootCmd.SetArgs([]string{"nft", "country", "block", "add", "USA"})
if err := rootCmd.Execute(); err == nil {
t.Fatal("expected error for bad country code, got nil")
}
}
func TestNftDoctorAliasCmd(t *testing.T) {
_, cleanup := initTestEnv(t)
defer cleanup()
origTransport := nftTransportOverride
origPeer := nftLeadPeerOverride
defer func() {
nftTransportOverride = origTransport
nftLeadPeerOverride = origPeer
}()
nftLeadPeerOverride = "lead"
nftTransportOverride = &mockNftTransport{
execOut: map[string][]byte{
"nft list table inet orca-ingress": []byte("dnat to 127.0.0.1:8443 dnat to 127.0.0.1:8080 ora_rl"),
},
}
resetRootFlags(t)
var buf bytes.Buffer
rootCmd.SetOut(&buf)
rootCmd.SetErr(&buf)
rootCmd.SetArgs([]string{"nft", "doctor"})
if err := rootCmd.Execute(); err != nil {
t.Fatalf("nft doctor: %v", err)
}
if !strings.Contains(buf.String(), "nft:table") {
t.Errorf("nft doctor alias did not run doctor nft checks:\n%s", buf.String())
}
}
func TestNftShowCmd_ExecError(t *testing.T) {
_, cleanup := initTestEnv(t)
defer cleanup()
origTransport := nftTransportOverride
origPeer := nftLeadPeerOverride
defer func() {
nftTransportOverride = origTransport
nftLeadPeerOverride = origPeer
}()
nftLeadPeerOverride = "lead"
nftTransportOverride = &mockNftTransport{
execErr: map[string]error{
"nft list table inet orca-ingress": errors.New("connection refused"),
},
}
resetRootFlags(t)
var buf bytes.Buffer
rootCmd.SetOut(&buf)
rootCmd.SetErr(&buf)
rootCmd.SetArgs([]string{"nft", "show"})
if err := rootCmd.Execute(); err == nil {
t.Fatal("expected error from exec failure, got nil")
}
}
var _ context.Context = context.Background()