Documentation
¶
Index ¶
- Constants
- Variables
- func AgentTokenExists(ctx context.Context, s KVStore, agentID string) (bool, error)
- func GenerateAPIKey() (string, error)
- func GenerateAgentToken() (string, error)
- func GetRootKeyRef(ctx context.Context, s KVStore) (string, error)
- func HasAgentToken(ctx context.Context, s KVStore, agentID string) bool
- func IsBootstrapped(ctx context.Context, s KVStore) bool
- func MarkBootstrapped(ctx context.Context, s KVStore) error
- func NormalizeAPIKeyScopes(scopes []string) ([]string, error)
- func RevokeAPIKey(ctx context.Context, s KVStore, keyID string) error
- func StoreAgentToken(ctx context.Context, s KVStore, agentID, token string) error
- func StoreAgentTokenIfAbsent(ctx context.Context, s KVStore, agentID, token string) (bool, error)
- func StoreRootKeyRef(ctx context.Context, s KVStore, rawKey string) error
- type APIKeyMeta
- func EnsureAPIKey(ctx context.Context, s KVStore, rawKey, label, createdBy string) (APIKeyMeta, error)
- func ListAPIKeys(ctx context.Context, s KVStore) ([]APIKeyMeta, error)
- func StoreAPIKey(ctx context.Context, s KVStore, rawKey, label, createdBy string) (APIKeyMeta, error)
- func StoreAPIKeyWithScopes(ctx context.Context, s KVStore, rawKey, label, createdBy string, ...) (APIKeyMeta, error)
- func ValidateAPIKey(ctx context.Context, s KVStore, rawKey string) (APIKeyMeta, error)
- type AgentTokenMeta
- type AtomicValueUpdater
- type HostEntry
- type HostVulnerabilityStat
- type KVStore
- type ScanResult
- type SnapshotMetadata
- type SubScan
- type SubScanProgress
- type ValkeyResponse
- type ValkeyValue
- type ValueCompareAndSetter
- type ValueCreator
- type VulnerabilityCounts
- type VulnerabilitySnapshot
- type VulnerabilitySummary
Constants ¶
const (
// APIKeyPrefix is prepended to all generated API keys for easy identification.
APIKeyPrefix = "sk_"
)
const (
SIRIUS_VALKEY = "sirius-valkey:6379"
)
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 ¶
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
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
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
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
GetRootKeyRef retrieves the raw root key stored during bootstrap.
func HasAgentToken ¶ added in v0.0.15
HasAgentToken conservatively treats failed reads as an existing token. Deprecated: use AgentTokenExists to handle unavailable storage explicitly.
func IsBootstrapped ¶ added in v0.0.15
IsBootstrapped returns true if a root key has already been generated.
func MarkBootstrapped ¶ added in v0.0.15
MarkBootstrapped sets the bootstrap flag so that a root key is not regenerated on subsequent startups.
func NormalizeAPIKeyScopes ¶ added in v0.0.20
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
RevokeAPIKey deletes an API key by its hash ID.
func StoreAgentToken ¶ added in v0.0.15
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
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.
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
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"`
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
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 ¶
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"`
}