store

package
v0.0.28 Latest Latest
Warning

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

Go to latest
Published: Nov 11, 2026 License: MIT Imports: 13 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// APIKeyPrefix is prepended to all generated API keys for easy identification.
	APIKeyPrefix = "sk_"
)
View Source
const (
	SIRIUS_VALKEY = "sirius-valkey:6379"
)
View Source
const ScopeMCPRead = "mcp:read"

ScopeMCPRead is the only scope currently granted to dedicated MCP readers. It authorizes an exact GET allow-list enforced by sirius-api; it never grants key management, writes, or generic store/queue/log/admin access.

Variables

View Source
var ErrKeyNotFound = errors.New("key not found")

ErrKeyNotFound identifies a missing key, rather than a failed store read.

Functions

func AgentTokenExists added in v0.0.20

func AgentTokenExists(ctx context.Context, s KVStore, agentID string) (bool, error)

AgentTokenExists distinguishes confirmed absence from a failed store read. Any stored value, including malformed metadata, reserves the agent ID.

func GenerateAPIKey added in v0.0.15

func GenerateAPIKey() (string, error)

GenerateAPIKey creates a cryptographically random API key with the sk_ prefix. The returned string is the only time the raw key is available.

func GenerateAgentToken added in v0.0.15

func GenerateAgentToken() (string, error)

GenerateAgentToken creates a cryptographically random token string for an agent. The token is 32 random bytes hex-encoded (64 characters).

func GetRootKeyRef added in v0.0.15

func GetRootKeyRef(ctx context.Context, s KVStore) (string, error)

GetRootKeyRef retrieves the raw root key stored during bootstrap.

func HasAgentToken added in v0.0.15

func HasAgentToken(ctx context.Context, s KVStore, agentID string) bool

HasAgentToken conservatively treats failed reads as an existing token. Deprecated: use AgentTokenExists to handle unavailable storage explicitly.

func IsBootstrapped added in v0.0.15

func IsBootstrapped(ctx context.Context, s KVStore) bool

IsBootstrapped returns true if a root key has already been generated.

func MarkBootstrapped added in v0.0.15

func MarkBootstrapped(ctx context.Context, s KVStore) error

MarkBootstrapped sets the bootstrap flag so that a root key is not regenerated on subsequent startups.

func NormalizeAPIKeyScopes added in v0.0.20

func NormalizeAPIKeyScopes(scopes []string) ([]string, error)

NormalizeAPIKeyScopes validates and canonicalizes a requested scope list. An empty list is valid and means "no scopes" (legacy full access) for callers that accept optional scopes, such as key creation. Any blank or unknown scope fails closed. Duplicates collapse to one entry; order follows first occurrence.

func RevokeAPIKey added in v0.0.15

func RevokeAPIKey(ctx context.Context, s KVStore, keyID string) error

RevokeAPIKey deletes an API key by its hash ID.

func StoreAgentToken added in v0.0.15

func StoreAgentToken(ctx context.Context, s KVStore, agentID, token string) error

StoreAgentToken explicitly replaces an agent token keyed by agent ID. Enrollment must use StoreAgentTokenIfAbsent to avoid replacing existing tokens.

func StoreAgentTokenIfAbsent added in v0.0.20

func StoreAgentTokenIfAbsent(ctx context.Context, s KVStore, agentID, token string) (bool, error)

StoreAgentTokenIfAbsent enrolls an agent atomically. Existing records are never overwritten, even if two callers have both just observed a missing key. Stores without atomic creation are rejected rather than using GET then SET.

func StoreAgentTokenWithMetadataIfAbsent added in v0.0.23

func StoreAgentTokenWithMetadataIfAbsent(ctx context.Context, s KVStore, meta AgentTokenMeta) (bool, error)

StoreAgentTokenWithMetadataIfAbsent atomically records optional neutral attribution.

func StoreRootKeyRef added in v0.0.15

func StoreRootKeyRef(ctx context.Context, s KVStore, rawKey string) error

StoreRootKeyRef stores the hash of the root key so the UI backend can read it from Valkey and use it for authenticated requests.

Types

type APIKeyMeta added in v0.0.15

type APIKeyMeta struct {
	ID         string   `json:"id"`               // SHA-256 hash of the raw key (also used as Valkey key suffix)
	Label      string   `json:"label"`            // Human-readable label
	Prefix     string   `json:"prefix"`           // First 8 characters of the raw key for display
	CreatedBy  string   `json:"created_by"`       // User or system that created the key
	CreatedAt  string   `json:"created_at"`       // RFC-3339 timestamp
	LastUsedAt string   `json:"last_used_at"`     // RFC-3339 timestamp, empty if never used
	Scopes     []string `json:"scopes,omitempty"` // Optional allow-list; empty preserves legacy full access
}

APIKeyMeta holds metadata about an API key. The raw key is never persisted.

Scopes is optional. A nil or empty slice means the key has no scope restriction and keeps the historical full-access semantics of keys created before scopes existed. A non-empty slice is an allow-list enforced by the API; unknown scope names are rejected at creation time and fail closed if they are ever persisted.

func EnsureAPIKey added in v0.0.15

func EnsureAPIKey(ctx context.Context, s KVStore, rawKey, label, createdBy string) (APIKeyMeta, error)

EnsureAPIKey returns existing metadata unchanged, or atomically creates an unrestricted legacy key after confirmed absence. Creation requires ValueCreator. Failed reads and malformed records fail closed. A concurrent creation wins; its metadata is reread rather than overwritten. Errors may have an uncertain outcome and must not be treated as confirmed absence.

func ListAPIKeys added in v0.0.15

func ListAPIKeys(ctx context.Context, s KVStore) ([]APIKeyMeta, error)

ListAPIKeys returns metadata for every API key stored in Valkey.

func StoreAPIKey added in v0.0.15

func StoreAPIKey(ctx context.Context, s KVStore, rawKey, label, createdBy string) (APIKeyMeta, error)

StoreAPIKey persists an unrestricted (legacy full-access) API key. The raw key is hashed and used as the lookup key; the raw key itself is never stored. Existing callers keep pre-scope semantics. Scoped keys must use StoreAPIKeyWithScopes.

func StoreAPIKeyWithScopes added in v0.0.20

func StoreAPIKeyWithScopes(ctx context.Context, s KVStore, rawKey, label, createdBy string, scopes []string) (APIKeyMeta, error)

StoreAPIKeyWithScopes persists API key metadata restricted to scopes. scopes must be non-empty and every entry must be a known scope; unknown or blank values fail closed and nothing is written. A nil or empty slice is rejected — use StoreAPIKey for legacy unrestricted keys so an accidental empty scope list cannot be confused with a scoped key.

func ValidateAPIKey added in v0.0.15

func ValidateAPIKey(ctx context.Context, s KVStore, rawKey string) (APIKeyMeta, error)

ValidateAPIKey checks whether the given raw key exists in Valkey. If valid it returns the associated metadata with a current LastUsedAt timestamp. Persisting that timestamp is best-effort and requires atomic compare-and-set support. Scope enforcement is the caller's responsibility; this function only loads the persisted metadata, including any scopes.

func (APIKeyMeta) AllowsUnrestricted added in v0.0.20

func (m APIKeyMeta) AllowsUnrestricted() bool

AllowsUnrestricted reports whether meta has no scope restriction. Nil and empty scopes preserve pre-scope full-access semantics.

func (APIKeyMeta) HasScope added in v0.0.20

func (m APIKeyMeta) HasScope(scope string) bool

HasScope reports whether meta grants scope. Unrestricted keys do not implicitly match a named scope; callers that want legacy full access must check AllowsUnrestricted first.

A key that carries any unknown or blank scope fails closed entirely: it matches no scope, even one that is otherwise present. That stops a persisted scope list from being treated as a partial grant after it has been widened outside StoreAPIKeyWithScopes.

type AgentTokenMeta added in v0.0.15

type AgentTokenMeta struct {
	AgentID      string `json:"agent_id"`
	SubjectID    string `json:"subject_id,omitempty"`
	CredentialID string `json:"credential_id,omitempty"`
	Token        string `json:"token"`
	CreatedAt    string `json:"created_at"`
	LastSeen     string `json:"last_seen"`
}

AgentTokenMeta holds metadata for a per-agent authentication token.

func GetAgentToken added in v0.0.15

func GetAgentToken(ctx context.Context, s KVStore, agentID string) (AgentTokenMeta, error)

GetAgentToken retrieves the stored token metadata for an agent.

func ValidateAgentToken added in v0.0.15

func ValidateAgentToken(ctx context.Context, s KVStore, agentID, token string) (AgentTokenMeta, error)

ValidateAgentToken checks whether the provided token matches the one stored for the given agent ID. On success, it updates the LastSeen timestamp.

type AtomicValueUpdater added in v0.0.20

type AtomicValueUpdater interface {
	CompareAndSwapValues(ctx context.Context, expected map[string]*string, updates map[string]*string) (bool, error)
}

AtomicValueUpdater is an optional KVStore capability for an all-or-none batch. A nil expectation requires absence; a nonnil expectation matches exact bytes, including an empty value. A nil update deletes; a nonnil update sets a value while preserving its existing TTL. Every updated key must have an expectation. Extra expectations are read-only guards. False means a guard did not match. Callers must reread and revalidate on conflict. Errors, including cancellation, may have an uncertain outcome and must not be treated as a confirmed conflict. Clustered stores require all guarded keys to share a hash slot.

type HostEntry added in v0.0.14

type HostEntry struct {
	ID       string   `json:"id"`
	IP       string   `json:"ip"`
	Hostname string   `json:"hostname,omitempty"`
	Aliases  []string `json:"aliases,omitempty"`
	Sources  []string `json:"sources,omitempty"`
}

HostEntry represents a discovered host with canonical IP identity. Multiple scanners may discover the same host; entries are merged by IP.

type HostVulnerabilityStat added in v0.0.12

type HostVulnerabilityStat struct {
	HostIP        string `json:"host_ip"`
	Hostname      string `json:"hostname,omitempty"`
	Total         int    `json:"total"`
	Critical      int    `json:"critical"`
	High          int    `json:"high"`
	Medium        int    `json:"medium"`
	Low           int    `json:"low"`
	Informational int    `json:"informational"`
}

HostVulnerabilityStat represents vulnerability statistics for a specific host

type KVStore

type KVStore interface {
	// SetValue sets the given key to the specified value.
	SetValue(ctx context.Context, key, value string) error
	// SetValueWithTTL sets the given key to the specified value with a TTL in seconds.
	SetValueWithTTL(ctx context.Context, key, value string, ttlSeconds int) error
	// GetValue retrieves the value associated with the given key.
	// Missing keys must return an error wrapping ErrKeyNotFound.
	GetValue(ctx context.Context, key string) (ValkeyResponse, error)
	// GetTTL retrieves the remaining TTL in seconds for the given key.
	GetTTL(ctx context.Context, key string) (int, error)
	// SetExpire sets the TTL for an existing key in seconds.
	SetExpire(ctx context.Context, key string, ttlSeconds int) error
	// ListKeys retrieves all keys matching the given pattern.
	ListKeys(ctx context.Context, pattern string) ([]string, error)
	// DeleteValue removes the value associated with the given key.
	DeleteValue(ctx context.Context, key string) error
	// Close shuts down the underlying connection.
	Close() error
}

KVStore defines the key/value operations our store supports.

func NewValkeyStore

func NewValkeyStore() (KVStore, error)

NewValkeyStore uses the configured address, defaulting to sirius-valkey:6379.

type ScanResult

type ScanResult struct {
	ID              string                 `json:"id"`
	Status          string                 `json:"status"`
	Targets         []string               `json:"targets"`
	Hosts           []HostEntry            `json:"hosts"`
	HostsCompleted  int                    `json:"hosts_completed"`
	Vulnerabilities []VulnerabilitySummary `json:"vulnerabilities"`
	StartTime       string                 `json:"start_time"`
	EndTime         string                 `json:"end_time,omitempty"`
	SubScans        map[string]SubScan     `json:"sub_scans,omitempty"`
}

type SnapshotMetadata added in v0.0.12

type SnapshotMetadata struct {
	TotalHosts               int     `json:"total_hosts"`
	HostsWithVulnerabilities int     `json:"hosts_with_vulnerabilities"`
	ScanCoveragePercent      float64 `json:"scan_coverage_percent"`
	SnapshotDurationMs       int64   `json:"snapshot_duration_ms"`
}

SnapshotMetadata contains metadata about the snapshot

type SubScan added in v0.0.14

type SubScan struct {
	Type     string          `json:"type"`
	Enabled  bool            `json:"enabled"`
	Status   string          `json:"status"`
	Progress SubScanProgress `json:"progress"`
	Metadata json.RawMessage `json:"metadata,omitempty"`
}

SubScan represents a modular scanner contribution to a scan. Each scanner type (network, agent, cloud, etc.) gets its own entry. Metadata is stored as json.RawMessage so that scanners that don't understand another scanner's metadata will preserve it verbatim during read-modify-write cycles.

type SubScanProgress added in v0.0.14

type SubScanProgress struct {
	Completed int    `json:"completed"`
	Total     int    `json:"total"`
	Label     string `json:"label,omitempty"`
}

SubScanProgress tracks completion progress for a sub-scan.

type ValkeyResponse

type ValkeyResponse struct {
	Message ValkeyValue `json:"Message"`
	Type    string      `json:"Type"`
}

type ValkeyValue

type ValkeyValue struct {
	Value string `json:"Value"`
}

type ValueCompareAndSetter added in v0.0.20

type ValueCompareAndSetter interface {
	CompareAndSetValue(ctx context.Context, key, expected, value string) (bool, error)
}

ValueCompareAndSetter is an optional KVStore capability for conditional updates. Missing keys do not match, even when expected is the empty string. Callers must reread and revalidate after a false result, not blindly retry.

type ValueCreator added in v0.0.20

type ValueCreator interface {
	SetValueIfAbsent(ctx context.Context, key, value string) (bool, error)
}

ValueCreator is an optional atomic KVStore capability. False means the key already exists. Errors must never be interpreted as confirmed absence.

type VulnerabilityCounts added in v0.0.12

type VulnerabilityCounts struct {
	Total         int `json:"total"`
	Critical      int `json:"critical"`
	High          int `json:"high"`
	Medium        int `json:"medium"`
	Low           int `json:"low"`
	Informational int `json:"informational"`
}

VulnerabilityCounts represents the total counts of vulnerabilities by severity

type VulnerabilitySnapshot added in v0.0.12

type VulnerabilitySnapshot struct {
	SnapshotID string                  `json:"snapshot_id"` // YYYY-MM-DD format
	Timestamp  time.Time               `json:"timestamp"`
	Counts     VulnerabilityCounts     `json:"counts"`
	ByHost     []HostVulnerabilityStat `json:"by_host"`
	Metadata   SnapshotMetadata        `json:"metadata"`
}

VulnerabilitySnapshot represents a point-in-time vulnerability state

type VulnerabilitySummary

type VulnerabilitySummary struct {
	ID          string  `json:"id"`
	Severity    string  `json:"severity"`
	Title       string  `json:"title"`
	Description string  `json:"description"`
	CVSSScore   float64 `json:"cvss_score,omitempty"`
	RiskScore   float64 `json:"risk_score,omitempty"`
	ScanSource  string  `json:"scan_source,omitempty"`
	HostID      string  `json:"host_id,omitempty"`
	AgentID     string  `json:"agent_id,omitempty"`
}

Directories

Path Synopsis
Package templates is the single source of truth for the Valkey contracts that bind the scanner stack together.
Package templates is the single source of truth for the Valkey contracts that bind the scanner stack together.

Jump to

Keyboard shortcuts

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