major overhaul initiated

This commit is contained in:
afeiszli
2021-05-25 12:48:04 -04:00
parent 82d430d09e
commit 78ae219b03
37 changed files with 2971 additions and 1754 deletions

View File

@@ -1,55 +1,318 @@
package main
import (
"fmt"
"github.com/gravitl/netmaker/netclient/functions"
"golang.zx2c4.com/wireguard/wgctrl"
nodepb "github.com/gravitl/netmaker/grpc"
"flag"
"errors"
"os/exec"
"strconv"
"github.com/urfave/cli/v2"
"os"
"os/exec"
"strconv"
"strings"
"github.com/gravitl/netmaker/netclient/command"
"github.com/gravitl/netmaker/netclient/config"
"log"
)
const (
// name of the service
name = "netclient"
description = "Netmaker Daemon Service"
)
var password string
var network string
var server string
var accesskey string
var (
wgclient *wgctrl.Client
)
var (
wcclient nodepb.NodeServiceClient
)
func main() {
tpassword := flag.String("p", "changeme", "This node's password for accessing the server regularly")
taccesskey := flag.String("k", "badkey", "an access key generated by the server and used for one-time access (install only)")
taccesstoken := flag.String("t", "badtoken", "an token generated by the server and used for one-time access (install only)")
tname := flag.String("name", "noname", "give the node a name at runtime")
tserver := flag.String("s", "localhost:50051", "The location (including port) of the remote gRPC server.")
tnetwork := flag.String("n", "nonetwork", "The node network you are attempting to join.")
tdnsoff := flag.Bool("dnsoff", false, "DNS Mode. If true, netclient will not alter system dns. false by default.")
tpublicip := flag.String("ip4", "nopubip", "The node network you are attempting to join.")
tnoauto := flag.Bool("na", false, "No auto mode. If true, netmclient will not be installed as a system service and you will have to retrieve updates manually via checkin command.")
tipforward := flag.String("nf", "on", "No Forward mode. If true, netclient will not check for IP forwarding. This may break functionality")
command := flag.String("c", "required", "The command to run")
flag.Parse()
app := cli.NewApp()
app.Name = "Netclient CLI"
app.Usage = "Netmaker's netclient agent and CLI. Used to perform interactions with Netmaker server and set local WireGuard config."
cliFlags := []cli.Flag{
&cli.StringFlag{
Name: "network",
Aliases: []string{"n"},
EnvVars: []string{"NETCLIENT_NETWORK"},
Value: "all",
Usage: "Network to perform specified action against.",
},
&cli.StringFlag{
Name: "password",
Aliases: []string{"p"},
EnvVars: []string{"NETCLIENT_PASSWORD"},
Value: "badpassword",
Usage: "Password for authenticating with netmaker.",
},
&cli.StringFlag{
Name: "endpoint",
Aliases: []string{"e"},
EnvVars: []string{"NETCLIENT_ENDPOINT"},
Value: "",
Usage: "Reachable (usually public) address for WireGuard (not the private WG address).",
},
&cli.StringFlag{
Name: "macaddress",
Aliases: []string{"m"},
EnvVars: []string{"NETCLIENT_MACADDRESS"},
Value: "",
Usage: "Mac Address for this machine. Used as a unique identifier within Netmaker network.",
},
&cli.StringFlag{
Name: "publickey",
Aliases: []string{"pubkey"},
EnvVars: []string{"NETCLIENT_PUBLICKEY"},
Value: "",
Usage: "Public Key for WireGuard Interface.",
},
&cli.StringFlag{
Name: "privatekey",
Aliases: []string{"privkey"},
EnvVars: []string{"NETCLIENT_PRIVATEKEY"},
Value: "",
Usage: "Private Key for WireGuard Interface.",
},
&cli.StringFlag{
Name: "port",
EnvVars: []string{"NETCLIENT_PORT"},
Value: "",
Usage: "Port for WireGuard Interface.",
},
&cli.IntFlag{
Name: "keepalive",
EnvVars: []string{"NETCLIENT_KEEPALIVE"},
Value: 0,
Usage: "Default PersistentKeepAlive for Peers in WireGuard Interface.",
},
&cli.StringFlag{
Name: "name",
EnvVars: []string{"NETCLIENT_NAME"},
Value: "",
Usage: "Identifiable name for machine within Netmaker network.",
},
&cli.StringFlag{
Name: "localaddress",
EnvVars: []string{"NETCLIENT_LOCALADDRESS"},
Value: "",
Usage: "Local address for machine. Can be used in place of Endpoint for machines on the same LAN.",
},
&cli.StringFlag{
Name: "address",
Aliases: []string{"a"},
EnvVars: []string{"NETCLIENT_ADDRESS"},
Value: "",
Usage: "WireGuard address for machine within Netmaker network.",
},
&cli.StringFlag{
Name: "addressIPv6",
Aliases: []string{"a6"},
EnvVars: []string{"NETCLIENT_ADDRESSIPV6"},
Value: "",
Usage: "WireGuard address for machine within Netmaker network.",
},
&cli.StringFlag{
Name: "interface",
Aliases: []string{"i"},
EnvVars: []string{"NETCLIENT_INTERFACE"},
Value: "",
Usage: "WireGuard local network interface name.",
},
&cli.StringFlag{
Name: "server",
Aliases: []string{"s"},
EnvVars: []string{"NETCLIENT_SERVER"},
Value: "",
Usage: "Address + GRPC Port (e.g. 1.2.3.4:50051) of Netmaker server.",
},
&cli.StringFlag{
Name: "key",
Aliases: []string{"k"},
EnvVars: []string{"NETCLIENT_ACCESSKEY"},
Value: "",
Usage: "Access Key for signing up machine with Netmaker server during initial 'add'.",
},
&cli.StringFlag{
Name: "token",
Aliases: []string{"t"},
EnvVars: []string{"NETCLIENT_ACCESSTOKEN"},
Value: "",
Usage: "Access Token for signing up machine with Netmaker server during initial 'add'.",
},
&cli.StringFlag{
Name: "localrange",
EnvVars: []string{"NETCLIENT_LOCALRANGE"},
Value: "",
Usage: "Local Range if network is local, for instance 192.168.1.0/24.",
},
&cli.StringFlag{
Name: "roaming",
EnvVars: []string{"NETCLIENT_ROAMING"},
Value: "on",
Usage: "Checks for changes in IP address during updates if 'on'. Stays static if 'off'. On by default.",
},
&cli.StringFlag{
Name: "dns",
EnvVars: []string{"NETCLIENT_DNS"},
Value: "",
Usage: "Sets private dns if 'on'. Ignores if 'off'. Will retrieve from network if unset.",
},
&cli.StringFlag{
Name: "islocal",
EnvVars: []string{"NETCLIENT_IS_LOCAL"},
Value: "",
Usage: "Sets endpoint to local address if 'yes'. Ignores if 'no'. Will retrieve from network if unset.",
},
&cli.StringFlag{
Name: "isdualstack",
EnvVars: []string{"NETCLIENT_IS_DUALSTACK"},
Value: "",
Usage: "Sets ipv6 address if 'yes'. Ignores if 'no'. Will retrieve from network if unset.",
},
&cli.StringFlag{
Name: "ipforwarding",
EnvVars: []string{"NETCLIENT_IPFORWARDING"},
Value: "on",
Usage: "Sets ip forwarding on if 'on'. Ignores if 'off'. On by default.",
},
&cli.StringFlag{
Name: "postup",
EnvVars: []string{"NETCLIENT_POSTUP"},
Value: "",
Usage: "Sets PostUp command for WireGuard.",
},
&cli.StringFlag{
Name: "postdown",
EnvVars: []string{"NETCLIENT_POSTDOWN"},
Value: "",
Usage: "Sets PostDown command for WireGuard.",
},
&cli.StringFlag{
Name: "daemon",
EnvVars: []string{"NETCLIENT_DAEMON"},
Value: "on",
Usage: "Installs daemon if 'on'. Ignores if 'off'. On by default.",
},
}
app.Commands = []*cli.Command{
{
Name: "register",
Usage: "Register with Netmaker Server for secure GRPC communications."
Flags: cliFlags,
Action: func(c *cli.Context) error {
cfg, err := config.GetCLIConfig(c)
if err != nil {
return err
}
if cfg.Server.Address == "" {
err = errors.New("No server address provided.")
return err
}
err = command.Register(cfg)
return err
},
},
{
Name: "join",
Usage: "Join a Netmaker network.",
Flags: cliFlags,
Action: func(c *cli.Context) error {
cfg, err := config.GetCLIConfig(c)
if err != nil {
return err
}
if cfg.Network == "all" {
err = errors.New("No network provided.")
return err
}
if cfg.Server.Address == "" {
err = errors.New("No server address provided.")
return err
}
err = command.Join(cfg)
return err
},
},
{
Name: "leave",
Usage: "Leave a Netmaker network.",
Flags: cliFlags,
// the action, or code that will be executed when
// we execute our `ns` command
Action: func(c *cli.Context) error {
cfg, err := config.GetCLIConfig(c)
if err != nil {
return err
}
err = command.Leave(cfg)
return err
},
},
{
Name: "checkin",
Usage: "Checks for local changes and then checks into the specified Netmaker network to ask about remote changes.",
Flags: cliFlags,
// the action, or code that will be executed when
// we execute our `ns` command
Action: func(c *cli.Context) error {
cfg, err := config.GetCLIConfig(c)
if err != nil {
return err
}
err = command.CheckIn(cfg)
return err
},
},
{
Name: "push",
Usage: "Push configuration changes to server.",
Flags: cliFlags,
// the action, or code that will be executed when
// we execute our `ns` command
Action: func(c *cli.Context) error {
cfg, err := config.GetCLIConfig(c)
if err != nil {
return err
}
err = command.Push(cfg)
return err
},
},
{
Name: "pull",
Usage: "Pull latest configuration and peers from server.",
Flags: cliFlags,
// the action, or code that will be executed when
// we execute our `ns` command
Action: func(c *cli.Context) error {
cfg, err := config.GetCLIConfig(c)
if err != nil {
return err
}
err = command.Pull(cfg)
return err
},
},
{
Name: "status",
Usage: "Check network status.",
Flags: cliFlags,
// the action, or code that will be executed when
// we execute our `ns` command
Action: func(c *cli.Context) error {
cfg, err := config.GetCLIConfig(c)
if err != nil {
return err
}
err = command.Status(cfg)
return err
},
},
{
Name: "uninstall",
Usage: "Uninstall the netclient system service.",
Flags: cliFlags,
// the action, or code that will be executed when
// we execute our `ns` command
Action: func(c *cli.Context) error {
cfg, err := config.GetCLIConfig(c)
if err != nil {
return err
}
err = command.Uninstall(cfg)
return err
},
},
}
// start our application
getID := exec.Command("id", "-u")
out, err := getID.Output()
@@ -67,128 +330,14 @@ func main() {
}
_, err = exec.LookPath("wg")
if err != nil {
log.Println(err)
log.Fatal("WireGuard not installed. Please install WireGuard (wireguard-tools) and try again.")
}
_, err = exec.LookPath("wg")
if err != nil {
log.Println(err)
log.Fatal("WireGuard not installed. Please install WireGuard (wireguard-tools) and try again.")
}
switch *command {
case "getport":
portno, err := functions.GetFreePort(51821)
fmt.Printf("Port Number: %v", portno)
fmt.Println("")
if err != nil {
log.Fatal(err)
}
case "required":
fmt.Println("command flag 'c' is required. Pick one of |install|checkin|update|remove|")
os.Exit(1)
log.Fatal("Exiting")
case "install":
if *taccesstoken == "badtoken" && (*tnetwork == "nonetwork" || *tnetwork == "") {
fmt.Println("Required, '-n'. No network provided. Exiting.")
os.Exit(1)
}
/*
if !*tnoforward {
forward := exec.Command("sysctl", "net.ipv4.ip_forward")
out, err := forward.Output()
if err != nil {
log.Fatal(err)
}
//s := strings.Split(string(out), " ", "\n")
s := strings.Fields(string(out))
if err != nil {
log.Fatal(err)
}
if s[2] != "1" {
log.Fatal("It is recommended to enable IP Forwarding. Current status is: " + s[2] + ", but should be 1. if you would like to run without IP Forwarding, re-run with flag '-nf true'")
}
}
*/
fmt.Println("Beginning agent installation.")
err := functions.Install(*taccesskey, *tpassword, *tserver, *tnetwork, *tnoauto, *taccesstoken, *tname, *tpublicip, *tdnsoff, *tipforward)
if err != nil {
fmt.Println("Error encountered while installing.")
if !strings.Contains(err.Error(), "ALREADY_INSTALLED") {
fmt.Println("Error installing: ", err)
fmt.Println("Cleaning up (uninstall)")
err = functions.Remove(*tnetwork)
if err != nil {
fmt.Println("Error uninstalling: ", err)
fmt.Println("Wiping local.")
err = functions.WipeLocal(*tnetwork)
if err != nil {
fmt.Println("Error removing artifacts: ", err)
}
err = functions.RemoveSystemDServices(*tnetwork)
if err != nil {
fmt.Println("Error removing services: ", err)
}
}
os.Exit(1)
} else {
fmt.Println(err.Error())
os.Exit(1)
}
}
/*
case "service-install":
fmt.Println("Beginning service installation.")
err := functions.ConfigureSystemD()
if err != nil {
fmt.Println("Error installing service: ", err)
os.Exit(1)
}
case "service-uninstall":
fmt.Println("Beginning service uninstall.")
err := functions.RemoveSystemDServices()
if err != nil {
fmt.Println("Error installing service: ", err)
os.Exit(1)
}
*/
case "checkin":
if *tnetwork == "nonetwork" || *tnetwork == "" {
fmt.Println("Required, '-n'. No network provided. Exiting.")
os.Exit(1)
}
fmt.Println("Beginning node check in for network " + *tnetwork)
err := functions.CheckIn(*tnetwork)
if err != nil {
fmt.Println("Error checking in: ", err)
os.Exit(1)
}
case "remove":
if *tnetwork == "nonetwork" || *tnetwork == "" {
fmt.Println("Required, '-n'. No network provided. Exiting.")
os.Exit(1)
}
fmt.Println("Beginning node cleanup.")
err := functions.Remove(*tnetwork)
if err != nil {
/*
fmt.Println("Error uninstalling: ", err)
fmt.Println("Wiping local.")
err = functions.WipeLocal()
if err != nil {
fmt.Println("Error removing artifacts: ", err)
}
err = functions.RemoveSystemDServices()
if err != nil {
fmt.Println("Error removing services: ", err)
}
*/
fmt.Println("Error deleting node: ", err)
os.Exit(1)
}
default:
fmt.Println("You must select from the following commands: install|remove|checkin", err)
os.Exit(1)
}
fmt.Println("Command " + *command + " Executed Successfully")
err = app.Run(os.Args)
if err != nil {
log.Fatal(err)
}
}