diff --git a/internal/platform/audit.go b/internal/platform/audit.go index ff69ff8..4719a57 100644 --- a/internal/platform/audit.go +++ b/internal/platform/audit.go @@ -30,9 +30,17 @@ var ( ) const ( - platformLabel = "eks-agent-platform/platform" - tenantLabel = "eks-agent-platform/tenant" - personaLabel = "eks-agent-platform/persona" + // Canonical ownership labels (resource-tagging standard). The operator + // stamps these on each tenant namespace; the audit accepts the legacy + // eks-agent-platform/* keys below as a fallback for a not-yet-migrated cluster. + platformLabel = "agents.nanohype.dev/platform" + tenantLabel = "agents.nanohype.dev/tenant" + personaLabel = "agents.nanohype.dev/persona" + + legacyPlatformLabel = "eks-agent-platform/platform" + legacyTenantLabel = "eks-agent-platform/tenant" + legacyPersonaLabel = "eks-agent-platform/persona" + pssEnforce = "pod-security.kubernetes.io/enforce" irsaAnnotation = "eks.amazonaws.com/role-arn" @@ -112,11 +120,22 @@ func auditPlatform(ctx context.Context, typed kubernetes.Interface, dyn dynamic. fmt.Sprintf("namespace %s is %q, want restricted", pssEnforce, orUnset(nsObj.Labels[pssEnforce])), "Restore the restricted Pod Security Standards label on the tenant namespace.")) } - for key, want := range map[string]string{platformLabel: name, tenantLabel: tenant, personaLabel: persona} { - if nsObj.Labels[key] != want { + // Read the canonical label, falling back to the legacy eks-agent-platform/* + // key so the audit is correct against both a migrated and a not-yet-migrated + // cluster. Ordered (not a map) for deterministic finding output. + for _, c := range []struct{ key, legacy, want string }{ + {platformLabel, legacyPlatformLabel, name}, + {tenantLabel, legacyTenantLabel, tenant}, + {personaLabel, legacyPersonaLabel, persona}, + } { + got := nsObj.Labels[c.key] + if got == "" { + got = nsObj.Labels[c.legacy] + } + if got != c.want { out = append(out, f(cloud.SeverityLow, cloud.PlatformLabelMissing, ns, - fmt.Sprintf("namespace label %s is %q, want %q", key, orUnset(nsObj.Labels[key]), want), - "Restore the eks-agent-platform ownership labels (drive cost attribution and network selection).")) + fmt.Sprintf("namespace label %s is %q, want %q", c.key, orUnset(got), c.want), + "Restore the agents.nanohype.dev ownership labels (drive cost attribution and network selection).")) } } diff --git a/internal/platform/audit_test.go b/internal/platform/audit_test.go index c16db4d..68d7ecf 100644 --- a/internal/platform/audit_test.go +++ b/internal/platform/audit_test.go @@ -142,6 +142,24 @@ func TestAudit_Conformant(t *testing.T) { } } +func TestAudit_AcceptsLegacyLabels(t *testing.T) { + // A not-yet-migrated cluster still carries the legacy eks-agent-platform/* + // ownership labels; the audit must accept them via fallback (no + // PlatformLabelMissing finding) and stay otherwise conformant. + objs := conformantObjects() + objs[0] = &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: tNS, Labels: map[string]string{ + pssEnforce: "restricted", legacyPlatformLabel: tName, legacyTenantLabel: tTen, legacyPersonaLabel: tPers, + }}} + typed := kubefake.NewSimpleClientset(objs...) + findings, err := Audit(context.Background(), typed, conformantDyn(), conformantRole()) + if err != nil { + t.Fatal(err) + } + if len(findings) != 0 { + t.Fatalf("legacy labels should be accepted, got %d findings: %+v", len(findings), findings) + } +} + func TestAudit_DriftDetected(t *testing.T) { // Namespace exists but PSS is wrong; NetworkPolicy and ServiceAccount absent. typed := kubefake.NewSimpleClientset(