From 5ac25964295a3d667775fa17a360915047a039e5 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 3 Jun 2020 11:59:24 -0700 Subject: [PATCH] More CLI work, link go.mod and go.sum for some Go editors to work. --- go.mod | 1 + go.sum | 1 + go/cmd/zerotier/cli/misc.go | 66 +++++++++++++++++++- go/cmd/zerotier/cli/network.go | 110 +++++++++++++++++++++++---------- go/cmd/zerotier/zerotier.go | 19 +++--- 5 files changed, 156 insertions(+), 41 deletions(-) create mode 120000 go.mod create mode 120000 go.sum diff --git a/go.mod b/go.mod new file mode 120000 index 000000000..7e6f5ab4a --- /dev/null +++ b/go.mod @@ -0,0 +1 @@ +go/go.mod \ No newline at end of file diff --git a/go.sum b/go.sum new file mode 120000 index 000000000..0be18f4e9 --- /dev/null +++ b/go.sum @@ -0,0 +1 @@ +go/go.sum \ No newline at end of file diff --git a/go/cmd/zerotier/cli/misc.go b/go/cmd/zerotier/cli/misc.go index 0ab1e064d..d1b4621f4 100644 --- a/go/cmd/zerotier/cli/misc.go +++ b/go/cmd/zerotier/cli/misc.go @@ -80,16 +80,76 @@ func apiDelete(basePath, authToken, urlPath string, result interface{}) int64 { func enabledDisabled(f bool) string { if f { - return "ENABLED" + return "enabled" } - return "DISABLED" + return "disabled" +} + +func allowedBlocked(f bool) string { + if f { + return "allowed" + } + return "blocked" +} + +// isTrueStringPrefixChars matches things like [Tt]rue, [Yy]es, 1, [Ee]nabled, and [Aa]llowed +var isTrueStringPrefixChars = [9]uint8{'t', 'T', 'y', 'Y', '1', 'e', 'E', 'a', 'A'} + +func isTrue(s string) bool { + if len(s) > 0 { + f := s[0] + for _, c := range isTrueStringPrefixChars { + if c == f { + return true + } + } + } + return false } func jsonDump(obj interface{}) string { - j, _ := json.MarshalIndent(obj, "", " ") + j, _ := json.MarshalIndent(obj, "", "\t") return string(j) } +// parseAddressFingerprintOrIdentity parses an argument as an address, fingerprint, or identity. +// If it's an address, only that return variable is filled out. Fingerprints fill out both address and +// fingerprint. Identity fills out all three. +func parseAddressFingerprintOrIdentity(s string) (a zerotier.Address, fp *zerotier.Fingerprint, id *zerotier.Identity) { + var err error + + s = strings.TrimSpace(s) + hasColon := strings.ContainsRune(s, ':') + hasDash := strings.ContainsRune(s, '-') + + if len(s) == zerotier.AddressStringLength && !hasColon && !hasDash { + a, err = zerotier.NewAddressFromString(s) + if err == nil { + return + } + } + + if hasDash { + fp, err = zerotier.NewFingerprintFromString(s) + if err == nil { + a = fp.Address + return + } + } + + if hasColon { + id, err = zerotier.NewIdentityFromString(s) + if err == nil { + a = id.Address() + fp = id.Fingerprint() + return + } + } + + a = zerotier.Address(0) + return +} + func readIdentity(s string) *zerotier.Identity { if strings.ContainsRune(s, ':') { id, _ := zerotier.NewIdentityFromString(s) diff --git a/go/cmd/zerotier/cli/network.go b/go/cmd/zerotier/cli/network.go index 00246fc98..298496895 100644 --- a/go/cmd/zerotier/cli/network.go +++ b/go/cmd/zerotier/cli/network.go @@ -17,34 +17,16 @@ import ( "fmt" "os" "strconv" + "strings" "zerotier/pkg/zerotier" ) -func Network(basePath, authToken string, args []string, jsonOutput bool) { - if len(args) != 1 { - Help() - os.Exit(1) - } - - if len(args[0]) != zerotier.NetworkIDStringLength { - fmt.Printf("ERROR: invalid network ID: %s\n", args[0]) - os.Exit(1) - } - nwid, err := strconv.ParseUint(args[0], 16, 64) - if err != nil { - fmt.Printf("ERROR: invalid network ID: %s\n", args[0]) - os.Exit(1) - } - nwids := fmt.Sprintf("%.16x", nwid) - - var network zerotier.APINetwork - apiGet(basePath, authToken, "/network/"+nwids, &network) - +func showNetwork(nwids string, network *zerotier.APINetwork, jsonOutput bool) { if jsonOutput { fmt.Println(jsonDump(&network)) } else { - fmt.Printf("%s: %s\n", nwids, network.Config.Name) + fmt.Printf("%s\t%s\n", nwids, network.Config.Name) fmt.Printf("\tstatus:\t%s\n", networkStatusStr(network.Config.Status)) enabled := "no" if network.PortEnabled { @@ -78,27 +60,93 @@ func Network(basePath, authToken string, args []string, jsonOutput bool) { fmt.Printf("->%s", r.Via.String()) } } - managedIPs := "disabled" + managedIPs := "blocked" if network.Settings.AllowManagedIPs { - managedIPs = "enabled" + managedIPs = "allowed" } - managedIPsGlobal := "disabled" + managedIPsGlobal := "blocked" if network.Settings.AllowGlobalIPs { - managedIPsGlobal = "enabled" + managedIPsGlobal = "allowed" } fmt.Printf("\n\tmanaged address local permissions:\t%s global %s\n", managedIPs, managedIPsGlobal) - managedRoutes := "diabled" + managedRoutes := "blocked" if network.Settings.AllowManagedRoutes { - managedRoutes = "enabled" + managedRoutes = "allowed" } - managedGlobalRoutes := "disabled" + managedGlobalRoutes := "blocked" if network.Settings.AllowGlobalRoutes { - managedGlobalRoutes = "enabled" + managedGlobalRoutes = "allowed" } - managedDefaultRoute := "disabled" + managedDefaultRoute := "blocked" if network.Settings.AllowDefaultRouteOverride { - managedDefaultRoute = "enabled" + managedDefaultRoute = "allowed" } fmt.Printf("\tmanaged route local permissions:\t%s global %s default %s\n", managedRoutes, managedGlobalRoutes, managedDefaultRoute) } } + +func Network(basePath, authToken string, args []string, jsonOutput bool) { + if len(args) < 1 { + Help() + os.Exit(1) + } + + if len(args[0]) != zerotier.NetworkIDStringLength { + fmt.Printf("ERROR: invalid network ID: %s\n", args[0]) + os.Exit(1) + } + nwid, err := strconv.ParseUint(args[0], 16, 64) + if err != nil { + fmt.Printf("ERROR: invalid network ID: %s\n", args[0]) + os.Exit(1) + } + nwids := fmt.Sprintf("%.16x", nwid) + + var network zerotier.APINetwork + apiGet(basePath, authToken, "/network/"+nwids, &network) + + if len(args) == 1 { + showNetwork(nwids, &network, jsonOutput) + } else { + switch args[1] { + case "show", "info": + showNetwork(nwids, &network, jsonOutput) + case "set": + if len(args) > 3 { + Help() + } else if len(args) > 2 { + fieldName := strings.ToLower(strings.TrimSpace(args[2])) + var field *bool + switch fieldName { + case "managedips": + field = &network.Settings.AllowManagedIPs + case "managedroutes": + field = &network.Settings.AllowGlobalRoutes + case "globalips": + field = &network.Settings.AllowGlobalIPs + case "globalroutes": + field = &network.Settings.AllowGlobalRoutes + case "defaultroute": + field = &network.Settings.AllowDefaultRouteOverride + default: + Help() + os.Exit(1) + } + + if len(args) == 3 { + *field = isTrue(args[2]) + } + + fmt.Printf("%s\t%t\n", fieldName, allowedBlocked(*field)) + } else { + fmt.Printf("manageips\t%s\n", allowedBlocked(network.Settings.AllowManagedIPs)) + fmt.Printf("manageroutes\t%s\n", allowedBlocked(network.Settings.AllowManagedRoutes)) + fmt.Printf("globalips\t%s\n", allowedBlocked(network.Settings.AllowGlobalIPs)) + fmt.Printf("globalroutes\t%s\n", allowedBlocked(network.Settings.AllowGlobalRoutes)) + fmt.Printf("defaultroute\t%s\n", allowedBlocked(network.Settings.AllowDefaultRouteOverride)) + } + } + } + + os.Exit(0) +} diff --git a/go/cmd/zerotier/zerotier.go b/go/cmd/zerotier/zerotier.go index 13aa73b54..b57f94e26 100644 --- a/go/cmd/zerotier/zerotier.go +++ b/go/cmd/zerotier/zerotier.go @@ -124,9 +124,6 @@ func main() { case "status", "info": authTokenRequired(authToken) cli.Status(basePath, authToken, cmdArgs, *jflag) - case "peers", "listpeers", "lspeers": - authTokenRequired(authToken) - cli.Peers(basePath, authToken, cmdArgs, *jflag, false) case "join": authTokenRequired(authToken) cli.Join(basePath, authToken, cmdArgs) @@ -139,17 +136,25 @@ func main() { case "network": authTokenRequired(authToken) cli.Network(basePath, authToken, cmdArgs, *jflag) - case "set": + case "peers", "listpeers", "lspeers": authTokenRequired(authToken) - cli.Set(basePath, authToken, cmdArgs) - case "identity": - cli.Identity(cmdArgs) + cli.Peers(basePath, authToken, cmdArgs, *jflag, false) + case "peer": + authTokenRequired(authToken) + case "roots": + authTokenRequired(authToken) + cli.Peers(basePath, authToken, cmdArgs, *jflag, true) case "root": authTokenRequired(authToken) cli.Root(basePath, authToken, cmdArgs, *jflag) + case "set": + authTokenRequired(authToken) + cli.Set(basePath, authToken, cmdArgs) case "controller": authTokenRequired(authToken) cli.Controller(basePath, authToken, cmdArgs, *jflag) + case "identity": + cli.Identity(cmdArgs) } // Commands in the 'cli' sub-package do not return, so if we make