Harden production workflows and agent admission

This commit is contained in:
Stanislav Rossovskii
2026-05-28 14:19:27 +04:00
parent a2e88b4e76
commit 37b1a1d6d6
109 changed files with 4927 additions and 894 deletions

View File

@@ -4,6 +4,7 @@ import (
"fmt"
"os"
"regexp"
"strconv"
"strings"
"time"
"unicode/utf8"
@@ -14,19 +15,24 @@ import (
var idPattern = regexp.MustCompile(`^[A-Za-z0-9._:-]+$`)
const (
maxIDLen = 128
maxLabelKeyLen = 64
maxLabelValueLen = 256
maxLabels = 32
maxIDLen = 128
maxLabelKeyLen = 64
maxLabelValueLen = 256
maxLabels = 32
// PH-019: bounded check inventory keeps {check_id} metric cardinality
// predictable. ValidateID already restricts each check_id to a stable
// identifier alphabet; this cap bounds the total. Override via
// MONLET_AGENT_MAX_CHECKS for fleets that genuinely need more.
defaultMaxChecks = 256
AgentVersionLabel = "monlet_agent_version"
defaultHeartbeat = 30 * time.Second
defaultHeartbeat = 10 * time.Second
defaultBatch = 10 * time.Second
defaultMetricsAddr = "127.0.0.1:9465"
)
type Config struct {
AgentID string `toml:"agent_id"`
Hostname string `toml:"hostname"`
Hostname string `toml:"-"`
StateDir string `toml:"state_dir"`
Labels map[string]string `toml:"labels"`
Server ServerConfig `toml:"server"`
@@ -37,7 +43,6 @@ type Config struct {
type ServerConfig struct {
Enabled *bool `toml:"enabled"`
URL string `toml:"url"`
Token string `toml:"token"`
HeartbeatInterval Duration `toml:"heartbeat_interval"`
BatchInterval Duration `toml:"batch_interval"`
}
@@ -124,11 +129,8 @@ func (c *Config) Validate() error {
if c.Server.URL == "" {
return fmt.Errorf("server.url is required when server.enabled = true")
}
if c.Server.Token == "" {
return fmt.Errorf("server.token is required when server.enabled = true")
}
} else if c.Server.URL != "" || c.Server.Token != "" {
return fmt.Errorf("server.url/token require server.enabled = true")
} else if c.Server.URL != "" {
return fmt.Errorf("server.url requires server.enabled = true")
}
if !c.PushesToServer() && !c.ExposesMetrics() {
return fmt.Errorf("server.enabled or metrics.enabled must be true")
@@ -136,6 +138,17 @@ func (c *Config) Validate() error {
if len(c.Checks) == 0 {
return fmt.Errorf("at least one check is required")
}
maxChecks := defaultMaxChecks
if v, ok := os.LookupEnv("MONLET_AGENT_MAX_CHECKS"); ok {
n, err := strconv.Atoi(v)
if err != nil || n <= 0 {
return fmt.Errorf("MONLET_AGENT_MAX_CHECKS must be a positive integer, got %q", v)
}
maxChecks = n
}
if len(c.Checks) > maxChecks {
return fmt.Errorf("too many checks: %d (max %d) — bounded for metric cardinality (PH-019)", len(c.Checks), maxChecks)
}
seen := make(map[string]struct{}, len(c.Checks))
for i := range c.Checks {
ch := &c.Checks[i]