Implement 'vpn firewall list', and move 'nebula create-cert' to 'vpn create-cert'

This commit is contained in:
Brian Picciano 2024-12-08 16:59:01 +01:00
parent a984ffc724
commit b38d780bdf
5 changed files with 180 additions and 7 deletions

View File

@ -38,10 +38,10 @@ var rootCmd = subCmd{
subCmdDaemon,
subCmdGarage,
subCmdHost,
subCmdNebula,
subCmdNetwork,
subCmdStorage,
subCmdVersion,
subCmdVPN,
)
},
}

View File

@ -197,7 +197,7 @@ var subCmdStorageAllocationRemove = subCmd{
var subCmdStorage = subCmd{
name: "storage",
descr: "Sub-commands having to do with configuration of storage on this host",
descr: "Sub-commands related to configuration of storage on this host",
do: func(ctx subCmdCtx) error {
return ctx.doSubCmd(
subCmdStorageAllocationAdd,

View File

@ -7,7 +7,7 @@ import (
"os"
)
var subCmdNebulaCreateCert = subCmd{
var subCmdVPNCreateCert = subCmd{
name: "create-cert",
descr: "Creates a signed nebula certificate file for an existing host and writes it to stdout",
do: func(ctx subCmdCtx) error {
@ -63,12 +63,13 @@ var subCmdNebulaCreateCert = subCmd{
},
}
var subCmdNebula = subCmd{
name: "nebula",
descr: "Sub-commands related to the nebula VPN",
var subCmdVPN = subCmd{
name: "vpn",
descr: "Sub-commands related to this host's VPN, which connects it to other hosts in the network",
do: func(ctx subCmdCtx) error {
return ctx.doSubCmd(
subCmdNebulaCreateCert,
subCmdVPNCreateCert,
subCmdVPNFirewall,
)
},
}

View File

@ -0,0 +1,64 @@
package main
import (
"fmt"
"isle/daemon/daecommon"
)
type firewallRuleView struct {
Index int `yaml:"index"`
daecommon.ConfigFirewallRule `yaml:",inline"`
}
func newFirewallRuleViews(
rules []daecommon.ConfigFirewallRule,
) []firewallRuleView {
views := make([]firewallRuleView, len(rules))
for i := range rules {
views[i] = firewallRuleView{
Index: i,
ConfigFirewallRule: rules[i],
}
}
return views
}
type firewallView struct {
Outbound []firewallRuleView `yaml:"outbound"`
Inbound []firewallRuleView `yaml:"inbound"`
}
func newFirewallView(firewallConfig daecommon.ConfigFirewall) firewallView {
return firewallView{
Outbound: newFirewallRuleViews(firewallConfig.Outbound),
Inbound: newFirewallRuleViews(firewallConfig.Inbound),
}
}
var subCmdVPNFirewallList = subCmd{
name: "list",
descr: "List all currently configured firewall rules",
do: doWithOutput(func(ctx subCmdCtx) (any, error) {
ctx, err := ctx.withParsedFlags()
if err != nil {
return nil, fmt.Errorf("parsing flags: %w", err)
}
config, err := ctx.getDaemonRPC().GetConfig(ctx)
if err != nil {
return nil, fmt.Errorf("getting network config: %w", err)
}
return newFirewallView(config.VPN.Firewall), nil
}),
}
var subCmdVPNFirewall = subCmd{
name: "firewall",
descr: "Sub-commands related to this host's VPN firewall",
do: func(ctx subCmdCtx) error {
return ctx.doSubCmd(
subCmdVPNFirewallList,
)
},
}

View File

@ -0,0 +1,108 @@
package main
import (
"context"
"encoding/json"
"isle/daemon/daecommon"
"isle/toolkit"
"strings"
"testing"
"github.com/stretchr/testify/require"
)
func TestVPNFirewallList(t *testing.T) {
t.Parallel()
tests := []struct {
name string
outbound, inbound []string
want map[string][]any
}{
{
name: "empty",
want: map[string][]any{
"outbound": {},
"inbound": {},
},
},
{
name: "single",
outbound: []string{
`{"port":"any","proto":"icmp","host":"any"}`,
},
want: map[string][]any{
"outbound": {
map[string]any{
"index": 0,
"port": "any",
"proto": "icmp",
"host": "any",
},
},
"inbound": {},
},
},
{
name: "multiple",
outbound: []string{
`{"port":"any","proto":"icmp","host":"any"}`,
},
inbound: []string{
`{"port":"any","proto":"icmp","host":"any"}`,
`{"port":"22","proto":"tcp","host":"foo"}`,
},
want: map[string][]any{
"outbound": {
map[string]any{
"index": 0,
"port": "any",
"proto": "icmp",
"host": "any",
},
},
"inbound": {
map[string]any{
"index": 0,
"port": "any",
"proto": "icmp",
"host": "any",
},
map[string]any{
"index": 1,
"port": "22",
"proto": "tcp",
"host": "foo",
},
},
},
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
var (
h = newRunHarness(t)
config daecommon.NetworkConfig
outboundRawJSON = "[" + strings.Join(test.outbound, ",") + "]"
inboundRawJSON = "[" + strings.Join(test.inbound, ",") + "]"
)
require.NoError(t, json.Unmarshal(
[]byte(outboundRawJSON), &config.VPN.Firewall.Outbound,
))
require.NoError(t, json.Unmarshal(
[]byte(inboundRawJSON), &config.VPN.Firewall.Inbound,
))
h.daemonRPC.
On("GetConfig", toolkit.MockArg[context.Context]()).
Return(config, nil).
Once()
h.runAssertStdout(t, test.want, "vpn", "firewall", "list")
})
}
}