2016-11-16 13:47:49 +00:00
|
|
|
package inmem
|
2016-09-30 01:19:51 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
2016-10-13 18:21:47 +00:00
|
|
|
"sort"
|
2016-11-02 14:59:53 +00:00
|
|
|
"strings"
|
2016-09-30 01:19:51 +00:00
|
|
|
"time"
|
|
|
|
|
2016-11-16 13:47:49 +00:00
|
|
|
kolide_errors "github.com/kolide/kolide-ose/server/errors"
|
2016-09-30 01:19:51 +00:00
|
|
|
"github.com/kolide/kolide-ose/server/kolide"
|
|
|
|
)
|
|
|
|
|
2016-11-16 13:47:49 +00:00
|
|
|
func (orm *Datastore) NewHost(host *kolide.Host) (*kolide.Host, error) {
|
2016-09-30 01:19:51 +00:00
|
|
|
orm.mtx.Lock()
|
|
|
|
defer orm.mtx.Unlock()
|
|
|
|
|
|
|
|
for _, h := range orm.hosts {
|
|
|
|
if host.NodeKey == h.NodeKey || host.UUID == h.UUID {
|
2016-11-16 13:47:49 +00:00
|
|
|
return nil, kolide_errors.ErrExists
|
2016-09-30 01:19:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-14 16:15:04 +00:00
|
|
|
host.ID = orm.nextID(host)
|
2016-10-16 11:56:20 +00:00
|
|
|
orm.hosts[host.ID] = host
|
2016-09-30 01:19:51 +00:00
|
|
|
|
|
|
|
return host, nil
|
|
|
|
}
|
|
|
|
|
2016-11-16 13:47:49 +00:00
|
|
|
func (orm *Datastore) SaveHost(host *kolide.Host) error {
|
2016-09-30 01:19:51 +00:00
|
|
|
orm.mtx.Lock()
|
|
|
|
defer orm.mtx.Unlock()
|
|
|
|
|
|
|
|
if _, ok := orm.hosts[host.ID]; !ok {
|
2016-11-16 13:47:49 +00:00
|
|
|
return kolide_errors.ErrNotFound
|
2016-09-30 01:19:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
orm.hosts[host.ID] = host
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2016-11-16 13:47:49 +00:00
|
|
|
func (orm *Datastore) DeleteHost(host *kolide.Host) error {
|
2016-09-30 01:19:51 +00:00
|
|
|
orm.mtx.Lock()
|
|
|
|
defer orm.mtx.Unlock()
|
|
|
|
|
|
|
|
if _, ok := orm.hosts[host.ID]; !ok {
|
2016-11-16 13:47:49 +00:00
|
|
|
return kolide_errors.ErrNotFound
|
2016-09-30 01:19:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
delete(orm.hosts, host.ID)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2016-11-16 13:47:49 +00:00
|
|
|
func (orm *Datastore) Host(id uint) (*kolide.Host, error) {
|
2016-09-30 01:19:51 +00:00
|
|
|
orm.mtx.Lock()
|
|
|
|
defer orm.mtx.Unlock()
|
|
|
|
|
|
|
|
host, ok := orm.hosts[id]
|
|
|
|
if !ok {
|
2016-11-16 13:47:49 +00:00
|
|
|
return nil, kolide_errors.ErrNotFound
|
2016-09-30 01:19:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return host, nil
|
|
|
|
}
|
|
|
|
|
2016-11-16 13:47:49 +00:00
|
|
|
func (orm *Datastore) ListHosts(opt kolide.ListOptions) ([]*kolide.Host, error) {
|
2016-09-30 01:19:51 +00:00
|
|
|
orm.mtx.Lock()
|
|
|
|
defer orm.mtx.Unlock()
|
|
|
|
|
2016-10-13 18:21:47 +00:00
|
|
|
// We need to sort by keys to provide reliable ordering
|
|
|
|
keys := []int{}
|
|
|
|
for k, _ := range orm.hosts {
|
|
|
|
keys = append(keys, int(k))
|
|
|
|
}
|
|
|
|
sort.Ints(keys)
|
|
|
|
|
2016-09-30 01:19:51 +00:00
|
|
|
hosts := []*kolide.Host{}
|
2016-10-13 18:21:47 +00:00
|
|
|
for _, k := range keys {
|
|
|
|
hosts = append(hosts, orm.hosts[uint(k)])
|
2016-09-30 01:19:51 +00:00
|
|
|
}
|
|
|
|
|
2016-10-17 14:01:14 +00:00
|
|
|
// Apply ordering
|
|
|
|
if opt.OrderKey != "" {
|
|
|
|
var fields = map[string]string{
|
|
|
|
"id": "ID",
|
|
|
|
"created_at": "CreatedAt",
|
|
|
|
"updated_at": "UpdatedAt",
|
|
|
|
"detail_update_time": "DetailUpdateTime",
|
|
|
|
"hostname": "HostName",
|
|
|
|
"uuid": "UUID",
|
|
|
|
"platform": "Platform",
|
|
|
|
"osquery_version": "OsqueryVersion",
|
|
|
|
"os_version": "OSVersion",
|
|
|
|
"uptime": "Uptime",
|
|
|
|
"memory": "PhysicalMemory",
|
|
|
|
"mac": "PrimaryMAC",
|
|
|
|
"ip": "PrimaryIP",
|
|
|
|
}
|
|
|
|
if err := sortResults(hosts, opt, fields); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-13 18:21:47 +00:00
|
|
|
// Apply limit/offset
|
|
|
|
low, high := orm.getLimitOffsetSliceBounds(opt, len(hosts))
|
|
|
|
hosts = hosts[low:high]
|
|
|
|
|
2016-09-30 01:19:51 +00:00
|
|
|
return hosts, nil
|
|
|
|
}
|
|
|
|
|
2016-11-16 13:47:49 +00:00
|
|
|
func (orm *Datastore) EnrollHost(uuid, hostname, ip, platform string, nodeKeySize int) (*kolide.Host, error) {
|
2016-09-30 01:19:51 +00:00
|
|
|
orm.mtx.Lock()
|
|
|
|
defer orm.mtx.Unlock()
|
|
|
|
|
|
|
|
if uuid == "" {
|
|
|
|
return nil, errors.New("missing uuid for host enrollment")
|
|
|
|
}
|
|
|
|
|
2016-10-05 00:17:55 +00:00
|
|
|
host := kolide.Host{
|
|
|
|
UUID: uuid,
|
|
|
|
HostName: hostname,
|
2016-10-06 00:10:44 +00:00
|
|
|
PrimaryIP: ip,
|
2016-10-05 00:17:55 +00:00
|
|
|
Platform: platform,
|
|
|
|
DetailUpdateTime: time.Unix(0, 0).Add(24 * time.Hour),
|
|
|
|
}
|
2016-09-30 01:19:51 +00:00
|
|
|
for _, h := range orm.hosts {
|
|
|
|
if h.UUID == uuid {
|
|
|
|
host = *h
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var err error
|
2016-11-16 13:47:49 +00:00
|
|
|
host.NodeKey, err = kolide.RandomText(nodeKeySize)
|
2016-09-30 01:19:51 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if hostname != "" {
|
|
|
|
host.HostName = hostname
|
|
|
|
}
|
|
|
|
if ip != "" {
|
2016-10-06 00:10:44 +00:00
|
|
|
host.PrimaryIP = ip
|
2016-09-30 01:19:51 +00:00
|
|
|
}
|
|
|
|
if platform != "" {
|
|
|
|
host.Platform = platform
|
|
|
|
}
|
|
|
|
|
|
|
|
if host.ID == 0 {
|
2016-10-14 16:15:04 +00:00
|
|
|
host.ID = orm.nextID(host)
|
2016-09-30 01:19:51 +00:00
|
|
|
}
|
|
|
|
orm.hosts[host.ID] = &host
|
|
|
|
|
|
|
|
return &host, nil
|
|
|
|
}
|
|
|
|
|
2016-11-16 13:47:49 +00:00
|
|
|
func (orm *Datastore) AuthenticateHost(nodeKey string) (*kolide.Host, error) {
|
2016-09-30 01:19:51 +00:00
|
|
|
orm.mtx.Lock()
|
|
|
|
defer orm.mtx.Unlock()
|
|
|
|
|
|
|
|
for _, host := range orm.hosts {
|
|
|
|
if host.NodeKey == nodeKey {
|
|
|
|
return host, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-16 13:47:49 +00:00
|
|
|
return nil, kolide_errors.ErrNotFound
|
2016-09-30 01:19:51 +00:00
|
|
|
}
|
|
|
|
|
2016-11-16 13:47:49 +00:00
|
|
|
func (orm *Datastore) MarkHostSeen(host *kolide.Host, t time.Time) error {
|
2016-09-30 01:19:51 +00:00
|
|
|
orm.mtx.Lock()
|
|
|
|
defer orm.mtx.Unlock()
|
|
|
|
|
|
|
|
host.UpdatedAt = t
|
|
|
|
|
|
|
|
for _, h := range orm.hosts {
|
|
|
|
if h.ID == host.ID {
|
|
|
|
h.UpdatedAt = t
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
2016-11-02 14:59:53 +00:00
|
|
|
|
2016-11-16 13:47:49 +00:00
|
|
|
func (orm *Datastore) SearchHosts(query string, omit ...uint) ([]kolide.Host, error) {
|
2016-11-02 14:59:53 +00:00
|
|
|
omitLookup := map[uint]bool{}
|
|
|
|
for _, o := range omit {
|
|
|
|
omitLookup[o] = true
|
|
|
|
}
|
|
|
|
|
|
|
|
var results []kolide.Host
|
|
|
|
|
|
|
|
orm.mtx.Lock()
|
|
|
|
defer orm.mtx.Unlock()
|
|
|
|
|
|
|
|
for _, h := range orm.hosts {
|
|
|
|
if len(results) == 10 {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strings.Contains(h.HostName, query) || strings.Contains(h.PrimaryIP, query)) && !omitLookup[h.ID] {
|
|
|
|
results = append(results, *h)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return results, nil
|
|
|
|
}
|
2016-11-09 23:33:16 +00:00
|
|
|
|
2016-11-16 13:47:49 +00:00
|
|
|
func (orm *Datastore) DistributedQueriesForHost(host *kolide.Host) (map[uint]string, error) {
|
2016-11-09 23:33:16 +00:00
|
|
|
// lookup of executions for this host
|
|
|
|
hostExecutions := map[uint]kolide.DistributedQueryExecutionStatus{}
|
|
|
|
for _, e := range orm.distributedQueryExecutions {
|
|
|
|
if e.HostID == host.ID {
|
|
|
|
hostExecutions[e.DistributedQueryCampaignID] = e.Status
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// lookup of labels for this host (only including matching labels)
|
|
|
|
hostLabels := map[uint]bool{}
|
|
|
|
labels, err := orm.ListLabelsForHost(host.ID)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
for _, l := range labels {
|
|
|
|
hostLabels[l.ID] = true
|
|
|
|
}
|
|
|
|
|
|
|
|
queries := map[uint]string{} // map campaign ID -> query string
|
|
|
|
for _, campaign := range orm.distributedQueryCampaigns {
|
|
|
|
if campaign.Status != kolide.QueryRunning {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
for _, target := range orm.distributedQueryCampaignTargets {
|
|
|
|
if campaign.ID == target.DistributedQueryCampaignID &&
|
|
|
|
((target.Type == kolide.TargetHost && target.TargetID == host.ID) ||
|
|
|
|
(target.Type == kolide.TargetLabel && hostLabels[target.TargetID])) &&
|
|
|
|
(hostExecutions[campaign.ID] == kolide.ExecutionWaiting) {
|
|
|
|
queries[campaign.ID] = orm.queries[campaign.QueryID].Query
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return queries, nil
|
|
|
|
}
|