fleet-manager: soft-disable optional planes when their PKI isn't staged yet
The compose wires the authorise (broker) and agent planes to fixed cert paths, so a first bring-up that hasn't run the PKI steps yet crash-looped on the first missing file (e.g. /pki/broker/clients/fleet-manager.crt) instead of booting. Treat a configured-but-absent cert as "plane not yet provisioned": log a loud WARNING and disable that plane, so the manager boots and each plane lights up as its PKI appears. A malformed/unreadable cert still hard-fails (real misconfig). The admin plane stays a hard requirement (FLEET_MGR_ADMIN_INSECURE is its bench escape). Adds a missingFiles() helper; hub push path already nil-guards a disabled agent plane.
This commit is contained in:
@@ -18,6 +18,7 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -132,15 +133,24 @@ func main() {
|
||||
|
||||
s := &server{cfg: cfg, store: store}
|
||||
|
||||
// Authorise pillar: the enrol-broker admin client (nil = disabled, so the
|
||||
// manager runs standalone before a broker is wired).
|
||||
// Authorise pillar: the enrol-broker admin client. Enabled when the broker URL
|
||||
// is set AND its client PKI is present. Missing PKI (not yet provisioned)
|
||||
// DISABLES the pillar with a loud warning rather than crash-looping the whole
|
||||
// manager — so a partial bring-up boots and the pillar lights up once the cert
|
||||
// is staged. A malformed/unreadable cert still hard-fails (a real misconfig).
|
||||
switch {
|
||||
case cfg.brokerAdminURL == "":
|
||||
log.Printf("authorise pillar DISABLED (set FLEET_MGR_BROKER_URL + client cert/key + CA to enable)")
|
||||
default:
|
||||
if miss := missingFiles(cfg.brokerClientCert, cfg.brokerClientKey, cfg.brokerCA); len(miss) > 0 {
|
||||
log.Printf("WARNING: authorise pillar DISABLED — broker PKI not found: %s (run enrol-broker/admin-pki.sh; see DEPLOY.md)", strings.Join(miss, ", "))
|
||||
break
|
||||
}
|
||||
broker, err := newBrokerClient(cfg)
|
||||
if err != nil {
|
||||
log.Fatalf("broker client: %v", err)
|
||||
}
|
||||
s.broker = broker
|
||||
if broker == nil {
|
||||
log.Printf("authorise pillar DISABLED (set FLEET_MGR_BROKER_URL + client cert/key + CA to enable)")
|
||||
}
|
||||
|
||||
// Metrics gateway: the manager is the only reader/writer of InfluxDB. nil (a
|
||||
@@ -159,15 +169,22 @@ func main() {
|
||||
// plane can run standalone (e.g. before any host is enrolled). The hub is the
|
||||
// live-stream registry the lifecycle API pushes desired-state through, and it
|
||||
// writes each snapshot to the metrics sink.
|
||||
if cfg.agentCert != "" && cfg.agentKey != "" && cfg.agentClientCA != "" {
|
||||
switch {
|
||||
case cfg.agentCert == "" || cfg.agentKey == "" || cfg.agentClientCA == "":
|
||||
log.Printf("agent plane DISABLED (set FLEET_MGR_AGENT_CERT/_KEY/_CLIENT_CA to enable)")
|
||||
default:
|
||||
if miss := missingFiles(cfg.agentCert, cfg.agentKey, cfg.agentClientCA); len(miss) > 0 {
|
||||
// Same soft-disable as the authorise pillar: boot without the agent
|
||||
// plane until its fleet-CA PKI is staged, rather than crash-looping.
|
||||
log.Printf("WARNING: agent plane DISABLED — PKI not found: %s (run server-pki.sh; see DEPLOY.md)", strings.Join(miss, ", "))
|
||||
break
|
||||
}
|
||||
s.hub = newAgentHub(store, sink)
|
||||
go func() {
|
||||
if err := serveAgent(cfg, s.hub); err != nil {
|
||||
log.Fatalf("agent plane: %v", err)
|
||||
}
|
||||
}()
|
||||
} else {
|
||||
log.Printf("agent plane DISABLED (set FLEET_MGR_AGENT_CERT/_KEY/_CLIENT_CA to enable)")
|
||||
}
|
||||
|
||||
// Admin browser auth = WebAuthn/passkey (secure mode only). Sets up the RP,
|
||||
@@ -292,6 +309,22 @@ func env(k, def string) string {
|
||||
return def
|
||||
}
|
||||
|
||||
// missingFiles returns the subset of the given paths that don't exist (or aren't
|
||||
// stat-able) on disk. Used to soft-disable an optional plane whose PKI hasn't
|
||||
// been provisioned yet, instead of crash-looping the whole manager.
|
||||
func missingFiles(paths ...string) []string {
|
||||
var miss []string
|
||||
for _, p := range paths {
|
||||
if p == "" {
|
||||
continue
|
||||
}
|
||||
if _, err := os.Stat(p); err != nil {
|
||||
miss = append(miss, p)
|
||||
}
|
||||
}
|
||||
return miss
|
||||
}
|
||||
|
||||
func envInt(k string, def int) int {
|
||||
if v := os.Getenv(k); v != "" {
|
||||
if n, err := strconv.Atoi(v); err == nil {
|
||||
|
||||
Reference in New Issue
Block a user