From c43c95c51c2fae1a93529f15c1854be0b8e71e56 Mon Sep 17 00:00:00 2001 From: Samuel Lorch Date: Sat, 6 May 2023 21:14:35 +0200 Subject: [PATCH] Add Wireguard API --- internal/api/vpn/interfaces.go | 92 ++++++++++++++++++++++++++++++++++ internal/api/vpn/peers.go | 92 ++++++++++++++++++++++++++++++++++ internal/api/vpn/status.go | 29 +++++++++++ internal/api/vpn/vpn.go | 11 ++++ main.go | 2 + 5 files changed, 226 insertions(+) create mode 100644 internal/api/vpn/interfaces.go create mode 100644 internal/api/vpn/peers.go create mode 100644 internal/api/vpn/status.go create mode 100644 internal/api/vpn/vpn.go diff --git a/internal/api/vpn/interfaces.go b/internal/api/vpn/interfaces.go new file mode 100644 index 0000000..c637673 --- /dev/null +++ b/internal/api/vpn/interfaces.go @@ -0,0 +1,92 @@ +package vpn + +import ( + "context" + "fmt" + + "nfsense.net/nfsense/internal/definitions/vpn" +) + +type GetWireguardInterfaceParameters struct { + ID string +} + +type GetWireguardInterfaceResult struct { + Name string `json:"name"` + vpn.WireguardInterface +} + +func (f *VPN) GetWireguardInterface(ctx context.Context, params GetWireguardInterfaceParameters) (GetWireguardInterfaceResult, error) { + _, ok := f.ConfigManager.GetPendingConfig().VPN.Wireguard.Interfaces[params.ID] + if !ok { + return GetWireguardInterfaceResult{}, fmt.Errorf("WireguardInterface does not Exist") + } + + return GetWireguardInterfaceResult{ + Name: params.ID, + WireguardInterface: f.ConfigManager.GetPendingConfig().VPN.Wireguard.Interfaces[params.ID], + }, nil +} + +type GetWireguardInterfacesResult struct { + Interfaces map[string]vpn.WireguardInterface +} + +func (f *VPN) GetWireguardInterfaces(ctx context.Context, params struct{}) (GetWireguardInterfacesResult, error) { + return GetWireguardInterfacesResult{ + Interfaces: f.ConfigManager.GetPendingConfig().VPN.Wireguard.Interfaces, + }, nil +} + +type CreateWireguardInterfaceParameters struct { + Name string `json:"name"` + vpn.WireguardInterface +} + +func (f *VPN) CreateWireguardInterface(ctx context.Context, params CreateWireguardInterfaceParameters) (struct{}, error) { + _, ok := f.ConfigManager.GetPendingConfig().VPN.Wireguard.Interfaces[params.Name] + if ok { + return struct{}{}, fmt.Errorf("WireguardInterface already Exists") + } + + t, conf := f.ConfigManager.StartTransaction() + defer t.Discard() + + conf.VPN.Wireguard.Interfaces[params.Name] = params.WireguardInterface + return struct{}{}, t.Commit() +} + +type UpdateWireguardInterfaceParameters struct { + Name string + vpn.WireguardInterface +} + +func (f *VPN) UpdateWireguardInterface(ctx context.Context, params UpdateWireguardInterfaceParameters) (struct{}, error) { + _, ok := f.ConfigManager.GetPendingConfig().VPN.Wireguard.Interfaces[params.Name] + if !ok { + return struct{}{}, fmt.Errorf("WireguardInterface does not Exist") + } + + t, conf := f.ConfigManager.StartTransaction() + defer t.Discard() + + conf.VPN.Wireguard.Interfaces[params.Name] = params.WireguardInterface + return struct{}{}, t.Commit() +} + +type DeleteWireguardInterfaceParameters struct { + Name string +} + +func (f *VPN) DeleteWireguardInterface(ctx context.Context, params DeleteWireguardInterfaceParameters) (struct{}, error) { + _, ok := f.ConfigManager.GetPendingConfig().VPN.Wireguard.Interfaces[params.Name] + if !ok { + return struct{}{}, fmt.Errorf("WireguardInterface does not Exist") + } + + t, conf := f.ConfigManager.StartTransaction() + defer t.Discard() + + delete(conf.VPN.Wireguard.Interfaces, params.Name) + return struct{}{}, t.Commit() +} diff --git a/internal/api/vpn/peers.go b/internal/api/vpn/peers.go new file mode 100644 index 0000000..6742f50 --- /dev/null +++ b/internal/api/vpn/peers.go @@ -0,0 +1,92 @@ +package vpn + +import ( + "context" + "fmt" + + "nfsense.net/nfsense/internal/definitions/vpn" +) + +type GetWireguardPeerParameters struct { + ID string +} + +type GetWireguardPeerResult struct { + Name string `json:"name"` + vpn.WireguardPeer +} + +func (f *VPN) GetWireguardPeer(ctx context.Context, params GetWireguardPeerParameters) (GetWireguardPeerResult, error) { + _, ok := f.ConfigManager.GetPendingConfig().VPN.Wireguard.Peers[params.ID] + if !ok { + return GetWireguardPeerResult{}, fmt.Errorf("WireguardPeer does not Exist") + } + + return GetWireguardPeerResult{ + Name: params.ID, + WireguardPeer: f.ConfigManager.GetPendingConfig().VPN.Wireguard.Peers[params.ID], + }, nil +} + +type GetWireguardPeersResult struct { + WireguardPeers map[string]vpn.WireguardPeer +} + +func (f *VPN) GetWireguardPeers(ctx context.Context, params struct{}) (GetWireguardPeersResult, error) { + return GetWireguardPeersResult{ + WireguardPeers: f.ConfigManager.GetPendingConfig().VPN.Wireguard.Peers, + }, nil +} + +type CreateWireguardPeerParameters struct { + Name string `json:"name"` + vpn.WireguardPeer +} + +func (f *VPN) CreateWireguardPeer(ctx context.Context, params CreateWireguardPeerParameters) (struct{}, error) { + _, ok := f.ConfigManager.GetPendingConfig().VPN.Wireguard.Peers[params.Name] + if ok { + return struct{}{}, fmt.Errorf("WireguardPeer already Exists") + } + + t, conf := f.ConfigManager.StartTransaction() + defer t.Discard() + + conf.VPN.Wireguard.Peers[params.Name] = params.WireguardPeer + return struct{}{}, t.Commit() +} + +type UpdateWireguardPeerParameters struct { + Name string + vpn.WireguardPeer +} + +func (f *VPN) UpdateWireguardPeer(ctx context.Context, params UpdateWireguardPeerParameters) (struct{}, error) { + _, ok := f.ConfigManager.GetPendingConfig().VPN.Wireguard.Peers[params.Name] + if !ok { + return struct{}{}, fmt.Errorf("WireguardPeer does not Exist") + } + + t, conf := f.ConfigManager.StartTransaction() + defer t.Discard() + + conf.VPN.Wireguard.Peers[params.Name] = params.WireguardPeer + return struct{}{}, t.Commit() +} + +type DeleteWireguardPeerParameters struct { + Name string +} + +func (f *VPN) DeleteWireguardPeer(ctx context.Context, params DeleteWireguardPeerParameters) (struct{}, error) { + _, ok := f.ConfigManager.GetPendingConfig().VPN.Wireguard.Peers[params.Name] + if !ok { + return struct{}{}, fmt.Errorf("WireguardPeer does not Exist") + } + + t, conf := f.ConfigManager.StartTransaction() + defer t.Discard() + + delete(conf.VPN.Wireguard.Peers, params.Name) + return struct{}{}, t.Commit() +} diff --git a/internal/api/vpn/status.go b/internal/api/vpn/status.go new file mode 100644 index 0000000..931ef14 --- /dev/null +++ b/internal/api/vpn/status.go @@ -0,0 +1,29 @@ +package vpn + +import ( + "bytes" + "context" + "fmt" + "os/exec" + + "golang.org/x/exp/slog" +) + +type GetWireguardStatusResult struct { + Status string +} + +func (f *VPN) GetWireguardStatus(ctx context.Context, params struct{}) (GetWireguardStatusResult, error) { + cmd := exec.Command("wg") + var out bytes.Buffer + cmd.Stdout = &out + + err := cmd.Run() + if err != nil { + return GetWireguardStatusResult{}, fmt.Errorf("restarting networkd: %w", err) + } + slog.Info("wg output", "out", out.String()) + return GetWireguardStatusResult{ + Status: out.String(), + }, nil +} diff --git a/internal/api/vpn/vpn.go b/internal/api/vpn/vpn.go new file mode 100644 index 0000000..5006b92 --- /dev/null +++ b/internal/api/vpn/vpn.go @@ -0,0 +1,11 @@ +package vpn + +import ( + "github.com/godbus/dbus/v5" + "nfsense.net/nfsense/internal/config" +) + +type VPN struct { + ConfigManager *config.ConfigManager + DbusConn *dbus.Conn +} diff --git a/main.go b/main.go index 5302532..e452613 100644 --- a/main.go +++ b/main.go @@ -16,6 +16,7 @@ import ( "nfsense.net/nfsense/internal/api/network" "nfsense.net/nfsense/internal/api/object" "nfsense.net/nfsense/internal/api/service" + "nfsense.net/nfsense/internal/api/vpn" "nfsense.net/nfsense/internal/chrony" "nfsense.net/nfsense/internal/config" dhcp "nfsense.net/nfsense/internal/dhcp_server" @@ -102,6 +103,7 @@ func RegisterAPIMethods(apiHandler *jsonrpc.Handler, configManager *config.Confi apiHandler.Register("Network", &network.Network{ConfigManager: configManager, DbusConn: dbusConn}) apiHandler.Register("Object", &object.Object{ConfigManager: configManager}) apiHandler.Register("Service", &service.Service{ConfigManager: configManager, DbusConn: dbusConn}) + apiHandler.Register("VPN", &vpn.VPN{ConfigManager: configManager, DbusConn: dbusConn}) } func RegisterApplyFunctions(configManager *config.ConfigManager) {