CMP-4341: Deliver runtime kubeletconfig via shared emptyDir instead of a host symlink#1255
CMP-4341: Deliver runtime kubeletconfig via shared emptyDir instead of a host symlink#1255Vincent056 wants to merge 2 commits into
Conversation
…ymlink
The node scanner reads the runtime kubeletconfig from a fixed path. Until now
the operator made it available by symlinking it onto the host under
/var/run/compliance-operator/kubeletconfig (-> the kubeletconfig ConfigMap
mount). That approach is fragile:
- the `ln -s` is not idempotent: the symlink persists on the host /run tmpfs
across scans, so the 2nd+ scan on a node hits the existing symlink and tries
to write inside the read-only ConfigMap mount, failing with
"ln: ... Read-only file system";
- that failure is masked by `| /bin/true`, so the scan silently proceeds;
- it depends on /host/var/run being writable, which is not guaranteed on all
platforms.
The runtime SSH config check already solves the same problem cleanly: it writes
the effective config into a shared "runtime-config" emptyDir mounted in both the
init container and the scanner, and the rule reads it from /tmp/runtime/...
Make runtime kubeletconfig use the same pattern: the init container now copies
the kubeletconfig ConfigMap into /host/tmp/runtime/openscap-kubeletconfig (the
shared emptyDir), and the scanner reads it there. No host symlink, no /var/run,
no read-only/idempotency issues.
NOTE: requires a matching ComplianceAsCode/content change -- the kubelet rules'
yamlfile_value `filepath` must move from
/var/run/compliance-operator/kubeletconfig/openscap-kubeletconfig to
/tmp/runtime/openscap-kubeletconfig.
CMP-4341
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
TestKubeletConfigIsScannedAcrossReruns scans two kubelet rules that PASS on a default OpenShift node (anonymous auth disabled, authz mode Webhook) and asserts they actually PASS - which only happens if the runtime kubeletconfig was delivered to the scanner and read. It then re-runs the scan on the same nodes and re-asserts, guarding against a non-idempotent delivery that only breaks on the 2nd+ scan on a node. This covers the emptyDir-based delivery introduced in the previous commit. CMP-4341 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
@Vincent056: This pull request references CMP-4341 which is a valid jira issue. Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "5.0.0" version, but no target version was set. DetailsIn response to this:
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 openshift-eng/jira-lifecycle-plugin repository. |
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: Vincent056 The full list of commands accepted by this bot can be found here. The pull request process is described here DetailsNeeds approval from an approver in each of these files:
Approvers can indicate their approval by writing |
|
Companion content PR (must merge together): ComplianceAsCode/content#14822 |
|
🤖 To deploy this PR, run the following command: |
|
/retest |
|
All PipelineRuns for this commit have already succeeded. Use |
|
@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. |
Summary
The node scanner reads the runtime kubeletconfig from a fixed path. Until now the operator made it available by symlinking it onto the host under
/var/run/compliance-operator/kubeletconfig(→ the kubeletconfig ConfigMap mount). That approach is fragile:ln -sis not idempotent: the symlink persists on the host/runtmpfs across scans, so the 2nd+ scan on a node hits the existing symlink and tries to write inside the read-only ConfigMap mount, failing withln: ... Read-only file system;| /bin/true, so the scan silently proceeds with no kubeletconfig — every kubeletyamlfile_valuecheck withcheck_existence: all_existthen fails;/host/var/runbeing writable, which is not guaranteed on all platforms.The runtime SSH config check already solves the same problem cleanly: it writes the effective config into a shared
runtime-configemptyDir mounted in both the init container and the scanner, and the rule reads it from/tmp/runtime/....This change makes runtime kubeletconfig use the same pattern: the init container now copies the kubeletconfig ConfigMap into
/host/tmp/runtime/openscap-kubeletconfig(the shared emptyDir), and the scanner reads it there. No host symlink, no/var/run, no read-only/idempotency issues.Companion content change (required)
This is a coordinated change. The kubelet rules'
yamlfile_valuefilepathmust move to/tmp/runtime/openscap-kubeletconfig:ComplianceAsCode/content PR: (linked below once opened)
Tests
TestKubeletConfigIsScannedAcrossReruns(serial e2e): scans two kubelet rules that PASS on a default node and asserts they actually PASS (only possible if the runtime kubeletconfig was delivered + read), then re-runs the scan on the same nodes and re-asserts — covering the non-idempotent-delivery regression.make verify(vet + gosec) cleango build ./...,go vet, unit tests passCMP-4341