Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 1 addition & 11 deletions cmd/admin/handlers/json-carves.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,16 +115,6 @@ func (h *HandlersAdmin) JSONCarvesHandler(w http.ResponseWriter, r *http.Request
data := make(CarveData)
data["path"] = q.Path
data["name"] = q.Name
// Preparing query targets
ts, _ := h.Queries.GetTargets(q.Name)
_ts := []CarveTarget{}
for _, t := range ts {
_t := CarveTarget{
Type: t.Type,
Value: t.Value,
}
_ts = append(_ts, _t)
}
// Preparing JSON
_c := CarveJSON{
Name: q.Name,
Expand All @@ -136,7 +126,7 @@ func (h *HandlersAdmin) JSONCarvesHandler(w http.ResponseWriter, r *http.Request
},
Status: status,
Progress: progress,
Targets: _ts,
Targets: parseCarveTarget(q.Target),
}
cJSON = append(cJSON, _c)
}
Expand Down
63 changes: 0 additions & 63 deletions cmd/admin/handlers/json-nodes.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,66 +111,3 @@ func (h *HandlersAdmin) JSONEnvironmentHandler(w http.ResponseWriter, r *http.Re
// Serve JSON
utils.HTTPResponse(w, utils.JSONApplicationUTF8, http.StatusOK, returned)
}

// JSONPlatformHandler - Handler for JSON endpoints by platform
func (h *HandlersAdmin) JSONPlatformHandler(w http.ResponseWriter, r *http.Request) {
if h.DebugHTTPConfig.Enabled {
utils.DebugHTTPDump(h.DebugHTTP, r, h.DebugHTTPConfig.ShowBody)
}
// Get context data
ctx := r.Context().Value(sessions.ContextKey(sessions.CtxSession)).(sessions.ContextValue)
// Check permissions
if !h.Users.CheckPermissions(ctx[sessions.CtxUser], users.AdminLevel, users.NoEnvironment) {
log.Info().Msgf("%s has insufficient permissions", ctx[sessions.CtxUser])
return
}
// Extract platform
platform := r.PathValue("platform")
if platform == "" {
log.Info().Msg("error getting platform")
return
}
// Extract target
target := r.PathValue("target")
if target == "" {
log.Info().Msg("error getting target")
return
}
// Verify target
if !NodeTargets[target] {
log.Info().Msgf("invalid target %s", target)
return
}
nodes, err := h.Nodes.GetByPlatform(platform, target, h.Settings.InactiveHours(settings.NoEnvironmentID))
if err != nil {
log.Err(err).Msg("error getting nodes")
return
}
// Prepare data to be returned
var nJSON []NodeJSON
for _, n := range nodes {
nj := NodeJSON{
UUID: n.UUID,
Username: n.Username,
Localname: n.Localname,
IP: n.IPAddress,
Platform: n.Platform,
Version: n.PlatformVersion,
Osquery: n.OsqueryVersion,
LastSeen: CreationTimes{
Display: utils.PastFutureTimes(n.UpdatedAt),
Timestamp: utils.TimeTimestamp(n.UpdatedAt),
},
FirstSeen: CreationTimes{
Display: utils.PastFutureTimes(n.CreatedAt),
Timestamp: utils.TimeTimestamp(n.CreatedAt),
},
}
nJSON = append(nJSON, nj)
}
returned := ReturnedNodes{
Data: nJSON,
}
// Serve JSON
utils.HTTPResponse(w, utils.JSONApplicationUTF8, http.StatusOK, returned)
}
12 changes: 1 addition & 11 deletions cmd/admin/handlers/json-queries.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,16 +84,6 @@ func (h *HandlersAdmin) JSONQueryJSON(q queries.DistributedQuery, env string) Qu
if q.Expired {
status = queries.StatusExpired
}
// Preparing query targets
ts, _ := h.Queries.GetTargets(q.Name)
_ts := []QueryTarget{}
for _, t := range ts {
_t := QueryTarget{
Type: t.Type,
Value: t.Value,
}
_ts = append(_ts, _t)
}
return QueryJSON{
Creator: q.Creator,
Name: q.Name,
Expand All @@ -104,7 +94,7 @@ func (h *HandlersAdmin) JSONQueryJSON(q queries.DistributedQuery, env string) Qu
},
Status: status,
Progress: progress,
Targets: _ts,
Targets: parseQueryTarget(q.Target),
}
}

Expand Down
148 changes: 88 additions & 60 deletions cmd/admin/handlers/post.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,27 +125,22 @@ func (h *HandlersAdmin) QueryRunPOSTHandler(w http.ResponseWriter, r *http.Reque
if q.ExpHours == 0 {
expTime = time.Time{}
}
newQuery := newQueryReady(ctx[sessions.CtxUser], q.Query, expTime, env.ID)
if err := h.Queries.Create(newQuery); err != nil {
adminErrorResponse(w, "error creating query", http.StatusInternalServerError, err)
return
}
// Get the query id
newQuery, err = h.Queries.Get(newQuery.Name, env.ID)
if err != nil {
newQuery := newQueryReady(ctx[sessions.CtxUser], q.Query, expTime, env.ID, q)
if err := h.Queries.Create(&newQuery); err != nil {
adminErrorResponse(w, "error creating query", http.StatusInternalServerError, err)
return
}
// List all the nodes that match the query
var expected []uint
targetNodesID := []uint{}
// TODO: Refactor this to use osctrl-api instead of direct DB queries
// Create environment target
// Extract targets by environment
if len(q.Environments) > 0 {
expected = []uint{}
for _, e := range q.Environments {
// TODO: Check if user has permissions to query the environment
if (e != "") && h.Envs.Exists(e) {
nodes, err := h.Nodes.GetByEnv(e, "active", h.Settings.InactiveHours(settings.NoEnvironmentID))
nodes, err := h.Nodes.GetByEnv(e, nodes.ActiveNodes, h.Settings.InactiveHours(settings.NoEnvironmentID))
if err != nil {
adminErrorResponse(w, "error getting nodes by environment", http.StatusInternalServerError, err)
return
Expand All @@ -160,10 +155,10 @@ func (h *HandlersAdmin) QueryRunPOSTHandler(w http.ResponseWriter, r *http.Reque
// Create platform target
if len(q.Platforms) > 0 {
expected = []uint{}
platforms, _ := h.Nodes.GetAllPlatforms()
platforms, _ := h.Nodes.GetEnvIDPlatforms(env.ID)
for _, p := range q.Platforms {
if (p != "") && checkValidPlatform(platforms, p) {
nodes, err := h.Nodes.GetByPlatform(p, "active", h.Settings.InactiveHours(settings.NoEnvironmentID))
nodes, err := h.Nodes.GetByPlatform(env.ID, p, nodes.ActiveNodes, h.Settings.InactiveHours(settings.NoEnvironmentID))
if err != nil {
adminErrorResponse(w, "error getting nodes by platform", http.StatusInternalServerError, err)
return
Expand Down Expand Up @@ -205,7 +200,26 @@ func (h *HandlersAdmin) QueryRunPOSTHandler(w http.ResponseWriter, r *http.Reque
}
targetNodesID = utils.Intersect(targetNodesID, expected)
}

// Create tags target
if len(q.Tags) > 0 {
expected = []uint{}
for _, _t := range q.Tags {
if _t != "" {
exist, tag := h.Tags.ExistsGet(tags.GetStrTagName(_t), env.ID)
if exist {
tagged, err := h.Tags.GetTaggedNodes(tag)
if err != nil {
log.Err(err).Msgf("error getting tagged nodes for tag %s", _t)
continue
}
for _, tn := range tagged {
expected = append(expected, tn.NodeID)
}
}
}
}
targetNodesID = utils.Intersect(targetNodesID, expected)
}
// If the list is empty, we don't need to create node queries
if len(targetNodesID) != 0 {
if err := h.Queries.CreateNodeQueries(targetNodesID, newQuery.ID); err != nil {
Expand Down Expand Up @@ -273,101 +287,115 @@ func (h *HandlersAdmin) CarvesRunPOSTHandler(w http.ResponseWriter, r *http.Requ
adminErrorResponse(w, "path can not be empty", http.StatusInternalServerError, nil)
return
}
query := generateCarveQuery(c.Path, false)
// Prepare and create new carve
carveName := generateCarveName()
// Set query expiration
expTime := queries.QueryExpiration(c.ExpHours)
if c.ExpHours == 0 {
expTime = time.Time{}
}
newQuery := queries.DistributedQuery{
Query: query,
Name: carveName,
Creator: ctx[sessions.CtxUser],
Expected: 0,
Executions: 0,
Active: true,
Completed: false,
Deleted: false,
Expired: false,
Expiration: expTime,
Type: queries.CarveQueryType,
Path: c.Path,
EnvironmentID: env.ID,
}
if err := h.Queries.Create(newQuery); err != nil {
newQuery := newCarveReady(ctx[sessions.CtxUser], c.Path, expTime, env.ID, c)
if err := h.Queries.Create(&newQuery); err != nil {
adminErrorResponse(w, "error creating carve", http.StatusInternalServerError, err)
return
}
// Temporary list of UUIDs to calculate Expected
var expected []string
// Create environment target
// List all the nodes that match the query
var expected []uint
targetNodesID := []uint{}
// Extract targets by environment
if len(c.Environments) > 0 {
expected = []uint{}
for _, e := range c.Environments {
// TODO: Check if user has permissions to query the environment
if (e != "") && h.Envs.Exists(e) {
if err := h.Queries.CreateTarget(carveName, queries.QueryTargetEnvironment, e); err != nil {
adminErrorResponse(w, "error creating carve environment target", http.StatusInternalServerError, err)
return
}
nodes, err := h.Nodes.GetByEnv(e, "active", h.Settings.InactiveHours(settings.NoEnvironmentID))
nodes, err := h.Nodes.GetByEnv(e, nodes.ActiveNodes, h.Settings.InactiveHours(settings.NoEnvironmentID))
if err != nil {
adminErrorResponse(w, "error getting nodes by environment", http.StatusInternalServerError, err)
return
}
for _, n := range nodes {
expected = append(expected, n.UUID)
expected = append(expected, n.ID)
}
}
}
targetNodesID = utils.Intersect(targetNodesID, expected)
}
// Create platform target
if len(c.Platforms) > 0 {
platforms, _ := h.Nodes.GetAllPlatforms()
expected = []uint{}
platforms, _ := h.Nodes.GetEnvIDPlatforms(env.ID)
for _, p := range c.Platforms {
if (p != "") && checkValidPlatform(platforms, p) {
if err := h.Queries.CreateTarget(carveName, queries.QueryTargetPlatform, p); err != nil {
adminErrorResponse(w, "error creating carve platform target", http.StatusInternalServerError, err)
return
}
nodes, err := h.Nodes.GetByPlatform(p, "active", h.Settings.InactiveHours(settings.NoEnvironmentID))
nodes, err := h.Nodes.GetByPlatform(env.ID, p, nodes.ActiveNodes, h.Settings.InactiveHours(settings.NoEnvironmentID))
if err != nil {
adminErrorResponse(w, "error getting nodes by platform", http.StatusInternalServerError, err)
return
}
for _, n := range nodes {
expected = append(expected, n.UUID)
expected = append(expected, n.ID)
}
}
}
targetNodesID = utils.Intersect(targetNodesID, expected)
}
// Create UUIDs target
if len(c.UUIDs) > 0 {
expected = []uint{}
for _, u := range c.UUIDs {
if (u != "") && h.Nodes.CheckByUUID(u) {
if err := h.Queries.CreateTarget(carveName, queries.QueryTargetUUID, u); err != nil {
adminErrorResponse(w, "error creating carve UUID target", http.StatusInternalServerError, err)
return
if u != "" {
node, err := h.Nodes.GetByUUID(u)
if err != nil {
log.Err(err).Msgf("error getting node %s and failed to create carve query for it", u)
continue
}
expected = append(expected, u)
expected = append(expected, node.ID)
}
}
targetNodesID = utils.Intersect(targetNodesID, expected)
}
// Create hostnames target
if len(c.Hosts) > 0 {
expected = []uint{}
for _, _h := range c.Hosts {
if (_h != "") && h.Nodes.CheckByHost(_h) {
if err := h.Queries.CreateTarget(carveName, queries.QueryTargetLocalname, _h); err != nil {
adminErrorResponse(w, "error creating carve hostname target", http.StatusInternalServerError, err)
return
if _h != "" {
node, err := h.Nodes.GetByIdentifier(_h)
if err != nil {
log.Err(err).Msgf("error getting node %s and failed to create carve query for it", _h)
continue
}
expected = append(expected, node.ID)
}
}
targetNodesID = utils.Intersect(targetNodesID, expected)
}
// Create tags target
if len(c.Tags) > 0 {
expected = []uint{}
for _, _t := range c.Tags {
if _t != "" {
exist, tag := h.Tags.ExistsGet(tags.GetStrTagName(_t), env.ID)
if exist {
tagged, err := h.Tags.GetTaggedNodes(tag)
if err != nil {
log.Err(err).Msgf("error getting tagged nodes for tag %s", _t)
continue
}
for _, tn := range tagged {
expected = append(expected, tn.NodeID)
}
}
}
}
targetNodesID = utils.Intersect(targetNodesID, expected)
}
// If the list is empty, we don't need to create node queries
if len(targetNodesID) != 0 {
if err := h.Queries.CreateNodeQueries(targetNodesID, newQuery.ID); err != nil {
log.Err(err).Msgf("error creating node queries for carve %s", newQuery.Name)
adminErrorResponse(w, "error creating node queries", http.StatusInternalServerError, err)
return
}
}
// Remove duplicates from expected
expectedClear := removeStringDuplicates(expected)
// Update value for expected
if err := h.Queries.SetExpected(carveName, len(expectedClear), env.ID); err != nil {
if err := h.Queries.SetExpected(newQuery.Name, len(targetNodesID), env.ID); err != nil {
adminErrorResponse(w, "error setting expected", http.StatusInternalServerError, err)
return
}
Expand Down
Loading
Loading