Skip to content

CMP-4605: Guard kubevirt NAD rules against NADs without a spec - #15020

Open
Vincent056 wants to merge 2 commits into
ComplianceAsCode:masterfrom
Vincent056:fix-nad-spec-guard
Open

CMP-4605: Guard kubevirt NAD rules against NADs without a spec#15020
Vincent056 wants to merge 2 commits into
ComplianceAsCode:masterfrom
Vincent056:fix-nad-spec-guard

Conversation

@Vincent056

Copy link
Copy Markdown
Contributor

Description

kubevirt-localnet-vlan-required and kubevirt-bridge-mac-spoof-filtering guard only has(n.spec.config). A NetworkAttachmentDefinition with no spec at all is legitimate (e.g. the istio-cni NAD), but it makes has(n.spec.config) raise no such key: spec at evaluation time — and the scanner maps missing-key errors to FAIL, so both rules false-FAIL on any cluster carrying such a NAD. Observed during CIS OCP-Virt profile validation on a 4.22 + Virtualization cluster.

Fix

Prepend !has(n.spec) || to both expressions, and add a spec-less NAD regression fixture to both cel/tests/cases.yaml.

Testing

Via celctl (the Compliance Operator's scanner engine): the new fixture fails against the unfixed expressions (5/6 and 6/7 cases) and 6/6 / 7/7 cases pass with the fix.

🤖 Generated with Claude Code

Vincent056 and others added 2 commits August 19, 2026 12:08
kubevirt-localnet-vlan-required and kubevirt-bridge-mac-spoof-filtering
guarded only has(n.spec.config). A NetworkAttachmentDefinition with no
spec at all is legitimate (e.g. the istio-cni NAD), but it makes
has(n.spec.config) raise 'no such key: spec' at evaluation time, and
the scanner maps missing-key errors to FAIL - so both rules false-FAIL
on any cluster carrying such a NAD.

Prepend !has(n.spec) to both expressions and add a spec-less NAD
regression fixture: it fails 5/6 and 6/7 against the unfixed
expressions and all cases pass with the fix (celctl, the operator's
scanner engine).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A NetworkAttachmentDefinition with spec.config set to an empty string
passes both has() guards but makes parseJSON crash with 'unexpected end
of JSON input', which the scanner surfaces as ERROR. Seen on a large
CNV engineering cluster during profile validation. Treat an empty
config as compliant, like an absent one, and add regression fixtures.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@yuumasato yuumasato left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Vincent056 Looks like this should actually handle an empty spec.config string?

It does handle the empty spec.config.
But I wonder if allowing a NAD without spec is healthy.

@Vincent056

Copy link
Copy Markdown
Contributor Author

Good question — I went back and forth on this too. I think skipping is correct for these two rules:

spec.config is what scopes a NAD for these checks: the rule first classifies the NAD (type: bridge / topology: localnet) and only then asserts the hardening attribute. A NAD with no spec/config can't be classified as a bridge or localnet network, so failing it under "VLAN required" / "MAC spoof filtering" would be a false finding with a misleading message. When a NAD is in scope, a missing hardening attribute does fail: a localnet without vlanID and a bridge without macspoofchk: true are both non-compliant (covered by the fixtures).

Config-less NADs are also a legitimate, spec-defined pattern rather than cruft: the NPWG NetworkAttachmentDefinition de-facto standard, §3.4.1 "Determining CNI Plugins for a NetworkAttachmentDefinition Object", makes them delegate to an on-disk CNI config file matching the NAD name (lookup rules 2–3), and real operators create them — the cluster that hit the original crash has a Maistra/service-mesh NAD with spec.config: "" from 2024. I replayed that exact object through both rules: compliant.

The kernel of truth in the concern: for delegation-style NADs the effective config lives on disk, where a platform scan can't see it. Failing these two rules wouldn't fix that blind spot, it would just mislabel it; if we want coverage there it'd be a separate (likely manual) control — the CIS VM-extension benchmark doesn't currently ask for it. Happy to file that as a follow-up if you think it's worth tracking.

(Noted while testing: a NAD with malformed non-empty JSON config makes these rules report ERROR, since CEL's parseJSON has no safe variant. The object is genuinely broken at that point, but an SDK tryParseJSON helper could turn that into a clean FAIL some day.)

@Vincent056

Copy link
Copy Markdown
Contributor Author

/retest-required

@taimurhafeez

Copy link
Copy Markdown
Contributor

/test e2e-aws-openshift-platform-compliance

@openshift-ci

openshift-ci Bot commented Aug 27, 2026

Copy link
Copy Markdown

@Vincent056: The following tests failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/e2e-aws-openshift-node-compliance 0f400ec link false /test e2e-aws-openshift-node-compliance
ci/prow/e2e-aws-openshift-platform-compliance d32be12 link true /test e2e-aws-openshift-platform-compliance

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants