box grant refuses incus-admin members, leaving them with no project #99

Closed
opened 2026-07-19 16:04:53 +00:00 by dan-claude-bot · 0 comments
dan-claude-bot commented 2026-07-19 16:04:53 +00:00 (Migrated from github.com)

box grant refuses incus-admin members, leaving them with no project

The refusal

host/grant-user.sh:69:

if id -nG "$user" | tr ' ' '\n' | grep -qx incus-admin; then
  echo "box grant: $user is in incus-admin — they already have the admin tier; there is nothing tighter to grant." >&2
  exit 1
fi

The reasoning in the comment: "admin membership wins at the socket", so
granting the restricted tier "would not restrict anything, it would only
mislead whoever reads the group list later."

Why that is wrong

It conflates permission with provisioning. They are separate, and
box grant supplies both:

  • Permission — the incus group, i.e. socket access. An incus-admin
    member does already have this, strictly stronger. The comment is right
    about this part.
  • Provisioning — the user-<uid> project, the boxnet narrowing, snapshot
    and backup allowances, and the box-net profile installed into their
    project
    . An incus-admin member gets none of this.

box_tier() (bin/box:30) resolves an incus-admin member to admin, so
they operate in the shared default project alongside root and every other
admin. They have no project of their own. Their boxes are not isolated from
other admins'. box grant — the only command that provisions a per-user
project — refuses to run for them.

The result: a human who is an admin on the host cannot get their own boxes
without either being removed from incus-admin first, or hand-running
incus-user and the project convergence themselves. This has bitten us in
practice.

Proposed change

Drop the refusal. Run the full convergence for incus-admin members, and
say plainly what it does and does not change:

  • the group step is a no-op (already stronger via incus-admin) — report it
    as such rather than adding them to incus
  • steps 2–5 run normally: project, bridge unpin, restricted.networks.access boxnet, snapshots, backups, box-net profile

Then say out loud what the grant cannot do for them: their incus-admin
membership still wins at the socket, so the project's restrictions are a
default placement, not a confinement — they can still reach the default
project and other users' instances whenever they choose to. That is the
honest version of the warning the current refusal is gesturing at, and it
belongs in the output rather than in a hard exit.

Alternative if the refusal is considered load-bearing: keep it as the default
and add --anyway / --provision-only. Weaker — it leaves the trap in place
for whoever hits it first, and rig's users apply would have to know to pass
the flag.

Why this is blocking

heavy-duty/rig wants users apply to call box grant for every user
carrying role boxheavy-duty/rig#49. A user who is both
incus-admin (by hand, break-glass) and role box (in the fleet users file)
makes that call exit 1 today. rig would have to special-case box's refusal —
or box stops refusing.

# `box grant` refuses incus-admin members, leaving them with no project ## The refusal `host/grant-user.sh:69`: ```sh if id -nG "$user" | tr ' ' '\n' | grep -qx incus-admin; then echo "box grant: $user is in incus-admin — they already have the admin tier; there is nothing tighter to grant." >&2 exit 1 fi ``` The reasoning in the comment: "admin membership wins at the socket", so granting the restricted tier "would not restrict anything, it would only mislead whoever reads the group list later." ## Why that is wrong It conflates **permission** with **provisioning**. They are separate, and `box grant` supplies both: - *Permission* — the `incus` group, i.e. socket access. An `incus-admin` member does already have this, strictly stronger. The comment is right about this part. - *Provisioning* — the `user-<uid>` project, the `boxnet` narrowing, snapshot and backup allowances, and the `box-net` profile installed **into their project**. An `incus-admin` member gets **none** of this. `box_tier()` (`bin/box:30`) resolves an `incus-admin` member to `admin`, so they operate in the **shared default project** alongside root and every other admin. They have no project of their own. Their boxes are not isolated from other admins'. `box grant` — the only command that provisions a per-user project — refuses to run for them. The result: a human who is an admin on the host cannot get their own boxes without either being removed from `incus-admin` first, or hand-running incus-user and the project convergence themselves. This has bitten us in practice. ## Proposed change Drop the refusal. Run the full convergence for `incus-admin` members, and say plainly what it does and does not change: - the group step is a no-op (already stronger via `incus-admin`) — report it as such rather than adding them to `incus` - steps 2–5 run normally: project, bridge unpin, `restricted.networks.access boxnet`, snapshots, backups, `box-net` profile Then say out loud what the grant cannot do for them: their `incus-admin` membership still wins at the socket, so the project's restrictions are a *default placement*, not a confinement — they can still reach the default project and other users' instances whenever they choose to. That is the honest version of the warning the current refusal is gesturing at, and it belongs in the output rather than in a hard exit. Alternative if the refusal is considered load-bearing: keep it as the default and add `--anyway` / `--provision-only`. Weaker — it leaves the trap in place for whoever hits it first, and rig's `users apply` would have to know to pass the flag. ## Why this is blocking `heavy-duty/rig` wants `users apply` to call `box grant` for every user carrying role `box` — heavy-duty/rig#49. A user who is both `incus-admin` (by hand, break-glass) and role `box` (in the fleet users file) makes that call exit 1 today. rig would have to special-case box's refusal — or box stops refusing.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: heavy-duty/box#99
No description provided.