What the gate allows¶
D is a dataset inside the tenant root, D↓ a dataset strictly below it, S a snapshot name.
| Command | Runs |
|---|---|
exit, echo -n, ps -Ao args= |
nothing (exit 0) |
command -v NAME |
nothing (exit 1: "not installed") |
zpool get -o value -H feature@extensible_dataset POOL |
same, only for the root's pool |
zfs get -H name D, zfs get -H receive_resume_token D, zfs get -H -p used D, zfs get -Hpd 1 -t snapshot guid,creation D, zfs get -Hpd 1 type,guid,creation D |
same |
zfs receive [-s] [-F] [-u] D↓ |
zfs receive -u [-s] [-F] D↓, then the encryption check |
zfs receive -A D↓ |
same |
zfs destroy [-r] D↓@S[,S...] |
same |
zfs destroy D↓@a; zfs destroy D↓@b (syncoid's chain) |
one zfs destroy D↓@a,b |
zfs destroy [-r] D↓ |
same |
zfs create [-p] D↓ |
same |
zfs list [-H] [-p] [-r] [-d N] [-t TYPES] [-o COLUMNS] [-s/-S COLUMN] [D] |
same, D defaults to the root; columns come from an allowlist |
zfs send [-w] [-L] [-c] [-e] [-R] [-p] [-i/-I ORIGIN] D@S |
same, the origin must be a snapshot of D |
zfs send -t TOKEN |
same, after checking the token names a snapshot inside the root |
Anything else exits 126 with zfs-tenant: command not allowed: <reason>, and every decision is logged to the auth log with the tenant root.
Every allowed command runs inside the tenant's zone.