77 lines
2.2 KiB
Go
77 lines
2.2 KiB
Go
package agent
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"regexp"
|
|
)
|
|
|
|
// Config contains bootstrap-only settings for the restricted agent.
|
|
type Config struct {
|
|
ListenAddress string
|
|
Secret []byte
|
|
AllowedRoots []string
|
|
RegistryPath string
|
|
DockerSocket string
|
|
DockerNetwork string
|
|
}
|
|
|
|
// LoadConfig reads the agent's bootstrap settings and shared secret file.
|
|
func LoadConfig() (Config, error) {
|
|
tokenFile := environment("DOGAMA_AGENT_TOKEN_FILE", "/var/lib/dogama-agent/secrets/token")
|
|
secret, err := readSecretFile(tokenFile)
|
|
if err != nil {
|
|
return Config{}, err
|
|
}
|
|
roots := make([]string, 0, 2)
|
|
for _, item := range []struct{ name, fallback string }{
|
|
{"DOGAMA_ALLOWED_SERVER_ROOT", "/srv/game-servers"},
|
|
{"DOGAMA_ALLOWED_BACKUP_ROOT", "/srv/game-backups"},
|
|
} {
|
|
if value := environment(item.name, item.fallback); value != "" {
|
|
roots = append(roots, value)
|
|
}
|
|
}
|
|
if len(roots) == 0 {
|
|
return Config{}, errors.New("at least one allowed root is required")
|
|
}
|
|
config := Config{
|
|
ListenAddress: environment("DOGAMA_AGENT_LISTEN_ADDRESS", ":8081"),
|
|
Secret: secret,
|
|
AllowedRoots: roots,
|
|
RegistryPath: environment("DOGAMA_AGENT_REGISTRY_PATH", "/var/lib/dogama-agent/registry.json"),
|
|
DockerSocket: environment("DOGAMA_DOCKER_SOCKET", "/var/run/docker.sock"),
|
|
DockerNetwork: environment("DOGAMA_DOCKER_NETWORK", "dogama-games"),
|
|
}
|
|
if !filepath.IsAbs(config.RegistryPath) || !filepath.IsAbs(config.DockerSocket) {
|
|
return Config{}, errors.New("registry and Docker socket paths must be absolute")
|
|
}
|
|
if !regexp.MustCompile(`^[A-Za-z0-9][A-Za-z0-9_.-]{0,127}$`).MatchString(config.DockerNetwork) {
|
|
return Config{}, errors.New("docker network name is invalid")
|
|
}
|
|
return config, nil
|
|
}
|
|
|
|
func readSecretFile(path string) ([]byte, error) {
|
|
body, err := os.ReadFile(path)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("read agent secret: %w", err)
|
|
}
|
|
body = bytes.TrimSuffix(body, []byte("\n"))
|
|
body = bytes.TrimSuffix(body, []byte("\r"))
|
|
if len(body) < 32 || len(body) > 4096 {
|
|
return nil, errors.New("agent secret must contain between 32 and 4096 bytes")
|
|
}
|
|
return body, nil
|
|
}
|
|
|
|
func environment(name, fallback string) string {
|
|
if value := os.Getenv(name); value != "" {
|
|
return value
|
|
}
|
|
return fallback
|
|
}
|