-
Notifications
You must be signed in to change notification settings - Fork 161
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
BED-5249: feat: Get Tier/Label List Endpoint #1213
base: main
Are you sure you want to change the base?
Changes from all commits
0ca8890
c7e7123
9b7c454
c3574ad
19c93a3
0af1ef7
202db3d
afeb73e
1ebb42e
db5537b
67d503e
38447ed
bae7b35
1db6ee3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,6 +18,7 @@ package v2 | |
|
||
import ( | ||
"encoding/json" | ||
"errors" | ||
"fmt" | ||
"log/slog" | ||
"net/http" | ||
|
@@ -29,6 +30,7 @@ import ( | |
"github.com/specterops/bloodhound/src/api" | ||
"github.com/specterops/bloodhound/src/auth" | ||
"github.com/specterops/bloodhound/src/ctx" | ||
"github.com/specterops/bloodhound/src/database" | ||
"github.com/specterops/bloodhound/src/model" | ||
"github.com/specterops/bloodhound/src/queries" | ||
"github.com/specterops/bloodhound/src/utils/validation" | ||
|
@@ -39,6 +41,69 @@ const ( | |
ErrInvalidSelectorType = "invalid selector type" | ||
) | ||
|
||
type GetAssetGroupTagsResponse struct { | ||
AssetGroupTags model.AssetGroupTags `json:"asset_group_tags"` | ||
Counts struct { | ||
Selectors map[int]int `json:"selectors"` | ||
Members map[int]int `json:"members"` | ||
} `json:"counts,omitempty"` | ||
} | ||
|
||
func (s Resources) GetAssetGroupTags(response http.ResponseWriter, request *http.Request) { | ||
const ( | ||
pnameTagType = "type" | ||
pnameIncludeCounts = "includeCounts" | ||
) | ||
var ( | ||
pvalsTagType = map[string]model.AssetGroupTagType{ | ||
strconv.Itoa(int(model.AssetGroupTagTypeLabel)): model.AssetGroupTagTypeLabel, | ||
strconv.Itoa(int(model.AssetGroupTagTypeTier)): model.AssetGroupTagTypeTier, | ||
"": model.AssetGroupTagTypeAll, // default | ||
} | ||
pvalsIncludeCounts = map[string]bool{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what does the "p" stand for in these const and variable names? |
||
"false": false, | ||
"true": true, | ||
"": false, // default | ||
} | ||
) | ||
|
||
var params = request.URL.Query() | ||
|
||
if paramTagType, ok := pvalsTagType[params.Get(pnameTagType)]; !ok { | ||
api.WriteErrorResponse(request.Context(), api.BuildErrorResponse(http.StatusBadRequest, "Invalid value specifed for tag type", request), response) | ||
} else if paramIncludeCounts, ok := pvalsIncludeCounts[params.Get(pnameIncludeCounts)]; !ok { | ||
api.WriteErrorResponse(request.Context(), api.BuildErrorResponse(http.StatusBadRequest, "Invalid value specifed for include counts", request), response) | ||
} else if tags, err := s.DB.GetAssetGroupTags(request.Context(), paramTagType); err != nil && !errors.Is(err, database.ErrNotFound) { | ||
api.HandleDatabaseError(request, response, err) | ||
} else { | ||
resp := GetAssetGroupTagsResponse{AssetGroupTags: tags} | ||
if paramIncludeCounts { | ||
ids := make([]int, 0, len(tags)) | ||
for i := range tags { | ||
ids = append(ids, tags[i].ID) | ||
} | ||
if selectorCounts, err := s.DB.GetAssetGroupTagSelectorCounts(request.Context(), ids); err != nil { | ||
api.HandleDatabaseError(request, response, err) | ||
return | ||
} else { | ||
resp.Counts.Selectors = selectorCounts | ||
} | ||
memberCounts := make(map[int]int, len(tags)) | ||
for _, tag := range tags { | ||
// TODO: use a more efficient query method | ||
if nodelist, err := s.GraphQuery.GetNodesByKind(request.Context(), tag.ToKind()); err != nil { | ||
Comment on lines
+93
to
+94
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we end up creating the method in the referenced comment we can use it here too instead of https://github.com/SpecterOps/BloodHound/pull/1307/files#r2027599359 |
||
api.HandleDatabaseError(request, response, err) | ||
return | ||
} else { | ||
memberCounts[tag.ID] = nodelist.Len() | ||
} | ||
} | ||
resp.Counts.Members = memberCounts | ||
} | ||
api.WriteBasicResponse(request.Context(), resp, http.StatusOK, response) | ||
} | ||
} | ||
|
||
// Checks that the selector seeds are valid. | ||
func validateSelectorSeeds(graph queries.Graph, seeds []model.SelectorSeed) error { | ||
// all seeds must be of the same type | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this can probably be private?