Skip to content

Commit ba2945f

Browse files
committed
Adding support to osctrl-cli to look up nodes via osctrl-api
1 parent 42c0be1 commit ba2945f

7 files changed

Lines changed: 90 additions & 63 deletions

File tree

cmd/api/handlers/nodes.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,8 @@ func (h *HandlersApi) LookupNodeHandler(w http.ResponseWriter, r *http.Request)
247247
} else {
248248
apiErrorResponse(w, "error getting node", http.StatusInternalServerError, err)
249249
}
250+
return
250251
}
251252
// Serialize and serve JSON
252-
utils.HTTPResponse(w, utils.JSONApplicationUTF8, http.StatusOK, _nodeToApiLookupResponse(n))
253+
utils.HTTPResponse(w, utils.JSONApplicationUTF8, http.StatusOK, n)
253254
}

cmd/api/handlers/utils.go

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"net/http"
55

66
"github.com/jmpsec/osctrl/pkg/logging"
7-
"github.com/jmpsec/osctrl/pkg/nodes"
87
"github.com/jmpsec/osctrl/pkg/types"
98
"github.com/jmpsec/osctrl/pkg/utils"
109
"github.com/rs/zerolog/log"
@@ -54,20 +53,3 @@ func checkValidPlatform(platforms []string, platform string) bool {
5453
}
5554
return false
5655
}
57-
58-
// Helper to convert a node into a ApiLookupResponse
59-
func _nodeToApiLookupResponse(node nodes.OsqueryNode) types.ApiLookupResponse {
60-
return types.ApiLookupResponse{
61-
UUID: node.UUID,
62-
Platform: node.Platform,
63-
PlatformVersion: node.PlatformVersion,
64-
OsqueryVersion: node.OsqueryVersion,
65-
Hostname: node.Hostname,
66-
Localname: node.Localname,
67-
IPAddress: node.IPAddress,
68-
Username: node.Username,
69-
Environment: node.Environment,
70-
HardwareSerial: node.HardwareSerial,
71-
LastSeen: node.LastSeen.String(),
72-
}
73-
}

cmd/cli/api-node.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,25 @@ func (api *OsctrlAPI) DeleteNode(env, identifier string) error {
6363
func (api *OsctrlAPI) TagNode(env, identifier, tag string) error {
6464
return nil
6565
}
66+
67+
// LookupNode to look up node from osctrl by identifier (UUID, localname or hostname)
68+
func (api *OsctrlAPI) LookupNode(identifier string) (nodes.OsqueryNode, error) {
69+
var node nodes.OsqueryNode
70+
l := types.ApiLookupRequest{
71+
Identifier: identifier,
72+
}
73+
jsonMessage, err := json.Marshal(l)
74+
if err != nil {
75+
return node, fmt.Errorf("error marshaling data %w", err)
76+
}
77+
jsonParam := strings.NewReader(string(jsonMessage))
78+
reqURL := fmt.Sprintf("%s%s%s/lookup", api.Configuration.URL, APIPath, APINodes)
79+
rawNode, err := api.PostGeneric(reqURL, jsonParam)
80+
if err != nil {
81+
return node, fmt.Errorf("error api request - %w - %s", err, string(rawNode))
82+
}
83+
if err := json.Unmarshal(rawNode, &node); err != nil {
84+
return node, fmt.Errorf("can not parse body - %w", err)
85+
}
86+
return node, nil
87+
}

cmd/cli/main.go

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1205,6 +1205,19 @@ func init() {
12051205
},
12061206
Action: cliWrapper(showNode),
12071207
},
1208+
{
1209+
Name: "lookup",
1210+
Aliases: []string{"f"},
1211+
Usage: "Lookup existing nodes by identifier (UUID, hostname or localname)",
1212+
Flags: []cli.Flag{
1213+
&cli.StringFlag{
1214+
Name: "identifier",
1215+
Aliases: []string{"id", "i"},
1216+
Usage: "Node identifier to be looked up (UUID, hostname or localname)",
1217+
},
1218+
},
1219+
Action: cliWrapper(lookupNode),
1220+
},
12081221
},
12091222
},
12101223
{
@@ -1688,12 +1701,12 @@ func checkDB(c *cli.Context) error {
16881701
// Initialize backend
16891702
db, err = backend.CreateDBManagerFile(dbConfigFile)
16901703
if err != nil {
1691-
return fmt.Errorf("Failed to create backend - %w", err)
1704+
return fmt.Errorf("failed to create backend - %w", err)
16921705
}
16931706
} else {
16941707
db, err = backend.CreateDBManager(dbConfig)
16951708
if err != nil {
1696-
return fmt.Errorf("Failed to create backend - %w", err)
1709+
return fmt.Errorf("failed to create backend - %w", err)
16971710
}
16981711
}
16991712
if err := db.Check(); err != nil {

cmd/cli/node.go

Lines changed: 50 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -190,30 +190,7 @@ func tagNode(c *cli.Context) error {
190190
return nil
191191
}
192192

193-
func showNode(c *cli.Context) error {
194-
// Get values from flags
195-
uuid := c.String("uuid")
196-
if uuid == "" {
197-
fmt.Println("❌ UUID is required")
198-
os.Exit(1)
199-
}
200-
env := c.String("env")
201-
if env == "" {
202-
fmt.Println("❌ environment is required")
203-
os.Exit(1)
204-
}
205-
var node nodes.OsqueryNode
206-
if dbFlag {
207-
node, err = nodesmgr.GetByUUID(uuid)
208-
if err != nil {
209-
return fmt.Errorf("error getting node - %w", err)
210-
}
211-
} else if apiFlag {
212-
node, err = osctrlAPI.GetNode(env, uuid)
213-
if err != nil {
214-
return fmt.Errorf("error getting node - %w", err)
215-
}
216-
}
193+
func _showNode(node nodes.OsqueryNode) error {
217194
header := []string{
218195
"Hostname",
219196
"UUID",
@@ -247,3 +224,52 @@ func showNode(c *cli.Context) error {
247224
}
248225
return nil
249226
}
227+
228+
func showNode(c *cli.Context) error {
229+
// Get values from flags
230+
uuid := c.String("uuid")
231+
if uuid == "" {
232+
fmt.Println("❌ UUID is required")
233+
os.Exit(1)
234+
}
235+
env := c.String("env")
236+
if env == "" {
237+
fmt.Println("❌ environment is required")
238+
os.Exit(1)
239+
}
240+
var node nodes.OsqueryNode
241+
if dbFlag {
242+
node, err = nodesmgr.GetByUUID(uuid)
243+
if err != nil {
244+
return fmt.Errorf("error getting node - %w", err)
245+
}
246+
} else if apiFlag {
247+
node, err = osctrlAPI.GetNode(env, uuid)
248+
if err != nil {
249+
return fmt.Errorf("error getting node - %w", err)
250+
}
251+
}
252+
return _showNode(node)
253+
}
254+
255+
func lookupNode(c *cli.Context) error {
256+
// Get values from flags
257+
identifier := c.String("identifier")
258+
if identifier == "" {
259+
fmt.Println("❌ identifier is required")
260+
os.Exit(1)
261+
}
262+
var node nodes.OsqueryNode
263+
if dbFlag {
264+
node, err = nodesmgr.GetByIdentifier(identifier)
265+
if err != nil {
266+
return fmt.Errorf("error getting node - %w", err)
267+
}
268+
} else if apiFlag {
269+
node, err = osctrlAPI.LookupNode(identifier)
270+
if err != nil {
271+
return fmt.Errorf("error getting node - %w", err)
272+
}
273+
}
274+
return _showNode(node)
275+
}

osctrl-api.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ paths:
322322
content:
323323
application/json:
324324
schema:
325-
$ref: "#/components/schemas/ApiLookupResponse"
325+
$ref: "#/components/schemas/OsqueryNode"
326326
400:
327327
description: bad request
328328
content:

pkg/types/types.go

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -114,20 +114,3 @@ type ApiTagsRequest struct {
114114
type ApiLookupRequest struct {
115115
Identifier string `json:"identifier"`
116116
}
117-
118-
// ApiLookupResponse to be returned to API lookup requests
119-
type ApiLookupResponse struct {
120-
ID uint `json:"id"`
121-
UUID string `json:"uuid"`
122-
Hostname string `json:"hostname"`
123-
Localname string `json:"localname"`
124-
IPAddress string `json:"ip_address"`
125-
Username string `json:"username"`
126-
HardwareSerial string `json:"hardware_serial"`
127-
Platform string `json:"platform"`
128-
PlatformVersion string `json:"platform_version"`
129-
OsqueryVersion string `json:"osquery_version"`
130-
Environment string `json:"environment"`
131-
EnvironmentUUID string `json:"environment_uuid"`
132-
LastSeen string `json:"last_seen"`
133-
}

0 commit comments

Comments
 (0)