111 lines
2.5 KiB
Go
111 lines
2.5 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/BurntSushi/toml"
|
|
)
|
|
|
|
type rawConfig struct {
|
|
Config
|
|
EnvFile string `toml:"env_file"`
|
|
MaxCacheSize string `toml:"max_cache_size"`
|
|
MaxCacheAgeStr string `toml:"max_cache_age"`
|
|
}
|
|
|
|
type Config struct {
|
|
CacheRoot string `toml:"cache_root"`
|
|
MirrorURLs []string `toml:"mirror_urls"`
|
|
MirroredRepos []string `toml:"mirrored_repos"`
|
|
Port string `toml:"port"`
|
|
Token string
|
|
MaxCacheSize int64
|
|
MaxCacheAge time.Duration
|
|
}
|
|
|
|
func ReadConfig(path string) (*Config, error) {
|
|
|
|
var rawcfg rawConfig
|
|
_, err := toml.DecodeFile(path, &rawcfg)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error loading config from %s: %w", path, err)
|
|
}
|
|
|
|
cfg := rawcfg.Config
|
|
|
|
err = cfg.loadToken(rawcfg.EnvFile)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error getting token: %v", err)
|
|
}
|
|
|
|
if rawcfg.MaxCacheSize == "" {
|
|
return nil, fmt.Errorf("max_cache_size must be set")
|
|
}
|
|
sizeBytes, err := strconv.ParseInt(strings.TrimSuffix(rawcfg.MaxCacheSize, "GB"), 10, 64)
|
|
sizeBytes = sizeBytes * 1024 * 1024 * 1024
|
|
if err != nil {
|
|
return nil, fmt.Errorf("invalid cache size string")
|
|
}
|
|
cfg.MaxCacheSize = sizeBytes
|
|
|
|
cfg.MaxCacheAge, err = time.ParseDuration(rawcfg.MaxCacheAgeStr)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error getting max_cache_age: %v", err)
|
|
}
|
|
|
|
if err = cfg.validate(); err != nil {
|
|
return nil, fmt.Errorf("invalid config: %w", err)
|
|
}
|
|
|
|
return &cfg, nil
|
|
}
|
|
|
|
func (c *Config) loadToken(path string) error {
|
|
|
|
info, err := os.Stat(path)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to stat env file: %v", err)
|
|
}
|
|
|
|
if info.Mode().Perm() != 0o640 {
|
|
return fmt.Errorf("env file perms not secure, expected 0640 got %o", info.Mode().Perm())
|
|
}
|
|
//#nosec G304 -- config is known path
|
|
data, err := os.ReadFile(path)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to read env file: %v", err)
|
|
}
|
|
|
|
key, val, ok := strings.Cut(strings.TrimSpace(string(data)), "=")
|
|
if !ok || key != "PKGSTASH_TOKEN" {
|
|
return fmt.Errorf("invalid env file format")
|
|
}
|
|
|
|
c.Token = val
|
|
return nil
|
|
|
|
}
|
|
|
|
func (c *Config) validate() error {
|
|
if c.CacheRoot == "" {
|
|
return fmt.Errorf("cache root is required")
|
|
}
|
|
if len(c.MirrorURLs) == 0 {
|
|
return fmt.Errorf("at least one mirror is required")
|
|
}
|
|
if len(c.MirroredRepos) == 0 {
|
|
return fmt.Errorf("at least one repo is required")
|
|
}
|
|
if c.Port == "" {
|
|
return fmt.Errorf("port required")
|
|
}
|
|
if c.Token == "" || c.Token == "changeme" {
|
|
return fmt.Errorf("auth token is required")
|
|
}
|
|
return nil
|
|
}
|