Tuesday Jun 26, 2007

ZFS Delegated Administration

ZFS Delegated Administration

ZFS now supports the ability to delegate zfs(1M) administrative tasks to ordinary users.

Two styles of delegated permissions are supported.  First the individual permission(s) can be explicitly specified, or the administrator can define a permission set.  A permission set can then later be updated and all of the consumers of the set will automatically pick up the change.  Permission sets all begin with the letter @ and are limited to 64 characters in length. Characters after the  @ sign  in a set name  have the same restrictions as normal ZFS file system names.
Granting permissions
Permissions are delegated with the allow subcommand to ZFS(1M).

zfs allow [-l] [-d] <"everyone"|user|group>[,<"everyone" |user|group>] \\
     <perm>|@<setname>[,<perm>|@<setname>...]  <filesystem|volume>
zfs allow [-l] [-d] -u <user> <perm>|@<setname>[,<perm>|@<setname>...]  <filesystem|volume>
zfs allow [-l] [-d] -g <group> <perm>|@<setname>[,<perm>|@<setname>...] <filesystem|volume>
zfs allow [-l] [-d] -e <perm>|@<setname>[,<perm>|@<setname>...]<filesystem|volume>
zfs allow -c <perm>|@<setname>[,<perm>|@<setname>...] <filesystem|volume>
zfs allow -s @setname <perm>|@<setname>[,<perm>...] <filesystem|volume>


If no flags are used, the permission(s) will be allowed for the specified
dataset and all of its descendents.

-l "Local" means that the permission is allowed for the
specified dataset, and not its descendents (unless -d is also
specified).

-d "Descendents" means that the permission is allowed for
descendent datasets, and not for this dataset (unless -l is also
specified).

-c "Create" means that the permission will be granted (Locally) to the
creator on any newly-created descendent file systems.

-s "Permission set"  means that the listed permission(s) will act as a
set.  Changing the permissions in a set will immediately change
what is allowed wherever the set is used.

Permissions

The actual permissions are pretty much self explanatory, but here is the list and what they allow you to do.
 
create create descendent datasets. (Must also have 'mount' permission)
destroy destroy dataset
snapshot take snapshots. (Must also have 'mount' permission)
rollback
rollback dataset. (Must also have mount)
clone create clone of any of the dataset's snaps. (must also have 'create' permission in clone's parent)
promote promote dataset. (must also have 'promote' permission in origin fs)
rename rename a dataset. (must also have 'create' and 'mount' permission in new parent)
mount mount and unmount the dataset
share share and unshare this dataset
send send any of the dataset's snapshots
receive create a descendent with zfs receive. (must also have 'create' permission)
allow Allows users to grant permissions they have to another user.
quota modify quotas
reservation set reservations
volsize set volsize property
recordsize set recordsize property
mountpoint set mountpoint property
sharenfs set sharenfs property
checksum set checksum property
compression set compressions property
atime set atime property
devices set devices property
exec set exec property
setuid set setuid property
readonly set readonly property
snapdir set snapdir property
aclmode set aclmode property
aclinherit set aclinherit property
copies set copies property
canmount set canmount property
xattr set xattr property
userprop allow user properties to be modified
shareiscsi set shareiscsi property


Permission Revoking

For removing permissions the unallow zfs(1M) subcommand is used.

zfs unallow [-r] [-l] [-d] <"everyone"|user|group>[,<"everyone"|user|group>...] \\
     [<perm>|@<setname>[,<perm>|@<setname>...]] <filesystem|volume>
zfs unallow [-r][-l][-d] -u user [<perm>|@<setname>[,<perm>|@<setname>...]] <filesystem|volume>
zfs unallow [-r][-l][-d] -g group [<perm>|@<setname>[,<perm>|@<setname>...]] <filesystem|volume>
zfs unallow [-r][-l][-d] -e [<perm>|@<setname>[,<perm>|@<setname>...]] <filesystem|volume>
zfs unallow [-r] -c  <perm>|@<setname>[,<perm>|@<setname>...] <filesystem|volume>
zfs unallow [-r] -s @<setname> [<perm>|@<setname>[,<perm>|@<setname>...]] <filesystem|volume>


Displaying Permissions

$ zfs allow <filesystem|volume>

Examples

First lets create just a simple setup where anybody in group "staff" can
create and mount file systems anywhere in the pool.

# zpool create sandbox c0t1d0

The individual users still need permission to create the mountpoints, so
lets just create a sticky directory.

# chmod 1777 /sandbox
# zfs allow staff create,mount sandbox


$ zfs allow sandbox
-------------------------------------------------------------
Local+Descendent permissions on (sandbox)
        group staff create,mount
-------------------------------------------------------------
marks$ zfs create sandbox/marks


user "marks" can't destroy this file system, since we didn't hand out destroy permission.

$ zfs destroy sandbox/marks
cannot destroy 'sandbox/marks': permission denied


Permission set example:

Permission sets need to be defined before they can be used.

# zfs allow -s @set1 create,mount,snapshot,clone,promote sandbox

Now lets assign this to the previosly created sandbox/marks file system.

# zfs allow marks @set1 sandbox/marks

# zfs allow sandbox/marks
-------------------------------------------------------------
Local+Descendent permissions on (sandbox/marks)
        user marks @set1
-------------------------------------------------------------
Permission sets on (sandbox)
        @set1 clone,create,mount,promote,snapshot
Local+Descendent permissions on (sandbox)
        group staff create,mount
-------------------------------------------------------------


Now lets see if "marks" can take a snpshot

marks$ zfs snapshot sandbox/marks@snap1

Lets make sure nobody else can.

tester$ zfs snapshot sandbox/marks@snap2
cannot create snapshot 'sandbox/marks@snap2': permission denied




Wednesday Nov 16, 2005

ZFS ACLs

ACLs


The ZFS file system uses a pure ACL model, that is compliant with the NFSv4 ACL model.  What is meant by pure ACL model, is that every file always has an ACL, unlike file systems such as UFS that have either an ACL or it has permission bits.  All access control decisions are governed by a file's ACL.  All file's still have permission bits, but they are constructed by analyzing a file's ACL.
NFSv4 ACL Overview
The ACL model in NFSv4 is similar to the Windows ACL model.  The NFSv4 ACL model supports a rich set of access permissions and inheritance controls.  An ACL in this model is composed of an array of access control entries (ACE).  Each ACE specifies the permissions, access type, inheritance flags and to whom the entry applies.  In the NFSv4 model the "who" argument of each ACE, may be either a username or groupname.  There are also a set of commonly know names, such as "owner@", "group@", "everyone@".  These abstractions are used by UNIX variant operating systems to indicate if the ACE is for the file owner, file group owner or for the world.  The everyone@ entry is not equivalent to the POSIX "other" class, it really is everyone.  The complete description of the NFSv4 ACL model is availabe in Section 5.11 of the NFSv4 protocol specification.
NFSv4 Access Permissions

Permission
Description
read_data
Permission to read the data of the file
list_data
Permission to list the contents of a directory
write_data
Permission to modify the file's data anywhere in the file's offset range.  This includes the ability to grow the file or write to an arbitrary offset.
add_file
Permission to add a new file to a directory
append_data
The ability to modify the data, but only starting at EOF.
add_subdirectory
Permission to create a subdirectory to a directory
read_xattr
The ability to read the extended attributes of a file or to do a lookup in the extended attributes directory.
write_xattr
The ability to create extended attributes or write to the extended attributes directory.
execute
Permission to execute a file
delete_child
Permission to delete a file within a directory
read_attributes
The ability to read basic attributes (non-ACLs) of a file.  Basic attributes are considered the stat(2) level attributes.
write_attributes
Permission to change the times associated with a file or directory to an arbitrary value
delete
Permission to delete a file
read_acl
Permission to read the ACL
write_acl
Permission to write a file's ACL
write_owner
Permission to change the owner or the ability to execute chown(1) or chgrp(1)
synchronize
Permission to access a file locally at the server with synchronous reads and writes.

NFSv4 Inheritance flags
Inheritance Flag
Description
file_inherit
Can be place on a directory and indicates that this ACE should be added to each new non-directory file created.
dir_inherit
Can be placed on a directory and indicates that this ACE should be added to each new directory created.
inherit_only
Placed on a directory, but does not apply to the directory itself, only to newly created files and directories.  This flag requires file_inherit and or dir_inherit to indicate what to inherit.
no_propagate
Placed on directories and indicates that ACL entries should only be inherited to one level of the tree.  This flag requires file_inherit and or dir_inherit to indicate what to inherit.
   
NFSv4 ACLs vs POSIX
The difficult part of using the NFSv4 ACL model was trying to still preserve POSIX compliance in the file system.  POSIX allows for what it calls "additonal" and "alternate" access methods.  An additional access method is defined to be layered upon the file permission bits, but they can only further restrict the standard access control mechanism.  The alternate file access control mechanism is defined to be independent of the file permission bits and which if enabled on a file may either restrict or extend the permissions of a given user.  Another major distinction between the additional and alternate access control mechanisms is that, any alternate file access control mechanism must be disabled after the file permission bits are changed with a chmod(2).  Additional mechanisms do not need to be disabled when a chmod is done.  

Most vendors that have implemented NFSv4 ACLs have taken the approach of "discarding" ACLs during a chmod(2).  This is a bit heavy handed, since a user went through the trouble of crafting a bunch of ACLs, only to have chmod(2) come through and destroy all of their hard work.  It was this single issue that was the biggest hurdle to POSIX compliance with ZFS in implementing NFSv4 ACLs.  In order to achieve this SamLisa and I spent far too long trying to come up with a model that would preserve as much of the original ACL, while still being useful.   What we came up with is a model that retains additional access methods, and disabled, but doesn't delete alternate access controls.  Sam and Lisa have filed an internet draft which has the details about the chmod(2) algorithm and how to make NFSv4 ACLs POSIX complient.

So whats cool about this
Lets assume we have the following directory /sandbox/test.dir.
Its initial ACL looks like:

    % ls -dv test.dir
    drwxr-xr-x   2 ongk     bin            2 Nov 15 14:11 test.dir
         0:owner@::deny
         1:owner@:list_directory/read_data/add_file/write_data/add_subdirectory
             /append_data/write_xattr/execute/write_attributes/write_acl
             /write_owner:allow
         2:group@:add_file/write_data/add_subdirectory/append_data:deny
         3:group@:list_directory/read_data/execute:allow
         4:everyone@:add_file/write_data/add_subdirectory/append_data/write_xattr
             /write_attributes/write_acl/write_owner:deny
         5:everyone@:list_directory/read_data/read_xattr/execute/read_attributes
             /read_acl/synchronize:allow



Now if I want to give "marks" the ability to create files, but not subdirectories in this
directory then the following ACL would achieve this.

    First lets make sure "marks" can't currently create files/directories

    $ mkdir /sandbox/bucket/test.dir/dir.1
    mkdir: Failed to make directory "/sandbox/test.dir/dir.1"; Permission denied


    $ touch /sandbox/test.dir/file.1
    touch: /sandbox/test.dir/file.1 cannot create


    Now lets give marks add_file permission

    % chmod A+user:marks:add_file:allow /sandbox/test.di
    % ls -dv test.dir

    drwxr-xr-x+  2 ongk     bin            2 Nov 15 14:11 test.dir
         0:user:marks:add_file/write_data:allow
         1:owner@::deny
         2:owner@:list_directory/read_data/add_file/write_data/add_subdirectory
             /append_data/write_xattr/execute/write_attributes/write_acl
             /write_owner:allow
         3:group@:add_file/write_data/add_subdirectory/append_data:deny
         4:group@:list_directory/read_data/execute:allow
         5:everyone@:add_file/write_data/add_subdirectory/append_data/write_xattr
             /write_attributes/write_acl/write_owner:deny
         6:everyone@:list_directory/read_data/read_xattr/execute/read_attributes
             /read_acl/synchronize:allow


    Now lets see if it works for user "marks"

    $ id
    uid=76928(marks) gid=10(staff)

    $ touch file.1
    $ ls -v file.1
    -rw-r--r--   1 marks    staff          0 Nov 15 10:12 file.1
         0:owner@:execute:deny
         1:owner@:read_data/write_data/append_data/write_xattr/write_attributes
             /write_acl/write_owner:allow
         2:group@:write_data/append_data/execute:deny
         3:group@:read_data:allow
         4:everyone@:write_data/append_data/write_xattr/execute/write_attributes
             /write_acl/write_owner:deny
         5:everyone@:read_data/read_xattr/read_attributes/read_acl/synchronize
             :allow


    Now lets make sure "marks" can't create directories.

    $ mkdir dir.1
     mkdir: Failed to make directory "dir.1"; Permission denied

The write_owner permission is handled in a special way.  It allows for a user to "take" ownership of a file.  The following example will help illustrate this.  With the write_owner a user can only do a chown(2) to himself or to a group that he is a member of.

    We will start out with the following file.

    ls -v file.test
    -rw-r--r--   1 ongk     staff          0 Nov 15 14:22 file.test
         0:owner@:execute:deny
         1:owner@:read_data/write_data/append_data/write_xattr/write_attributes
             /write_acl/write_owner:allow
         2:group@:write_data/append_data/execute:deny
         3:group@:read_data:allow
         4:everyone@:write_data/append_data/write_xattr/execute/write_attributes
             /write_acl/write_owner:deny
         5:everyone@:read_data/read_xattr/read_attributes/read_acl/synchronize
             :allow


    Now if user "marks" tries to chown(2) the file to himself he will get an error.

     $ chown marks file.test
     chown: file.test: Not owner

     $ chgrp staff file.test
     chgrp: file.test: Not owner


     Now lets give "marks" explicit write_owner permission.

     % chmod A+user:marks:write_owner:allow file.test
     % ls -v file.test

     -rw-r--r--+  1 ongk     staff          0 Nov 15 14:22 file.test
          0:user:marks:write_owner:allow
          1:owner@:execute:deny
          2:owner@:read_data/write_data/append_data/write_xattr/write_attributes
              /write_acl/write_owner:allow
          3:group@:write_data/append_data/execute:deny
          4:group@:read_data:allow
          5:everyone@:write_data/append_data/write_xattr/execute/write_attributes
              /write_acl/write_owner:deny
          6:everyone@:read_data/read_xattr/read_attributes/read_acl/synchronize
              :allow

    Now lets see who "marks" can chown the file to.
   
    $ id
    uid=76928(marks) gid=10(staff)
    $ groups
    staff storage
    $ chown bin file.test
    chown: file.test: Not owner


    So "marks" can't give the file away.

    $ chown marks:staff file.test
   
Now lets look at an example to show how a user can be granted special delete permissions.  ZFS doesn't create any delete permissions when a file is created, instead it uses write_data/execute for permission to write to a directory and execute to search the directory.

    Lets first create a read-only directory and then give "marks" the ability to delete files.

    % ls -dv test.dir
    dr-xr-xr-x   2 ongk     bin            2 Nov 15 14:11 test.dir
         0:owner@:add_file/write_data/add_subdirectory/append_data:deny
         1:owner@:list_directory/read_data/write_xattr/execute/write_attributes
             /write_acl/write_owner:allow
         2:group@:add_file/write_data/add_subdirectory/append_data:deny
         3:group@:list_directory/read_data/execute:allow
         4:everyone@:add_file/write_data/add_subdirectory/append_data/write_xattr
             /write_attributes/write_acl/write_owner:deny
         5:everyone@:list_directory/read_data/read_xattr/execute/read_attributes
             /read_acl/synchronize:allow


    Now the directory has the following files:

    ls -l
    total 3
    -r--r--r--   1 ongk     bin            0 Nov 15 14:28 file.1
    -r--r--r--   1 ongk     bin            0 Nov 15 14:28 file.2
    -r--r--r--   1 ongk     bin            0 Nov 15 14:28 file.3


    Now lets see if "marks" can delete any of the files?

    $  rm file.1
    rm: file.1: override protection 444 (yes/no)? y
    rm: file.1 not removed: Permission denied

    Now lets give "marks" delete permission on just file.1

    chmod A+user:marks:delete:allow file.1
    ls -v file.1
    -r--r--r--+  1 ongk     bin            0 Nov 15 14:28 file.1
         0:user:marks:delete:allow
         1:owner@:write_data/append_data/execute:deny
         2:owner@:read_data/write_xattr/write_attributes/write_acl/write_owner
             :allow
         3:group@:write_data/append_data/execute:deny
         4:group@:read_data:allow
         5:everyone@:write_data/append_data/write_xattr/execute/write_attributes
             /write_acl/write_owner:deny
         6:everyone@:read_data/read_xattr/read_attributes/read_acl/synchronize
             :allow


    $ rm file.1
    rm: file.1: override protection 444 (yes/no)? y


Lets see what a chmod(1) that changes the mode would do to a file with a ZFS ACL.
We will start out with the following ACL which gives user bin read_data and write_data permission.

    ls -v file.1
    -rw-r--r--+  1 marks    staff          0 Nov 15 10:12 file.1
         0:user:bin:read_data/write_data:allow
         1:owner@:execute:deny
         2:owner@:read_data/write_data/append_data/write_xattr/write_attributes
             /write_acl/write_owner:allow
         3:group@:write_data/append_data/execute:deny
         4:group@:read_data:allow
         5:everyone@:write_data/append_data/write_xattr/execute/write_attributes
             /write_acl/write_owner:deny
         6:everyone@:read_data/read_xattr/read_attributes/read_acl/synchronize
             :allow


   
chmod 640 file.1
    $ ls -v file.1
    -rw-r-----+  1 marks    staff          0 Nov 15 10:12 file.1
         0:user:bin:write_data:deny
         1:user:bin:read_data/write_data:allow
         2:owner@:execute:deny
         3:owner@:read_data/write_data/append_data/write_xattr/write_attributes
             /write_acl/write_owner:allow
         4:group@:write_data/append_data/execute:deny
         5:group@:read_data:allow
         6:everyone@:read_data/write_data/append_data/write_xattr/execute
             /write_attributes/write_acl/write_owner:deny
         7:everyone@:read_xattr/read_attributes/read_acl/synchronize:allow


    In this example ZFS has prepended a deny ACE to take away write_data permission.  This
    is an example of disabling "alternate" access methods.  More details about
    how ACEs are disabled are described in internet draft.
 
The ZFS admin guide and the chmod(1) manpages have many more examples of setting ACLs and how the inheritance model works.

With the ZFS ACL model access control is no longer limited to the simple "rwx" model that UNIX has used since its inception.


   
About

marks

Search

Categories
  • ZFS
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today
Bookmarks
Feeds