Skip to content

CMP-4323: Fix file_permissions_cni_conf for /etc/kubernetes/cni/net.d and runtime lock files#14755

Open
Vincent056 wants to merge 2 commits into
ComplianceAsCode:masterfrom
Vincent056:CMP-4323-cni-conf-exclude-lock
Open

CMP-4323: Fix file_permissions_cni_conf for /etc/kubernetes/cni/net.d and runtime lock files#14755
Vincent056 wants to merge 2 commits into
ComplianceAsCode:masterfrom
Vincent056:CMP-4323-cni-conf-exclude-lock

Conversation

@Vincent056

@Vincent056 Vincent056 commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

Description:

The file_permissions_cni_conf rules (and the _not_s390x / _s390x variants) only matched CNI config files under /etc/cni/net.d/. This caused two problems, both reported against the rule:

  1. Runtime lock file false FAIL. /etc/cni/net.d/ can contain cni.lock — a zero-byte flock sentinel created by CRI-O/podman with mode 0644. The original regex ^/etc/cni/net.d/.*$ matched it and reported FAIL on otherwise-compliant clusters.

  2. Wrong / missing directory (CMP-4323). /etc/cni/net.d/ is populated by the cri-o RPM (the 100-crio-bridge.conflist / 200-loopback.conflist bootstrap configs). It is not the directory CRI-O actually reads — OpenShift sets CRI-O's network_dir to /etc/kubernetes/cni/net.d/ (via the machine-config-operator crio drop-in), where the active Multus configuration (00-multus.conf) lives. On OpenShift 4.22 the cri-o RPM no longer ships the /etc/cni/net.d/ bootstrap configs and the directory is absent, so the rule matched nothing and silently provided no coverage while the real configuration in /etc/kubernetes/cni/net.d/ went unchecked.

This narrows the regex to real CNI config-file extensions (fixing #1) and broadens it to cover both directories (fixing #2):

filepath: ^/etc/cni/net.d/.*$
       -> ^/etc/(kubernetes/)?cni/net.d/.*\.(conf|conflist|json)$

Rationale:

cni.lock is a runtime lock file, not a network configuration file, and its 0644 mode is set by the container runtime — not something an admin can or should remediate. Restricting the check to actual CNI config-file extensions (.conf, .conflist, .json) excludes both cni.lock and the 0644 whereabouts.d/nodename file, while the (kubernetes/)? group keeps the rule meaningful across OpenShift versions: it verifies whatever CNI config files exist, in whichever directory is present, and fails if any are more permissive than 0600.

The directory layout by version (verified on live clusters):

OCP cri-o /etc/cni/net.d/ /etc/kubernetes/cni/net.d/
4.19 1.32 present (*.conflist, 0600) present (00-multus.conf, 0600)
4.20 1.33 present (*.conflist, 0600) present
4.22 1.35 absent present (only location)

Validation:

Built the ocp4 datastream and ran it through the compliance-operator with debug: true on three live clusters (4.19, 4.20, 4.22):

  • Clean clusters → PASS / COMPLIANT on master and worker pools.
  • Negative test: seeding a 0644 .conf into the matching directory (old path on 4.19, new path on 4.20/4.22) flips that node to FAIL — confirming the rule actively collects and evaluates files in both locations, i.e. the PASS is real coverage and not a vacuous none_exist pass.

Review Hints:

  • The EXCLUDED_FILES mechanism in the file_permissions template only applies to the is_directory branch, not the filepath_is_regex branch this rule uses, so narrowing/broadening the regex is the appropriate fix.
  • Grouping/alternation in filepath regexes is already used elsewhere with the same template family (e.g. file_permissions_var_log_kube_audit uses ^/var/log/kube-apiserver($|/.*$)).
  • The sibling file_owner_cni_conf / file_groupowner_cni_conf rules are intentionally left unchanged (the lock file is root:root); they can be broadened to the new path in a follow-up if desired.

Reported via Red Hat Jira CMP-4323 (and the earlier OCPBUGS-22995, which first noted the rule checks /etc/cni/net.d/ instead of /etc/kubernetes/cni/net.d/).

@Vincent056 Vincent056 changed the title OCP4: Exclude runtime lock files from file_permissions_cni_conf CMP-4323: Exclude runtime lock files from file_permissions_cni_conf Jun 2, 2026
@jan-cerny jan-cerny added the OpenShift OpenShift product related. label Jun 4, 2026
name: file_permissions
vars:
filepath: ^/etc/cni/net.d/.*$
filepath: ^/etc/cni/net.d/.*\.(conf|conflist|json)$

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 in OCP 4.22 directory /etc/cni/net.d/ doesn't exist.
This one exists though, and is mentioned in the ticket:

ls /etc/kubernetes/cni/net.d/
00-multus.conf  whereabouts.d

Not sure if it changed from 4.19 to 4.20... can check

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.

OCP 4.12 has this for example:

sh-4.4# ls /etc/cni/net.d
100-crio-bridge.conf  200-loopback.conf
sh-4.4# ls /etc/kubernetes/cni/net.d/
00-multus.conf  multus.d  whereabouts.d

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.

OCP 4.19 has the similar directories as 4.12

sh-5.1# ls /etc/cni/net.d/
100-crio-bridge.conflist  200-loopback.conflist
sh-5.1# ls /etc/kubernetes/cni/net.d/
00-multus.conf  whereabouts.d

@Vincent056 Vincent056 Jun 11, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@yuumasato Good catch, confirmed on live clusters: /etc/cni/net.d/ is shipped by the cri-o RPM and is gone on 4.22 (cri-o stopped shipping the bridge/loopback bootstrap configs between 1.33/4.20 and 1.35/4.22).

I've updated the regex to broaden coverage to both directories:

^/etc/cni/net.d/.*$  ->  ^/etc/(kubernetes/)?cni/net.d/.*\.(conf|conflist|json)$

The extension filter still excludes cni.lock and the 0644 whereabouts.d/nodename.

Validated via compliance-operator (debug scans) on 4.19, 4.20, and 4.22: clean clusters PASS, and seeding a 0644 .conf into the relevant dir (old path on 4.19, new path on 4.20/4.22) flips that node to FAIL.

@Vincent056 Vincent056 changed the title CMP-4323: Exclude runtime lock files from file_permissions_cni_conf CMP-4323: Fix file_permissions_cni_conf for /etc/kubernetes/cni/net.d and runtime lock files Jun 11, 2026

@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.

The sibling file_owner_cni_conf / file_groupowner_cni_conf rules are intentionally left unchanged (the lock file is root:root); they can be broadened to the new path in a follow-up if desired.

Nit: for the sake of completenes, I'd fix the regex path in those rules as well.

Also, there seems to be some unrelated test failures, may be worth rebasing to latest master commit.

60/287 Test  #58: python-unit-ssg-module ...........................................***Failed    6.18 sec
============================= test session starts ==============================
platform linux -- Python 3.14.5, pytest-9.0.3, pluggy-1.6.0
rootdir: /__w/content/content
configfile: pyproject.toml
plugins: cov-7.1.0
collected 245 items

Vincent056 and others added 2 commits June 11, 2026 14:28
The file_permissions_cni_conf rules matched every file under
/etc/cni/net.d/ with the regex ^/etc/cni/net.d/.*$ and required mode
0600. The directory can also contain cni.lock, a zero-byte flock
sentinel created by CRI-O/podman with mode 0644. The actual CNI
configuration files (e.g. 100-crio-bridge.conflist,
200-loopback.conflist) are already 0600 and compliant, but cni.lock
caused the rule to FAIL.

Narrow the regex to only match CNI configuration files
(.conf, .conflist, .json) so the runtime lock file is no longer
checked. This avoids false FAILs while still verifying the permissions
of the actual network configuration files.

CMP-4323
The file_permissions_cni_conf rules only matched CNI config files under
/etc/cni/net.d/. That directory is populated by the cri-o RPM (the
100-crio-bridge.conflist / 200-loopback.conflist bootstrap configs), but it is
not the directory CRI-O actually reads: OpenShift sets CRI-O's network_dir to
/etc/kubernetes/cni/net.d/ (via the machine-config-operator crio drop-in), where
the active Multus configuration (00-multus.conf) lives. On OpenShift 4.22 the
cri-o RPM no longer ships the /etc/cni/net.d/ bootstrap configs and the directory
is absent, so the rule matched nothing and silently provided no coverage while
the real configuration in /etc/kubernetes/cni/net.d/ went unchecked.

Broaden the regex to match CNI config files in either directory:

    ^/etc/cni/net.d/.*\.(conf|conflist|json)$
    -> ^/etc/(kubernetes/)?cni/net.d/.*\.(conf|conflist|json)$

The extension filter still excludes the cni.lock runtime sentinel and the 0644
whereabouts.d/nodename file. With check_existence "none_exist" the rule passes on
whichever directory exists and fails if any CNI config file in either tree is more
permissive than 0600.

Validated via compliance-operator (debug scans) on live OCP 4.19, 4.20 and 4.22
clusters: clean clusters PASS, and seeding a 0644 .conf into the matching
directory (old path on 4.19, new path on 4.20/4.22) flips that node to FAIL,
confirming real coverage in both locations.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@Vincent056 Vincent056 force-pushed the CMP-4323-cni-conf-exclude-lock branch from b47b8aa to 8113b2b Compare June 11, 2026 21:29
@openshift-ci

openshift-ci Bot commented Jun 11, 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/4.20-images 8113b2b link true /test 4.20-images
ci/prow/4.21-images 8113b2b link true /test 4.21-images
ci/prow/e2e-aws-openshift-platform-compliance 8113b2b 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

OpenShift OpenShift product related.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants