Skip to content

Commit

Permalink
Merge pull request #93 from xxxserxxx/error_cascade_clean
Browse files Browse the repository at this point in the history
Error cascade clean
  • Loading branch information
naggie authored Aug 13, 2024
2 parents baf0beb + 9129dc5 commit a24e64a
Show file tree
Hide file tree
Showing 10 changed files with 190 additions and 121 deletions.
46 changes: 34 additions & 12 deletions cmd/cli/add.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,35 @@ import (
)

// Add prompts for the required information and creates a new peer
func Add(hostname string, privKey, pubKey bool, owner, description string, confirm bool) {
func Add(hostname string, privKey, pubKey bool, owner, description string, confirm bool) error {
config, err := LoadConfigFile()
check(err, "failed to load configuration file")
if err != nil {
return fmt.Errorf("%w - failed to load configuration file", err)
}
server := GetServer(config)

var private, public string
if privKey {
private = MustPromptString("private key", true)
if private, err = PromptString("private key", true); err != nil {
return err
}
}
if pubKey {
public = MustPromptString("public key", true)
if public, err = PromptString("public key", true); err != nil {
return err
}
}
if owner == "" {
owner = MustPromptString("owner", true)
owner, err = PromptString("owner", true)
if err != nil {
return fmt.Errorf("%w - invalid input for owner", err)
}
}
if description == "" {
description = MustPromptString("Description", true)
description, err = PromptString("Description", true)
if err != nil {
return fmt.Errorf("%w - invalid input for Description", err)
}
}

// publicKey := MustPromptString("PublicKey (optional)", false)
Expand All @@ -37,22 +49,32 @@ func Add(hostname string, privKey, pubKey bool, owner, description string, confi
fmt.Fprintln(os.Stderr)

peer, err := lib.NewPeer(server, private, public, owner, hostname, description)
check(err, "failed to get new peer")
if err != nil {
return fmt.Errorf("%w - failed to get new peer", err)
}

// TODO Some kind of recovery here would be nice, to avoid
// leaving things in a potential broken state

config.MustAddPeer(peer)
if err = config.AddPeer(peer); err != nil {
return fmt.Errorf("%w - failed to add new peer", err)
}

peerType := viper.GetString("output")

peerConfigBytes, err := lib.AsciiPeerConfig(peer, peerType, *server)
check(err, "failed to get peer configuration")
if err != nil {
return fmt.Errorf("%w - failed to get peer configuration", err)
}
os.Stdout.Write(peerConfigBytes.Bytes())

config.MustSave()
if err = config.Save(); err != nil {
return fmt.Errorf("%w - failed to save config file", err)
}

server = GetServer(config)
err = server.ConfigureDevice()
check(err, "failed to configure device")
if err = server.ConfigureDevice(); err != nil {
return fmt.Errorf("%w - failed to configure device", err)
}
return nil
}
24 changes: 0 additions & 24 deletions cmd/cli/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,12 +106,6 @@ func LoadConfigFile() (*DsnetConfig, error) {
return &conf, nil
}

func MustLoadConfigFile() *DsnetConfig {
config, err := LoadConfigFile()
check(err, "failed to load configuration file")
return config
}

// Save writes the configuration to disk
func (conf *DsnetConfig) Save() error {
configFile := viper.GetString("config_file")
Expand All @@ -124,12 +118,6 @@ func (conf *DsnetConfig) Save() error {
return nil
}

// MustSave is like Save except it exits on error
func (conf *DsnetConfig) MustSave() {
err := conf.Save()
check(err, "failed to save config file")
}

// AddPeer adds a provided peer to the Peers list in the conf
func (conf *DsnetConfig) AddPeer(peer lib.Peer) error {
// TODO validate all PeerConfig (keys etc)
Expand Down Expand Up @@ -169,12 +157,6 @@ func (conf *DsnetConfig) AddPeer(peer lib.Peer) error {
return nil
}

// MustAddPeer is like AddPeer, except it exist on error
func (conf *DsnetConfig) MustAddPeer(peer lib.Peer) {
err := conf.AddPeer(peer)
check(err)
}

// RemovePeer removes a peer from the peer list based on hostname
func (conf *DsnetConfig) RemovePeer(hostname string) error {
peerIndex := -1
Expand All @@ -195,12 +177,6 @@ func (conf *DsnetConfig) RemovePeer(hostname string) error {
return nil
}

// MustRemovePeer is like RemovePeer, except it exits on error
func (conf *DsnetConfig) MustRemovePeer(hostname string) {
err := conf.RemovePeer(hostname)
check(err)
}

func (conf DsnetConfig) GetWgPeerConfigs() []wgtypes.PeerConfig {
wgPeers := make([]wgtypes.PeerConfig, 0, len(conf.Peers))

Expand Down
54 changes: 38 additions & 16 deletions cmd/cli/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,31 @@ import (
"github.com/spf13/viper"
)

func Init() {
func Init() error {
listenPort := viper.GetInt("listen_port")
configFile := viper.GetString("config_file")
interfaceName := viper.GetString("interface_name")

_, err := os.Stat(configFile)

if !os.IsNotExist(err) {
ExitFail("Refusing to overwrite existing %s", configFile)
return fmt.Errorf("%w - Refusing to overwrite existing %s", err, configFile)
}

privateKey, err := lib.GenerateJSONPrivateKey()
check(err, "failed to generate private key")
if err != nil {
return fmt.Errorf("%w - failed to generate private key", err)
}

externalIPV4, err := getExternalIP()
check(err)
if err != nil {
return err
}

externalIPV6, err := getExternalIP6()
if err != nil {
return err
}

conf := &DsnetConfig{
PrivateKey: privateKey,
Expand All @@ -40,7 +49,7 @@ func Init() {
Peers: []PeerConfig{},
Domain: "dsnet",
ExternalIP: externalIPV4,
ExternalIP6: getExternalIP6(),
ExternalIP6: externalIPV6,
InterfaceName: interfaceName,
Networks: []lib.JSONIPNet{},
PersistentKeepalive: 25,
Expand All @@ -49,21 +58,28 @@ func Init() {
server := GetServer(conf)

ipv4, err := server.AllocateIP()
check(err, "failed to allocate ipv4 address")
if err != nil {
return fmt.Errorf("%w - failed to allocate ipv4 address", err)
}

ipv6, err := server.AllocateIP6()
check(err, "failed to allocate ipv6 address")
if err != nil {
return fmt.Errorf("%w - failed to allocate ipv6 address", err)
}

conf.IP = ipv4
conf.IP6 = ipv6

if len(conf.ExternalIP) == 0 && len(conf.ExternalIP6) == 0 {
ExitFail("Could not determine any external IP, v4 or v6")
return fmt.Errorf("Could not determine any external IP, v4 or v6")
}

conf.MustSave()
if err := conf.Save(); err != nil {
return fmt.Errorf("%w - failed to save config file", err)
}

fmt.Printf("Config written to %s. Please check/edit.\n", configFile)
return nil
}

// get a random IPv4 /22 subnet on 10.0.0.0 (1023 hosts) (or /24?)
Expand Down Expand Up @@ -119,20 +135,24 @@ func getExternalIP() (net.IP, error) {
Timeout: 5 * time.Second,
}
resp, err := client.Get("https://ipv4.icanhazip.com/")
check(err)
if err != nil {
return nil, err
}
defer resp.Body.Close()

if resp.StatusCode == http.StatusOK {
body, err := ioutil.ReadAll(resp.Body)
check(err)
if err != nil {
return nil, err
}
IP = net.ParseIP(strings.TrimSpace(string(body)))
return IP.To4(), nil
}

return nil, errors.New("failed to determine external ip")
}

func getExternalIP6() net.IP {
func getExternalIP6() (net.IP, error) {
var IP net.IP
conn, err := net.Dial("udp", "2001:4860:4860::8888:53")
if err == nil {
Expand All @@ -143,7 +163,7 @@ func getExternalIP6() net.IP {

// check is not a ULA
if IP[0] != 0xfd && IP[0] != 0xfc {
return IP
return IP, nil
}
}

Expand All @@ -156,11 +176,13 @@ func getExternalIP6() net.IP {

if resp.StatusCode == http.StatusOK {
body, err := ioutil.ReadAll(resp.Body)
check(err)
if err != nil {
return nil, err
}
IP = net.ParseIP(strings.TrimSpace(string(body)))
return IP
return IP, nil
}
}

return net.IP{}
return net.IP{}, nil
}
34 changes: 25 additions & 9 deletions cmd/cli/regenerate.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@ import (
"github.com/spf13/viper"
)

func Regenerate(hostname string, confirm bool) {
config := MustLoadConfigFile()
func Regenerate(hostname string, confirm bool) error {
config, err := LoadConfigFile()
if err != nil {
return fmt.Errorf("%w - failure to load config file", err)
}
server := GetServer(config)

found := false
Expand All @@ -21,36 +24,49 @@ func Regenerate(hostname string, confirm bool) {
for _, peer := range server.Peers {
if peer.Hostname == hostname {
privateKey, err := lib.GenerateJSONPrivateKey()
check(err, "failed to generate private key")
if err != nil {
return fmt.Errorf("%w - failed to generate private key", err)
}

preshareKey, err := lib.GenerateJSONKey()
check(err, "failed to generate preshared key")
if err != nil {
return fmt.Errorf("%w - failed to generate preshared key", err)
}

peer.PrivateKey = privateKey
peer.PublicKey = privateKey.PublicKey()
peer.PresharedKey = preshareKey

err = config.RemovePeer(hostname)
check(err, "failed to regenerate peer")
if err != nil {
return fmt.Errorf("%w - failed to regenerate peer", err)
}

peerType := viper.GetString("output")

peerConfigBytes, err := lib.AsciiPeerConfig(peer, peerType, *server)
check(err, "failed to get peer configuration")
if err != nil {
return fmt.Errorf("%w - failed to get peer configuration", err)
}
os.Stdout.Write(peerConfigBytes.Bytes())
found = true
config.MustAddPeer(peer)
if err = config.AddPeer(peer); err != nil {
return fmt.Errorf("%w - failure to add peer", err)
}

break
}
}

if !found {
ExitFail(fmt.Sprintf("unknown hostname: %s", hostname))
return fmt.Errorf("unknown hostname: %s", hostname)
}

// Get a new server configuration so we can update the wg interface with the new peer details
server = GetServer(config)
config.MustSave()
if err = config.Save(); err != nil {
return fmt.Errorf("%w - failure saving config", err)
}
server.ConfigureDevice()
return nil
}
22 changes: 15 additions & 7 deletions cmd/cli/remove.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,27 @@ package cli

import "fmt"

func Remove(hostname string, confirm bool) {
conf := MustLoadConfigFile()
func Remove(hostname string, confirm bool) error {
conf, err := LoadConfigFile()
if err != nil {
return fmt.Errorf("%w - failed to load config", err)
}

err := conf.RemovePeer(hostname)
check(err, "failed to update config")
if err = conf.RemovePeer(hostname); err != nil {
return fmt.Errorf("%w - failed to update config", err)
}

if !confirm {
ConfirmOrAbort("Do you really want to remove %s?", hostname)
}

conf.MustSave()
if err = conf.Save(); err != nil {
return fmt.Errorf("%w - failure to save config", err)
}
server := GetServer(conf)

err = server.ConfigureDevice()
check(err, fmt.Sprintf("failed to sync server config to wg interface: %s", server.InterfaceName))
if err = server.ConfigureDevice(); err != nil {
return fmt.Errorf("%w - failed to sync server config to wg interface: %s", err, server.InterfaceName)
}
return nil
}
Loading

0 comments on commit a24e64a

Please sign in to comment.