Posix ACLs are the only clear-cut elegant way to do this, this is how I deal with shared read/write resource conflicts particularly on web-based systems. Here is a running example.
In my example I have a directory called /var/www/html/share
.
In addition I have the users alice
, bob
, deploy
and bower
First, I have created a group called html
and then added the users to this group.
groupadd html
for i in alice bob deploy bower; do usermod -a -G html $user; done
Now, I have then added a file ACL against this html
group onto that folder.
setfacl -m g:html:rwx /var/www/html/share
setfacl -d -m g:html:rwx /var/www/html/share
The second command is important, it causes inheritance to occur.
Now, we can test out the behaviour of this.
# for user in alice bob bower deploy; do \
sudo -u $user touch "/var/www/html/share/file_${user}" \
done
[root@localhost html]# ls -l /var/www/html/share/
total 0
-rw-rw-r--+ 1 alice alice 0 May 13 23:08 file_alice
-rw-rw-r--+ 1 bob bob 0 May 13 23:08 file_bob
-rw-rw-r--+ 1 bower bower 0 May 13 23:08 file_bower
-rw-rw-r--+ 1 deploy deploy 0 May 13 23:08 file_deploy
[root@localhost html]#
At first glance, it looks as though the file ownerships are all just simple, and will not allow one user to interact with anothers. However, we can inspect the ACL using getfacl
which shows more infomation.
# getfacl file_Al
getfacl: file_Al: No such file or directory
[root@localhost share]# getfacl file_alice
# file: file_alice
# owner: alice
# group: alice
user::rw-
group::r-x #effective:r--
group:html:rwx #effective:rw-
mask::rw-
other::r--
You can see that the html
group has control over these files.
Note: the standard unix GROUP permission denotes the mask against the permissions. As it is rw
for files it is also effectively rw
for the ACL, despite the actual permission granted being rwx
.
Lets test other users can modify/delete these files.
# sudo -u alice /bin/bash
[alice@localhost share]$ pwd
/var/www/html/share
[alice@localhost share]$ echo "hello world" >>file_alice
[alice@localhost share]$ echo "hello world" >>file_bob
[alice@localhost share]$ echo "hello world" >>file_deploy
[alice@localhost share]$ echo "hello world" >>file_bower
[alice@localhost share]$ ll
total 16
-rw-rw-r--+ 1 alice alice 12 May 13 23:15 file_alice
-rw-rw-r--+ 1 bob bob 12 May 13 23:15 file_bob
-rw-rw-r--+ 1 bower bower 12 May 13 23:15 file_bower
-rw-rw-r--+ 1 deploy deploy 12 May 13 23:15 file_deploy
[alice@localhost share]$ rm file_deploy
Finally, the tricky bit. What happens when alice makes a directory?
[alice@localhost share]$ mkdir dir_alice;
[alice@localhost share]$ ls -l
total 12
drwxrwxr-x+ 1 alice alice 0 May 13 23:16 dir_alice
-rw-rw-r--+ 1 alice alice 12 May 13 23:15 file_alice
-rw-rw-r--+ 1 bob bob 12 May 13 23:15 file_bob
-rw-rw-r--+ 1 bower bower 12 May 13 23:15 file_bower
[alice@localhost share]$ getfacl dir_alice
# file: dir_alice
# owner: alice
# group: alice
user::rwx
group::r-x
group:html:rwx
mask::rwx
other::r-x
default:user::rwx
default:group::r-x
default:group:html:rwx
default:mask::rwx
default:other::r-x
Because we passed -d
to setfacl
it instructs new directories to also inherit (and apply that inheritance to further subdirectories). So, now as user deploy
we can add and edit existing files inside of that new subdirectory.
[alice@localhost share]$ touch dir_alice/file_indir_alice
[alice@localhost share]$ exit
exit
# sudo -u deploy /bin/bash
[deploy@localhost share]$ cd /var/www/html/share/dir_alice/
[deploy@localhost dir_alice]$ touch file_indir_deploy
[deploy@localhost dir_alice]$ rm file_indir_alice
[deploy@localhost dir_alice]$