Add CARING Kubernetes RBAC benchmark

This commit is contained in:
2026-05-23 06:53:30 +02:00
parent 3f510855ef
commit fb3ac750d5
32 changed files with 1688 additions and 79 deletions

View File

@@ -10,8 +10,12 @@ import yaml
GENERATED_NOTICE = "<!-- GENERATED by info_tech_canon; do not edit by hand. -->"
RETRIEVAL_ARTIFACT_KINDS = {
"access-descriptor-set",
"benefit-analysis",
"benchmark-findings",
"benchmark-workspace",
"capture-criteria",
"caring-mapping",
"comparison-frame",
"comparison-report",
"concept-catalog",
@@ -27,6 +31,7 @@ RETRIEVAL_ARTIFACT_KINDS = {
"mapping-expectation",
"model",
"model-extension",
"native-concept-map",
"pattern",
"profile-alignment",
"profile",
@@ -869,10 +874,18 @@ def _safe_id(value: str) -> str:
def _summary_for_artifact(artifact: Any) -> str:
if artifact.kind == "profile-artifact":
return f"Example artifact for the {artifact.provenance.get('profile', 'unknown')} profile: {artifact.title}."
if artifact.kind == "access-descriptor-set":
return f"Structured CARING access descriptor set: {artifact.title}."
if artifact.kind == "benefit-analysis":
return f"Consumer benefit analysis against canon surfaces: {artifact.title}."
if artifact.kind == "benchmark-findings":
return f"Benchmark findings, gaps, and canon pressure: {artifact.title}."
if artifact.kind == "benchmark-workspace":
return f"Benchmark workspace definition and review criteria: {artifact.title}."
if artifact.kind == "capture-criteria":
return f"Criteria for canonical entity and edge capture: {artifact.title}."
if artifact.kind == "caring-mapping":
return f"Native access model to CARING mapping: {artifact.title}."
if artifact.kind == "comparison-frame":
return f"Structured comparison questions and domains: {artifact.title}."
if artifact.kind == "comparison-report":
@@ -899,6 +912,8 @@ def _summary_for_artifact(artifact: Any) -> str:
return f"Expected mappings between consumer graph capture and canon surfaces: {artifact.title}."
if artifact.kind == "model-extension":
return f"Candidate extension to an existing canon model: {artifact.title}."
if artifact.kind == "native-concept-map":
return f"Native source concept map for assimilation or benchmark work: {artifact.title}."
if artifact.kind == "pattern":
return f"Reusable canon pattern: {artifact.title}."
if artifact.kind == "profile-alignment":

View File

@@ -53,8 +53,12 @@ REQUIRED_SCHEMAS = (
)
RETRIEVAL_BRIEF_KINDS = {
"access-descriptor-set",
"benefit-analysis",
"benchmark-findings",
"benchmark-workspace",
"capture-criteria",
"caring-mapping",
"comparison-frame",
"comparison-report",
"concept-catalog",
@@ -69,6 +73,7 @@ RETRIEVAL_BRIEF_KINDS = {
"mapping-expectation",
"model",
"model-extension",
"native-concept-map",
"pattern",
"profile-alignment",
"profile",
@@ -243,6 +248,40 @@ REPO_SCOPING_REQUIRED_EXTENSION_CANDIDATES = {
"extension/scope-md-interface",
}
CARING_K8S_BENCHMARK_ARTIFACT_IDS = {
"benchmark/caring/kubernetes-rbac",
"benchmark/caring/kubernetes-rbac/access-descriptors",
"benchmark/caring/kubernetes-rbac/caring-mapping",
"benchmark/caring/kubernetes-rbac/findings",
"benchmark/caring/kubernetes-rbac/native-concepts",
}
CARING_K8S_REQUIRED_NATIVE_CONCEPTS = {
"Role",
"ClusterRole",
"RoleBinding",
"ClusterRoleBinding",
"ServiceAccount",
"Namespace",
"Verb",
"Resource",
"Scope",
}
CARING_K8S_REQUIRED_CASES = {
"namespace-pod-reader",
"workload-creator-derived-execution",
"cluster-secret-reader",
"namespace-as-tenant-boundary",
}
CARING_K8S_REQUIRED_DESCRIPTOR_CLASSES = {
"declared_access",
"effective_access",
"derived_capability",
"induced_access",
}
def structural_checks(context: Any) -> dict[str, list[dict[str, Any]]]:
errors: list[dict[str, Any]] = []
@@ -270,6 +309,11 @@ def structural_checks(context: Any) -> dict[str, list[dict[str, Any]]]:
context.infospace.artifacts,
errors,
)
_check_caring_kubernetes_rbac_benchmark_assets(
context.infospace_root,
context.infospace.artifacts,
errors,
)
_check_optional_assets(context.infospace_root, warnings)
return {"errors": errors, "warnings": warnings}
@@ -1167,6 +1211,216 @@ def _check_repo_scoping_comparison_assets(
)
def _check_caring_kubernetes_rbac_benchmark_assets(
infospace_root: Path,
artifacts: list[Any],
errors: list[dict[str, Any]],
) -> None:
artifact_ids = {artifact.id for artifact in artifacts}
for artifact_id in sorted(CARING_K8S_BENCHMARK_ARTIFACT_IDS - artifact_ids):
errors.append(
{
"code": "missing_caring_kubernetes_rbac_benchmark_artifact",
"artifact_id": artifact_id,
}
)
benchmark_root = infospace_root / "standards" / "caring" / "benchmarks" / "kubernetes-rbac"
if not benchmark_root.is_dir():
errors.append(
{
"code": "missing_caring_kubernetes_rbac_benchmark_workspace",
"path": "infospace/standards/caring/benchmarks/kubernetes-rbac",
}
)
return
benchmark = _read_yaml(benchmark_root / "benchmark.yaml", errors)
if isinstance(benchmark, dict):
for field in ("source_corpus", "expected_outputs", "review_criteria"):
items = benchmark.get(field) or []
if not isinstance(items, list) or not items:
errors.append(
{
"code": "missing_caring_kubernetes_benchmark_field",
"field": field,
}
)
cases = benchmark.get("cases") or []
if not isinstance(cases, list):
errors.append(
{
"code": "invalid_caring_kubernetes_benchmark_cases",
"path": "infospace/standards/caring/benchmarks/kubernetes-rbac/benchmark.yaml",
}
)
else:
case_ids = {
str(case.get("id"))
for case in cases
if isinstance(case, dict) and case.get("id")
}
for case_id in sorted(CARING_K8S_REQUIRED_CASES - case_ids):
errors.append(
{
"code": "missing_caring_kubernetes_benchmark_case",
"case": case_id,
}
)
native = _read_yaml(benchmark_root / "native-concepts.yaml", errors)
if isinstance(native, dict):
if native.get("namespace_tenant_boundary_warning") is not True:
errors.append(
{
"code": "missing_caring_kubernetes_namespace_warning",
"path": "infospace/standards/caring/benchmarks/kubernetes-rbac/native-concepts.yaml",
}
)
concepts = native.get("concepts") or []
if not isinstance(concepts, list):
errors.append(
{
"code": "invalid_caring_kubernetes_native_concepts",
"path": "infospace/standards/caring/benchmarks/kubernetes-rbac/native-concepts.yaml",
}
)
else:
native_names = {
str(concept.get("native"))
for concept in concepts
if isinstance(concept, dict) and concept.get("native")
}
for concept in sorted(CARING_K8S_REQUIRED_NATIVE_CONCEPTS - native_names):
errors.append(
{
"code": "missing_caring_kubernetes_native_concept",
"concept": concept,
}
)
mapping = _read_yaml(benchmark_root / "caring-mapping.yaml", errors)
if isinstance(mapping, dict):
if mapping.get("namespace_tenant_boundary_warning") is not True:
errors.append(
{
"code": "missing_caring_kubernetes_mapping_namespace_warning",
"path": "infospace/standards/caring/benchmarks/kubernetes-rbac/caring-mapping.yaml",
}
)
mappings = mapping.get("mappings") or []
if not isinstance(mappings, list):
errors.append(
{
"code": "invalid_caring_kubernetes_mappings",
"path": "infospace/standards/caring/benchmarks/kubernetes-rbac/caring-mapping.yaml",
}
)
else:
mapped_names = {
str(item.get("native_concept"))
for item in mappings
if isinstance(item, dict) and item.get("native_concept")
}
for concept in sorted(CARING_K8S_REQUIRED_NATIVE_CONCEPTS - mapped_names):
errors.append(
{
"code": "missing_caring_kubernetes_mapping",
"concept": concept,
}
)
analysis_rules = mapping.get("analysis_rules") or []
if not isinstance(analysis_rules, list) or not analysis_rules:
errors.append(
{
"code": "missing_caring_kubernetes_analysis_rules",
"path": "infospace/standards/caring/benchmarks/kubernetes-rbac/caring-mapping.yaml",
}
)
descriptors = _read_yaml(benchmark_root / "access-descriptors.yaml", errors)
if isinstance(descriptors, dict):
descriptor_classes = set(descriptors.get("descriptor_classes") or [])
for descriptor_class in sorted(
CARING_K8S_REQUIRED_DESCRIPTOR_CLASSES - descriptor_classes
):
errors.append(
{
"code": "missing_caring_kubernetes_descriptor_class",
"descriptor_class": descriptor_class,
}
)
descriptor_items = descriptors.get("descriptors") or []
if not isinstance(descriptor_items, list):
errors.append(
{
"code": "invalid_caring_kubernetes_descriptors",
"path": "infospace/standards/caring/benchmarks/kubernetes-rbac/access-descriptors.yaml",
}
)
else:
used_classes = {
str(item.get("descriptor_class"))
for item in descriptor_items
if isinstance(item, dict) and item.get("descriptor_class")
}
for descriptor_class in sorted(
CARING_K8S_REQUIRED_DESCRIPTOR_CLASSES - used_classes
):
errors.append(
{
"code": "missing_caring_kubernetes_descriptor_example",
"descriptor_class": descriptor_class,
}
)
required_fields = (
"subject",
"scope",
"plane",
"capabilities",
"exposure_mode",
"lifecycle_state",
"native_evidence",
)
for item in descriptor_items:
if not isinstance(item, dict):
continue
for field in required_fields:
if not item.get(field):
errors.append(
{
"code": "incomplete_caring_kubernetes_descriptor",
"descriptor": item.get("id"),
"field": field,
}
)
findings = _read_yaml(benchmark_root / "findings-and-canon-pressure.yaml", errors)
if isinstance(findings, dict):
for field in ("stable_findings", "gaps", "conflicts", "proposed_changes"):
items = findings.get(field) or []
if not isinstance(items, list) or not items:
errors.append(
{
"code": "missing_caring_kubernetes_findings_field",
"field": field,
}
)
stable_findings = findings.get("stable_findings") or []
finding_ids = {
str(finding.get("id"))
for finding in stable_findings
if isinstance(finding, dict) and finding.get("id")
}
if "finding/namespace-not-tenant-boundary" not in finding_ids:
errors.append(
{
"code": "missing_caring_kubernetes_namespace_finding",
"path": "infospace/standards/caring/benchmarks/kubernetes-rbac/findings-and-canon-pressure.yaml",
}
)
def _artifact_paths_by_path(
infospace_root: Path,
errors: list[dict[str, Any]],