fleet-manager: checkpoint 3 — authorise pillar (broker fold-in, births inventory)
The AUTHORISE pillar: the manager owns the enrolment queue UX, the enrol-broker
stays the state machine + step-ca signer (v1 'alongside' fold-in).
enrol-broker (minimal, backward-compatible change):
- admin approve/deny now return the decided Enrolment as JSON when the caller
sends Accept: application/json. Browsers still redirect; other API callers
(verify-serving.sh) still get 204. The cert PEM stays unexported (only the
requesting host gets it via /status) — the JSON carries cert_serial, hostnqn,
context, fingerprint, cn.
fleet-manager:
- broker.go: mTLS client for the broker admin plane (Pending/Approve/Deny),
nil when unconfigured so the manager runs standalone.
- admin.go: GET /api/enrol/pending (proxy), POST /api/enrol/{id}/approve
(drives broker, then BIRTHS the inventory record — identity from the returned
serial/hostnqn/context, binding from the operator's optional body, enrolled
with the HUMAN approver = the manager's admin mTLS CN), POST .../deny.
503 when the broker isn't wired.
Test: httptest mock broker asserts the Accept:application/json approve, pending
proxy, inventory birth (identity+binding+enrolled), and the disabled-503 path.
Broker + manager both build/vet/test/gofmt clean.
This commit is contained in:
@@ -36,6 +36,12 @@ type config struct {
|
||||
agentKey string
|
||||
agentClientCA string // FLEET CA (verifies host TPM identity certs)
|
||||
|
||||
// enrol-broker admin plane (the authorise pillar drives it over mTLS).
|
||||
brokerAdminURL string
|
||||
brokerClientCert string
|
||||
brokerClientKey string
|
||||
brokerCA string
|
||||
|
||||
inventoryPath string
|
||||
seed bool
|
||||
hostnqnBase string
|
||||
@@ -54,6 +60,11 @@ func loadConfig() config {
|
||||
agentKey: env("FLEET_MGR_AGENT_KEY", ""),
|
||||
agentClientCA: env("FLEET_MGR_AGENT_CLIENT_CA", ""),
|
||||
|
||||
brokerAdminURL: env("FLEET_MGR_BROKER_URL", ""),
|
||||
brokerClientCert: env("FLEET_MGR_BROKER_CLIENT_CERT", ""),
|
||||
brokerClientKey: env("FLEET_MGR_BROKER_CLIENT_KEY", ""),
|
||||
brokerCA: env("FLEET_MGR_BROKER_CA", ""),
|
||||
|
||||
inventoryPath: env("FLEET_MGR_INVENTORY", "/var/lib/fleet-manager/inventory.json"),
|
||||
seed: env("FLEET_MGR_SEED", "") == "true",
|
||||
hostnqnBase: env("HOSTNQN_BASE", "nqn.2026-06.org.example.fleet:host-"),
|
||||
@@ -62,9 +73,10 @@ func loadConfig() config {
|
||||
|
||||
// server bundles the shared dependencies the handlers close over.
|
||||
type server struct {
|
||||
cfg config
|
||||
store Store
|
||||
hub *agentHub // live agent streams; nil if the agent plane isn't configured
|
||||
cfg config
|
||||
store Store
|
||||
hub *agentHub // live agent streams; nil if the agent plane isn't configured
|
||||
broker *brokerClient // enrol-broker admin client; nil if authorise isn't configured
|
||||
}
|
||||
|
||||
func main() {
|
||||
@@ -83,6 +95,17 @@ 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).
|
||||
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)")
|
||||
}
|
||||
|
||||
// Agent plane (gRPC/mTLS, fleet CA). Started only when configured; the admin
|
||||
// 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.
|
||||
|
||||
Reference in New Issue
Block a user