Harden production workflows and agent admission
This commit is contained in:
@@ -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]
|
||||
|
||||
Reference in New Issue
Block a user