mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-08-20 14:33:30 +00:00
Keep default monitor token inventory current
This commit is contained in:
parent
f6aa8db93a
commit
8dc771f09b
3 changed files with 58 additions and 4 deletions
|
|
@ -2726,6 +2726,13 @@ would mutate. Distinct rows are retained so Agent Doctor does not disguise two
|
|||
installations as one healthy machine. Mock mode has no authoritative token
|
||||
inventory for its synthetic hosts and therefore must not turn fixture token IDs
|
||||
into missing-credential incidents.
|
||||
|
||||
The default-org monitor retains the canonical server configuration pointer
|
||||
rather than a tenant-isolation copy, so tokens minted after startup become part
|
||||
of that current inventory immediately and cannot produce a false
|
||||
`agent_credential_missing` diagnosis. `MultiTenantMonitor` deep-copies only
|
||||
non-default tenant configuration; those tenant copies remain isolated from the
|
||||
primary runtime's mutable token state.
|
||||
`internal/fleethealth/agent_test.go` and
|
||||
`internal/monitoring/agent_fleet_doctor_test.go` are the focused runtime proofs.
|
||||
|
||||
|
|
|
|||
|
|
@ -2630,6 +2630,48 @@ func TestTenantMonitorWiresOrgIdentityIntoNotifications(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestDefaultOrgMonitorSharesCanonicalRuntimeTokenInventory(t *testing.T) {
|
||||
dataDir := t.TempDir()
|
||||
baseCfg := &config.Config{DataPath: dataDir, ConfigPath: dataDir}
|
||||
mtm := NewMultiTenantMonitor(baseCfg, config.NewMultiTenantPersistence(dataDir), nil)
|
||||
t.Cleanup(mtm.Stop)
|
||||
|
||||
monitor, err := mtm.GetMonitor("default")
|
||||
if err != nil {
|
||||
t.Fatalf("GetMonitor(default) error = %v", err)
|
||||
}
|
||||
if monitor.GetConfig() != baseCfg {
|
||||
t.Fatal("default monitor must retain the canonical server config pointer")
|
||||
}
|
||||
|
||||
now := time.Now().UTC()
|
||||
config.Mu.Lock()
|
||||
baseCfg.APITokens = []config.APITokenRecord{{
|
||||
ID: "fresh-agent-token",
|
||||
Name: "Fresh agent token",
|
||||
CreatedAt: now,
|
||||
Scopes: []string{config.ScopeAgentExec},
|
||||
}}
|
||||
config.Mu.Unlock()
|
||||
monitor.mu.Lock()
|
||||
monitor.state.Hosts = []models.Host{{
|
||||
ID: "agent-fresh-token",
|
||||
Hostname: "fresh-token-host",
|
||||
Status: "online",
|
||||
LastSeen: now,
|
||||
AgentVersion: "6.2.2",
|
||||
TokenID: "fresh-agent-token",
|
||||
CommandsEnabled: true,
|
||||
}}
|
||||
monitor.mu.Unlock()
|
||||
|
||||
diagnostics := monitor.GetAgentFleetDiagnostics("6.2.2", now)
|
||||
agent := requireAgentDiagnostic(t, diagnostics, "agent-agent-fresh-token")
|
||||
if diagnosticHasAnyReason(agent.Reasons, AgentFleetReasonCredentialMissing, AgentFleetReasonExecScopeMissing) {
|
||||
t.Fatalf("fresh canonical token was diagnosed as unavailable: %+v", agent.Reasons)
|
||||
}
|
||||
}
|
||||
|
||||
// Instance-wide notification settings (webhook security allowlist, public
|
||||
// URL) propagate through ForEachMonitor; it must visit every live tenant
|
||||
// monitor so no org's manager is left observing stale security settings.
|
||||
|
|
|
|||
|
|
@ -184,10 +184,15 @@ func (mtm *MultiTenantMonitor) GetMonitor(orgID string) (*Monitor, error) {
|
|||
log.Info().Str("org_id", orgID).Msg("initializing tenant monitor")
|
||||
|
||||
// 1. Load Tenant Config
|
||||
// Deep copy the base config to ensure tenant isolation.
|
||||
// Each tenant gets its own independent config that won't share
|
||||
// credential slices or other mutable state with other tenants.
|
||||
tenantConfig := mtm.baseConfig.DeepCopy()
|
||||
// The default org is the primary runtime and must retain the canonical
|
||||
// configuration pointer owned by the server. Runtime auth mutations such as
|
||||
// freshly minted agent tokens need to become visible to monitoring-backed
|
||||
// diagnostics immediately. Non-default tenants remain isolated deep copies
|
||||
// so their mutable state and credentials cannot alias the primary runtime.
|
||||
tenantConfig := mtm.baseConfig
|
||||
if orgID != "default" {
|
||||
tenantConfig = mtm.baseConfig.DeepCopy()
|
||||
}
|
||||
|
||||
// Clear inherited credentials - tenants must load their own
|
||||
// This prevents credential leakage between tenants
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue