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
7 changes: 7 additions & 0 deletions cmd/admin/handlers/templates.go
Original file line number Diff line number Diff line change
Expand Up @@ -1422,6 +1422,12 @@ func (h *HandlersAdmin) TagsGETHandler(w http.ResponseWriter, r *http.Request) {
log.Err(err).Msg("error getting tags")
return
}
// Get current tags count
tagsCount, err := h.Tags.CountTaggedNodes(tags)
if err != nil {
log.Err(err).Msg("error getting tags count")
return
}
// Get if the user is admin
user, err := h.Users.Get(ctx[sessions.CtxUser])
if err != nil {
Expand All @@ -1434,6 +1440,7 @@ func (h *HandlersAdmin) TagsGETHandler(w http.ResponseWriter, r *http.Request) {
Metadata: h.TemplateMetadata(ctx, h.ServiceMetadata, user.Admin),
Environments: h.allowedEnvironments(ctx[sessions.CtxUser], envAll),
Tags: tags,
CounterTags: tagsCount,
}
if err := t.Execute(w, templateData); err != nil {
log.Err(err).Msg("template error")
Expand Down
1 change: 1 addition & 0 deletions cmd/admin/handlers/types-templates.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ type TagsTemplateData struct {
Environments []environments.TLSEnvironment
Platforms []string
Tags []tags.AdminTag
CounterTags tags.TagCounter
Metadata TemplateMetadata
LeftMetadata AsideLeftMetadata
}
Expand Down
6 changes: 3 additions & 3 deletions cmd/admin/templates/tags.html
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,12 @@
<th>Color</th>
<th>Icon</th>
<th>Environment</th>
<th>Tagged Nodes</th>
<th></th>
</tr>
</thead>
<tbody>
{{ $counterTags := $.CounterTags }}
{{range $i, $t := $.Tags}}
<tr>
<td>
Expand All @@ -70,6 +72,7 @@
<b>{{ environmentFinder $t.EnvironmentID $.Environments false }}</b>
<input type="hidden" value="{{ environmentFinder $t.EnvironmentID $.Environments true }}" id="tag_env_{{ $t.Name }}">
</td>
<td>{{with index $counterTags $t.ID}}{{.}}{{else}}0{{end}}</td>
<td>
<button type="button" class="btn btn-sm btn-ghost-danger" onclick="confirmDeleteTag('{{ $t.Name }}');">
<i class="far fa-trash-alt"></i>
Expand Down Expand Up @@ -138,13 +141,10 @@ <h4 id="modal_title_tag" class="modal-title"></h4>
<select class="form-control" name="tag_type" id="tag_type">
<option value=""></option>
<option value="0">Environment</option>
<option value="1">UUID</option>
<option value="2">Platform</option>
<option value="3">Localname</option>
<option value="4">Custom</option>
<option value="5">Unknown</option>
<option value="6">Tag</option>
<option value="7">Hostname</option>
</select>
</div>
</div>
Expand Down
6 changes: 0 additions & 6 deletions cmd/cli/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,12 +163,6 @@ func tagNode(c *cli.Context) error {
switch tagType {
case tags.TagTypeEnvStr:
tagTypeInt = tags.TagTypeEnv
case tags.TagTypeUUIDStr:
tagTypeInt = tags.TagTypeUUID
case tags.TagTypeLocalnameStr:
tagTypeInt = tags.TagTypeLocalname
case tags.TagTypeHostnameStr:
tagTypeInt = tags.TagTypeHostname
case tags.TagTypePlatformStr:
tagTypeInt = tags.TagTypePlatform
case tags.TagTypeTagStr:
Expand Down
62 changes: 44 additions & 18 deletions pkg/tags/tags.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,14 @@ const (
DefaultAutocreated = "Autocreated"
// TagTypeEnv as tag type for environment name
TagTypeEnv uint = 0
// TagTypeUUID as tag type for node UUID
TagTypeUUID uint = 1
// TagTypePlatform as tag type for node platform
TagTypePlatform uint = 2
// TagTypeLocalname as tag type for node localname
TagTypeLocalname uint = 3
// TagTypeCustom as tag type for custom tags
TagTypeCustom uint = 4
// TagTypeUnknown as tag type for unknown tags
TagTypeUnknown uint = 5
// TagTypeTag as tag type for regular tags
TagTypeTag uint = 6
// TagTypeHostname as tag type for hostname tags
TagTypeHostname uint = 7
// ActionAdd as action to add a tag
ActionAdd string = "add"
// ActionEdit as action to edit a tag
Expand All @@ -44,18 +38,12 @@ const (
ActionUntag string = "untag"
// TagCustomEnv as custom tag for environment name
TagCustomEnv string = TagTypeEnvStr
// TagCustomUUID as custom tag for node UUID
TagCustomUUID string = TagTypeUUIDStr
// TagCustomPlatform as custom tag for node platform
TagCustomPlatform string = TagTypePlatformStr
// TagCustomLocalname as custom tag for node localname
TagCustomLocalname string = TagTypeLocalnameStr
// TagCustomUnknown as custom tag for unknown tags
TagCustomUnknown string = TagTypeUnknownStr
// TagCustomTag as custom tag for regular tags
TagCustomTag string = TagTypeTagStr
// TagCustomHostname as custom tag for hostname tags
TagCustomHostname string = TagTypeHostnameStr
)

// AdminTag to hold all tags
Expand Down Expand Up @@ -90,6 +78,9 @@ type TaggedNode struct {
UserID uint
}

// TagCounter to hold tagged node counts
type TagCounter map[uint]int

// TagManager have all tags
type TagManager struct {
DB *gorm.DB
Expand Down Expand Up @@ -148,13 +139,9 @@ func (m *TagManager) New(name, description, color, icon, user string, envID uint
case TagTypeEnv:
tagCustom = TagCustomEnv
cohort = true
case TagTypeUUID:
tagCustom = TagCustomUUID
case TagTypePlatform:
tagCustom = TagCustomPlatform
cohort = true
case TagTypeLocalname:
tagCustom = TagCustomLocalname
case TagTypeCustom:
tagCustom = custom
case TagTypeUnknown:
Expand Down Expand Up @@ -399,7 +386,7 @@ func (m *TagManager) ChangeEnvironment(tag *AdminTag, envID uint) error {

// AutoTagNode to automatically tag a node based on multiple fields
func (m *TagManager) AutoTagNode(env string, node nodes.OsqueryNode, user string) error {
l := []string{env, node.UUID, node.Platform, node.Localname}
l := []string{env, node.Platform}
return m.TagNodeMulti(l, node, user, true, "")
}

Expand Down Expand Up @@ -538,8 +525,47 @@ func (m *TagManager) GetNodeTags(tagged []AdminTag) ([]AdminTagForNode, error) {
// GetTaggedNodes to retrieve tagged nodes with a given tag name and environment
func (m *TagManager) GetTaggedNodes(tag AdminTag) ([]TaggedNode, error) {
var tagged []TaggedNode
if err := m.DB.Where("id = ?", tag.ID).Find(&tagged).Error; err != nil {
if err := m.DB.Where("admin_tag_id = ?", tag.ID).Find(&tagged).Error; err != nil {
return tagged, err
}
return tagged, nil
}

// CountTaggedNodes to count tagged nodes for a given list of tags
func (m *TagManager) CountTaggedNodes(tags []AdminTag) (TagCounter, error) {
tagCounter := make(TagCounter)
if len(tags) == 0 {
return tagCounter, nil
}
// Collect tag IDs
tagIDs := make([]uint, len(tags))
for i, t := range tags {
tagIDs[i] = t.ID
}
// Result struct for query
type result struct {
AdminTagID uint
Count int
}
var results []result
// Grouped count query
if err := m.DB.
Model(&TaggedNode{}).
Select("admin_tag_id, COUNT(*) as count").
Where("admin_tag_id IN ?", tagIDs).
Group("admin_tag_id").
Scan(&results).Error; err != nil {
return tagCounter, err
}
// Populate TagCounter from results
for _, r := range results {
tagCounter[r.AdminTagID] = r.Count
}
// Ensure all tags are present in the map (with zero if not found)
for _, id := range tagIDs {
if _, ok := tagCounter[id]; !ok {
tagCounter[id] = 0
}
}
return tagCounter, nil
}
26 changes: 0 additions & 26 deletions pkg/tags/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,8 @@ import (
const (
// TagTypeEnvStr is the tag type for shortened environment
TagTypeEnvStr = "env"
// TagTypeUUIDStr is the tag type for UUID
TagTypeUUIDStr = "uuid"
// TagTypePlatformStr is the tag type for platform
TagTypePlatformStr = "platform"
// TagTypeLocalnameStr is the tag type for localname
TagTypeLocalnameStr = "localname"
// TagTypeHostnameStr is the tag type for hostname
TagTypeHostnameStr = "hostname"
// TagTypeCustomStr is the tag type for custom
TagTypeCustomStr = "custom"
// TagTypeUnknownStr is the tag type for unknown
Expand Down Expand Up @@ -50,14 +44,8 @@ func TagTypeDecorator(tagType uint) string {
switch tagType {
case TagTypeEnv:
return TagTypeEnvStr
case TagTypeUUID:
return TagTypeUUIDStr
case TagTypePlatform:
return TagTypePlatformStr
case TagTypeLocalname:
return TagTypeLocalnameStr
case TagTypeHostname:
return TagTypeHostnameStr
case TagTypeCustom:
return TagTypeCustomStr
case TagTypeTag:
Expand All @@ -72,12 +60,8 @@ func TagTypeParser(tagType string) uint {
switch strings.ToUpper(tagType) {
case strings.ToUpper(TagTypeEnvStr):
return TagTypeEnv
case strings.ToUpper(TagTypeUUIDStr):
return TagTypeUUID
case strings.ToUpper(TagTypePlatformStr):
return TagTypePlatform
case strings.ToUpper(TagTypeLocalnameStr):
return TagTypeLocalname
case strings.ToUpper(TagTypeCustomStr):
return TagTypeCustom
case strings.ToUpper(TagTypeTagStr):
Expand All @@ -93,14 +77,8 @@ func SetCustomTag(tagType uint, custom string) string {
switch tagType {
case TagTypeEnv:
tagCustom = TagCustomEnv
case TagTypeUUID:
tagCustom = TagCustomUUID
case TagTypePlatform:
tagCustom = TagCustomPlatform
case TagTypeLocalname:
tagCustom = TagCustomLocalname
case TagTypeHostname:
tagCustom = TagCustomHostname
case TagTypeCustom:
tagCustom = custom
case TagTypeUnknown:
Expand Down Expand Up @@ -138,12 +116,8 @@ func ValidateCustom(anyCustom string) string {
switch strings.ToUpper(anyCustom) {
case strings.ToUpper(TagTypeEnvStr):
return TagTypeEnvStr
case strings.ToUpper(TagTypeUUIDStr):
return TagTypeUUIDStr
case strings.ToUpper(TagTypePlatformStr):
return TagTypePlatformStr
case strings.ToUpper(TagTypeLocalnameStr):
return TagTypeLocalnameStr
case strings.ToUpper(TagTypeCustomStr):
return TagTypeCustomStr
case strings.ToUpper(TagTypeTagStr):
Expand Down
6 changes: 0 additions & 6 deletions pkg/tags/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,27 +20,21 @@ func TestGetHex(t *testing.T) {

func TestTagTypeDecorator(t *testing.T) {
assert.Equal(t, "env", TagTypeDecorator(0))
assert.Equal(t, "uuid", TagTypeDecorator(1))
assert.Equal(t, "platform", TagTypeDecorator(2))
assert.Equal(t, "localname", TagTypeDecorator(3))
assert.Equal(t, "custom", TagTypeDecorator(4))
assert.Equal(t, "unknown", TagTypeDecorator(5))
}

func TestTagTypeParser(t *testing.T) {
assert.Equal(t, uint(0), TagTypeParser("env"))
assert.Equal(t, uint(1), TagTypeParser("uuid"))
assert.Equal(t, uint(2), TagTypeParser("platform"))
assert.Equal(t, uint(3), TagTypeParser("localname"))
assert.Equal(t, uint(4), TagTypeParser("custom"))
assert.Equal(t, uint(5), TagTypeParser("unknown"))
}

func TestTagCustom(t *testing.T) {
assert.Equal(t, "env", SetCustomTag(0, "CUSTOM-VALUE"))
assert.Equal(t, "uuid", SetCustomTag(1, "CUSTOM-VALUE"))
assert.Equal(t, "platform", SetCustomTag(2, "CUSTOM-VALUE"))
assert.Equal(t, "localname", SetCustomTag(3, "CUSTOM-VALUE"))
assert.Equal(t, "CUSTOM-VALUE", SetCustomTag(4, "CUSTOM-VALUE"))
assert.Equal(t, "unknown", SetCustomTag(5, "CUSTOM-VALUE"))
}
Expand Down
Loading