From d1b780c7be6d72d046b3d5bfe33dac3b10959f54 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 1 Oct 2019 13:09:53 -0700 Subject: [PATCH] addroot --- go/cmd/zerotier/cli/addroot.go | 43 +++++++++++++++++++++++++++++++++ go/cmd/zerotier/cli/help.go | 4 ++-- go/cmd/zerotier/cli/misc.go | 17 +++++++++++++ go/pkg/zerotier/api.go | 44 ++++++++++++++++++++++++++++------ 4 files changed, 99 insertions(+), 9 deletions(-) diff --git a/go/cmd/zerotier/cli/addroot.go b/go/cmd/zerotier/cli/addroot.go index 317c2693a..b0cafcd74 100644 --- a/go/cmd/zerotier/cli/addroot.go +++ b/go/cmd/zerotier/cli/addroot.go @@ -13,6 +13,49 @@ package cli +import ( + "fmt" + "io/ioutil" + "net/url" + "os" + "strings" + + "zerotier/pkg/zerotier" +) + // AddRoot CLI command func AddRoot(basePath, authToken string, args []string) { + if len(args) == 0 { + Help() + os.Exit(0) + } + + locData, err := ioutil.ReadFile(args[0]) + if err != nil { + fmt.Printf("ERROR: unable to read locator: %s\n", err.Error()) + os.Exit(1) + } + loc, err := zerotier.NewLocatorFromBytes(locData) + if err != nil { + fmt.Printf("ERROR: invalid locator in file '%s': %s\n", args[0], err.Error()) + os.Exit(1) + } + + var name string + if len(args) > 1 { + if len(args) > 2 { + Help() + os.Exit(1) + } + name = strings.TrimSpace(args[1]) + } + + var result zerotier.Root + apiPost(basePath, authToken, "/root/"+url.PathEscape(name), &zerotier.Root{ + Name: name, + Locator: loc, + }, &result) + + fmt.Println(jsonDump(&result)) + os.Exit(0) } diff --git a/go/cmd/zerotier/cli/help.go b/go/cmd/zerotier/cli/help.go index 57186f1b2..d5a8c9c9e 100644 --- a/go/cmd/zerotier/cli/help.go +++ b/go/cmd/zerotier/cli/help.go @@ -40,13 +40,13 @@ Commands: service Start in system service mode status Show ZeroTier service status and config peers Show VL1 peers - roots Show VL1 root servers + roots Show configured VL1 root servers addroot [name] Add a VL1 root removeroot Remove a VL1 root locator [args] Locator management commands new
[...] Create and sign a locator newdnskey Create a secure DNS name and secret - getdns Create secure DNS TXT records + getdns Create secure DNS TXT records identity [args] Identity management commands new [c25519|p384] Create new identity (including secret) getpublic Extract only public part of identity diff --git a/go/cmd/zerotier/cli/misc.go b/go/cmd/zerotier/cli/misc.go index 8923f2adc..6473839f4 100644 --- a/go/cmd/zerotier/cli/misc.go +++ b/go/cmd/zerotier/cli/misc.go @@ -38,6 +38,23 @@ func apiGet(basePath, authToken, urlPath string, result interface{}) { } } +func apiPost(basePath, authToken, urlPath string, post, result interface{}) { + statusCode, err := zerotier.APIPost(basePath, zerotier.APISocketName, authToken, urlPath, post, result) + if err != nil { + fmt.Printf("FATAL: API response code %d: %s\n", statusCode, err.Error()) + os.Exit(1) + return + } + if statusCode != http.StatusOK { + if statusCode == http.StatusUnauthorized { + fmt.Printf("FATAL: API response code %d: unauthorized (authorization token incorrect)\n", statusCode) + } + fmt.Printf("FATAL: API response code %d\n", statusCode) + os.Exit(1) + return + } +} + func enabledDisabled(f bool) string { if f { return "ENABLED" diff --git a/go/pkg/zerotier/api.go b/go/pkg/zerotier/api.go index 4f5bd00fe..8747ac629 100644 --- a/go/pkg/zerotier/api.go +++ b/go/pkg/zerotier/api.go @@ -74,8 +74,11 @@ func APIPost(basePath, socketName, authToken, queryPath string, post, result int if err != nil { return http.StatusTeapot, err } - err = json.NewDecoder(resp.Body).Decode(result) - return resp.StatusCode, err + if result != nil { + err = json.NewDecoder(resp.Body).Decode(result) + return resp.StatusCode, err + } + return resp.StatusCode, nil } // APIStatus is the object returned by API status inquiries @@ -337,7 +340,21 @@ func createAPIServer(basePath string, node *Node) (*http.Server, error) { } } - if req.Method == http.MethodPost || req.Method == http.MethodPut { + if req.Method == http.MethodDelete { + if queriedID == 0 { + _ = apiSendObj(out, req, http.StatusBadRequest, nil) + } else { + networks := node.Networks() + for _, nw := range networks { + if nw.id == queriedID { + _ = node.Leave(queriedID) + _ = apiSendObj(out, req, http.StatusOK, nw) + return + } + } + _ = apiSendObj(out, req, http.StatusNotFound, nil) + } + } else if req.Method == http.MethodPost || req.Method == http.MethodPut { if queriedID == 0 { _ = apiSendObj(out, req, http.StatusBadRequest, nil) } else { @@ -377,7 +394,7 @@ func createAPIServer(basePath string, node *Node) (*http.Server, error) { _ = apiSendObj(out, req, http.StatusNotFound, nil) } } else { - out.Header().Set("Allow", "GET, HEAD, PUT, POST") + out.Header().Set("Allow", "GET, HEAD, PUT, POST, DELETE") _ = apiSendObj(out, req, http.StatusMethodNotAllowed, nil) } }) @@ -401,11 +418,24 @@ func createAPIServer(basePath string, node *Node) (*http.Server, error) { queriedName = req.URL.Path[6:] } - if req.Method == http.MethodPost || req.Method == http.MethodPut { + if req.Method == http.MethodDelete { + if len(queriedName) > 0 { + roots := node.Roots() + for _, r := range roots { + if r.Name == queriedName { + node.RemoveRoot(queriedName) + _ = apiSendObj(out, req, http.StatusOK, r) + return + } + } + } + _ = apiSendObj(out, req, http.StatusNotFound, nil) + } else if req.Method == http.MethodPost || req.Method == http.MethodPut { var r Root if apiReadObj(out, req, &r) == nil { - if r.Name != queriedName && (r.Locator == nil || r.Locator.Identity == nil || r.Locator.Identity.address.String() != queriedName) { + if r.Name != queriedName { _ = apiSendObj(out, req, http.StatusBadRequest, nil) + return } err := node.SetRoot(r.Name, r.Locator) if err != nil { @@ -431,7 +461,7 @@ func createAPIServer(basePath string, node *Node) (*http.Server, error) { } _ = apiSendObj(out, req, http.StatusNotFound, nil) } else { - out.Header().Set("Allow", "GET, HEAD, PUT, POST") + out.Header().Set("Allow", "GET, HEAD, PUT, POST, DELETE") _ = apiSendObj(out, req, http.StatusMethodNotAllowed, nil) } })