Skip to content

Enable readOnlyRootFilesystem for console and download pod#1123

Open
ableischwitz wants to merge 1 commit intoopenshift:mainfrom
ableischwitz:main
Open

Enable readOnlyRootFilesystem for console and download pod#1123
ableischwitz wants to merge 1 commit intoopenshift:mainfrom
ableischwitz:main

Conversation

@ableischwitz
Copy link

@ableischwitz ableischwitz commented Mar 4, 2026

This pull request addresses the enablement of readOnlyRootFilesystem for the console and download pods managed by the openshift-console-operator.

In order to allow the download pod to save it's Python-script to /tmp an emptyDir for this directory was added as a volume. Same for the console pod.
While the console and client-downloads work as expected, there may be an issue with dynamic-plugins. They may need to get their own dedicated volumes, which location I wasn't able to identify.
The addition should be fairly easy now, as only the defaultVolumeConfig and the resulting test will have to be adjusted.

Summary by CodeRabbit

  • Chores
    • Console container filesystem is now configured as read-only for enhanced security.
    • Downloads service now includes temporary writable storage support.

@openshift-ci openshift-ci bot requested review from jhadvig and spadgett March 4, 2026 18:57
@openshift-ci
Copy link
Contributor

openshift-ci bot commented Mar 4, 2026

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: ableischwitz
Once this PR has been reviewed and has the lgtm label, please assign therealjon for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-ci openshift-ci bot added the needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. label Mar 4, 2026
@openshift-ci
Copy link
Contributor

openshift-ci bot commented Mar 4, 2026

Hi @ableischwitz. Thanks for your PR.

I'm waiting for a openshift member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should join the org to skip this step.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

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.

@coderabbitai
Copy link

coderabbitai bot commented Mar 4, 2026

Note

.coderabbit.yaml has unrecognized properties

CodeRabbit is using all valid settings from your configuration. Unrecognized properties (listed below) have been ignored and may indicate typos or deprecated fields that can be removed.

⚠️ Parsing warnings (1)
Validation error: Unrecognized key(s) in object: 'version', 'path_filters'
⚙️ Configuration instructions
  • Please see the configuration documentation for more information.
  • You can also validate your configuration using the online YAML validator.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Walkthrough

The changes enable read-only root filesystems in console and downloads Kubernetes deployments by adding a temporary writable emptyDir volume at /tmp. Code modifications support EmptyDir volume configuration in deployment generation, with test fixtures updated accordingly.

Changes

Cohort / File(s) Summary
Kubernetes Deployment Manifests
bindata/assets/deployments/console-deployment.yaml, bindata/assets/deployments/downloads-deployment.yaml
Console deployment sets readOnlyRootFilesystem to true; downloads deployment adds emptyDir volume named "tmp" with mount at /tmp.
Deployment Code Generation
pkg/console/subresource/deployment/deployment.go
Introduces isEmptyDir flag to volumeConfig; adds "tmp" volume entry at /tmp with isEmptyDir flag; updates volume assembly logic to handle EmptyDir volumes.
Deployment Tests
pkg/console/subresource/deployment/deployment_test.go
Updates test fixtures across TestWithConsoleVolumes and TestDefaultDownloadsDeployment to include tmpVolume and tmpVolumeMount in default and derived volume sets.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly reflects the main changes: enabling readOnlyRootFilesystem for console and download pods, which is the primary security enhancement across the changeset.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs).
Share your feedback on Discord.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
bindata/assets/deployments/downloads-deployment.yaml (1)

52-59: ⚠️ Potential issue | 🟠 Major

download-server root filesystem is still writable, so the PR objective is only partially implemented.

You added the /tmp EmptyDir correctly, but readOnlyRootFilesystem is still false. That leaves the downloads container outside the intended hardening scope.

🔧 Proposed fix
          securityContext:
-            readOnlyRootFilesystem: false
+            readOnlyRootFilesystem: true
             allowPrivilegeEscalation: false
             capabilities:
               drop:
               - ALL

Also update the corresponding expected value in pkg/console/subresource/deployment/deployment_test.go (downloadsDeploymentPodSpecSingleReplica securityContext) from utilpointer.Bool(false) to utilpointer.Bool(true).

Also applies to: 267-269

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@bindata/assets/deployments/downloads-deployment.yaml` around lines 52 - 59,
The download-server container's PodSecurityContext still has
readOnlyRootFilesystem: false so make it true: locate the download-server
container spec in the deployment YAML and change readOnlyRootFilesystem to true
(ensure you keep allowPrivilegeEscalation:false and capabilities.drop: ALL and
the /tmp EmptyDir volumeMount). Also update the test expectation named
downloadsDeploymentPodSpecSingleReplica in deployment_test.go to use
utilpointer.Bool(true) instead of utilpointer.Bool(false) so the unit test
matches the hardened manifest; apply the same readOnlyRootFilesystem change
where it appears again around the other occurrence (lines referenced in the
review).
🧹 Nitpick comments (1)
pkg/console/subresource/deployment/deployment.go (1)

308-315: Enforce exclusive volume source selection to avoid silent overwrite.

isSecret, isConfigMap, and isEmptyDir are documented as mutually exclusive, but the current independent if chain can overwrite vols[i] if more than one flag is ever set.

♻️ Proposed defensive refactor
-	for i, item := range volumeConfig {
-		if item.isSecret {
-			vols[i] = corev1.Volume{
-				Name: item.name,
-				VolumeSource: corev1.VolumeSource{
-					Secret: &corev1.SecretVolumeSource{
-						SecretName: item.name,
-					},
-				},
-			}
-		}
-		if item.isConfigMap {
-			var items []corev1.KeyToPath
-			for key, val := range item.mappedKeys {
-				items = append(items, corev1.KeyToPath{
-					Key:  key,
-					Path: val,
-				})
-			}
-			vols[i] = corev1.Volume{
-				Name: item.name,
-				VolumeSource: corev1.VolumeSource{
-					ConfigMap: &corev1.ConfigMapVolumeSource{
-						LocalObjectReference: corev1.LocalObjectReference{
-							Name: item.name,
-						},
-						Items: items,
-					},
-				},
-			}
-		}
-		if item.isEmptyDir {
-			vols[i] = corev1.Volume{
-				Name: item.name,
-				VolumeSource: corev1.VolumeSource{
-					EmptyDir: &corev1.EmptyDirVolumeSource{},
-				},
-			}
-		}
-	}
+	for i, item := range volumeConfig {
+		switch {
+		case item.isSecret && !item.isConfigMap && !item.isEmptyDir:
+			vols[i] = corev1.Volume{
+				Name: item.name,
+				VolumeSource: corev1.VolumeSource{
+					Secret: &corev1.SecretVolumeSource{
+						SecretName: item.name,
+					},
+				},
+			}
+		case item.isConfigMap && !item.isSecret && !item.isEmptyDir:
+			var items []corev1.KeyToPath
+			for key, val := range item.mappedKeys {
+				items = append(items, corev1.KeyToPath{Key: key, Path: val})
+			}
+			vols[i] = corev1.Volume{
+				Name: item.name,
+				VolumeSource: corev1.VolumeSource{
+					ConfigMap: &corev1.ConfigMapVolumeSource{
+						LocalObjectReference: corev1.LocalObjectReference{Name: item.name},
+						Items:                items,
+					},
+				},
+			}
+		case item.isEmptyDir && !item.isSecret && !item.isConfigMap:
+			vols[i] = corev1.Volume{
+				Name: item.name,
+				VolumeSource: corev1.VolumeSource{
+					EmptyDir: &corev1.EmptyDirVolumeSource{},
+				},
+			}
+		default:
+			klog.Warningf("invalid volumeConfig for %q: exactly one source type must be set", item.name)
+		}
+	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/console/subresource/deployment/deployment.go` around lines 308 - 315, The
current independent checks for item.isSecret, item.isConfigMap, and
item.isEmptyDir can silently overwrite vols[i]; change this to enforce
exclusivity by replacing the independent ifs with either an if/else-if chain or
a validation that detects when more than one of item.isSecret, item.isConfigMap,
item.isEmptyDir is true and returns an error (or logs and skips) before
assigning vols[i]; ensure the assignment to vols[i] (corev1.Volume with the
appropriate VolumeSource) only happens once for the selected type to avoid
silent overwrites.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@bindata/assets/deployments/downloads-deployment.yaml`:
- Around line 52-59: The download-server container's PodSecurityContext still
has readOnlyRootFilesystem: false so make it true: locate the download-server
container spec in the deployment YAML and change readOnlyRootFilesystem to true
(ensure you keep allowPrivilegeEscalation:false and capabilities.drop: ALL and
the /tmp EmptyDir volumeMount). Also update the test expectation named
downloadsDeploymentPodSpecSingleReplica in deployment_test.go to use
utilpointer.Bool(true) instead of utilpointer.Bool(false) so the unit test
matches the hardened manifest; apply the same readOnlyRootFilesystem change
where it appears again around the other occurrence (lines referenced in the
review).

---

Nitpick comments:
In `@pkg/console/subresource/deployment/deployment.go`:
- Around line 308-315: The current independent checks for item.isSecret,
item.isConfigMap, and item.isEmptyDir can silently overwrite vols[i]; change
this to enforce exclusivity by replacing the independent ifs with either an
if/else-if chain or a validation that detects when more than one of
item.isSecret, item.isConfigMap, item.isEmptyDir is true and returns an error
(or logs and skips) before assigning vols[i]; ensure the assignment to vols[i]
(corev1.Volume with the appropriate VolumeSource) only happens once for the
selected type to avoid silent overwrites.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 54fa7746-24cd-4555-b144-04cd547bb25f

📥 Commits

Reviewing files that changed from the base of the PR and between 5e38222 and 29c40d9.

📒 Files selected for processing (4)
  • bindata/assets/deployments/console-deployment.yaml
  • bindata/assets/deployments/downloads-deployment.yaml
  • pkg/console/subresource/deployment/deployment.go
  • pkg/console/subresource/deployment/deployment_test.go

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

Labels

needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant