mirror of
https://tangled.org/evan.jarrett.net/at-container-registry
synced 2026-09-21 01:34:16 +00:00
125 lines
4.3 KiB
Go
125 lines
4.3 KiB
Go
// Package config provides Viper-based configuration for the scanner service.
|
|
package config
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/spf13/viper"
|
|
|
|
"atcr.io/pkg/config"
|
|
)
|
|
|
|
// Config holds all scanner configuration.
|
|
type Config struct {
|
|
Version string `yaml:"version" comment:"Configuration format version."`
|
|
LogLevel string `yaml:"log_level" comment:"Log level: debug, info, warn, error."`
|
|
LogShipper config.LogShipperConfig `yaml:"log_shipper" comment:"Remote log shipping settings."`
|
|
Server ServerConfig `yaml:"server" comment:"Health endpoint settings."`
|
|
Hold HoldConfig `yaml:"hold" comment:"Hold service connection settings."`
|
|
Scanner ScannerConfig `yaml:"scanner" comment:"Worker pool settings."`
|
|
Vuln VulnConfig `yaml:"vuln" comment:"Vulnerability scanning (Grype) settings."`
|
|
}
|
|
|
|
// ServerConfig defines the health endpoint settings.
|
|
type ServerConfig struct {
|
|
// Listen address for the health endpoint.
|
|
Addr string `yaml:"addr" comment:"Listen address for the health endpoint, e.g. \":9090\"."`
|
|
}
|
|
|
|
// HoldConfig defines the hold service connection.
|
|
type HoldConfig struct {
|
|
// WebSocket URL of the hold service.
|
|
URL string `yaml:"url" comment:"WebSocket URL of the hold service (REQUIRED), e.g. \"ws://localhost:8080\"."`
|
|
|
|
// Shared secret for scanner authentication.
|
|
Secret string `yaml:"secret" comment:"Shared secret for scanner WebSocket auth (REQUIRED)."`
|
|
}
|
|
|
|
// ScannerConfig defines worker pool settings.
|
|
type ScannerConfig struct {
|
|
// Number of concurrent scan workers.
|
|
Workers int `yaml:"workers" comment:"Number of concurrent scan workers."`
|
|
|
|
// Maximum priority queue depth.
|
|
QueueSize int `yaml:"queue_size" comment:"Maximum priority queue depth."`
|
|
}
|
|
|
|
// VulnConfig defines vulnerability scanning settings.
|
|
type VulnConfig struct {
|
|
// Enable Grype vulnerability scanning.
|
|
Enabled bool `yaml:"enabled" comment:"Enable Grype vulnerability scanning."`
|
|
|
|
// Directory for the Grype vulnerability database.
|
|
DBPath string `yaml:"db_path" comment:"Directory for the Grype vulnerability database."`
|
|
|
|
// Directory for temporary layer extraction.
|
|
TmpDir string `yaml:"tmp_dir" comment:"Directory for temporary layer extraction."`
|
|
|
|
// Maximum total compressed image size in bytes. Images exceeding this are skipped. 0 = no limit.
|
|
MaxImageSize int64 `yaml:"max_image_size" comment:"Maximum total compressed image size in bytes. 0 = no limit. Default: 2 GiB."`
|
|
}
|
|
|
|
// setScannerDefaults registers all default values on the given Viper instance.
|
|
func setScannerDefaults(v *viper.Viper) {
|
|
v.SetDefault("version", "0.1")
|
|
v.SetDefault("log_level", "info")
|
|
|
|
// Server defaults
|
|
v.SetDefault("server.addr", ":9090")
|
|
|
|
// Hold defaults
|
|
v.SetDefault("hold.url", "")
|
|
v.SetDefault("hold.secret", "")
|
|
|
|
// Scanner defaults
|
|
v.SetDefault("scanner.workers", 1)
|
|
v.SetDefault("scanner.queue_size", 100)
|
|
|
|
// Vuln defaults
|
|
v.SetDefault("vuln.enabled", true)
|
|
v.SetDefault("vuln.db_path", "/var/lib/atcr-scanner/vulndb")
|
|
v.SetDefault("vuln.tmp_dir", "/var/lib/atcr-scanner/tmp")
|
|
v.SetDefault("vuln.max_image_size", 2*1024*1024*1024) // 2 GiB
|
|
|
|
// Log shipper defaults
|
|
v.SetDefault("log_shipper.batch_size", 100)
|
|
v.SetDefault("log_shipper.flush_interval", "5s")
|
|
}
|
|
|
|
// DefaultConfig returns a Config populated with all default values (no validation).
|
|
func DefaultConfig() *Config {
|
|
v := config.NewViper("SCANNER", "")
|
|
setScannerDefaults(v)
|
|
|
|
cfg := &Config{}
|
|
_ = v.Unmarshal(cfg, config.UnmarshalOption())
|
|
return cfg
|
|
}
|
|
|
|
// ExampleYAML returns a fully-commented YAML configuration with default values.
|
|
func ExampleYAML() ([]byte, error) {
|
|
return config.MarshalCommentedYAML("ATCR Scanner Configuration", DefaultConfig())
|
|
}
|
|
|
|
// LoadConfig builds a complete configuration using Viper layered loading:
|
|
// defaults -> YAML file -> environment variables.
|
|
// yamlPath is optional; empty string means env-only (backward compatible).
|
|
func LoadConfig(yamlPath string) (*Config, error) {
|
|
v := config.NewViper("SCANNER", yamlPath)
|
|
setScannerDefaults(v)
|
|
|
|
cfg := &Config{}
|
|
if err := v.Unmarshal(cfg, config.UnmarshalOption()); err != nil {
|
|
return nil, fmt.Errorf("failed to unmarshal config: %w", err)
|
|
}
|
|
|
|
if cfg.Hold.URL == "" {
|
|
return nil, fmt.Errorf("hold.url is required (env: SCANNER_HOLD_URL)")
|
|
}
|
|
if cfg.Hold.Secret == "" {
|
|
return nil, fmt.Errorf("hold.secret is required (env: SCANNER_HOLD_SECRET)")
|
|
}
|
|
|
|
return cfg, nil
|
|
}
|