Repository navigation
SCC use Role and RoleBinding are not cleaned up when the controller.devfile.io/scc attribute is removed #1694
Description
Description
When a DevWorkspace sets controller.devfile.io/scc, DWO creates a namespaced devworkspace-use-<scc>
Role and RoleBinding granting the workspace ServiceAccount use on that SCC.
Changing the attribute after it has been set is rejected
(... attribute cannot be modified after being set -- workspace must be deleted), but removing it
is allowed, and nothing cleans up the RBAC that was created for it.
Three separate code paths gate on the same "is the attribute present?" check, so once it is removed all
three quietly skip:
webhook/workspace/handler/access_control.go:33—validateUserPermissionsreturns early when the
new spec has no SCC attribute, so removal is never compared against the previous value.pkg/provision/workspace/rbac/role.go:35—syncRolesreturns before it can reconcile the SCC Role
away.pkg/provision/workspace/rbac/finalize.go:27—FinalizeRBAConly callsfinalizeSCCRBACwhile the
attribute is present, so deleting the workspace skips SCC cleanup entirely.
The result is a Role and RoleBinding left in the namespace, still referencing the workspace
ServiceAccount, with no remaining workspace that would ever trigger cleanup.
This is a cleanup/lifecycle gap rather than an access-control one — see Additional context below.
How To Reproduce
Needs OpenShift, a non-privileged user who holds use on anyuid, and the DWO controller
ServiceAccount holding the SCC cluster-wide (a namespaced add-scc-to-user is not sufficient, since
the Role is created in the workspace namespace).
Setup, as cluster-admin — OPERATOR_NS is where DWO runs, OPENSHIFT_USER is the non-privileged
user, NS is their namespace:
OPERATOR_NS=devworkspace-controller
OPENSHIFT_USER=developer
NS=dw-test
oc adm policy add-cluster-role-to-user system:openshift:scc:anyuid -z devworkspace-controller-serviceaccount -n $OPERATOR_NS
oc create role use-anyuid --verb=use --resource=securitycontextconstraints --resource-name=anyuid -n $NS
oc adm policy add-role-to-user use-anyuid $OPENSHIFT_USER --role-namespace=$NS -n $NS-
As the non-privileged user, create a workspace requesting the SCC.
started: trueis required —
the Role is only created during provisioning.kubectl apply -n $NS -f - <<EOF kind: DevWorkspace apiVersion: workspace.devfile.io/v1alpha2 metadata: name: scc-leak spec: started: true routingClass: basic template: attributes: controller.devfile.io/scc: anyuid components: - name: dev container: image: quay.io/wto/web-terminal-tooling:latest args: ["tail", "-f", "/dev/null"] memoryLimit: 512Mi EOF
-
As cluster-admin, confirm DWO created the RBAC — both objects are present:
oc get role,rolebinding devworkspace-use-anyuid -n $NS -
As the non-privileged user, remove the attribute. The patch is accepted:
kubectl patch dw scc-leak -n $NS --type json -p '[{"op":"remove","path":"/spec/template/attributes/controller.devfile.io~1scc"}]'
-
As the non-privileged user, delete the workspace:
kubectl delete dw scc-leak -n $NS -
As cluster-admin, the Role and RoleBinding are still present, with no workspaces left in the
namespace:oc get role,rolebinding devworkspace-use-anyuid -n $NS oc get rolebinding devworkspace-use-anyuid -n $NS -o jsonpath='{.subjects}' oc get dw -n $NS
The binding still references the deleted workspace's ServiceAccount, e.g.
[{"kind":"ServiceAccount","name":"workspace9a52dbfdefd34a29-sa","namespace":"..."}].
Expected behavior
Either:
- removal of
controller.devfile.io/sccis rejected once the attribute has been set, consistent with
how modification is already handled; or - removal is allowed, and the corresponding
devworkspace-use-<scc>Role and RoleBinding are removed
along with it (subject to the existing check for other workspaces in the namespace still using that
SCC).
Either way, deleting the workspace should not leave SCC RBAC behind.
Additional context
Not an access-control issue. Re-adding an SCC attribute later goes through the full
LocalSubjectAccessReview again — both the previous attribute and any validated-SCC record are gone at
that point — so nobody gains access they were not already entitled to. The impact is stale RBAC
accumulating in workspace namespaces, bound to ServiceAccounts that no longer exist.
Consistency with existing intent. The comment above the modification check
(access_control.go:55) gives the rationale as "Don't allow attribute to be changed once it is set,
otherwise we can't clean up the SCC when the workspace is deleted." Removal is exactly that
uncleaned case, so this looks more like an unhandled path than a deliberate decision.
Version. Reproduced on main (OpenShift 4.22.1, CRC). Noticed while reviewing #1693, which
rewrites validateUserPermissions in this area but does not change this behaviour — the early return
is present on main as well, which is why this is filed separately.
Activity