Repository navigation
Description
cozy:tenant:use:base grants console, VNC and power control on every VirtualMachineInstance in a tenant namespace, with no resourceNames. That is right for the VMs a tenant created and wrong for the platform-owned ones that also land there.
The rule is at packages/system/cozystack-basics/templates/clusterroles.yaml:165-190 and is bound per namespace by packages/apps/tenant/templates/tenant.yaml:51-61. It was written for the VM catalog, where console and power buttons are the point. Nothing about it is specific to the apps that own the VMs, because RBAC cannot express that: the authorizer answers before the object is read, so it sees the verb, the GVR, the namespace and the name from the request path, and nothing else. No label selectors, no owner references, and no deny rules. resourceNames is the only lever there is.
Three charts create VMs in tenant namespaces today: vm-instance, kubernetes-nodes (which ComputePlane also uses) and site-router. Only the first is tenant-owned in the sense the grant assumes.
Why it matters now
site-router's gateway VM is a platform-owned appliance carrying the guest firewall that compensates for a relaxed OVN port, so the chart always renders its boot disk as the pinned appliance. The console reaching inside it was a real escalation until the bootloader was locked (#3426). That fix removes what the console was worth on that one VM. It does not make the grant correct, and it does not touch the super-admin path below.
ComputePlane is the sharper case and has its own issue: the tenant is explicitly given no admin kubeconfig for that cluster, yet holds console and restart on its nodes.
There is a second tier to the same problem. cozy:tenant:super-admin:base (clusterroles.yaml:293-299) grants kubevirt.io virtualmachines with verb *, bound in every tenant namespace, so that tier does not need the console at all: it can edit a platform-owned VM directly, swap its cloud-init secretRef and have the guest install whatever it names on the next boot. Flux drift correction is off, so the edit persists. Any scoping that covers only the console subresources leaves this open.
Proposal
Drop the blanket rule from cozy:tenant:use:base, and have each chart that creates VMs grant console, VNC, portforward and power on its own VMs by name.
For statically named VMs this is trivial and race free, because the Role ships in the same release as the VM it names. site-router then simply does not emit one, and the grant is absent rather than neutralized.
CAPK-generated worker names are the hard part. They carry a random suffix and resourceNames has no wildcard or prefix match, so those need a controller that watches VMs and rewrites the Role. kubernetes-nodes already runs a reconcile Job, so there is somewhere for it to live. Expect a brief window after a VM is created where the dashboard returns 403 until the Role catches up.
Things that will bite
list cannot be scoped by resourceNames, because a list request carries no name. The current rule grants get and list on the console and VNC subresources; list on a subresource with no collection endpoint looks like carry-over, but that needs checking against virtctl and the dashboard before it is dropped.
This changes RBAC for every tenant in every installation. Getting the scope wrong takes console access away from tenants for their own VMs, so it needs a staged rollout rather than a single flip.
Activity