Skip to content

Update RBAC to ensure Update verb for Wasm objects#5186

Merged
ricochet merged 2 commits into
wasmCloud:mainfrom
jfleitz:jfleitz/rbac-update
May 21, 2026
Merged

Update RBAC to ensure Update verb for Wasm objects#5186
ricochet merged 2 commits into
wasmCloud:mainfrom
jfleitz:jfleitz/rbac-update

Conversation

@jfleitz

@jfleitz jfleitz commented May 21, 2026

Copy link
Copy Markdown
Contributor

Summary

This PR does two related things:

  1. Grants the operator the update verb on the */finalizers subresources for every CRD in the runtime.wasmcloud.dev apiGroup. Without this, the GC admission plugin rejects any child object the operator tries to create with blockOwnerDeletion: true in its ownerReferences.
  2. Brings runtime-operator/config/rbac/role.yaml (generated by controller-gen via make manifests) into sync with what the operator actually needs at runtime. Several markers were either missing or silently dropped, leaving the generated role incomplete and drifted from the Helm chart.

Why

Deploying the operator into a namespace surfaced this error during reconciliation:

workloadreplicasets.runtime.wasmcloud.dev "workload-a-f8bfc7c55" is forbidden:
  cannot set blockOwnerDeletion if an ownerReference refers to a resource you
  can't set finalizers on

The Kubernetes garbage-collection admission plugin enforces that a caller setting blockOwnerDeletion: true on a child object must have the update verb on <owner-kind>/finalizers. The operator builds child resources (e.g. a WorkloadReplicaSet owned by a Workload) with blockOwnerDeletion set, so it needs workloads/finalizers (and the same for the other CRDs in the apiGroup).

Changes

Helm chart (charts/runtime-operator/templates/operator/clusterrole.yaml)

Adds a new rule granting update on the four runtime.wasmcloud.dev/*/finalizers subresources (artifacts, workloads, workloadreplicasets, workloaddeployments). hosts/finalizers is intentionally not added here — Hosts live in the operator's own namespace and are already granted finalizer permissions via the namespaced Role in role.yaml.

This rule is the manual sync from config/rbac/role.yaml, which now produces the same shape via make manifests.

Annotations (source of truth)

  • workload_controller.go — Added markers for configmaps, secrets, and events. These resources are consumed by the workload reconciler (utils.go::ResolveConfigFrom, ResolveSecretFrom, MaterializeImagePullSecret and the Recorder.Eventf call site) but had no +kubebuilder:rbac marker, so they never appeared in the generated role.

  • workload_route_controller.go and host_pod_controller.go — Moved existing markers for pods, services, and endpointslices from declaration-attached comments (above the Reconcile / SetupWithManager funcs) to package-level comments at the top of the file. controller-gen v0.16.4 was silently dropping the declaration-attached markers on these two files even though they were syntactically identical to working markers on other controllers (the package-level placement is processed reliably). A short pointer comment was left near the original location so future maintainers can find them.

Generated manifests (runtime-operator/config/rbac/role.yaml)

Regenerated via make manifests. New rules in the file reflect the annotation changes above — no hand edits.

Result

After this PR, make manifests produces a config/rbac/role.yaml containing the full set of permissions the operator actually needs:

""                  configmaps, secrets, services     get;list;watch
""                  events                            create;get;list;patch;update;watch
""                  pods                              get;list;patch;watch
discovery.k8s.io    endpointslices                    create;delete;get;list;patch;update;watch
runtime.wasmcloud.dev   artifacts, hosts, workloads,
                        workloadreplicasets,
                        workloaddeployments           create;delete;get;list;patch;update;watch
runtime.wasmcloud.dev   */finalizers                  update
runtime.wasmcloud.dev   */status                      get;patch;update

The Helm chart maps this generated role into its structural layout (namespaced Role for Hosts and leader election, ClusterRole for everything else, with the existing watchNamespaces conditional for per-namespace bindings). The chart is now consistent with the generated source of truth and no longer drifts in the resources it grants.

Test plan

  • make manifests runs cleanly and produces no diff beyond what is committed
  • go build ./... passes
  • Fresh helm install of the chart succeeds; operator pod reaches Ready
  • Apply a Workload and confirm the WorkloadReplicaSet is created without the cannot set blockOwnerDeletion error
  • Delete the Workload and confirm the owned WorkloadReplicaSet is garbage-collected (verifies the blockOwnerDeletion chain is actually working, not just permitted)
  • Repeat the Workload create/delete cycle with operator.watchNamespaces set, to confirm the per-namespace RBAC path still works

For the last step on "Repeat the Workload with watchNamespaces", I used the following settings in values.local.yaml:

gateway:
  enabled: false
operator:
  image:
    tag: "canary"
  watchNamespaces: ["test-1"]
  hostNamespaces: ["test-1"]

    
runtime:
  image:
    tag: "canary"
  hostGroups:
    - name: default
      namespace: "test-1"
      replicas: 3

And then deployed the wasmCloud test app to that namespace:

kubectl apply -f https://raw.githubusercontent.com/wasmCloud/wasmCloud/refs/heads/main/templates/http-hello-world/manifests/workloaddeployment.yaml -n test-1 

There were no errors that occurred and the wasmCloud curl test returned successfully.

Signed-off-by: Jeremy Fleitz jeremy@cosmonic.com

Signed-off-by: Jeremy Fleitz <jeremy@cosmonic.com>
@jfleitz jfleitz requested review from a team as code owners May 21, 2026 01:40

@ricochet ricochet left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

missing services/finalizers update

@jfleitz

jfleitz commented May 21, 2026

Copy link
Copy Markdown
Contributor Author

missing services/finalizers update

Thanks for catching! I added the services/finalizers update verb and then retested by making a k8s service first before creating the WorkloadDeployment manifest, so that the operator would need update permissions for updating the service.

@ricochet

Copy link
Copy Markdown
Contributor

need to push? No new commits

Signed-off-by: Bailey Hayes <bailey@cosmonic.com>
@ricochet

Copy link
Copy Markdown
Contributor

Pushed the fix and tested via automation in #5187

@ricochet ricochet merged commit 9a8452a into wasmCloud:main May 21, 2026
57 checks passed
@jfleitz jfleitz deleted the jfleitz/rbac-update branch June 12, 2026 13:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants