Skip to content

OCPCLOUD-1645: Security: Configure RBAC for capi operator#493

Open
sunzhaohua2 wants to merge 1 commit intoopenshift:mainfrom
sunzhaohua2:rbac
Open

OCPCLOUD-1645: Security: Configure RBAC for capi operator#493
sunzhaohua2 wants to merge 1 commit intoopenshift:mainfrom
sunzhaohua2:rbac

Conversation

@sunzhaohua2
Copy link
Contributor

@sunzhaohua2 sunzhaohua2 commented Mar 12, 2026

This PR replaces the insecure wildcard RBAC permissions (*:*:*) with explicit, scoped permissions following the principle of least privilege

Summary by CodeRabbit

  • Chores

    • Replaced broad wildcard RBAC with explicit, granular cluster- and namespace-scoped permissions for cluster controller components, reducing permission surface.
    • Added a namespace-scoped capi-controllers role with scoped permissions for core resources, leases, apps, and provider RBAC.
    • Renamed and tightened pull-secret role to cluster-capi-operator-pull-secret, restricting read access to the specific pull secret.
  • New Features

    • Added cluster-capi-operator:cluster-reader ClusterRole to provide aggregated read-only access across cluster API resources and statuses.

@openshift-ci-robot
Copy link

Pipeline controller notification
This repo is configured to use the pipeline controller. Second-stage tests will be triggered either automatically or after lgtm label is added, depending on the repository configuration. The pipeline controller will automatically detect which contexts are required and will utilize /test Prow commands to trigger the second stage.

For optional jobs, comment /test ? to see a list of all defined jobs. To trigger manually all jobs from second stage use /pipeline required command.

This repository is configured in: LGTM mode

@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 12, 2026
@openshift-ci-robot
Copy link

openshift-ci-robot commented Mar 12, 2026

@sunzhaohua2: This pull request references OCPCLOUD-1645 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 PR replaces the insecure wildcard RBAC permissions (*:*:*) with explicit, scoped permissions following the principle of least privilege

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.

@coderabbitai
Copy link

coderabbitai bot commented Mar 12, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Replaced wildcard RBAC in openshift-capi-controllers ClusterRole with explicit apiGroups/resources/verbs; added namespace Role capi-controllers in openshift-cluster-api; introduced cluster-capi-operator:cluster-reader ClusterRole; renamed/scoped pull-secret Role to cluster-capi-operator-pull-secret in openshift-config.

Changes

Cohort / File(s) Summary
RBAC manifest
manifests/0000_30_cluster-api_03_rbac_roles.yaml
Expanded ClusterRole openshift-capi-controllers from wildcard rules to explicit multi-section rules (authentication/authorization, core resources, coordination.k8s.io leases, apps, rbac, cluster.x CRs and status, infra providers, machine.openshift.io, config.openshift.io, apiextensions/webhooks, metal3/IPAM, MachineConfig, CRD/status, etc.). Added namespace-scoped Role capi-controllers in openshift-cluster-api with detailed core/apps/RBAC/leases permissions. Added new ClusterRole cluster-capi-operator:cluster-reader (read-only aggregation). Renamed pull-secret Role to cluster-capi-operator-pull-secret in openshift-config, restricting to secrets with resourceNames: [pull-secret] and get verb. Pay attention to removal of wildcards and redistributed verbs/resource scoping.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Test Structure And Quality ❓ Inconclusive The custom check requests Ginkgo test code quality review, but the PR exclusively modifies RBAC manifest YAML files with no test code changes. Clarify if this check applies to the PR. If test review is needed, provide specific test files; otherwise adjust criteria to assess RBAC manifest changes.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and clearly summarizes the main change: configuring RBAC (role-based access control) for the capi operator, which aligns with the core objective of replacing wildcard permissions with explicit, scoped permissions.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Stable And Deterministic Test Names ✅ Passed PR modifies only YAML RBAC manifest files with no Ginkgo test code added or modified.

✏️ 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
📝 Coding Plan
  • Generate coding plan for human review comments

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

@sunzhaohua2
Copy link
Contributor Author

/hold

for test

@openshift-ci openshift-ci bot added the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Mar 12, 2026
@openshift-ci
Copy link
Contributor

openshift-ci bot commented Mar 12, 2026

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign damdo 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-robot
Copy link

openshift-ci-robot commented Mar 12, 2026

@sunzhaohua2: This pull request references OCPCLOUD-1645 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 PR replaces the insecure wildcard RBAC permissions (*:*:*) with explicit, scoped permissions following the principle of least privilege

Summary by CodeRabbit

  • Chores
  • Refined access control permissions to follow the principle of least privilege, replacing broad permissions with explicit, granular resource-level access grants across multiple system components and namespaces.
  • Improved security posture by narrowing the scope of permissions for critical cluster operations.

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.

Actionable comments posted: 2

🧹 Nitpick comments (1)
manifests/0000_30_cluster-api_03_rbac_roles.yaml (1)

187-191: Remove the legacy extensions DaemonSet grant if the supported 4.22 floor no longer serves that API group.

If this payload only targets modern Kubernetes/OpenShift, this rule is dead privilege and weakens the cleanup. Keeping the apps DaemonSet read is enough unless there is still an explicit compatibility path using extensions.

Suggested diff
-# Extensions (legacy daemonsets support during drain operations)
-- apiGroups: [extensions]
-  resources:
-  - daemonsets
-  verbs: [get, list, watch]
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@manifests/0000_30_cluster-api_03_rbac_roles.yaml` around lines 187 - 191, The
RBAC rule currently grants read access to DaemonSets in the legacy apiGroup
"extensions"; remove the dead-privilege entry by deleting the apiGroups:
[extensions] stanza for the DaemonSet rule and ensure the equivalent rule for
apiGroups: [apps] (resources: ["daemonsets"], verbs: ["get","list","watch"])
remains or is present; if backward compatibility is required instead, gate
inclusion behind a clear compatibility flag or comment, but otherwise drop the
"extensions" grant entirely.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@manifests/0000_30_cluster-api_03_rbac_roles.yaml`:
- Around line 284-318: Update the existing RoleBinding named
cluster-capi-operator-pull-secret in the openshift-config namespace so its
roleRef.name points to the new Role capi-controllers (instead of the old role
name), and add a new RoleBinding in the openshift-config-managed namespace that
binds the capi-controllers Role to the same subject(s) (serviceAccount and
namespace) used by the operator (mirror the subjects from
cluster-capi-operator-pull-secret) so the operator retains access to the
pull-secret and managed configmaps; ensure the new RoleBinding.roleRef.apiGroup
is rbac.authorization.k8s.io and kind is Role.
- Around line 23-27: Remove the unnecessary "create" verb from the Nodes RBAC
rule: in the rule that lists resources: - nodes and verbs: [get, list, watch,
create, update, patch, delete] remove "create" so the verbs only include the
operations performed by this controller (get, list, watch, update, patch,
delete); update the manifest entry that defines the Node management RBAC rule
(the section referencing "nodes" and its "verbs") to enforce least privilege.

---

Nitpick comments:
In `@manifests/0000_30_cluster-api_03_rbac_roles.yaml`:
- Around line 187-191: The RBAC rule currently grants read access to DaemonSets
in the legacy apiGroup "extensions"; remove the dead-privilege entry by deleting
the apiGroups: [extensions] stanza for the DaemonSet rule and ensure the
equivalent rule for apiGroups: [apps] (resources: ["daemonsets"], verbs:
["get","list","watch"]) remains or is present; if backward compatibility is
required instead, gate inclusion behind a clear compatibility flag or comment,
but otherwise drop the "extensions" grant entirely.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Pro

Run ID: 3369d44c-2e4e-4203-8176-98f516b64c26

📥 Commits

Reviewing files that changed from the base of the PR and between 48b44cd and 5cb0fa7.

📒 Files selected for processing (1)
  • manifests/0000_30_cluster-api_03_rbac_roles.yaml

@openshift-ci-robot
Copy link

openshift-ci-robot commented Mar 12, 2026

@sunzhaohua2: This pull request references OCPCLOUD-1645 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 PR replaces the insecure wildcard RBAC permissions (*:*:*) with explicit, scoped permissions following the principle of least privilege

Summary by CodeRabbit

  • Chores
  • Replaced broad wildcard RBAC permissions with explicit, granular resource- and namespace-scoped permissions across cluster controller components.
  • Reduced permission scopes for several existing roles and added a new role providing read access to managed configuration.
  • Resulting change tightens observable access surfaces and alters which resources and namespaces controllers can access.

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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@manifests/0000_30_cluster-api_03_rbac_roles.yaml`:
- Around line 40-46: The cluster-wide Role in
manifests/0000_30_cluster-api_03_rbac_roles.yaml currently grants
create/update/patch/delete on core namespaced resources (secrets, configmaps,
services, serviceaccounts); change that cluster-scoped rule to read-only (get,
list, watch) for those resources and remove create/update/patch/delete verbs,
and then add corresponding namespace-scoped Roles (or update existing Roles) to
grant the necessary write verbs for secrets, configmaps, services, and
serviceaccounts within each target namespace so writes remain only in
namespace-scoped Role bindings.
- Around line 210-215: The RBAC entry currently allows create/patch/delete on
roles and rolebindings cluster-wide; change it to a namespaced Role scoped to
the openshift-cluster-api namespace (instead of a ClusterRole) so the verbs on
the resources "roles" and "rolebindings" (and the verbs array [get, list, watch,
create, update, patch, delete]) only apply inside that namespace; alternatively
further tighten by setting resourceNames to the specific Role/RoleBinding names
the controller needs and ensure any RoleBinding/ClusterRoleBinding granting the
SA wider access is removed.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Pro

Run ID: 44c3b234-7847-4889-9e50-ef5c8ce7ba6b

📥 Commits

Reviewing files that changed from the base of the PR and between 5cb0fa7 and 5a43c38.

📒 Files selected for processing (1)
  • manifests/0000_30_cluster-api_03_rbac_roles.yaml

@openshift-ci-robot
Copy link

openshift-ci-robot commented Mar 12, 2026

@sunzhaohua2: This pull request references OCPCLOUD-1645 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 PR replaces the insecure wildcard RBAC permissions (*:*:*) with explicit, scoped permissions following the principle of least privilege

Summary by CodeRabbit

  • Chores
  • Replaced broad wildcard RBAC permissions with explicit, granular resource- and namespace-scoped permissions for cluster controller components.
  • Tightened several existing roles to limit verbs and target specific resources (including leader election leases and core secrets/configmaps/services), and scoped pull-secret access to a named secret with read-only permission.
  • Result: reduced permission surface and more restrictive controller access.

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.

@openshift-ci-robot
Copy link

openshift-ci-robot commented Mar 12, 2026

@sunzhaohua2: This pull request references OCPCLOUD-1645 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 PR replaces the insecure wildcard RBAC permissions (*:*:*) with explicit, scoped permissions following the principle of least privilege

Summary by CodeRabbit

  • Chores
  • Replaced broad wildcard RBAC permissions with explicit, granular resource- and namespace-scoped permissions for cluster controller components.
  • Added a new role (capi-controllers) with scoped permissions for core resources, leases, apps, and RBAC within the cluster-api namespace.
  • Renamed and tightened the pull-secret role to cluster-capi-operator-pull-secret, limiting access to the specific pull-secret with read-only permission.
  • Result: reduced permission surface and more restrictive controller access.

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.

@sunzhaohua2
Copy link
Contributor Author

/test ?

@openshift-ci
Copy link
Contributor

openshift-ci bot commented Mar 12, 2026

@sunzhaohua2: The following commands are available to trigger required jobs:

/test build
/test e2e-aws-capi-techpreview
/test e2e-aws-ovn
/test e2e-aws-ovn-serial-1of2
/test e2e-aws-ovn-serial-2of2
/test e2e-aws-ovn-techpreview
/test e2e-aws-ovn-techpreview-upgrade
/test e2e-azure-capi-techpreview
/test e2e-azure-ovn-techpreview-upgrade
/test e2e-gcp-capi-techpreview
/test e2e-gcp-ovn-techpreview
/test e2e-openstack-capi-techpreview
/test e2e-openstack-ovn-techpreview
/test e2e-vsphere-capi-techpreview
/test images
/test lint
/test okd-scos-images
/test unit
/test vendor
/test verify-deps

The following commands are available to trigger optional jobs:

/test e2e-azure-ovn-techpreview
/test e2e-metal3-capi-techpreview
/test okd-scos-e2e-aws-ovn
/test regression-clusterinfra-aws-ipi-techpreview-capi

Use /test all to run the following jobs that were automatically triggered:

pull-ci-openshift-cluster-capi-operator-main-build
pull-ci-openshift-cluster-capi-operator-main-images
pull-ci-openshift-cluster-capi-operator-main-lint
pull-ci-openshift-cluster-capi-operator-main-okd-scos-images
pull-ci-openshift-cluster-capi-operator-main-unit
pull-ci-openshift-cluster-capi-operator-main-vendor
pull-ci-openshift-cluster-capi-operator-main-verify-deps
Details

In response to this:

/test ?

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.

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.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@manifests/0000_30_cluster-api_03_rbac_roles.yaml`:
- Around line 232-250: Remove the unused parent-resource verbs by editing the
RBAC rule for the resource "clusteroperators": remove the "update" and "patch"
verbs and only keep the verbs actually required (e.g., "get", "list", "watch",
and the one-time "create" if bootstrap is needed); ensure any ongoing status
updates use the separate rule for "clusteroperators/status" with "get",
"update", and "patch". If bootstrap still needs a one-time "create" on
"clusteroperators", split that into its own rule containing only "create" (and
no "update"/"patch") and leave the status operations solely on the
"clusteroperators/status" rule referenced by operator code such as
Status().Patch() in pkg/operatorstatus/operator_status.go.
- Around line 458-471: The current RBAC rule grants write verbs (create, update,
patch, delete) to both "deployments" and "replicasets"; remove those write verbs
for "replicasets" since the operator only reconciles Deployments. Fix by
splitting the rule into two rules (or separate resource entries): one for
"deployments" with verbs [get, list, watch, create, update, patch, delete] and a
second for "replicasets" with read-only verbs [get, list, watch]; update the
rule entries that mention the resources "deployments" and "replicasets"
accordingly so only "deployments" retain create/update/patch/delete.
- Around line 252-279: The RBAC rules for CRDs and webhook configurations in the
Cluster API role (the rules granting verbs update/patch/delete on
apiextensions.k8s.io/customresourcedefinitions and
admissionregistration.k8s.io/*webhookconfigurations) are intentionally broad;
add an explicit documented acknowledgement of this security trade-off near these
rules explaining the assumption that only trusted provider manifests are
deployed and that dynamic provider installation requires global CRD/webhook
mutating permissions, and also include recommended mitigations (e.g., restrict
resourceNames when possible, apply provider onboarding via an admission-gated
namespace or separate mechanism, or use a dedicated service account scoped to
provider installation) so reviewers understand the boundary and future
tightening options.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Pro

Run ID: 368265f3-4724-498a-9b6d-3c66604101bd

📥 Commits

Reviewing files that changed from the base of the PR and between 80a9a51 and 44091f4.

📒 Files selected for processing (1)
  • manifests/0000_30_cluster-api_03_rbac_roles.yaml

Comment on lines +232 to +250
- apiGroups:
- config.openshift.io
resources:
- clusteroperators
verbs:
- get
- list
- watch
- create
- update
- patch
- apiGroups:
- config.openshift.io
resources:
- clusteroperators/status
verbs:
- get
- update
- patch
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== ClusterOperator references =="
rg -n -C4 --type go 'ClusterOperator|clusteroperators'

echo
echo "== Explicit status writes =="
rg -n -C4 --type go 'Status\(\)\.(Update|Patch)\('

echo
echo "== Nearby create/update/patch call sites =="
rg -n -C6 --type go 'ClusterOperator|clusteroperators|\.Create\(|\.Update\(|\.Patch\('

Repository: openshift/cluster-capi-operator

Length of output: 50389


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Searching for ClusterOperator writes in main code (excluding vendor) =="
# Find files that reference ClusterOperator outside vendor directories
find . -type f -name "*.go" ! -path "*/vendor/*" ! -path "*/.git/*" | xargs grep -l "ClusterOperator" 2>/dev/null | head -20

echo
echo "== Looking for .Create calls on ClusterOperator clients =="
find . -type f -name "*.go" ! -path "*/vendor/*" ! -path "*/.git/*" -exec grep -l "Create.*ClusterOperator\|clusteroperators.*Create\|\.Create(" {} \; 2>/dev/null | head -10

echo
echo "== Searching for Status().Update/Patch patterns =="
find . -type f -name "*.go" ! -path "*/vendor/*" ! -path "*/.git/*" -exec grep -l "Status()" {} \; 2>/dev/null | head -10

Repository: openshift/cluster-capi-operator

Length of output: 2092


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Examining ClusterOperator controller for write operations ==="
wc -l ./pkg/controllers/clusteroperator/clusteroperator_controller.go

echo
echo "=== ClusterOperator controller content ==="
cat -n ./pkg/controllers/clusteroperator/clusteroperator_controller.go

echo
echo "=== operatorstatus package (likely handles status writes) ==="
cat -n ./pkg/operatorstatus/operator_status.go

Repository: openshift/cluster-capi-operator

Length of output: 17863


Remove unnecessary update and patch verbs on parent clusteroperators resource.

The code only uses create once to bootstrap the ClusterOperator object, then uses Status().Patch() for all subsequent updates (see pkg/operatorstatus/operator_status.go lines 131 and 211). The parent-resource update and patch verbs are unused and should be removed. If bootstrap still needs create, split that rule out separately.

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

In `@manifests/0000_30_cluster-api_03_rbac_roles.yaml` around lines 232 - 250,
Remove the unused parent-resource verbs by editing the RBAC rule for the
resource "clusteroperators": remove the "update" and "patch" verbs and only keep
the verbs actually required (e.g., "get", "list", "watch", and the one-time
"create" if bootstrap is needed); ensure any ongoing status updates use the
separate rule for "clusteroperators/status" with "get", "update", and "patch".
If bootstrap still needs a one-time "create" on "clusteroperators", split that
into its own rule containing only "create" (and no "update"/"patch") and leave
the status operations solely on the "clusteroperators/status" rule referenced by
operator code such as Status().Patch() in pkg/operatorstatus/operator_status.go.

Copy link
Contributor

@mdbooth mdbooth left a comment

Choose a reason for hiding this comment

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

Can you explain how this was generated? It contains many permissions I find surprising for the controllers endpoint.

Comment on lines +178 to +190
# clusterctl
- apiGroups:
- clusterctl.cluster.x-k8s.io
resources:
- providers
verbs:
- get
- list
- watch
- create
- update
- patch
- delete
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think we need this?

Comment on lines +27 to +38
# Node management (for machine lifecycle)
- apiGroups:
- ""
resources:
- nodes
verbs:
- get
- list
- watch
- update
- patch
- delete
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need this?

Comment on lines +40 to +55
# Pod management (for draining nodes)
- apiGroups:
- ""
resources:
- pods
verbs:
- get
- list
- watch
- delete
- apiGroups:
- ""
resources:
- pods/eviction
verbs:
- create
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need this?

@openshift-ci-robot
Copy link

openshift-ci-robot commented Mar 13, 2026

@sunzhaohua2: This pull request references OCPCLOUD-1645 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 PR replaces the insecure wildcard RBAC permissions (*:*:*) with explicit, scoped permissions following the principle of least privilege

Summary by CodeRabbit

  • Chores

  • Replaced broad wildcard RBAC with explicit, granular cluster- and namespace-scoped permissions for cluster controller components, reducing permission surface.

  • Added a namespace-scoped capi-controllers role with scoped permissions for core resources, leases, apps, and provider RBAC.

  • Renamed and tightened pull-secret role to cluster-capi-operator-pull-secret, restricting read access to the specific pull secret.

  • New Features

  • Added cluster-capi-operator:cluster-reader ClusterRole to provide aggregated read-only access across cluster API resources and statuses.

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.

Actionable comments posted: 1

🧹 Nitpick comments (2)
manifests/0000_30_cluster-api_03_rbac_roles.yaml (2)

395-449: Consider adding status subresources to cluster-reader ClusterRole.

The cluster-reader aggregation provides read access to CAPI resources but doesn't include the /status subresources. For complete observability, cluster admins may benefit from reading status as well.

Suggested addition
 # CAPI core resources
 - apiGroups:
   - cluster.x-k8s.io
   resources:
   - clusters
   - machines
   - machinesets
+  - clusters/status
+  - machines/status
+  - machinesets/status
   verbs:
   - get
   - list
   - watch

Similar additions could be made for infrastructure provider status subresources.

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

In `@manifests/0000_30_cluster-api_03_rbac_roles.yaml` around lines 395 - 449, The
ClusterRole cluster-capi-operator:cluster-reader currently grants get/list/watch
on core CAPI resources and provider resources but omits their status
subresources; update the rules for the cluster.x-k8s.io and
infrastructure.cluster.x-k8s.io sections (the blocks listing resources like
clusters, machines, machinesets and awsclusters, awsmachines, etc.) to also
include the corresponding "/status" subresources (e.g., clusters/status,
machines/status, machinesets/status and awsclusters/status, awsmachines/status,
…) so read-only clients can view resource status as well.

193-210: Consider removing update from parent clusteroperators resource.

Based on prior analysis, the operator only uses create for initial bootstrap and Status().Patch() for ongoing updates. The update verb on the parent resource (line 202) appears unused. Keeping only create on the parent and update/patch on the /status subresource would further tighten permissions.

Suggested diff
 - apiGroups:
   - config.openshift.io
   resources:
   - clusteroperators
   verbs:
   - get
   - list
   - watch
   - create
-  - update
#!/bin/bash
# Verify if update on parent clusteroperators resource is actually used
echo "=== Searching for Update calls on ClusterOperator (not status) ==="
rg -n "\.Update\(" pkg/ --type go -A2 -B2 | grep -i "clusteroperator" | head -20

echo
echo "=== Check for UpdateContext calls ==="
rg -n "UpdateContext\(" pkg/ --type go | grep -v "Status" | head -10

echo
echo "=== Look at operator_status.go for the actual update patterns ==="
rg -n "Update|Patch" pkg/operatorstatus/ --type go -B2 -A2 | head -50
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@manifests/0000_30_cluster-api_03_rbac_roles.yaml` around lines 193 - 210,
Remove the unnecessary "update" verb from the parent "clusteroperators" resource
block (leave only "create", "get", "list", "watch") and keep "get", "update",
"patch" on the "clusteroperators/status" subresource; this tightens RBAC because
the operator uses Create for bootstrap and Status().Patch()/Status().Update()
for status changes instead of updating the parent resource directly—locate the
RBAC block referencing "clusteroperators" and the separate block for
"clusteroperators/status" in the manifest and drop the "update" entry from the
parent resource verbs.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@manifests/0000_30_cluster-api_03_rbac_roles.yaml`:
- Around line 272-290: The comment "Metal3 (baremetal infrastructure -
read-only)" is inaccurate because the RBAC rules for resources baremetalhosts,
baremetalhosts/status, and baremetalhosts/finalizers include write verbs
(update, patch); update that comment to reflect read/write permissions (e.g.,
"Metal3 (baremetal infrastructure - read/write)") or otherwise describe that
these rules grant update/patch on baremetalhosts and update on status/finalizers
so the comment matches the actual verbs.

---

Nitpick comments:
In `@manifests/0000_30_cluster-api_03_rbac_roles.yaml`:
- Around line 395-449: The ClusterRole cluster-capi-operator:cluster-reader
currently grants get/list/watch on core CAPI resources and provider resources
but omits their status subresources; update the rules for the cluster.x-k8s.io
and infrastructure.cluster.x-k8s.io sections (the blocks listing resources like
clusters, machines, machinesets and awsclusters, awsmachines, etc.) to also
include the corresponding "/status" subresources (e.g., clusters/status,
machines/status, machinesets/status and awsclusters/status, awsmachines/status,
…) so read-only clients can view resource status as well.
- Around line 193-210: Remove the unnecessary "update" verb from the parent
"clusteroperators" resource block (leave only "create", "get", "list", "watch")
and keep "get", "update", "patch" on the "clusteroperators/status" subresource;
this tightens RBAC because the operator uses Create for bootstrap and
Status().Patch()/Status().Update() for status changes instead of updating the
parent resource directly—locate the RBAC block referencing "clusteroperators"
and the separate block for "clusteroperators/status" in the manifest and drop
the "update" entry from the parent resource verbs.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Pro

Run ID: 975a5d71-158c-4a21-8d5e-059ef7cb9930

📥 Commits

Reviewing files that changed from the base of the PR and between 44091f4 and f30ca41.

📒 Files selected for processing (1)
  • manifests/0000_30_cluster-api_03_rbac_roles.yaml

Comment on lines +272 to +290
# Metal3 (baremetal infrastructure - read-only)
- apiGroups:
- metal3.io
resources:
- baremetalhosts
verbs:
- get
- list
- watch
- update
- patch
- apiGroups:
- metal3.io
resources:
- baremetalhosts/status
- baremetalhosts/finalizers
verbs:
- update

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Comment is misleading - Metal3 permissions include write verbs.

The comment on line 272 says "read-only" but the rule includes update and patch verbs on baremetalhosts, and update on status/finalizers. Consider updating the comment to accurately reflect the permissions.

Suggested diff
-# Metal3 (baremetal infrastructure - read-only)
+# Metal3 (baremetal infrastructure - read and update for host management)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@manifests/0000_30_cluster-api_03_rbac_roles.yaml` around lines 272 - 290, The
comment "Metal3 (baremetal infrastructure - read-only)" is inaccurate because
the RBAC rules for resources baremetalhosts, baremetalhosts/status, and
baremetalhosts/finalizers include write verbs (update, patch); update that
comment to reflect read/write permissions (e.g., "Metal3 (baremetal
infrastructure - read/write)") or otherwise describe that these rules grant
update/patch on baremetalhosts and update on status/finalizers so the comment
matches the actual verbs.

@openshift-ci
Copy link
Contributor

openshift-ci bot commented Mar 13, 2026

@sunzhaohua2: 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.

@sunzhaohua2
Copy link
Contributor Author

Can you explain how this was generated? It contains many permissions I find surprising for the controllers endpoint.

@mdbooth thank you checking this, I had Claude check Jira and generate the file based on the mapi file I’ve made some adjustments to it and will do some testing. If you notice any issues, please let me know, thank you!

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

Labels

do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants