You can't delegate a ZFS administration permission to delete only snapshots

February 12, 2020

ZFS has a system that lets you selectively delegate administration permissions from root to other users (exposed through 'zfs allow') on a per filesystem tree basis. This led to the following interesting question (and answer) over on the fediverse:

@wxcafe: hey can anyone here confirm that there's no zfs permission for destroying only snapshots?

@cks: I can confirm this based on the ZFS on Linux code. The 'can you destroy a snapshot' code delegates to a general 'can you destroy things' permission check that uses the overall 'destroy' permission.

(It also requires mount permissions, presumably because you have to be able to unmount something that you're about to destroy.)

The requirement for unmount means that delegating 'destroy' permissions may not work on Linux (or may not always work), because only root can unmount things on Linux. I haven't tested to see whether ZFS will let you delegate unmount permission (and thereby pass its internal checks) but then later the unmount operation will fail, or whether the permission cannot be delegated on Linux (which would mean that you can't delegate 'destroy' either).

The inability to allow people to only delete snapshots is a bit unfortunately, because you can delegate the ability to create them (as the 'snapshot' permission). It would be nice to be able to delegate snapshot management entirely to people (or to an unprivileged account used for automated snapshot management) but not let them destroy the filesystem itself.

This situation is the outcome of two separate and individually sensible design decisions, which combine together here in a not great way. First, ZFS decided that creating snapshots would be a separate 'zfs' command but destroying them would be part of 'zfs destroy' (a decision that I personally dislike because of how it puts you that much closer to an irreversible error). Then when it added delegated permissions, ZFS chose to delegate pretty much by 'zfs' commands, although it could have chosen a different split. Since destroying snapshots is part of 'zfs destroy', it is all covered under one 'destroy' permission.

(The code in the ZFS kernel module does not require this; it has a separate permission check function for each sort of thing being destroyed. They all just call a common permission check function.)

The good news is that while writing this entry and reading the 'zfs allow' manpage, I realized that there may sort of be a workaround under specific situations. I'll just quote myself on Mastodon:

Actually I think it may be possible to do this in practice under selective circumstances. You can delegate a permission only for descendants of a filesystem, not for the filesystem itself, so if a filesystem will only ever have snapshots underneath it, I think that a 'descendants only' destroy delegation will in practice only let people destroy snapshots, because that's all that exists.

Disclaimer: this is untested.

On our fileservers, we don't have nested filesystems (or at least not any that contain data), so we could do this; anything that we'll snapshot has no further real filesystems as children. However in other setups you would have a mixture of real filesystems and snapshots under a top level filesystem, and delegating 'destroy' permission would allow people to destroy both.

(This assumes that you can delegate 'unmount' permission so that the ZFS code will allow you to do destroys in the first place. The relevant ZFS code checks for unmount permission before it checks for destroy permission.)

Comments on this page:

By Michael at 2020-02-13 04:16:16:

Wouldn't a workaround be to add a sudoers entry to allow users (possibly restricted to a particular group) to execute zfs destroy if and only if the only argument that follows the destroy contains a @?

A brief glance over sudoers(8) seems to indicate that this could be accomplished using something like UNTESTED

%snapshotters ALL = /sbin/zfs destroy [^-][^@]+@[^@], !/sbin/zfs destroy *

That would need to be tested, but it should allow users in the "snapshotters" group to run sudo zfs destroy x@y but not sudo zfs destroy x.

If file systems are named in a way that indicates the owning user, it could be made more specific; for example:

pete ALL = /sbin/zfs destroy tank/pete/[^@/]+@[^@], !/sbin/zfs destroy *

to allow Pete to destroy snapshots only (since no other ZFS dataset name will include a @), and even then only immediately under tank/pete.

Again, all of this is UNTESTED. Standard disclaimer, any use is at your own risk, buyer gets to keep all the leftover pieces, and so on. Yes, it'll require a bit of maintenance, but probably not a great deal more so than delegated ZFS permissions. The only obvious downside I can see is that the sudoers configuration is more fragile, in the sense that mistakes can lock out legitimate users.

By penguin at 2020-02-13 09:25:04:


title typo!

By Peter Tribble at 2020-02-13 11:32:00:

I stumbled across this a while back, and logged a bug (which went nowhere).

By cks at 2020-02-13 16:42:54:

Whoops, I've now fixed the title typo. Thanks for noticing and mentioning it.

Written on 12 February 2020.
« Some git aliases that I use
The /bin versus /usr split and diskless workstations »

Page tools: View Source, View Normal, Add Comment.
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Wed Feb 12 22:35:04 2020
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.