CMP-4323: Fix file_permissions_cni_conf for /etc/kubernetes/cni/net.d and runtime lock files#14755
Conversation
| name: file_permissions | ||
| vars: | ||
| filepath: ^/etc/cni/net.d/.*$ | ||
| filepath: ^/etc/cni/net.d/.*\.(conf|conflist|json)$ |
There was a problem hiding this comment.
@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
There was a problem hiding this comment.
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.dThere was a problem hiding this comment.
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
There was a problem hiding this comment.
@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.
yuumasato
left a comment
There was a problem hiding this comment.
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
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>
b47b8aa to
8113b2b
Compare
|
@Vincent056: The following tests failed, say
Full PR test history. Your PR dashboard. DetailsInstructions 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. |
Description:
The
file_permissions_cni_confrules (and the_not_s390x/_s390xvariants) only matched CNI config files under/etc/cni/net.d/. This caused two problems, both reported against the rule:Runtime lock file false FAIL.
/etc/cni/net.d/can containcni.lock— a zero-byteflocksentinel created by CRI-O/podman with mode0644. The original regex^/etc/cni/net.d/.*$matched it and reported FAIL on otherwise-compliant clusters.Wrong / missing directory (CMP-4323).
/etc/cni/net.d/is populated by the cri-o RPM (the100-crio-bridge.conflist/200-loopback.conflistbootstrap configs). It is not the directory CRI-O actually reads — OpenShift sets CRI-O'snetwork_dirto/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):
Rationale:
cni.lockis a runtime lock file, not a network configuration file, and its0644mode 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 bothcni.lockand the0644whereabouts.d/nodenamefile, 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 than0600.The directory layout by version (verified on live clusters):
/etc/cni/net.d//etc/kubernetes/cni/net.d/*.conflist,0600)00-multus.conf,0600)*.conflist,0600)Validation:
Built the
ocp4datastream and ran it through the compliance-operator withdebug: trueon three live clusters (4.19, 4.20, 4.22):0644.confinto 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 vacuousnone_existpass.Review Hints:
EXCLUDED_FILESmechanism in thefile_permissionstemplate only applies to theis_directorybranch, not thefilepath_is_regexbranch this rule uses, so narrowing/broadening the regex is the appropriate fix.filepathregexes is already used elsewhere with the same template family (e.g.file_permissions_var_log_kube_audituses^/var/log/kube-apiserver($|/.*$)).file_owner_cni_conf/file_groupowner_cni_confrules are intentionally left unchanged (the lock file isroot: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/).