From ba2945f725f94342a403ffa24c76819a449ae679 Mon Sep 17 00:00:00 2001 From: Javier Marcos <1271349+javuto@users.noreply.github.com> Date: Sun, 1 Jun 2025 19:24:26 +0200 Subject: [PATCH 1/5] Adding support to osctrl-cli to look up nodes via osctrl-api --- cmd/api/handlers/nodes.go | 3 +- cmd/api/handlers/utils.go | 18 ---------- cmd/cli/api-node.go | 22 ++++++++++++ cmd/cli/main.go | 17 +++++++-- cmd/cli/node.go | 74 ++++++++++++++++++++++++++------------- osctrl-api.yaml | 2 +- pkg/types/types.go | 17 --------- 7 files changed, 90 insertions(+), 63 deletions(-) diff --git a/cmd/api/handlers/nodes.go b/cmd/api/handlers/nodes.go index 1854e29e..e0d17a53 100644 --- a/cmd/api/handlers/nodes.go +++ b/cmd/api/handlers/nodes.go @@ -247,7 +247,8 @@ func (h *HandlersApi) LookupNodeHandler(w http.ResponseWriter, r *http.Request) } else { apiErrorResponse(w, "error getting node", http.StatusInternalServerError, err) } + return } // Serialize and serve JSON - utils.HTTPResponse(w, utils.JSONApplicationUTF8, http.StatusOK, _nodeToApiLookupResponse(n)) + utils.HTTPResponse(w, utils.JSONApplicationUTF8, http.StatusOK, n) } diff --git a/cmd/api/handlers/utils.go b/cmd/api/handlers/utils.go index ff725889..83fffd4d 100644 --- a/cmd/api/handlers/utils.go +++ b/cmd/api/handlers/utils.go @@ -4,7 +4,6 @@ import ( "net/http" "github.com/jmpsec/osctrl/pkg/logging" - "github.com/jmpsec/osctrl/pkg/nodes" "github.com/jmpsec/osctrl/pkg/types" "github.com/jmpsec/osctrl/pkg/utils" "github.com/rs/zerolog/log" @@ -54,20 +53,3 @@ func checkValidPlatform(platforms []string, platform string) bool { } return false } - -// Helper to convert a node into a ApiLookupResponse -func _nodeToApiLookupResponse(node nodes.OsqueryNode) types.ApiLookupResponse { - return types.ApiLookupResponse{ - UUID: node.UUID, - Platform: node.Platform, - PlatformVersion: node.PlatformVersion, - OsqueryVersion: node.OsqueryVersion, - Hostname: node.Hostname, - Localname: node.Localname, - IPAddress: node.IPAddress, - Username: node.Username, - Environment: node.Environment, - HardwareSerial: node.HardwareSerial, - LastSeen: node.LastSeen.String(), - } -} diff --git a/cmd/cli/api-node.go b/cmd/cli/api-node.go index a830ff83..fa66092d 100644 --- a/cmd/cli/api-node.go +++ b/cmd/cli/api-node.go @@ -63,3 +63,25 @@ func (api *OsctrlAPI) DeleteNode(env, identifier string) error { func (api *OsctrlAPI) TagNode(env, identifier, tag string) error { return nil } + +// LookupNode to look up node from osctrl by identifier (UUID, localname or hostname) +func (api *OsctrlAPI) LookupNode(identifier string) (nodes.OsqueryNode, error) { + var node nodes.OsqueryNode + l := types.ApiLookupRequest{ + Identifier: identifier, + } + jsonMessage, err := json.Marshal(l) + if err != nil { + return node, fmt.Errorf("error marshaling data %w", err) + } + jsonParam := strings.NewReader(string(jsonMessage)) + reqURL := fmt.Sprintf("%s%s%s/lookup", api.Configuration.URL, APIPath, APINodes) + rawNode, err := api.PostGeneric(reqURL, jsonParam) + if err != nil { + return node, fmt.Errorf("error api request - %w - %s", err, string(rawNode)) + } + if err := json.Unmarshal(rawNode, &node); err != nil { + return node, fmt.Errorf("can not parse body - %w", err) + } + return node, nil +} diff --git a/cmd/cli/main.go b/cmd/cli/main.go index eaab5610..c994a5af 100644 --- a/cmd/cli/main.go +++ b/cmd/cli/main.go @@ -1205,6 +1205,19 @@ func init() { }, Action: cliWrapper(showNode), }, + { + Name: "lookup", + Aliases: []string{"f"}, + Usage: "Lookup existing nodes by identifier (UUID, hostname or localname)", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "identifier", + Aliases: []string{"id", "i"}, + Usage: "Node identifier to be looked up (UUID, hostname or localname)", + }, + }, + Action: cliWrapper(lookupNode), + }, }, }, { @@ -1688,12 +1701,12 @@ func checkDB(c *cli.Context) error { // Initialize backend db, err = backend.CreateDBManagerFile(dbConfigFile) if err != nil { - return fmt.Errorf("Failed to create backend - %w", err) + return fmt.Errorf("failed to create backend - %w", err) } } else { db, err = backend.CreateDBManager(dbConfig) if err != nil { - return fmt.Errorf("Failed to create backend - %w", err) + return fmt.Errorf("failed to create backend - %w", err) } } if err := db.Check(); err != nil { diff --git a/cmd/cli/node.go b/cmd/cli/node.go index aafb2359..74ed9215 100644 --- a/cmd/cli/node.go +++ b/cmd/cli/node.go @@ -190,30 +190,7 @@ func tagNode(c *cli.Context) error { return nil } -func showNode(c *cli.Context) error { - // Get values from flags - uuid := c.String("uuid") - if uuid == "" { - fmt.Println("❌ UUID is required") - os.Exit(1) - } - env := c.String("env") - if env == "" { - fmt.Println("❌ environment is required") - os.Exit(1) - } - var node nodes.OsqueryNode - if dbFlag { - node, err = nodesmgr.GetByUUID(uuid) - if err != nil { - return fmt.Errorf("error getting node - %w", err) - } - } else if apiFlag { - node, err = osctrlAPI.GetNode(env, uuid) - if err != nil { - return fmt.Errorf("error getting node - %w", err) - } - } +func _showNode(node nodes.OsqueryNode) error { header := []string{ "Hostname", "UUID", @@ -247,3 +224,52 @@ func showNode(c *cli.Context) error { } return nil } + +func showNode(c *cli.Context) error { + // Get values from flags + uuid := c.String("uuid") + if uuid == "" { + fmt.Println("❌ UUID is required") + os.Exit(1) + } + env := c.String("env") + if env == "" { + fmt.Println("❌ environment is required") + os.Exit(1) + } + var node nodes.OsqueryNode + if dbFlag { + node, err = nodesmgr.GetByUUID(uuid) + if err != nil { + return fmt.Errorf("error getting node - %w", err) + } + } else if apiFlag { + node, err = osctrlAPI.GetNode(env, uuid) + if err != nil { + return fmt.Errorf("error getting node - %w", err) + } + } + return _showNode(node) +} + +func lookupNode(c *cli.Context) error { + // Get values from flags + identifier := c.String("identifier") + if identifier == "" { + fmt.Println("❌ identifier is required") + os.Exit(1) + } + var node nodes.OsqueryNode + if dbFlag { + node, err = nodesmgr.GetByIdentifier(identifier) + if err != nil { + return fmt.Errorf("error getting node - %w", err) + } + } else if apiFlag { + node, err = osctrlAPI.LookupNode(identifier) + if err != nil { + return fmt.Errorf("error getting node - %w", err) + } + } + return _showNode(node) +} diff --git a/osctrl-api.yaml b/osctrl-api.yaml index a2e0dcee..107352b7 100644 --- a/osctrl-api.yaml +++ b/osctrl-api.yaml @@ -322,7 +322,7 @@ paths: content: application/json: schema: - $ref: "#/components/schemas/ApiLookupResponse" + $ref: "#/components/schemas/OsqueryNode" 400: description: bad request content: diff --git a/pkg/types/types.go b/pkg/types/types.go index 1d681aad..c4537293 100644 --- a/pkg/types/types.go +++ b/pkg/types/types.go @@ -114,20 +114,3 @@ type ApiTagsRequest struct { type ApiLookupRequest struct { Identifier string `json:"identifier"` } - -// ApiLookupResponse to be returned to API lookup requests -type ApiLookupResponse struct { - ID uint `json:"id"` - UUID string `json:"uuid"` - Hostname string `json:"hostname"` - Localname string `json:"localname"` - IPAddress string `json:"ip_address"` - Username string `json:"username"` - HardwareSerial string `json:"hardware_serial"` - Platform string `json:"platform"` - PlatformVersion string `json:"platform_version"` - OsqueryVersion string `json:"osquery_version"` - Environment string `json:"environment"` - EnvironmentUUID string `json:"environment_uuid"` - LastSeen string `json:"last_seen"` -} From 9a76195aaf6751dbc0bec80142ddf57f89189ddc Mon Sep 17 00:00:00 2001 From: Javier Marcos <1271349+javuto@users.noreply.github.com> Date: Sun, 1 Jun 2025 19:34:58 +0200 Subject: [PATCH 2/5] Update cmd/cli/api-node.go Use `bytes.NewReader(jsonMessage)` instead of converting to string to avoid unnecessary memory allocation. Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- cmd/cli/api-node.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/cli/api-node.go b/cmd/cli/api-node.go index fa66092d..a705ac15 100644 --- a/cmd/cli/api-node.go +++ b/cmd/cli/api-node.go @@ -74,7 +74,7 @@ func (api *OsctrlAPI) LookupNode(identifier string) (nodes.OsqueryNode, error) { if err != nil { return node, fmt.Errorf("error marshaling data %w", err) } - jsonParam := strings.NewReader(string(jsonMessage)) + jsonParam := bytes.NewReader(jsonMessage) reqURL := fmt.Sprintf("%s%s%s/lookup", api.Configuration.URL, APIPath, APINodes) rawNode, err := api.PostGeneric(reqURL, jsonParam) if err != nil { From 86b1668d7b5484dfa3d2673027436e8903d62690 Mon Sep 17 00:00:00 2001 From: Javier Marcos <1271349+javuto@users.noreply.github.com> Date: Sun, 1 Jun 2025 19:56:25 +0200 Subject: [PATCH 3/5] Update cmd/cli/api-node.go Constructing the URL using `path.Join` to avoid manual concatenation errors. Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- cmd/cli/api-node.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/cli/api-node.go b/cmd/cli/api-node.go index a705ac15..8ce245b2 100644 --- a/cmd/cli/api-node.go +++ b/cmd/cli/api-node.go @@ -75,7 +75,7 @@ func (api *OsctrlAPI) LookupNode(identifier string) (nodes.OsqueryNode, error) { return node, fmt.Errorf("error marshaling data %w", err) } jsonParam := bytes.NewReader(jsonMessage) - reqURL := fmt.Sprintf("%s%s%s/lookup", api.Configuration.URL, APIPath, APINodes) + reqURL := path.Join(api.Configuration.URL, APIPath, APINodes, "lookup") rawNode, err := api.PostGeneric(reqURL, jsonParam) if err != nil { return node, fmt.Errorf("error api request - %w - %s", err, string(rawNode)) From a3eff02def4ff076a7f9676a0f009096f6857639 Mon Sep 17 00:00:00 2001 From: Javier Marcos <1271349+javuto@users.noreply.github.com> Date: Sun, 1 Jun 2025 19:58:59 +0200 Subject: [PATCH 4/5] import bytes --- cmd/cli/api-node.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmd/cli/api-node.go b/cmd/cli/api-node.go index 8ce245b2..f0f0d9d8 100644 --- a/cmd/cli/api-node.go +++ b/cmd/cli/api-node.go @@ -1,8 +1,10 @@ package main import ( + "bytes" "encoding/json" "fmt" + "path" "strings" "github.com/jmpsec/osctrl/pkg/nodes" From 0b5af7af9b00a39dcf9fd29c34cf5324f55bafec Mon Sep 17 00:00:00 2001 From: Javier Marcos <1271349+javuto@users.noreply.github.com> Date: Sun, 1 Jun 2025 20:47:27 +0200 Subject: [PATCH 5/5] Using path.Join --- cmd/cli/api-carve.go | 23 ++++++++++++----------- cmd/cli/api-environment.go | 9 +++++---- cmd/cli/api-login.go | 7 ++++--- cmd/cli/api-node.go | 9 ++++----- cmd/cli/api-query.go | 17 +++++++++-------- cmd/cli/api-tag.go | 21 +++++++++++---------- cmd/cli/api-user.go | 5 +++-- 7 files changed, 48 insertions(+), 43 deletions(-) diff --git a/cmd/cli/api-carve.go b/cmd/cli/api-carve.go index 448415cb..59882369 100644 --- a/cmd/cli/api-carve.go +++ b/cmd/cli/api-carve.go @@ -1,9 +1,10 @@ package main import ( + "bytes" "encoding/json" "fmt" - "strings" + "path" "github.com/jmpsec/osctrl/pkg/carves" "github.com/jmpsec/osctrl/pkg/queries" @@ -15,7 +16,7 @@ import ( // GetCarveQueries to retrieve carves from osctrl func (api *OsctrlAPI) GetCarveQueries(target, env string) ([]queries.DistributedQuery, error) { var qs []queries.DistributedQuery - reqURL := fmt.Sprintf("%s%s%s/%s/queries/%s", api.Configuration.URL, APIPath, APICarves, env, target) + reqURL := path.Join(api.Configuration.URL, APIPath, APICarves, env, "queries", target) rawCs, err := api.GetGeneric(reqURL, nil) if err != nil { return qs, fmt.Errorf("error api request - %w - %s", err, string(rawCs)) @@ -29,7 +30,7 @@ func (api *OsctrlAPI) GetCarveQueries(target, env string) ([]queries.Distributed // GetCarves to retrieve carves from osctrl func (api *OsctrlAPI) GetCarves(env string) ([]carves.CarvedFile, error) { var cs []carves.CarvedFile - reqURL := fmt.Sprintf("%s%s%s/%s/list", api.Configuration.URL, APIPath, APICarves, env) + reqURL := path.Join(api.Configuration.URL, APIPath, APICarves, env, "list") rawCs, err := api.GetGeneric(reqURL, nil) if err != nil { return cs, fmt.Errorf("error api request - %w - %s", err, string(rawCs)) @@ -43,7 +44,7 @@ func (api *OsctrlAPI) GetCarves(env string) ([]carves.CarvedFile, error) { // GetCarve to retrieve one carve from osctrl func (api *OsctrlAPI) GetCarve(env, name string) (carves.CarvedFile, error) { var c carves.CarvedFile - reqURL := fmt.Sprintf("%s%s%s/%s/%s", api.Configuration.URL, APIPath, APICarves, env, name) + reqURL := path.Join(api.Configuration.URL, APIPath, APICarves, env, name) rawC, err := api.GetGeneric(reqURL, nil) if err != nil { return c, fmt.Errorf("error api request - %w - %s", err, string(rawC)) @@ -57,7 +58,7 @@ func (api *OsctrlAPI) GetCarve(env, name string) (carves.CarvedFile, error) { // DeleteCarve to delete carve from osctrl func (api *OsctrlAPI) DeleteCarve(env, name string) (types.ApiGenericResponse, error) { var r types.ApiGenericResponse - reqURL := fmt.Sprintf("%s%s%s/%s/%s/%s", api.Configuration.URL, APIPath, APICarves, env, settings.CarveDelete, name) + reqURL := path.Join(api.Configuration.URL, APIPath, APICarves, env, settings.CarveDelete, name) rawQ, err := api.PostGeneric(reqURL, nil) if err != nil { return r, fmt.Errorf("error api request - %w - %s", err, string(rawQ)) @@ -71,7 +72,7 @@ func (api *OsctrlAPI) DeleteCarve(env, name string) (types.ApiGenericResponse, e // ExpireCarve to expire carve from osctrl func (api *OsctrlAPI) ExpireCarve(env, name string) (types.ApiGenericResponse, error) { var r types.ApiGenericResponse - reqURL := fmt.Sprintf("%s%s%s/%s/%s/%s", api.Configuration.URL, APIPath, APICarves, env, settings.QueryExpire, name) + reqURL := path.Join(api.Configuration.URL, APIPath, APICarves, env, settings.QueryExpire, name) rawQ, err := api.PostGeneric(reqURL, nil) if err != nil { return r, fmt.Errorf("error api request - %w - %s", err, string(rawQ)) @@ -85,7 +86,7 @@ func (api *OsctrlAPI) ExpireCarve(env, name string) (types.ApiGenericResponse, e // CompleteCarve to complete a carve from osctrl func (api *OsctrlAPI) CompleteCarve(env, name string) (types.ApiGenericResponse, error) { var r types.ApiGenericResponse - reqURL := fmt.Sprintf("%s%s%s/%s/%s/%s", api.Configuration.URL, APIPath, APICarves, env, settings.CarveComplete, name) + reqURL := path.Join(api.Configuration.URL, APIPath, APICarves, env, settings.CarveComplete, name) rawQ, err := api.PostGeneric(reqURL, nil) if err != nil { return r, fmt.Errorf("error api request - %w - %s", err, string(rawQ)) @@ -97,19 +98,19 @@ func (api *OsctrlAPI) CompleteCarve(env, name string) (types.ApiGenericResponse, } // RunCarve to initiate a carve in osctrl -func (api *OsctrlAPI) RunCarve(env, uuid, path string, exp int) (types.ApiQueriesResponse, error) { +func (api *OsctrlAPI) RunCarve(env, uuid, fPath string, exp int) (types.ApiQueriesResponse, error) { c := types.ApiDistributedCarveRequest{ UUID: uuid, - Path: path, + Path: fPath, ExpHours: exp, } var r types.ApiQueriesResponse - reqURL := fmt.Sprintf("%s%s%s/%s", api.Configuration.URL, APIPath, APICarves, env) + reqURL := path.Join(api.Configuration.URL, APIPath, APICarves, env) jsonMessage, err := json.Marshal(c) if err != nil { log.Err(err).Msg("error marshaling data") } - jsonParam := strings.NewReader(string(jsonMessage)) + jsonParam := bytes.NewReader(jsonMessage) rawC, err := api.PostGeneric(reqURL, jsonParam) if err != nil { return r, fmt.Errorf("error api request - %w - %s", err, string(rawC)) diff --git a/cmd/cli/api-environment.go b/cmd/cli/api-environment.go index 111dab9c..9e47143d 100644 --- a/cmd/cli/api-environment.go +++ b/cmd/cli/api-environment.go @@ -4,6 +4,7 @@ import ( "encoding/json" "fmt" "io" + "path" "github.com/jmpsec/osctrl/pkg/environments" "github.com/jmpsec/osctrl/pkg/settings" @@ -13,7 +14,7 @@ import ( // GetEnvironments to retrieve all environments from osctrl func (api *OsctrlAPI) GetEnvironments() ([]environments.TLSEnvironment, error) { var envs []environments.TLSEnvironment - reqURL := fmt.Sprintf("%s%s%s", api.Configuration.URL, APIPath, APIEnvironments) + reqURL := path.Join("%s%s%s", api.Configuration.URL, APIPath, APIEnvironments) rawEnvs, err := api.GetGeneric(reqURL, nil) if err != nil { return envs, fmt.Errorf("error api request - %w - %s", err, string(rawEnvs)) @@ -27,7 +28,7 @@ func (api *OsctrlAPI) GetEnvironments() ([]environments.TLSEnvironment, error) { // GetEnvironment to retrieve users from osctrl func (api *OsctrlAPI) GetEnvironment(identifier string) (environments.TLSEnvironment, error) { var e environments.TLSEnvironment - reqURL := fmt.Sprintf("%s%s%s/%s", api.Configuration.URL, APIPath, APIEnvironments, identifier) + reqURL := path.Join("%s%s%s/%s", api.Configuration.URL, APIPath, APIEnvironments, identifier) rawE, err := api.GetGeneric(reqURL, nil) if err != nil { return e, fmt.Errorf("error api request - %w - %s", err, string(rawE)) @@ -41,7 +42,7 @@ func (api *OsctrlAPI) GetEnvironment(identifier string) (environments.TLSEnviron // GetEnvMap to retrieve a map of environments by ID func (api *OsctrlAPI) GetEnvMap() (environments.MapEnvByID, error) { var envMap environments.MapEnvByID - reqURL := fmt.Sprintf("%s%s%s/map/id", api.Configuration.URL, APIPath, APIEnvironments) + reqURL := path.Join(api.Configuration.URL, APIPath, APIEnvironments, "map", "id") rawE, err := api.GetGeneric(reqURL, nil) if err != nil { return envMap, fmt.Errorf("error api request - %w - %s", err, string(rawE)) @@ -95,7 +96,7 @@ func (api *OsctrlAPI) NotexpireRemove(identifier string) (string, error) { // ExtendEnrollment to extend in time the enrollment URL of an environment func (api *OsctrlAPI) ActionEnrollmentRemove(identifier, action, target string, data io.Reader) (string, error) { var res types.ApiGenericResponse - reqURL := fmt.Sprintf("%s%s%s/%s/%s/%s", api.Configuration.URL, APIPath, APIEnvironments, identifier, target, action) + reqURL := path.Join(api.Configuration.URL, APIPath, APIEnvironments, identifier, target, action) rawE, err := api.PostGeneric(reqURL, data) if err != nil { return "", fmt.Errorf("error api request - %w - %s", err, string(rawE)) diff --git a/cmd/cli/api-login.go b/cmd/cli/api-login.go index 5899a789..6d3859af 100644 --- a/cmd/cli/api-login.go +++ b/cmd/cli/api-login.go @@ -1,9 +1,10 @@ package main import ( + "bytes" "encoding/json" "fmt" - "strings" + "path" "github.com/jmpsec/osctrl/pkg/types" ) @@ -20,8 +21,8 @@ func (api *OsctrlAPI) PostLogin(env, username, password string, expHours int) (t if err != nil { return res, fmt.Errorf("error marshaling data %w", err) } - jsonParam := strings.NewReader(string(jsonMessage)) - reqURL := fmt.Sprintf("%s%s%s/%s", api.Configuration.URL, APIPath, APILogin, env) + jsonParam := bytes.NewReader(jsonMessage) + reqURL := path.Join(api.Configuration.URL, APIPath, APILogin, env) rawRes, err := api.PostGeneric(reqURL, jsonParam) if err != nil { return res, fmt.Errorf("error api request - %w - %s", err, string(rawRes)) diff --git a/cmd/cli/api-node.go b/cmd/cli/api-node.go index f0f0d9d8..29f183b8 100644 --- a/cmd/cli/api-node.go +++ b/cmd/cli/api-node.go @@ -5,7 +5,6 @@ import ( "encoding/json" "fmt" "path" - "strings" "github.com/jmpsec/osctrl/pkg/nodes" "github.com/jmpsec/osctrl/pkg/types" @@ -14,7 +13,7 @@ import ( // GetNodes to retrieve nodes from osctrl func (api *OsctrlAPI) GetNodes(env, target string) ([]nodes.OsqueryNode, error) { var nds []nodes.OsqueryNode - reqURL := fmt.Sprintf("%s%s%s/%s/%s", api.Configuration.URL, APIPath, APINodes, env, target) + reqURL := path.Join(api.Configuration.URL, APIPath, APINodes, env, target) rawNodes, err := api.GetGeneric(reqURL, nil) if err != nil { return nds, fmt.Errorf("error api request - %w - %s", err, string(rawNodes)) @@ -28,7 +27,7 @@ func (api *OsctrlAPI) GetNodes(env, target string) ([]nodes.OsqueryNode, error) // GetNode to retrieve one node from osctrl func (api *OsctrlAPI) GetNode(env, identifier string) (nodes.OsqueryNode, error) { var node nodes.OsqueryNode - reqURL := fmt.Sprintf("%s%s%s/%s/node/%s", api.Configuration.URL, APIPath, APINodes, env, identifier) + reqURL := path.Join(api.Configuration.URL, APIPath, APINodes, env, "node", identifier) rawNode, err := api.GetGeneric(reqURL, nil) if err != nil { return node, fmt.Errorf("error api request - %w - %s", err, string(rawNode)) @@ -45,12 +44,12 @@ func (api *OsctrlAPI) DeleteNode(env, identifier string) error { UUID: identifier, } var r types.ApiGenericResponse - reqURL := fmt.Sprintf("%s%s%s/%s/delete", api.Configuration.URL, APIPath, APINodes, env) + reqURL := path.Join(api.Configuration.URL, APIPath, APINodes, env, "delete") jsonMessage, err := json.Marshal(n) if err != nil { return fmt.Errorf("error marshaling data - %w", err) } - jsonParam := strings.NewReader(string(jsonMessage)) + jsonParam := bytes.NewReader(jsonMessage) rawN, err := api.PostGeneric(reqURL, jsonParam) if err != nil { return fmt.Errorf("error api request - %w - %s", err, string(rawN)) diff --git a/cmd/cli/api-query.go b/cmd/cli/api-query.go index bf65f161..c873ff8e 100644 --- a/cmd/cli/api-query.go +++ b/cmd/cli/api-query.go @@ -1,9 +1,10 @@ package main import ( + "bytes" "encoding/json" "fmt" - "strings" + "path" "github.com/jmpsec/osctrl/pkg/queries" "github.com/jmpsec/osctrl/pkg/settings" @@ -13,7 +14,7 @@ import ( // GetQueries to retrieve queries from osctrl func (api *OsctrlAPI) GetQueries(target, env string) ([]queries.DistributedQuery, error) { var qs []queries.DistributedQuery - reqURL := fmt.Sprintf("%s%s%s/%s/list/%s", api.Configuration.URL, APIPath, APIQueries, env, target) + reqURL := path.Join(api.Configuration.URL, APIPath, APIQueries, env, "list", target) rawQs, err := api.GetGeneric(reqURL, nil) if err != nil { return qs, fmt.Errorf("error api request - %w - %s", err, string(rawQs)) @@ -27,7 +28,7 @@ func (api *OsctrlAPI) GetQueries(target, env string) ([]queries.DistributedQuery // GetQuery to retrieve one query from osctrl func (api *OsctrlAPI) GetQuery(env, name string) (queries.DistributedQuery, error) { var q queries.DistributedQuery - reqURL := fmt.Sprintf("%s%s%s/%s/%s", api.Configuration.URL, APIPath, APIQueries, env, name) + reqURL := path.Join(api.Configuration.URL, APIPath, APIQueries, env, name) rawQ, err := api.GetGeneric(reqURL, nil) if err != nil { return q, fmt.Errorf("error api request - %w - %s", err, string(rawQ)) @@ -41,7 +42,7 @@ func (api *OsctrlAPI) GetQuery(env, name string) (queries.DistributedQuery, erro // DeleteQuery to delete query from osctrl func (api *OsctrlAPI) DeleteQuery(env, name string) (types.ApiGenericResponse, error) { var r types.ApiGenericResponse - reqURL := fmt.Sprintf("%s%s%s/%s/%s/%s", api.Configuration.URL, APIPath, APIQueries, env, settings.QueryDelete, name) + reqURL := path.Join(api.Configuration.URL, APIPath, APIQueries, env, settings.QueryDelete, name) rawQ, err := api.PostGeneric(reqURL, nil) if err != nil { return r, fmt.Errorf("error api request - %w - %s", err, string(rawQ)) @@ -55,7 +56,7 @@ func (api *OsctrlAPI) DeleteQuery(env, name string) (types.ApiGenericResponse, e // ExpireQuery to expire query from osctrl func (api *OsctrlAPI) ExpireQuery(env, name string) (types.ApiGenericResponse, error) { var r types.ApiGenericResponse - reqURL := fmt.Sprintf("%s%s%s/%s/%s/%s", api.Configuration.URL, APIPath, APIQueries, env, settings.QueryExpire, name) + reqURL := path.Join(api.Configuration.URL, APIPath, APIQueries, env, settings.QueryExpire, name) rawQ, err := api.PostGeneric(reqURL, nil) if err != nil { return r, fmt.Errorf("error api request - %w - %s", err, string(rawQ)) @@ -69,7 +70,7 @@ func (api *OsctrlAPI) ExpireQuery(env, name string) (types.ApiGenericResponse, e // CompleteQuery to complete a query from osctrl func (api *OsctrlAPI) CompleteQuery(env, name string) (types.ApiGenericResponse, error) { var r types.ApiGenericResponse - reqURL := fmt.Sprintf("%s%s%s/%s/%s/%s", api.Configuration.URL, APIPath, APIQueries, env, settings.QueryComplete, name) + reqURL := path.Join(api.Configuration.URL, APIPath, APIQueries, env, settings.QueryComplete, name) rawQ, err := api.PostGeneric(reqURL, nil) if err != nil { return r, fmt.Errorf("error api request - %w - %s", err, string(rawQ)) @@ -89,13 +90,13 @@ func (api *OsctrlAPI) RunQuery(env, uuid, query string, hidden bool, exp int) (t ExpHours: exp, } var r types.ApiQueriesResponse - reqURL := fmt.Sprintf("%s%s%s/%s", api.Configuration.URL, APIPath, APIQueries, env) + reqURL := path.Join(api.Configuration.URL, APIPath, APIQueries, env) jsonMessage, err := json.Marshal(q) if err != nil { return r, fmt.Errorf("error marshaling data - %w", err) } - jsonParam := strings.NewReader(string(jsonMessage)) + jsonParam := bytes.NewReader(jsonMessage) rawQ, err := api.PostGeneric(reqURL, jsonParam) if err != nil { return r, fmt.Errorf("error api request - %w - %s", err, string(rawQ)) diff --git a/cmd/cli/api-tag.go b/cmd/cli/api-tag.go index f8e74912..4c4f31a1 100644 --- a/cmd/cli/api-tag.go +++ b/cmd/cli/api-tag.go @@ -1,9 +1,10 @@ package main import ( + "bytes" "encoding/json" "fmt" - "strings" + "path" "github.com/jmpsec/osctrl/pkg/tags" "github.com/jmpsec/osctrl/pkg/types" @@ -12,7 +13,7 @@ import ( // GetAllTags to retrieve all tags from osctrl func (api *OsctrlAPI) GetAllTags() ([]tags.AdminTag, error) { var tgs []tags.AdminTag - reqURL := fmt.Sprintf("%s%s%s", api.Configuration.URL, APIPath, APITags) + reqURL := path.Join(api.Configuration.URL, APIPath, APITags) rawTgs, err := api.GetGeneric(reqURL, nil) if err != nil { return tgs, fmt.Errorf("error api request - %w - %s", err, string(rawTgs)) @@ -26,7 +27,7 @@ func (api *OsctrlAPI) GetAllTags() ([]tags.AdminTag, error) { // GetTags to retrieve tags from osctrl by environment func (api *OsctrlAPI) GetTags(env string) ([]tags.AdminTag, error) { var tgs []tags.AdminTag - reqURL := fmt.Sprintf("%s%s%s/%s", api.Configuration.URL, APIPath, APITags, env) + reqURL := path.Join(api.Configuration.URL, APIPath, APITags, env) rawTgs, err := api.GetGeneric(reqURL, nil) if err != nil { return tgs, fmt.Errorf("error api request - %w - %s", err, string(rawTgs)) @@ -40,7 +41,7 @@ func (api *OsctrlAPI) GetTags(env string) ([]tags.AdminTag, error) { // GetTag to retrieve a tag from osctrl by environment and name func (api *OsctrlAPI) GetTag(env, name string) (tags.AdminTag, error) { var t tags.AdminTag - reqURL := fmt.Sprintf("%s%s%s/%s/%s", api.Configuration.URL, APIPath, APITags, env, name) + reqURL := path.Join(api.Configuration.URL, APIPath, APITags, env, name) rawT, err := api.GetGeneric(reqURL, nil) if err != nil { return t, fmt.Errorf("error api request - %w - %s", err, string(rawT)) @@ -62,12 +63,12 @@ func (api *OsctrlAPI) AddTag(envUUID, name, color, icon, description string, tag EnvUUID: envUUID, TagType: tagType, } - reqURL := fmt.Sprintf("%s%s%s/%s/%s", api.Configuration.URL, APIPath, APITags, envUUID, tags.ActionAdd) + reqURL := path.Join(api.Configuration.URL, APIPath, APITags, envUUID, tags.ActionAdd) jsonMessage, err := json.Marshal(t) if err != nil { return r, fmt.Errorf("error marshaling data - %w", err) } - jsonParam := strings.NewReader(string(jsonMessage)) + jsonParam := bytes.NewReader(jsonMessage) rawT, err := api.PostGeneric(reqURL, jsonParam) if err != nil { return r, fmt.Errorf("error api request - %w", err) @@ -85,12 +86,12 @@ func (api *OsctrlAPI) DeleteTag(envUUID, name string) (types.ApiGenericResponse, Name: name, EnvUUID: envUUID, } - reqURL := fmt.Sprintf("%s%s%s/%s/%s", api.Configuration.URL, APIPath, APITags, envUUID, tags.ActionRemove) + reqURL := path.Join(api.Configuration.URL, APIPath, APITags, envUUID, tags.ActionRemove) jsonMessage, err := json.Marshal(t) if err != nil { return r, fmt.Errorf("error marshaling data - %w", err) } - jsonParam := strings.NewReader(string(jsonMessage)) + jsonParam := bytes.NewReader(jsonMessage) rawT, err := api.PostGeneric(reqURL, jsonParam) if err != nil { return r, fmt.Errorf("error api request - %w", err) @@ -112,12 +113,12 @@ func (api *OsctrlAPI) EditTag(envUUID, name, color, icon, description string, ta EnvUUID: envUUID, TagType: tagType, } - reqURL := fmt.Sprintf("%s%s%s/%s/%s", api.Configuration.URL, APIPath, APITags, envUUID, tags.ActionEdit) + reqURL := path.Join(api.Configuration.URL, APIPath, APITags, envUUID, tags.ActionEdit) jsonMessage, err := json.Marshal(t) if err != nil { return r, fmt.Errorf("error marshaling data - %w", err) } - jsonParam := strings.NewReader(string(jsonMessage)) + jsonParam := bytes.NewReader(jsonMessage) rawT, err := api.PostGeneric(reqURL, jsonParam) if err != nil { return r, fmt.Errorf("error api request - %w", err) diff --git a/cmd/cli/api-user.go b/cmd/cli/api-user.go index ebc41398..bae62037 100644 --- a/cmd/cli/api-user.go +++ b/cmd/cli/api-user.go @@ -3,6 +3,7 @@ package main import ( "encoding/json" "fmt" + "path" "github.com/jmpsec/osctrl/pkg/users" ) @@ -10,7 +11,7 @@ import ( // GetUsers to retrieve users from osctrl func (api *OsctrlAPI) GetUsers() ([]users.AdminUser, error) { var us []users.AdminUser - reqURL := fmt.Sprintf("%s%s%s", api.Configuration.URL, APIPath, APIUSers) + reqURL := path.Join(api.Configuration.URL, APIPath, APIUSers) rawUs, err := api.GetGeneric(reqURL, nil) if err != nil { return us, fmt.Errorf("error api request - %w - %s", err, string(rawUs)) @@ -24,7 +25,7 @@ func (api *OsctrlAPI) GetUsers() ([]users.AdminUser, error) { // GetUser to retrieve one user from osctrl func (api *OsctrlAPI) GetUser(username string) (users.AdminUser, error) { var u users.AdminUser - reqURL := fmt.Sprintf("%s%s%s/%s", api.Configuration.URL, APIPath, APIUSers, username) + reqURL := path.Join("%s%s%s/%s", api.Configuration.URL, APIPath, APIUSers, username) rawU, err := api.GetGeneric(reqURL, nil) if err != nil { return u, fmt.Errorf("error api request - %w - %s", err, string(rawU))