fix: add spec.security.seLinuxRelabel opt-out for relabel init container - #98
Merged
Conversation
The operator unconditionally adds a privileged "selinux-relabel" init container whenever persistence is enabled. On clusters where SELinux relabeling does not apply (NFS-backed storage, or nodes that are not SELinux-enforcing such as Ubuntu with AppArmor), the container's chcon fails permanently with "Operation not supported", leaving the pod stuck in Init:CrashLoopBackOff and the Service returning 503. There was no way to disable it via the Instance CRD. Add a backward-compatible opt-out field, spec.security.seLinuxRelabel (*bool, default true). The init container is now gated on both PersistenceEnabled and SELinuxRelabelEnabled. Unset preserves today's behavior so existing SELinux-enforcing clusters are unaffected; an explicit false skips the init container entirely. Closes #96 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Root cause
internal/resources/podtemplate.gounconditionally appends a privilegedselinux-relabelinit container whenever persistence is enabled. The only gate wasPersistenceEnabled(instance).The init container runs
chcon -R system_u:object_r:container_file_t:<level> /paperclipto make the data volume's MCS categories match the pod's SELinux level. On SELinux-enforcing nodes this is required. But on clusters where relabeling does not apply,chconfails permanently:In those cases
chconreturnsOperation not supported, the init container never succeeds, the pod is stuck inInit:CrashLoopBackOff, and the Service returns 503. There was no CRD field to disable it (issue #96).The fix: an opt-out CRD field
Added a backward-compatible opt-out field:
spec.security.seLinuxRelabel(*bool)SecuritySpecinapi/v1alpha1/paperclipinstance_types.go. Chosen because the relabel is a security concern and the init container already reads its SELinux level fromspec.security.podSecurityContext.seLinuxOptions-- this is the least-surprising home and sits next to the siblingnetworkPolicy.enabled/ persistenceenabledopt-out fields.true(kubebuilder default), which preserves today's behavior: the init container is still added whenever persistence is enabled. Existing SELinux-enforcing clusters are therefore completely unaffected.*bool) so an explicitfalsesurvives marshaling instead of being dropped by omitempty and re-defaulted to true by the API server on every controller update (same bug class already documented forPersistenceSpec.EnabledandNetworkPolicySpec.Enabled).CRD field
Gate
New resolver in
internal/resources/common.go(nil => true), mirroringNetworkPolicyEnabled:Podtemplate gate changed from:
to:
Everything else about the init container is identical.
Why existing SELinux clusters stay unaffected
Unset (the default for every existing CR) resolves to
true, so the init container is added exactly as before. We deliberately did not makechcon|| true-- on genuinely SELinux-enforcing clusters that would mask real relabel failures and let pods start with mislabeled data. The explicit opt-out is the non-surprising fix.Future enhancement (out of scope for this PR): auto-detect applicability (storage class / node SELinux mode) instead of requiring the operator to opt out.
Tests
Table-driven unit test
TestBuildStatefulSetSELinuxRelabelOptOutininternal/resources/resources_test.go:selinux-relabelinit container present (legacy preserved)E2E: added a low-effort assertion +
stsInitContainerNameshelper intest/e2e/e2e_test.goon the existinge2e-bootspec (persistence on, field unset) that theselinux-relabelinit container is present. Not run locally (requires a Kind cluster + real app image); CI e2e will exercise it.Docs
README.md: new "SELinux Relabel" subsection under Security documenting the field, itstruedefault, and when to set itfalse(NFS / non-SELinux clusters).Generated files
Ran
make generate && make manifests && make sync-chart-crds; committed:api/v1alpha1/zz_generated.deepcopy.goconfig/crd/bases/paperclip.inc_instances.yamlcharts/paperclip-operator/templates/crds/paperclip.inc_instances.yamlRe-running the make targets produces no drift.
Verification
gofmt -l .go vet ./...go build ./...go test ./internal/resources/git statusafter re-running make targetsgolangci-lint run ./...Closes #96
🤖 Generated with Claude Code