Skip to content

CONSOLE-5138: Enable readOnlyRootFilesystem for console and download pod#1123

Open
ableischwitz wants to merge 2 commits intoopenshift:mainfrom
ableischwitz:main
Open

CONSOLE-5138: Enable readOnlyRootFilesystem for console and download pod#1123
ableischwitz wants to merge 2 commits 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. ---> This was affecting only plugins which do version check the console. The example deployment lists the version as "0.0.1-snapshot" and this wasn't sufficient. Therefore no issues seen with ReadOnlyRootfilesystem enabled visible any more.

The addition should be fairly easy now, as only the defaultVolumeConfig and the resulting test will have to be adjusted.

Summary by CodeRabbit

  • Security Enhancements
    • Hardened container security by enforcing read-only root filesystems for console and downloads services.
    • Configured writable temporary storage volumes where necessary to ensure services function properly with read-only root filesystems.

@openshift-ci openshift-ci bot requested review from jhadvig and spadgett March 4, 2026 18:57
@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

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: 4cb23170-ddd0-403e-8d55-a0ef0a2174cb

📥 Commits

Reviewing files that changed from the base of the PR and between c1214cb and ea4062a.

⛔ Files ignored due to path filters (1)
  • pkg/console/subresource/deployment/deployment_test.go is excluded by !**/*_test.go
📒 Files selected for processing (1)
  • bindata/assets/deployments/downloads-deployment.yaml
🚧 Files skipped from review as they are similar to previous changes (1)
  • bindata/assets/deployments/downloads-deployment.yaml
📜 Recent review details
🧰 Additional context used
🔀 Multi-repo context openshift/console

[::openshift/console::] Findings

  • Downloads server requires a writable TempDir at runtime:

    • cmd/downloads/main.go:31 (defer os.RemoveAll(downloadsServerConfig.TempDir)) and 39 (http.FileServer(http.Dir(downloadsServerConfig.TempDir))) — downloads serves files from TempDir and removes it on exit.
    • cmd/downloads/config/downloads_config.go: declaration of TempDir (line ~56) and multiple uses creating directories and files under TempDir (lines ~275, 283, 295, 304–316, 306–308, 352, 361). These call createHTMLFile, os.Symlink, etc., indicating runtime writes to TempDir.
  • Cluster/resource types and tooling reference the same Kubernetes fields changed by the PR:

    • vendor/k8s.io/api/core/v1/types.go: ReadOnlyRootFilesystem field present (ReadOnlyRootFilesystem *bool) — confirms the PR modifies a standard Kubernetes field.
    • vendor/k8s.io/api/core/v1/types_swagger_doc_generated.go: doc string for "readOnlyRootFilesystem".
  • emptyDir is used widely in repo test/manifests and frontend fixtures (examples):

    • Multiple frontend test/fixture files include emptyDir volumes (e.g., frontend/packages/* test data and samples) — indicates emptyDir is an established pattern in this repo for ephemeral writable storage.
  • Other occurrences of /tmp usage in repo tooling:

    • pkg/helm/chartverifier/chart_verifier.go and pkg/helm/actions/config.go reference "/tmp" (repository cache), showing other components expect writable /tmp in some contexts.

Notes / caveats observed while searching

  • bindata/assets/deployments and pkg/console/subresource/deployment paths referenced in the PR were not present/readable in the checked-out workspace (sed/ls errors). The cmd/downloads and downloads_config.go results above are from repo files that were found. Verify the generated bindata and deployment manifests in the PR branch or build artifacts to confirm exact manifest changes.

Conclusion

  • The downloads server is a confirmed consumer that needs a writable filesystem at runtime; mounting an emptyDir at the TempDir path (/tmp) is necessary to make readOnlyRootFilesystem: true safe for the downloads container.
  • Kubernetes API types confirm readOnlyRootFilesystem is the correct field to set.
  • There are multiple repo examples of emptyDir usage, so adding an emptyDir mount is consistent with existing patterns.

Walkthrough

The changes enforce read-only root filesystems in Kubernetes deployment containers (console and download-server) by setting readOnlyRootFilesystem: true. To maintain functionality, writable /tmp directories are provided via emptyDir volumes. Supporting code changes add EmptyDir volume handling to the deployment generation logic.

Changes

Cohort / File(s) Summary
Kubernetes Deployment Manifests
bindata/assets/deployments/console-deployment.yaml, bindata/assets/deployments/downloads-deployment.yaml
Set readOnlyRootFilesystem: true in container securityContext. Downloads manifest additionally adds a tmp emptyDir volume and corresponding volumeMount at /tmp to enable writable temporary storage.
Deployment Generation Logic
pkg/console/subresource/deployment/deployment.go
Introduces isEmptyDir flag to volumeConfig for EmptyDir volume support, adds default "tmp" volume configuration at /tmp, and updates withConsoleVolumes to handle EmptyDir volume creation.
Test Fixtures and Validation
pkg/console/subresource/deployment/deployment_test.go
Updates test data structures to include tmpVolume and tmpVolumeMount entries across defaultVolumes, trustedVolumes, customLogoVolumes, allVolumes and their corresponding mount sets to reflect the new emptyDir volume in test scenarios.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~15 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
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@jhadvig jhadvig added ok-to-test Indicates a non-member PR verified by an org member that is safe to test. and removed needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. labels Mar 11, 2026
@jhadvig
Copy link
Member

jhadvig commented Mar 12, 2026

/retest

Copy link
Member

@jhadvig jhadvig left a comment

Choose a reason for hiding this comment

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

/approve
/lgtm

@openshift-ci openshift-ci bot added the lgtm Indicates that a PR is ready to be merged. label Mar 20, 2026
@openshift-ci
Copy link
Contributor

openshift-ci bot commented Mar 20, 2026

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: ableischwitz, jhadvig

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

The pull request process is described 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 approved Indicates a PR has been approved by an approver from all required OWNERS files. label Mar 20, 2026
@jhadvig
Copy link
Member

jhadvig commented Mar 20, 2026

QE Approver:
/assign @yapei
Docs Approver:
assign @jseseCCS
PX Approver:
/assign @rh-joshbeverly

@ableischwitz ableischwitz changed the title Enable readOnlyRootFilesystem for console and download pod CONSOLE-5138: Enable readOnlyRootFilesystem for console and download pod Mar 20, 2026
@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Mar 20, 2026
@openshift-ci-robot
Copy link
Contributor

openshift-ci-robot commented Mar 20, 2026

@ableischwitz: This pull request references CONSOLE-5138 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 "4.22.0" version, but no target version was set.

Details

In response to this:

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. ---> This was affecting only plugins which do version check the console. The example deployment lists the version as "0.0.1-snapshot" and this wasn't sufficient. Therefore no issues seen with ReadOnlyRootfilesystem enabled visible any more.

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.

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.

@rh-joshbeverly
Copy link

/label px-approved

@openshift-ci openshift-ci bot added the px-approved Signifies that Product Support has signed off on this PR label Mar 20, 2026
@yanpzhan
Copy link

Checked on cluster launched against the pr, the 'readOnlyRootFilesystem' in console deployment was set true, 'readOnlyRootFilesystem' in console deployment was set false:

# oc get deployment console -n openshift-console -o jsonpath='{.spec.template.spec.containers[0].securityContext}'
{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"readOnlyRootFilesystem":true}
# oc get deployment downloads -n openshift-console -o jsonpath='{.spec.template.spec.containers[0].securityContext}'
{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"readOnlyRootFilesystem":false}
# oc get pod -n openshift-console
NAME                         READY   STATUS    RESTARTS   AGE
console-6dc7c64d77-4jp4w     1/1     Running   0          16m
console-6dc7c64d77-x9b2m     1/1     Running   0          3m31s
downloads-745bc685f4-fccp9   1/1     Running   0          3m13s
downloads-745bc685f4-xshqj   1/1     Running   0          16m

/verified by yanpzhan

@openshift-ci-robot openshift-ci-robot added the verified Signifies that the PR passed pre-merge verification criteria label Mar 23, 2026
@openshift-ci-robot
Copy link
Contributor

@yanpzhan: This PR has been marked as verified by yanpzhan.

Details

In response to this:

Checked on cluster launched against the pr, the 'readOnlyRootFilesystem' in console deployment was set true, 'readOnlyRootFilesystem' in console deployment was set false:

# oc get deployment console -n openshift-console -o jsonpath='{.spec.template.spec.containers[0].securityContext}'
{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"readOnlyRootFilesystem":true}
# oc get deployment downloads -n openshift-console -o jsonpath='{.spec.template.spec.containers[0].securityContext}'
{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"readOnlyRootFilesystem":false}
# oc get pod -n openshift-console
NAME                         READY   STATUS    RESTARTS   AGE
console-6dc7c64d77-4jp4w     1/1     Running   0          16m
console-6dc7c64d77-x9b2m     1/1     Running   0          3m31s
downloads-745bc685f4-fccp9   1/1     Running   0          3m13s
downloads-745bc685f4-xshqj   1/1     Running   0          16m

/verified by yanpzhan

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.

@ableischwitz
Copy link
Author

@yanpzhan @jhadvig the download deployment should be with ReadOnlyRootFilesystem too - I'll update the pull request with that addition.

@openshift-ci-robot openshift-ci-robot removed the verified Signifies that the PR passed pre-merge verification criteria label Mar 24, 2026
@openshift-ci openshift-ci bot removed the lgtm Indicates that a PR is ready to be merged. label Mar 24, 2026
@openshift-ci
Copy link
Contributor

openshift-ci bot commented Mar 24, 2026

New changes are detected. LGTM label has been removed.

@openshift-ci-robot
Copy link
Contributor

openshift-ci-robot commented Mar 24, 2026

@ableischwitz: This pull request references CONSOLE-5138 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 "4.22.0" version, but no target version was set.

Details

In response to this:

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. ---> This was affecting only plugins which do version check the console. The example deployment lists the version as "0.0.1-snapshot" and this wasn't sufficient. Therefore no issues seen with ReadOnlyRootfilesystem enabled visible any more.

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 read-only for enhanced security.

  • Removed explicit Content Security Policy toggle from operator and server config paths.

  • Updated build base images.

  • New Features

  • Downloads service now includes an ephemeral writable /tmp volume to support runtime temporary files.

  • Tests

  • Test fixtures updated to reflect added temporary volume and mounts.

  • Documentation

  • CI/review configuration updated.

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.

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.

🧹 Nitpick comments (1)
.coderabbit.yaml (1)

16-18: Avoid blanket exclusion of all Go tests from review scope.

Line 18 excludes every *_test.go file, which can hide important regression/safety signals in PRs that rely on test updates. Prefer excluding only noisy test paths instead of all Go tests.

Suggested adjustment
   path_filters:
   - "!vendor/**"
-  - "!**/*_test.go"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.coderabbit.yaml around lines 16 - 18, The path_filters currently
blanket-excludes all Go tests via the pattern "!**/*_test.go" which hides
important test changes; update the configuration by removing or narrowing that
pattern in the path_filters section (leave the vendor exclusion "!vendor/**"
as-is) and replace the blanket test exclusion with targeted exclusions for known
noisy test directories or file patterns (e.g., specific fixtures or
generated-test folders) so that most *_test.go files remain in review scope;
refer to the path_filters entry and the "!**/*_test.go" pattern to locate and
change this.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In @.coderabbit.yaml:
- Around line 16-18: The path_filters currently blanket-excludes all Go tests
via the pattern "!**/*_test.go" which hides important test changes; update the
configuration by removing or narrowing that pattern in the path_filters section
(leave the vendor exclusion "!vendor/**" as-is) and replace the blanket test
exclusion with targeted exclusions for known noisy test directories or file
patterns (e.g., specific fixtures or generated-test folders) so that most
*_test.go files remain in review scope; refer to the path_filters entry and the
"!**/*_test.go" pattern to locate and change this.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: 104d4cf6-ed06-4757-9817-152fe5a6341d

📥 Commits

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

⛔ Files ignored due to path filters (3)
  • pkg/console/subresource/configmap/configmap_test.go is excluded by !**/*_test.go
  • pkg/console/subresource/configmap/tech_preview_test.go is excluded by !**/*_test.go
  • pkg/console/subresource/deployment/deployment_test.go is excluded by !**/*_test.go
📒 Files selected for processing (9)
  • .coderabbit.yaml
  • Dockerfile.ocp
  • bindata/assets/deployments/downloads-deployment.yaml
  • pkg/console/operator/operator.go
  • pkg/console/operator/sync_v400.go
  • pkg/console/starter/starter.go
  • pkg/console/subresource/configmap/configmap.go
  • pkg/console/subresource/consoleserver/config_builder.go
  • pkg/console/subresource/consoleserver/types.go
💤 Files with no reviewable changes (3)
  • pkg/console/operator/sync_v400.go
  • pkg/console/starter/starter.go
  • pkg/console/subresource/configmap/configmap.go
📜 Review details
🧰 Additional context used
📓 Path-based instructions (3)
pkg/**/*.go

⚙️ CodeRabbit configuration file

pkg/**/*.go: Review Go code following OpenShift operator patterns.
See CONVENTIONS.md for coding standards and patterns.
Controllers should use the library-go factory pattern.
Status conditions should use status.Handle* functions.

Files:

  • pkg/console/operator/operator.go
  • pkg/console/subresource/consoleserver/config_builder.go
  • pkg/console/subresource/consoleserver/types.go
**

⚙️ CodeRabbit configuration file

-Focus on major issues impacting performance, readability, maintainability and security. Avoid nitpicks and avoid verbosity.

Files:

  • pkg/console/operator/operator.go
  • Dockerfile.ocp
  • pkg/console/subresource/consoleserver/config_builder.go
  • bindata/assets/deployments/downloads-deployment.yaml
  • pkg/console/subresource/consoleserver/types.go
bindata/assets/**/*.yaml

⚙️ CodeRabbit configuration file

bindata/assets/**/*.yaml: Review YAML assets for Kubernetes resource correctness.
Ensure proper annotations for cluster profiles.

Files:

  • bindata/assets/deployments/downloads-deployment.yaml
🔀 Multi-repo context openshift/console

[::openshift/console::]

  • downloads server writes files to a temp dir at runtime:

    • cmd/downloads/main.go: creates DownloadsServerConfig and defers os.RemoveAll(downloadsServerConfig.TempDir). (cmd/downloads/main.go:31-34) — consumer behavior requires a writable filesystem for TempDir inside the container.
    • cmd/downloads uses downloadsServerConfig.TempDir as the file server root (cmd/downloads/main.go:39).
    • downloads config implementation manipulates/creates directories under DownloadsServerConfig.TempDir (cmd/downloads/config/downloads_config.go:275–316) — explicit directory creation and file writes occur at runtime.
  • Docker image and packaging for downloads:

    • Dockerfile.downloads: installs binaries and places defaultArtifactsConfig.yaml under /opt/downloads; CMD runs the downloads binary that serves TempDir (Dockerfile.downloads:18–28). If the container root is read-only, the downloads process still needs a writable path for TempDir (not /opt/downloads).
  • Kubernetes API types confirm fields used:

    • vendor/k8s.io/api/core/v1/types.go and generated proto/docs include ReadOnlyRootFilesystem and EmptyDir volume types (vendor/k8s.io/api/core/v1/types.go:8158 and generated.proto). These show the API fields the PR modifies are standard Kubernetes fields.
  • Repo contains numerous examples of emptyDir usage in front-end/integration-test fixtures (frontend/**: various files referencing emptyDir), indicating emptyDir is an established pattern in this repo for ephemeral writable storage.

Implication backed by observed files: the downloads server requires a writable TempDir at runtime (writes HTML and artifacts into TempDir). To enable readOnlyRootFilesystem for the downloads container you must mount an emptyDir (or other writable volume) at the path used for TempDir. The repository contains Dockerfile.downloads and cmd/downloads/* that show where writes occur and where a mount is needed.

🔇 Additional comments (7)
Dockerfile.ocp (1)

1-1: Version bump is consistent across build and runtime stages.

No blocking concerns here; keeping both stages on the same OCP minor is a clean update.

Also applies to: 8-8

bindata/assets/deployments/downloads-deployment.yaml (2)

52-59: Read-only root filesystem is correctly paired with writable /tmp.

This hardening is implemented safely: startup writes to /tmp remain functional via the new mount.


267-269: emptyDir volume wiring is correct.

tmp is declared at pod level and matches the container volumeMount, which is the right pattern for ephemeral writable space.

.coderabbit.yaml (3)

1-4: Good config modernization and verbosity setup.

The language, inheritance enablement, and review detail visibility changes look clean and consistent.

Also applies to: 15-15


48-53: Code-guideline file pattern coverage looks good.

Including AGENTS.md, CLAUDE.md, ARCHITECTURE.md, CONVENTIONS.md, and TESTING.md should improve review context quality.


54-62: Strong linked-repository guidance.

This instruction is specific and should help catch cross-repo config-structure drift between operator and console.

pkg/console/subresource/consoleserver/types.go (1)

20-35: The concern about wire-format compatibility is incorrect. The operator's config_builder.go never populated ContentSecurityPolicyEnabled when constructing the Config struct (only ContentSecurityPolicy is set), so console was already receiving this field as missing/false. Removing the field from the schema simply aligns it with what was actually being emitted. No code found in either repository reads or depends on contentSecurityPolicyEnabled, so this removal does not introduce a compatibility issue with any supported console version.

			> Likely an incorrect or invalid review comment.

@ableischwitz ableischwitz marked this pull request as draft March 24, 2026 09:13
@openshift-ci openshift-ci bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Mar 24, 2026
@ableischwitz ableischwitz marked this pull request as ready for review March 24, 2026 10:28
@openshift-ci openshift-ci bot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Mar 24, 2026
@openshift-ci openshift-ci bot requested a review from jhadvig March 24, 2026 10:28
@openshift-ci-robot
Copy link
Contributor

openshift-ci-robot commented Mar 24, 2026

@ableischwitz: This pull request references CONSOLE-5138 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 "4.22.0" version, but no target version was set.

Details

In response to this:

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. ---> This was affecting only plugins which do version check the console. The example deployment lists the version as "0.0.1-snapshot" and this wasn't sufficient. Therefore no issues seen with ReadOnlyRootfilesystem enabled visible any more.

The addition should be fairly easy now, as only the defaultVolumeConfig and the resulting test will have to be adjusted.

Summary by CodeRabbit

  • Security Enhancements
  • Hardened container security by enforcing read-only root filesystems for console and downloads services.
  • Configured writable temporary storage volumes where necessary to ensure services function properly with read-only root filesystems.

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.

@ableischwitz
Copy link
Author

/retest

@yanpzhan
Copy link

@ableischwitz @jhadvig Checked against latest code, now downloads deployment also set "readOnlyRootFilesystem" as 'true':

# oc get deployment downloads -n openshift-console -o jsonpath='{.spec.template.spec.containers[0].securityContext}'
{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"readOnlyRootFilesystem":true}

@ableischwitz
Copy link
Author

/retest-required

@openshift-ci
Copy link
Contributor

openshift-ci bot commented Mar 25, 2026

@ableischwitz: all tests passed!

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.

@yanpzhan
Copy link

/verified by yanpzhan

@openshift-ci-robot openshift-ci-robot added the verified Signifies that the PR passed pre-merge verification criteria label Mar 26, 2026
@openshift-ci-robot
Copy link
Contributor

@yanpzhan: This PR has been marked as verified by yanpzhan.

Details

In response to this:

/verified by yanpzhan

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.

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

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. ok-to-test Indicates a non-member PR verified by an org member that is safe to test. px-approved Signifies that Product Support has signed off on this PR verified Signifies that the PR passed pre-merge verification criteria

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants