2016-09-30 01:19:51 +00:00
|
|
|
package datastore
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
2016-10-17 19:30:47 +00:00
|
|
|
"sort"
|
2016-09-30 01:19:51 +00:00
|
|
|
"strconv"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/kolide/kolide-ose/server/kolide"
|
|
|
|
)
|
|
|
|
|
|
|
|
func (orm *inmem) NewLabel(label *kolide.Label) (*kolide.Label, error) {
|
|
|
|
newLabel := *label
|
|
|
|
|
2016-10-17 19:30:47 +00:00
|
|
|
orm.mtx.Lock()
|
2016-09-30 01:19:51 +00:00
|
|
|
for _, l := range orm.labels {
|
|
|
|
if l.Name == label.Name {
|
|
|
|
return nil, ErrExists
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-14 16:15:04 +00:00
|
|
|
newLabel.ID = orm.nextID(label)
|
2016-09-30 01:19:51 +00:00
|
|
|
orm.labels[newLabel.ID] = &newLabel
|
2016-10-17 19:30:47 +00:00
|
|
|
orm.mtx.Unlock()
|
2016-09-30 01:19:51 +00:00
|
|
|
|
|
|
|
return &newLabel, nil
|
|
|
|
}
|
|
|
|
|
2016-10-14 15:59:27 +00:00
|
|
|
func (orm *inmem) ListLabelsForHost(hid uint) ([]kolide.Label, error) {
|
2016-09-30 01:19:51 +00:00
|
|
|
// First get IDs of label executions for the host
|
|
|
|
resLabels := []kolide.Label{}
|
2016-10-17 19:30:47 +00:00
|
|
|
|
|
|
|
orm.mtx.Lock()
|
2016-09-30 01:19:51 +00:00
|
|
|
for _, lqe := range orm.labelQueryExecutions {
|
2016-10-03 03:14:35 +00:00
|
|
|
if lqe.HostID == hid && lqe.Matches {
|
2016-09-30 01:19:51 +00:00
|
|
|
if label := orm.labels[lqe.LabelID]; label != nil {
|
|
|
|
resLabels = append(resLabels, *label)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-10-17 19:30:47 +00:00
|
|
|
orm.mtx.Unlock()
|
2016-09-30 01:19:51 +00:00
|
|
|
|
|
|
|
return resLabels, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (orm *inmem) LabelQueriesForHost(host *kolide.Host, cutoff time.Time) (map[string]string, error) {
|
|
|
|
// Get post-cutoff executions for host
|
|
|
|
execedQueryIDs := map[uint]uint{} // Map queryID -> labelID
|
2016-10-17 19:30:47 +00:00
|
|
|
|
|
|
|
orm.mtx.Lock()
|
2016-09-30 01:19:51 +00:00
|
|
|
for _, lqe := range orm.labelQueryExecutions {
|
|
|
|
if lqe.HostID == host.ID && (lqe.UpdatedAt == cutoff || lqe.UpdatedAt.After(cutoff)) {
|
|
|
|
label := orm.labels[lqe.LabelID]
|
|
|
|
execedQueryIDs[label.QueryID] = label.ID
|
|
|
|
}
|
|
|
|
}
|
2016-10-17 19:30:47 +00:00
|
|
|
orm.mtx.Unlock()
|
2016-09-30 01:19:51 +00:00
|
|
|
|
|
|
|
queryToLabel := map[uint]uint{} // Map queryID -> labelID
|
|
|
|
for _, label := range orm.labels {
|
|
|
|
queryToLabel[label.QueryID] = label.ID
|
|
|
|
}
|
|
|
|
|
|
|
|
resQueries := map[string]string{}
|
|
|
|
for _, query := range orm.queries {
|
|
|
|
_, execed := execedQueryIDs[query.ID]
|
|
|
|
labelID := queryToLabel[query.ID]
|
|
|
|
if query.Platform == host.Platform && !execed {
|
|
|
|
resQueries[strconv.Itoa(int(labelID))] = query.Query
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return resQueries, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (orm *inmem) getLabelByIDString(id string) (*kolide.Label, error) {
|
|
|
|
labelID, err := strconv.Atoi(id)
|
|
|
|
if err != nil {
|
|
|
|
return nil, errors.New("non-int label ID")
|
|
|
|
}
|
|
|
|
|
2016-10-17 19:30:47 +00:00
|
|
|
orm.mtx.Lock()
|
2016-09-30 01:19:51 +00:00
|
|
|
label, ok := orm.labels[uint(labelID)]
|
2016-10-17 19:30:47 +00:00
|
|
|
orm.mtx.Unlock()
|
|
|
|
|
2016-09-30 01:19:51 +00:00
|
|
|
if !ok {
|
|
|
|
return nil, errors.New("label ID not found: " + string(labelID))
|
|
|
|
}
|
|
|
|
|
|
|
|
return label, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (orm *inmem) RecordLabelQueryExecutions(host *kolide.Host, results map[string]bool, t time.Time) error {
|
|
|
|
// Record executions
|
|
|
|
for strLabelID, matches := range results {
|
|
|
|
label, err := orm.getLabelByIDString(strLabelID)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
updated := false
|
2016-10-17 19:30:47 +00:00
|
|
|
orm.mtx.Lock()
|
2016-09-30 01:19:51 +00:00
|
|
|
for _, lqe := range orm.labelQueryExecutions {
|
|
|
|
if lqe.LabelID == label.ID && lqe.HostID == host.ID {
|
|
|
|
// Update existing execution values
|
|
|
|
lqe.UpdatedAt = t
|
|
|
|
lqe.Matches = matches
|
|
|
|
updated = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if !updated {
|
|
|
|
// Create new execution
|
|
|
|
lqe := kolide.LabelQueryExecution{
|
|
|
|
HostID: host.ID,
|
|
|
|
LabelID: label.ID,
|
|
|
|
UpdatedAt: t,
|
|
|
|
Matches: matches,
|
|
|
|
}
|
2016-10-14 16:15:04 +00:00
|
|
|
lqe.ID = orm.nextID(lqe)
|
2016-09-30 01:19:51 +00:00
|
|
|
orm.labelQueryExecutions[lqe.ID] = &lqe
|
|
|
|
}
|
2016-10-17 19:30:47 +00:00
|
|
|
orm.mtx.Unlock()
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (orm *inmem) DeleteLabel(lid uint) error {
|
|
|
|
orm.mtx.Lock()
|
|
|
|
delete(orm.labels, lid)
|
|
|
|
orm.mtx.Unlock()
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (orm *inmem) Label(lid uint) (*kolide.Label, error) {
|
|
|
|
orm.mtx.Lock()
|
|
|
|
label, ok := orm.labels[lid]
|
|
|
|
orm.mtx.Unlock()
|
|
|
|
|
|
|
|
if !ok {
|
|
|
|
return nil, errors.New("Label not found")
|
|
|
|
}
|
|
|
|
return label, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (orm *inmem) ListLabels(opt kolide.ListOptions) ([]*kolide.Label, error) {
|
|
|
|
// We need to sort by keys to provide reliable ordering
|
|
|
|
keys := []int{}
|
|
|
|
|
|
|
|
orm.mtx.Lock()
|
|
|
|
for k, _ := range orm.labels {
|
|
|
|
keys = append(keys, int(k))
|
|
|
|
}
|
|
|
|
sort.Ints(keys)
|
|
|
|
|
|
|
|
labels := []*kolide.Label{}
|
|
|
|
for _, k := range keys {
|
|
|
|
labels = append(labels, orm.labels[uint(k)])
|
|
|
|
}
|
|
|
|
orm.mtx.Unlock()
|
|
|
|
|
|
|
|
// Apply ordering
|
|
|
|
if opt.OrderKey != "" {
|
|
|
|
var fields = map[string]string{
|
|
|
|
"id": "ID",
|
|
|
|
"created_at": "CreatedAt",
|
|
|
|
"updated_at": "UpdatedAt",
|
|
|
|
"name": "Name",
|
|
|
|
}
|
|
|
|
if err := sortResults(labels, opt, fields); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2016-09-30 01:19:51 +00:00
|
|
|
}
|
|
|
|
|
2016-10-17 19:30:47 +00:00
|
|
|
// Apply limit/offset
|
|
|
|
low, high := orm.getLimitOffsetSliceBounds(opt, len(labels))
|
|
|
|
labels = labels[low:high]
|
|
|
|
|
|
|
|
return labels, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (orm *inmem) SaveLabel(label *kolide.Label) error {
|
|
|
|
orm.mtx.Lock()
|
|
|
|
if _, ok := orm.labels[label.ID]; !ok {
|
|
|
|
return ErrNotFound
|
|
|
|
}
|
|
|
|
|
|
|
|
orm.labels[label.ID] = label
|
|
|
|
orm.mtx.Unlock()
|
|
|
|
|
2016-09-30 01:19:51 +00:00
|
|
|
return nil
|
|
|
|
}
|