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
2 changes: 1 addition & 1 deletion cmd/admin/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ func osctrlAdminService() {
log.Info().Msg("Initialize settings")
settingsmgr = settings.NewSettings(db.Conn)
log.Info().Msg("Initialize nodes")
nodesmgr = nodes.CreateNodes(db.Conn, redis.Client)
nodesmgr = nodes.CreateNodes(db.Conn)
log.Info().Msg("Initialize queries")
queriesmgr = queries.CreateQueries(db.Conn)
log.Info().Msg("Initialize carves")
Expand Down
2 changes: 1 addition & 1 deletion cmd/api/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ func osctrlAPIService() {
log.Info().Msg("Initialize settings")
settingsmgr = settings.NewSettings(db.Conn)
log.Info().Msg("Initialize nodes")
nodesmgr = nodes.CreateNodes(db.Conn, redis.Client)
nodesmgr = nodes.CreateNodes(db.Conn)
log.Info().Msg("Initialize queries")
queriesmgr = queries.CreateQueries(db.Conn)
log.Info().Msg("Initialize carves")
Expand Down
2 changes: 1 addition & 1 deletion cmd/cli/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -1800,7 +1800,7 @@ func cliWrapper(action func(*cli.Context) error) func(*cli.Context) error {
// Initialize settings
settingsmgr = settings.NewSettings(db.Conn)
// Initialize nodes
nodesmgr = nodes.CreateNodes(db.Conn, nil)
nodesmgr = nodes.CreateNodes(db.Conn)
// Initialize queries
queriesmgr = queries.CreateQueries(db.Conn)
// Initialize carves
Expand Down
2 changes: 1 addition & 1 deletion cmd/tls/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ func osctrlService() {
log.Info().Msg("Initialize settings")
settingsmgr = settings.NewSettings(db.Conn)
log.Info().Msg("Initialize nodes")
nodesmgr = nodes.CreateNodes(db.Conn, redis.Client)
nodesmgr = nodes.CreateNodes(db.Conn)
log.Info().Msg("Initialize tags")
tagsmgr = tags.CreateTagManager(db.Conn)
log.Info().Msg("Initialize queries")
Expand Down
8 changes: 0 additions & 8 deletions pkg/cache/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"fmt"

redis "github.com/go-redis/redis/v8"
"github.com/jmpsec/osctrl/pkg/types"

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed the dependency for types pkg. I think the redis instance has never been used in the code. But let's keep them for now.

"github.com/spf13/viper"
)

Expand All @@ -30,13 +29,6 @@ type JSONConfigurationRedis struct {
ConnRetry int `json:"connRetry"`
}

// CachedQueryWriteData to store in cache query logs
type CachedQueryWriteData struct {
UnixTime int `json:"unixTime"`
HostIdentifier string `json:"hostIdentifier"`
QueryData types.QueryWriteData
}

// LoadConfiguration to load the redis configuration file and assign to variables
func LoadConfiguration(file, key string) (JSONConfigurationRedis, error) {
var config JSONConfigurationRedis
Expand Down
139 changes: 0 additions & 139 deletions pkg/nodes/cache.go

This file was deleted.

16 changes: 0 additions & 16 deletions pkg/nodes/metadata.go

This file was deleted.

77 changes: 77 additions & 0 deletions pkg/nodes/models.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package nodes

import (
"time"

"gorm.io/gorm"
)

// OsqueryNode as abstraction of a node
type OsqueryNode struct {
gorm.Model
NodeKey string `gorm:"index"`
UUID string `gorm:"index"`
Platform string
PlatformVersion string
OsqueryVersion string
Hostname string
Localname string
IPAddress string
Username string
OsqueryUser string
Environment string
CPU string
Memory string
HardwareSerial string
DaemonHash string
ConfigHash string
BytesReceived int
RawEnrollment string
LastSeen time.Time
UserID uint
EnvironmentID uint
ExtraData string
}

// ArchiveOsqueryNode as abstraction of an archived node
type ArchiveOsqueryNode struct {
gorm.Model
NodeKey string `gorm:"index"`
UUID string `gorm:"index"`
Trigger string
Platform string
PlatformVersion string
OsqueryVersion string
Hostname string
Localname string
IPAddress string
Username string
OsqueryUser string
Environment string
CPU string
Memory string
HardwareSerial string
ConfigHash string
DaemonHash string
BytesReceived int
RawEnrollment string
LastSeen time.Time
UserID uint
EnvironmentID uint
ExtraData string
}

// NodeMetadata to hold metadata for a node
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
}
80 changes: 80 additions & 0 deletions pkg/nodes/node-cache.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package nodes

import (
"context"
"time"

"github.com/jmpsec/osctrl/pkg/cache"
)

const (
cacheName = "nodes"
// Default time-to-live for cached nodes
defaultTTL = 60 * time.Minute
// Default cleanup interval for the cache
defaultCleanupInterval = 30 * time.Minute
)

// NodeCache provides cached access to OsqueryNode objects
type NodeCache struct {
// The cache itself, storing OsqueryNode objects
cache *cache.MemoryCache[OsqueryNode]

// Reference to the node manager for cache misses
nodes *NodeManager
}

// NewNodeCache creates a new node cache
func NewNodeCache(nodes *NodeManager) *NodeCache {
// Create a new cache with appropriate cleanup interval
nodeCache := cache.NewMemoryCache(
cache.WithCleanupInterval[OsqueryNode](defaultCleanupInterval),
cache.WithName[OsqueryNode](cacheName),
)

return &NodeCache{
cache: nodeCache,
nodes: nodes,
}
}

// GetByKey retrieves a node by node_key, using cache when available
func (nc *NodeCache) GetByKey(ctx context.Context, nodeKey string) (OsqueryNode, error) {
// Try to get from cache first
if node, found := nc.cache.Get(ctx, nodeKey); found {
return node, nil
}

// Not in cache, fetch from database
node, err := nc.nodes.getByKeyFromDB(nodeKey)
if err != nil {
return OsqueryNode{}, err
}

// Store in cache for future requests
nc.cache.Set(ctx, nodeKey, node, defaultTTL)

return node, nil
}

// InvalidateNode removes a specific node from the cache
func (nc *NodeCache) InvalidateNode(ctx context.Context, nodeKey string) {
nc.cache.Delete(ctx, nodeKey)
}

// InvalidateAll clears the entire cache
func (nc *NodeCache) InvalidateAll(ctx context.Context) {
nc.cache.Clear(ctx)
}

// UpdateNodeInCache updates a node in the cache
func (nc *NodeCache) UpdateNodeInCache(ctx context.Context, node OsqueryNode) {
nc.cache.Set(ctx, node.NodeKey, node, defaultTTL)
}

// Close stops the cleanup goroutine and releases resources
func (nc *NodeCache) Close() {
if nc.cache != nil {
nc.cache.Stop()
}
}
Loading