Skip to content
Open
118 changes: 118 additions & 0 deletions api/v1beta1/datastores/interfaces.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package datastores

import "errors"

// Common errors for datastores
var (
ErrNotFound = errors.New("entity not found")
ErrStoreUnhealthy = errors.New("datastore is unhealthy")
ErrNotImplemented = errors.New("operation not implemented")
ErrInvalidArgument = errors.New("invalid argument")
)

// StoreError wraps an error with additional context about the store
type StoreError struct {
StoreName string
Operation string
Err error
}

func (e *StoreError) Error() string {
return e.StoreName + "." + e.Operation + ": " + e.Err.Error()
}

func (e *StoreError) Unwrap() error {
return e.Err
}

// DataStore is the base interface for all datastores
type DataStore interface {
// Name returns the name of this datastore
Name() string

// GetHealth returns the current health status of the datastore
GetHealth() *HealthInfo

// GetMetrics returns operational metrics for the datastore
GetMetrics() *DataStoreMetrics
}

// ProcessStore provides access to process information
type ProcessStore interface {
DataStore

// GetProcess retrieves process information by entity ID
// Returns nil, false if the process is not found
GetProcess(entityId uint64) (*ProcessInfo, bool)

// GetChildProcesses returns all child processes of the given process
// Returns empty slice if no children found
GetChildProcesses(entityId uint64) ([]*ProcessInfo, error)
}

// ContainerStore provides access to container information
type ContainerStore interface {
DataStore

// GetContainer retrieves container information by container ID
// Returns nil, false if the container is not found
GetContainer(id string) (*ContainerInfo, bool)

// GetContainerByName retrieves container information by container name
// Returns nil, false if no container with that name is found
GetContainerByName(name string) (*ContainerInfo, bool)
}

// KernelSymbolStore provides access to kernel symbol information
type KernelSymbolStore interface {
DataStore

// ResolveSymbolByAddress resolves a kernel address to symbol information
// Returns multiple symbols if aliases exist at the same address
// Returns ErrNotFound if the address cannot be resolved
ResolveSymbolByAddress(addr uint64) ([]*SymbolInfo, error)

// GetSymbolAddress returns the address of a named symbol
// If multiple symbols exist with the same name (in different modules),
// returns the address of the first one found.
// Returns ErrNotFound if the symbol is not found
GetSymbolAddress(name string) (uint64, error)

// ResolveSymbolsBatch resolves multiple addresses to symbols in one call
// Returns a map of address -> symbol info for found symbols
// Missing addresses are not included in the result map
ResolveSymbolsBatch(addrs []uint64) (map[uint64][]*SymbolInfo, error)
}

// DNSStore provides access to cached DNS query responses
type DNSStore interface {
DataStore

// GetDNSResponse retrieves cached DNS response for a query
// Returns nil, false if no cached response is found
GetDNSResponse(query string) (*DNSResponse, bool)
}

// SystemStore provides access to immutable system information
type SystemStore interface {
DataStore

// GetSystemInfo returns complete system information collected at startup
// This data is immutable and never changes during the Tracee process lifetime
GetSystemInfo() *SystemInfo
}

// SyscallStore provides access to syscall metadata for the current architecture
type SyscallStore interface {
DataStore

// GetSyscallName returns the syscall name for a given ID
// Returns empty string and false if the syscall ID is not found
// Note: Syscall IDs are architecture-specific (x86 vs ARM)
GetSyscallName(id int32) (string, bool)

// GetSyscallID returns the syscall ID for a given name
// Returns 0 and false if the syscall name is not found
// Note: Syscall IDs are architecture-specific (x86 vs ARM)
GetSyscallID(name string) (int32, bool)
}
40 changes: 40 additions & 0 deletions api/v1beta1/datastores/registry.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package datastores

// Registry provides unified access to all datastores
type Registry interface {
// Processes returns the process datastore
Processes() ProcessStore

// Containers returns the container datastore
Containers() ContainerStore

// KernelSymbols returns the kernel symbol datastore
KernelSymbols() KernelSymbolStore

// DNS returns the DNS cache datastore
DNS() DNSStore

// System returns the system information datastore
System() SystemStore

// Syscalls returns the syscall information datastore
Syscalls() SyscallStore

// GetCustom retrieves a custom datastore by name
// Returns ErrNotFound if the datastore is not registered
GetCustom(name string) (DataStore, error)

// List returns names of all registered datastores
List() []string

// IsAvailable checks if a datastore with the given name is available
IsAvailable(name string) bool

// GetMetadata returns metadata about a specific datastore
// Returns ErrNotFound if the datastore is not registered
GetMetadata(name string) (*DataStoreMetadata, error)

// GetMetrics returns metrics for a specific datastore
// Returns ErrNotFound if the datastore is not registered
GetMetrics(name string) (*DataStoreMetrics, error)
}
108 changes: 108 additions & 0 deletions api/v1beta1/datastores/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package datastores

import "time"

// ProcessInfo contains information about a process
type ProcessInfo struct {
EntityID uint64 // Primary key (hash from ProcessTree) - matches Event.Process.EntityId
PID uint32 // OS process ID (for display/logging)
PPID uint32 // OS parent PID (for display/logging)
Name string // Binary name only: "bash"
Exe string // Full path: "/usr/bin/bash"
StartTime time.Time // Process start time
UID uint32 // User ID
GID uint32 // Group ID
// Phase 2: CmdLine/Args (memory impact)
}

// ContainerInfo contains information about a container
type ContainerInfo struct {
ID string // Container ID
Name string // Container name
Image string // Container image
ImageDigest string // Image digest
Runtime string // Runtime (docker, containerd, crio)
StartTime time.Time // Container start time
Pod *K8sPodInfo // Kubernetes pod info (nil for non-K8s containers)
// Phase 2: Labels (requires runtime extraction), Status, PID, Env, Mounts
}

// K8sPodInfo contains Kubernetes pod metadata
type K8sPodInfo struct {
Name string // Pod name
UID string // Pod UID
Namespace string // Pod namespace
Sandbox bool // Whether this is a sandbox container
}

// SymbolInfo contains information about a kernel symbol
type SymbolInfo struct {
Name string // Symbol name
Address uint64 // Symbol address
Module string // Module name (or "system" for kernel symbols)
}

// DNSResponse contains DNS query response information
type DNSResponse struct {
Query string // DNS query (domain name)
IPs []string // Resolved IP addresses
Domains []string // Resolved domain names (for reverse lookups)
}

// HealthStatus represents the health state of a datastore
type HealthStatus int

const (
HealthUnknown HealthStatus = iota
HealthHealthy
HealthUnhealthy
)

func (h HealthStatus) String() string {
switch h {
case HealthHealthy:
return "healthy"
case HealthUnhealthy:
return "unhealthy"
default:
return "unknown"
}
}

// HealthInfo contains health information about a datastore
type HealthInfo struct {
Status HealthStatus // Current health status
Message string // Empty if healthy, error details if not
LastCheck time.Time // When health was last checked
}

// DataStoreMetrics contains metrics about datastore operations
type DataStoreMetrics struct {
ItemCount int64 // Number of items in store
SuccessCount uint64 // Number of successful requests
ErrorCount uint64 // Number of failed requests
CacheHits uint64 // Number of cache hits (if applicable)
CacheMisses uint64 // Number of cache misses (if applicable)
LastAccess time.Time // Last access time
}

// DataStoreMetadata contains metadata about a datastore
type DataStoreMetadata struct {
Name string // Human-readable name (e.g., "processes")
Description string // What this store provides
Config map[string]any // Store-specific configuration
}

// SystemInfo contains immutable system-level information collected at startup
type SystemInfo struct {
Architecture string // CPU architecture (e.g., "x86_64", "aarch64")
KernelRelease string // Kernel version (e.g., "5.15.0-generic")
Hostname string // System hostname
BootTime time.Time // System boot time
TraceeStartTime time.Time // Time when Tracee started
OSName string // OS name (e.g., "Ubuntu")
OSVersion string // OS version (e.g., "22.04")
OSPrettyName string // Human-readable full OS name (e.g., "Ubuntu 22.04 LTS")
TraceeVersion string // Tracee version string
InitNamespaces map[string]uint32 // Init process namespaces (cgroup, ipc, mnt, net, pid, etc.)
}
18 changes: 10 additions & 8 deletions pkg/datastores/container/containers.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"regexp"
"strings"
"sync"
"sync/atomic"
"syscall"
"time"
"unsafe"
Expand Down Expand Up @@ -40,13 +41,14 @@

// Manager contains information about running containers in the host.
type Manager struct {
cgroups *cgroup.Cgroups
cgroupsMap map[uint32]CgroupDir
containerMap map[string]Container
deleted []uint64
lock sync.RWMutex // protecting both cgroups and deleted fields
enricher runtime.Service
bpfMapName string
cgroups *cgroup.Cgroups
cgroupsMap map[uint32]CgroupDir
containerMap map[string]Container
deleted []uint64
lock sync.RWMutex // protecting both cgroups and deleted fields
enricher runtime.Service
bpfMapName string
lastAccessNano atomic.Int64 // last datastore access time (Unix nano)
}

// CgroupDir represents a cgroup dir (which may be a container cgroup dir).
Expand Down Expand Up @@ -575,7 +577,7 @@
return nil
}

func (c *Manager) GetContainer(containerId string) (Container, error) {
func (c *Manager) LookupContainer(containerId string) (Container, error) {

Check warning on line 580 in pkg/datastores/container/containers.go

View check run for this annotation

Codecov / codecov/patch

pkg/datastores/container/containers.go#L580

Added line #L580 was not covered by tests
c.lock.RLock()
defer c.lock.RUnlock()
cont, ok := c.containerMap[containerId]
Expand Down
Loading