nodes

package
v0.5.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 12, 2026 License: MIT Imports: 7 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// ActiveNodes to represent active nodes
	ActiveNodes = "active"
	// InactiveNodes to represent inactive nodes
	InactiveNodes = "inactive"
	// AllNodes to represent all nodes
	AllNodes = "all"
	// EnvSelector to represent environment selector
	EnvironmentSelector = "environment"
	// PlatformSelector to represent platform selector
	PlatformSelector = "platform"
)

Variables

View Source
var SortableColumns = map[string]string{
	"uuid":      "uuid",
	"hostname":  "hostname",
	"localname": "localname",
	"ip":        "ip_address",
	"platform":  "platform",
	"version":   "platform_version",
	"osquery":   "osquery_version",
	"lastseen":  "last_seen",
	"firstseen": "created_at",
}

SortableColumns is the closed set of columns that may be ordered by external callers. Enforced in GetByEnvPaged so the allowlist is part of the data layer, not just the HTTP handler. Resolves audit finding U-DB-1.

Functions

func ActiveTimeCutoff added in v0.4.5

func ActiveTimeCutoff(hours int64) time.Time

ActiveTimeCutoff returns the cutoff time for active nodes based on the specified number of hours

func ApplyNodeTarget added in v0.4.5

func ApplyNodeTarget(query *gorm.DB, target string, hours int64) *gorm.DB

ApplyNodeTarget adds the appropriate query constraints for the target node status (active, inactive, all) to the provided gorm query. Default is all nodes.

func IsActive

func IsActive(n OsqueryNode, inactive int64) bool

IsActive determines if a node is active based on when it was last seen. The inactive parameter specifies the number of hours a node can be without checking in before it's considered inactive. This number is expected positive. Returns true if the node has checked in within the specified timeframe.

Types

type ArchiveOsqueryNode

type ArchiveOsqueryNode struct {
	ID              uint           `gorm:"primarykey" json:"id"`
	CreatedAt       time.Time      `json:"created_at"`
	UpdatedAt       time.Time      `json:"updated_at"`
	DeletedAt       gorm.DeletedAt `gorm:"index" json:"-"`
	NodeKey         string         `gorm:"index" json:"-"`
	UUID            string         `gorm:"index" json:"uuid"`
	Trigger         string         `json:"trigger"`
	Platform        string         `json:"platform"`
	PlatformVersion string         `json:"platform_version"`
	OsqueryVersion  string         `json:"osquery_version"`
	Hostname        string         `json:"hostname"`
	Localname       string         `json:"localname"`
	IPAddress       string         `json:"ip_address"`
	Username        string         `json:"username"`
	OsqueryUser     string         `json:"osquery_user"`
	Environment     string         `json:"environment"`
	CPU             string         `json:"cpu"`
	Memory          string         `json:"memory"`
	HardwareSerial  string         `json:"hardware_serial"`
	ConfigHash      string         `json:"config_hash"`
	DaemonHash      string         `json:"daemon_hash"`
	BytesReceived   int            `json:"bytes_received"`
	RawEnrollment   string         `json:"-"`
	LastSeen        time.Time      `json:"last_seen"`
	UserID          uint           `json:"user_id"`
	EnvironmentID   uint           `json:"environment_id"`
	ExtraData       string         `json:"extra_data"`
}

ArchiveOsqueryNode as abstraction of an archived node

type NodeCache added in v0.4.5

type NodeCache struct {
	// contains filtered or unexported fields
}

NodeCache provides cached access to OsqueryNode objects

func NewNodeCache added in v0.4.5

func NewNodeCache(nodes *NodeManager) *NodeCache

NewNodeCache creates a new node cache

func (*NodeCache) Close added in v0.4.5

func (nc *NodeCache) Close()

Close stops the cleanup goroutine and releases resources

func (*NodeCache) GetByKey added in v0.4.5

func (nc *NodeCache) GetByKey(ctx context.Context, nodeKey string) (OsqueryNode, error)

GetByKey retrieves a node by node_key, using cache when available

func (*NodeCache) InvalidateAll added in v0.4.5

func (nc *NodeCache) InvalidateAll(ctx context.Context)

InvalidateAll clears the entire cache

func (*NodeCache) InvalidateNode added in v0.4.5

func (nc *NodeCache) InvalidateNode(ctx context.Context, nodeKey string)

InvalidateNode removes a specific node from the cache

func (*NodeCache) UpdateNodeInCache added in v0.4.5

func (nc *NodeCache) UpdateNodeInCache(ctx context.Context, node OsqueryNode)

UpdateNodeInCache updates a node in the cache

type NodeManager

type NodeManager struct {
	DB    *gorm.DB
	Cache *NodeCache
}

NodeManager to handle all nodes of the system

func CreateNodes

func CreateNodes(backend *gorm.DB) *NodeManager

CreateNodes to initialize the nodes struct and its tables

func (*NodeManager) Archive

func (n *NodeManager) Archive(uuid, trigger string) error

Archive to archive osquery node by UUID

func (*NodeManager) ArchiveDeleteByUUID

func (n *NodeManager) ArchiveDeleteByUUID(uuid string) error

ArchiveDeleteByUUID to archive and delete an existing node record by UUID

func (*NodeManager) CheckByHost

func (n *NodeManager) CheckByHost(host string) bool

CheckByHost to check if node exists by Hostname

func (*NodeManager) CheckByUUID

func (n *NodeManager) CheckByUUID(uuid string) bool

CheckByUUID to check if node exists by UUID UUID is expected uppercase

func (*NodeManager) CheckByUUIDEnv

func (n *NodeManager) CheckByUUIDEnv(uuid, environment string) bool

CheckByUUIDEnv to check if node exists by UUID in a specific environment UUID is expected uppercase

func (*NodeManager) CountAll added in v0.4.8

func (n *NodeManager) CountAll() (int64, error)

CountAll to count all nodes

func (*NodeManager) CountAllByEnv added in v0.4.8

func (n *NodeManager) CountAllByEnv(envID uint) (int64, error)

CountAllByEnv to count all nodes

func (*NodeManager) CountByEnvTarget added in v0.4.8

func (n *NodeManager) CountByEnvTarget(env string, target string, hours int64) (int64, error)

CountByEnvTarget counts nodes for an environment after applying target (active/inactive/all)

func (*NodeManager) CountSearchByEnv added in v0.4.8

func (n *NodeManager) CountSearchByEnv(env, term, target string, hours int64) (int64, error)

CountSearchByEnv counts matching nodes for a search term with target filters

func (*NodeManager) Create

func (n *NodeManager) Create(node *OsqueryNode) error

Create to insert new osquery node generating new node_key

func (*NodeManager) GetAllPlatforms

func (n *NodeManager) GetAllPlatforms() ([]string, error)

GetAllPlatforms to get all different platform with nodes in them

func (*NodeManager) GetByEnv

func (n *NodeManager) GetByEnv(env, target string, hours int64) ([]OsqueryNode, error)

GetByEnv to retrieve target nodes by environment

func (*NodeManager) GetByEnvPage deprecated added in v0.4.8

func (n *NodeManager) GetByEnvPage(env, target string, hours int64, offset, limit int, orderBy string, desc bool) ([]OsqueryNode, error)

Deprecated: prefer GetByEnvPaged which applies the column allowlist at the package layer and unifies search, paging, and sorting into a single call. Retained for the legacy admin UI's callers in cmd/admin/handlers/json-nodes.go; the orderBy parameter is gated by SortableColumns so an unknown column silently falls back to `last_seen DESC` rather than interpolating into SQL.

func (*NodeManager) GetByEnvPaged added in v0.5.2

func (n *NodeManager) GetByEnvPaged(env, target string, hours int64, search string, page, pageSize int, sortColumn string, desc bool, platformBucket string) (NodesPage, error)

GetByEnvPaged returns a page of nodes for an environment, applying the target filter (all / active / inactive), optional search, optional sort, and the optional platform bucket filter ("linux" / "darwin" / "windows" / "other"). The sort column is validated against SortableColumns; unknown columns fall back to last_seen DESC. This is the single canonical paginated reader.

page is 1-indexed. pageSize is clamped to [1, 500] with default 50. platformBucket is one of the buckets normalizePlatformBucket recognises; an empty string disables the filter. Unknown buckets also disable it (so the caller can pass user input directly without input-validation boilerplate).

func (*NodeManager) GetByIdentifier

func (n *NodeManager) GetByIdentifier(identifier string) (OsqueryNode, error)

GetByIdentifier to retrieve full node object from DB, by uuid or hostname or localname UUID is expected uppercase

func (*NodeManager) GetByIdentifierEnv added in v0.4.7

func (n *NodeManager) GetByIdentifierEnv(identifier string, envid uint) (OsqueryNode, error)

GetByIdentifierEnv to retrieve full node object from DB, by uuid or hostname or localname UUID is expected uppercase

func (*NodeManager) GetByKey

func (n *NodeManager) GetByKey(nodekey string) (OsqueryNode, error)

GetByKey to retrieve full node object from DB or cache, by node_key node_key is expected lowercase

func (*NodeManager) GetByPlatform

func (n *NodeManager) GetByPlatform(envID uint, platform, target string, hours int64) ([]OsqueryNode, error)

GetByPlatform to retrieve target nodes by platform

func (*NodeManager) GetBySelector

func (n *NodeManager) GetBySelector(stype, selector, target string, hours int64) ([]OsqueryNode, error)

GetBySelector to retrieve target nodes by selector

func (*NodeManager) GetByUUID

func (n *NodeManager) GetByUUID(uuid string) (OsqueryNode, error)

GetByUUID to retrieve full node object from DB, by uuid UUID is expected uppercase

func (*NodeManager) GetByUUIDEnv

func (n *NodeManager) GetByUUIDEnv(uuid string, envid uint) (OsqueryNode, error)

GetByUUIDEnv to retrieve full node object from DB, by uuid and environment ID UUID is expected uppercase

func (*NodeManager) GetEnvIDPlatforms added in v0.4.7

func (n *NodeManager) GetEnvIDPlatforms(envID uint) ([]string, error)

GetEnvIDPlatforms to get the platforms with nodes in them by environment

func (*NodeManager) GetEnvPlatforms

func (n *NodeManager) GetEnvPlatforms(environment string) ([]string, error)

GetEnvPlatforms to get the platforms with nodes in them by environment

func (*NodeManager) GetOsqueryVersionCounts added in v0.5.2

func (n *NodeManager) GetOsqueryVersionCounts() ([]OsqueryVersionCount, error)

GetOsqueryVersionCounts wrapper.

func (*NodeManager) GetPlatformCountsByEnv added in v0.5.2

func (n *NodeManager) GetPlatformCountsByEnv(environment string) (PlatformCounts, error)

GetPlatformCountsByEnv exposes the package-level helper through NodeManager so handlers don't reach into n.DB directly.

func (*NodeManager) GetStatsByEnv

func (n *NodeManager) GetStatsByEnv(environment string, hours int64) (StatsData, error)

GetStatsByEnv to populate table stats about nodes by environment

func (*NodeManager) Gets

func (n *NodeManager) Gets(target string, hours int64) ([]OsqueryNode, error)

Gets to retrieve all/active/inactive nodes

func (*NodeManager) IncreaseBytes

func (n *NodeManager) IncreaseBytes(node OsqueryNode, incBytes int) error

IncreaseBytes to update received bytes per node

func (*NodeManager) MetadataRefresh

func (n *NodeManager) MetadataRefresh(node OsqueryNode, updates map[string]interface{}) error

MetadataRefresh to perform all needed update operations per node to keep metadata refreshed

func (*NodeManager) NewHistoryEntry

func (n *NodeManager) NewHistoryEntry(entry interface{}) error

NewHistoryEntry to insert new entry for the history of Hostnames

func (*NodeManager) RefreshLastSeenBatch added in v0.4.4

func (n *NodeManager) RefreshLastSeenBatch(nodeID []uint) error

func (*NodeManager) SearchByEnv added in v0.4.8

func (n *NodeManager) SearchByEnv(env, term, target string, hours int64) ([]OsqueryNode, error)

SearchByEnv to search nodes by environment and search term

func (*NodeManager) SearchByEnvPage deprecated added in v0.4.8

func (n *NodeManager) SearchByEnvPage(env, term, target string, hours int64, offset, limit int, orderBy string, desc bool) ([]OsqueryNode, error)

Deprecated: prefer GetByEnvPaged. Same orderBy hardening as GetByEnvPage.

func (*NodeManager) SearchByField added in v0.4.8

func (n *NodeManager) SearchByField(fieldType, term, target string, hours int64, limit int) ([]OsqueryNode, error)

SearchByField searches nodes by a specific field (uuid, hostname or localname) with pagination fieldType must be one of: "uuid", "hostname", "localname"

func (*NodeManager) UpdateByUUID

func (n *NodeManager) UpdateByUUID(data OsqueryNode, uuid string) error

UpdateByUUID to update an existing node record by UUID

func (*NodeManager) UpdateIP added in v0.4.4

func (n *NodeManager) UpdateIP(nodeID uint, ip string) error

func (*NodeManager) UpdateMetadataByUUID

func (n *NodeManager) UpdateMetadataByUUID(uuid string, metadata NodeMetadata) error

UpdateMetadataByUUID to update node metadata by UUID

type NodeMetadata

type NodeMetadata struct {
	IPAddress       string
	Username        string
	OsqueryUser     string
	Hostname        string
	Localname       string
	ConfigHash      string
	DaemonHash      string
	OsqueryVersion  string
	Platform        string
	PlatformVersion string
	BytesReceived   int
}

NodeMetadata to hold metadata for a node

type NodesPage added in v0.5.2

type NodesPage struct {
	Items      []OsqueryNode
	TotalItems int64
}

NodesPage is the canonical paginated-list result for nodes.

type OsqueryNode

type OsqueryNode struct {
	ID              uint           `gorm:"primarykey" json:"id"`
	CreatedAt       time.Time      `json:"created_at"`
	UpdatedAt       time.Time      `json:"updated_at"`
	DeletedAt       gorm.DeletedAt `gorm:"index" json:"-"`
	NodeKey         string         `gorm:"index" json:"-"`
	UUID            string         `gorm:"index" json:"uuid"`
	Platform        string         `json:"platform"`
	PlatformVersion string         `json:"platform_version"`
	OsqueryVersion  string         `json:"osquery_version"`
	Hostname        string         `json:"hostname"`
	Localname       string         `json:"localname"`
	IPAddress       string         `json:"ip_address"`
	Username        string         `json:"username"`
	OsqueryUser     string         `json:"osquery_user"`
	Environment     string         `json:"environment"`
	CPU             string         `json:"cpu"`
	Memory          string         `json:"memory"`
	HardwareSerial  string         `json:"hardware_serial"`
	DaemonHash      string         `json:"daemon_hash"`
	ConfigHash      string         `json:"config_hash"`
	BytesReceived   int            `json:"bytes_received"`
	RawEnrollment   string         `json:"-"`
	LastSeen        time.Time      `json:"last_seen"`
	UserID          uint           `json:"user_id"`
	EnvironmentID   uint           `json:"environment_id"`
	ExtraData       string         `json:"extra_data"`
}

OsqueryNode as abstraction of a node

type OsqueryVersionCount added in v0.5.2

type OsqueryVersionCount struct {
	Version string `json:"version"`
	Count   int64  `json:"count"`
}

OsqueryVersionCount is one row of the osquery-versions breakdown. Used by the dashboard's "agent fleet hygiene" panel to spot stale agents.

func GetOsqueryVersionCounts added in v0.5.2

func GetOsqueryVersionCounts(db *gorm.DB) ([]OsqueryVersionCount, error)

GetOsqueryVersionCounts returns the per-version node counts across every environment the caller's already filtered down to (no env arg — the dashboard renders fleet-wide; if a per-env variant is wanted later it lives next to this one). Sorted by count DESC so the most-common version sits first. One GROUP BY query.

type PlatformCounts added in v0.5.2

type PlatformCounts struct {
	Linux   int64 `json:"linux"`
	Darwin  int64 `json:"darwin"`
	Windows int64 `json:"windows"`
	Other   int64 `json:"other"`
}

PlatformCounts buckets nodes by `platform` value. Three families are normalized into the canonical osquery-side names; everything else lands in Other. The buckets mirror what the SPA's Nodes-table QuickFilters chip row shows ([Linux] [Windows] [macOS] [Other]).

func GetPlatformCountsByEnv added in v0.5.2

func GetPlatformCountsByEnv(db *gorm.DB, environment string) (PlatformCounts, error)

GetPlatformCountsByEnv returns the per-platform node counts for one env. One GROUP BY `platform` query, then we bucket the rows in Go because osquery agents report `kali`, `ubuntu`, `centos`, etc. — all of which collapse into the `linux` bucket. Doing the mapping client-side keeps the SQL portable and easy to extend.

Counts include both active and inactive nodes — that's the right shape for a "this env runs 12 Linux boxes" filter chip; "how many of those are active right now" lives on StatsData and is rendered separately.

type StatsData

type StatsData struct {
	Total    int64 `json:"total"`
	Active   int64 `json:"active"`
	Inactive int64 `json:"inactive"`
}

StatsData to display node stats

func GetStats added in v0.4.5

func GetStats(db *gorm.DB, column, value string, hours int64) (StatsData, error)

GetStats retrieves node statistics (total, active, inactive) for the given filter condition

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL