How to have setfacl inheritance without execute permissions on files?

I'm trying to figure out how you properly run setfacl(1) on a directory and its contents without letting the execute permission "x" get assigned to files. I've been reading the forums and documentation the past few days, as well as trying different outcomes, and nothing seems to work.

This is on 14.3-RELEASE-p7 with ZFS, so NFSv4 ACLs are required. ZFS properties are configured with passthrough.

Code:
aclmode               passthrough
aclinherit            passthrough

I have a web server that needs multiple developers to have the ability to modify files under certain directories. They will also need the ability to create directories within them. I use nginx and I'm wanting the www user to have read-only permissions.

My first attempts had me creating a "developers" group. The default permissions on my web root folder is owned by root:wheel and 0755 (on directories) and 0644 (on files). On the specific folders that the users need to modify, I've changed permissions to be root:developers and 0775 (on directories) and 0664 (on files).

Code:
chown -R root:wheel /usr/local/www/website/
chown -R root:developers /usr/local/www/website/public_html/modules
chown -R root:developers /usr/local/www/website/public_html/plugins
find /usr/local/www/website -type d -exec chmod 0755 {} \;
find /usr/local/www/website -type f -exec chmod 0644 {} \;
find /usr/local/www/website/public_html/modules -type d -exec chmod 0775 {} \;
find /usr/local/www/website/public_html/modules -type f -exec chmod 0664 {} \;
find /usr/local/www/website/public_html/plugins -type d -exec chmod 0775 {} \;
find /usr/local/www/website/public_html/plugins -type f -exec chmod 0664 {} \;

This works, technically. The problems arise when new files are created. The files being created need to be 0664, but are being created as 0644. So just set the umask to 0002 and call it a day. However, I'm not sure how to reliably set the umask for all users across multiple methods of creating files. They can be ssh'd in or they can be scp'ing, maybe even using an app like WinSCP. And I only care about the umask being set for these specific directories/files.

That led me to setfacl. I've used it before in the Linux world, but this is my first time attempting it in FreeBSD+ZFS.

My understanding is that I can simply run:
setfacl -R -a g:developers:rwxpaARWcs:fd:allow /usr/local/www/website/public_html

This does work, but it applies the same set of permissions to both directories and files. I don't want "x" or execute on files. I cannot find anywhere that explains if this is even possible.

Code:
[~]# getfacl /usr/local/www/website/public_html/test/randomfile546
# file: /usr/local/www/website/public_html/test/randomfile546
# owner: root
# group: wheel
  group:developers:rwxp--aARWc--s:------I:allow
            owner@:rw-p--aARWcCos:-------:allow
            group@:r-----a-R-c--s:-------:allow
         everyone@:r-----a-R-c--s:-------:allow

I have seen these discussions already:

https://forums.freebsd.org/threads/...not-working-being-updated-with-setfacl.82298/

https://forums.freebsd.org/threads/trouble-with-acls-setfacl.77121/

https://forums.freebsd.org/threads/do-correct-order-for-nfsv4-acl-with-setfacl-in-scripts.96444/

http://bsdwiki.reedmedia.net/wiki/View_and_modify_ACLs.html

If you can offer any help, it would be much appreciated.
 
The files being created need to be 0664

I don't want "x" or execute on files.
Try without the "execute" ( "x" , setfacl(1)) access permission on the directory from which the inheritance starts.

I haven't tested it extensively, tested on a regular directory, and ZFS dataset mount point ( .../test in this example), no zfsprops(7) "aclmode" and "aclinherit" "=passthrough" set.

Rich (BB code):
root@test:/usr/local/www/website # setfacl -a 0 g:developers:rwpaARWcCos:fd:allow  public_html

root@test:/usr/local/www/website # getfacl public_html
# file: public_html
# owner: root
# group: wheel
  group:developers:rw-p--aARWcCos:fd-----:allow
            owner@:rwxp--aARWcCos:-------:allow
            group@:r-x---a-R-c--s:-------:allow
         everyone@:r-x---a-R-c--s:-------:allow

root@test:/usr/local/www/website # mkdir public_html/test

root@test:/usr/local/www/website # chown :developers public_html/test

root@sfaclTest:/usr/local/www/website # getfacl public_html/test
# file: test
# owner: root
# group: developers
  group:developers:rw-p--aARWc--s:fd----I:allow
            owner@:rwxp--aARWcCos:-------:allow
            group@:r-x---a-R-c--s:-------:allow
         everyone@:r-x---a-R-c--s:-------:allow


john@test:/usr/local/www/website/public_html/test % id -p
uid     john
groups  wheel john developers

john@test:/usr/local/www/website/public_html/test % touch file-john0

john@test:/usr/local/www/website/public_html/test % ls -l file-john0
-rw-rw-r--+ 1 john developers 0 Mar 14 08:27 file-john0
-rw-rw-r--+ ... file-john0 = 664 file-john0
 
I'm trying to figure out how you properly run setfacl(1) on a directory and its contents without letting the execute permission "x" get assigned to files. […]

My understanding is that I can simply run:
setfacl -R -a g:developers:rwxpaARWcs:fd:allow /usr/local/www/website/public_html[…]
You’ll need two ACEs, one with file_inherit lacking the directory traversal (x) bit, one with dir_inherit. That means for this command the :fd: needs to be changed to :d:. That is what Peter Eriksson wrote in Thread 77121.​
 
Thank you both for you help!

Try without the "execute" ( "x" , setfacl(1)) access permission on the directory from which the inheritance starts.

This works!? I'm need to test with aclmode and aclinherit not set to =passthrough, but rather their defaults, and see if I even needed those set in the first place.

I'm unsure how this works. I guess the ACEs are setup in a manner that if any ACE satisfies the action, it works? I can only assume that's why my test user is able to traverse the sub-directory, because of the default ACE group@:r-x---a-R-c--s:-------:allow, even though I created a new ACE without x on :fd:. Knowing this might be the case, I'm curious to try out some other scenarios.

Code:
[root@test ~]# setfacl -R -m g:developers:rwpaARWcs:fd:allow /usr/local/www/website/public_html/test
[root@test ~]# getfacl /usr/local/www/website/public_html/test
# file: /usr/local/www/website/public_html/test
# owner: root
# group: developers
  group:developers:rw-p--aARWc--s:fd-----:allow
            owner@:rwxp--aARWcCos:-------:allow
            group@:r-x---a-R-c--s:-------:allow
         everyone@:r-x---a-R-c--s:-------:allow

Then with my test user I created two files and a sub-directory:

Code:
[rwtest@test /usr/local/www/website/public_html/test]$ id -p
uid    rwtest
groups    rwtest developers
[rwtest@test /usr/local/www/website/public_html/test]$ touch file-rwtest01
[rwtest@test /usr/local/www/website/public_html/test]$ mkdir dir-rwtest01
[rwtest@test /usr/local/www/website/public_html/test]$ touch dir-rwtest01/file-rwtest02
[rwtest@test /usr/local/www/website/public_html/test]$ ls -l
total 1
drwxrwxr-x+ 2 rwtest developers 3 Mar 14 15:23 dir-rwtest01
-rw-rw-r--+ 1 rwtest developers 0 Mar 14 15:23 file-rwtest01
[rwtest@test /usr/local/www/website/public_html/test]$ ls -l dir-rwtest01/
total 1
-rw-rw-r--+ 1 rwtest developers 0 Mar 14 15:23 file-rwtest0

And the resulting getfacl output:

Code:
[root@test ~]# getfacl /usr/local/www/website/public_html/test/file-rwtest01
# file: /usr/local/www/website/public_html/test/file-rwtest01
# owner: rwtest
# group: developers
  group:developers:rw-p--aARWc--s:------I:allow
            owner@:rw-p--aARWcCos:-------:allow
            group@:r-----a-R-c--s:-------:allow
         everyone@:r-----a-R-c--s:-------:allow
[root@test ~]# getfacl /usr/local/www/website/public_html/test/dir-rwtest01/
# file: /usr/local/www/website/public_html/test/dir-rwtest01/
# owner: rwtest
# group: developers
  group:developers:rw-p--aARWc--s:fd----I:allow
            owner@:rwxp--aARWcCos:-------:allow
            group@:r-x---a-R-c--s:-------:allow
         everyone@:r-x---a-R-c--s:-------:allow
[root@test ~]# getfacl /usr/local/www/website/public_html/test/dir-rwtest01/file-rwtest02
# file: /usr/local/www/website/public_html/test/dir-rwtest01/file-rwtest02
# owner: rwtest
# group: developers
  group:developers:rw-p--aARWc--s:------I:allow
            owner@:rw-p--aARWcCos:-------:allow
            group@:r-----a-R-c--s:-------:allow
         everyone@:r-----a-R-c--s:-------:allow



You’ll need two ACEs, one with file_inherit lacking the directory traversal (x) bit, one with dir_inherit. That means for this command the :fd: needs to be changed to :d:. That is what Peter Eriksson wrote in Thread 77121.​

I totally overlooked Peter Eriksson's comment, so thank you. His acltool(1) (https://github.com/ptrrkssn/acltool) looks really interesting and I might end up having to try it. His example showed acltool setting two ACEs, but I cannot seem to recreate that solution with the standard setfacl. However, as I am writing this out and also reviewing how T-Daemon wrote their command, I see my error of using -m instead of -a <num>.

Here's how I was initially running setfacl with x set for :d: only:

Code:
[root@test ~]# setfacl -R -m g:developers:rwxpaARWcs:d:allow /usr/local/www/website/public_html/test
[root@test ~]# getfacl /usr/local/www/website/public_html/test
# file: /usr/local/www/website/public_html/test
# owner: root
# group: wheel
  group:developers:rwxp--aARWc--s:-d-----:allow
            owner@:rwxp--aARWcCos:-------:allow
            group@:r-x---a-R-c--s:-------:allow
         everyone@:r-x---a-R-c--s:-------:allow

Then I added the second ACE without x set for :f: only, but it overwrote the ACE I initially ran for :d:. I was expecting two ACEs to be listed, but instead only got one.

Code:
[root@test ~]# setfacl -R -m g:developers:rwpaARWcs:f:allow /usr/local/www/website/public_html/test
[root@test ~]# getfacl /usr/local/www/website/public_html/test
# file: /usr/local/www/website/public_html/test
# owner: root
# group: wheel
  group:developers:rw-p--aARWc--s:f------:allow
            owner@:rwxp--aARWcCos:-------:allow
            group@:r-x---a-R-c--s:-------:allow
         everyone@:r-x---a-R-c--s:-------:allow

After seeing my error, I reset the ACEs and now ran setfacl again, but with -a and the results are what I would expect.

Code:
[root@test ~]# setfacl -R -b /usr/local/www/website/public_html/test
[root@test ~]# setfacl -R -a 0 g:developers:rwxpaARWcs:d:allow /usr/local/www/website/public_html/test
[root@test ~]# setfacl -R -a 1 g:developers:rwpaARWcs:f:allow /usr/local/www/website/public_html/test
[root@test ~]# getfacl /usr/local/www/website/public_html/test/
# file: /usr/local/www/website/public_html/test/
# owner: root
# group: developers
  group:developers:rwxp--aARWc--s:-d-----:allow
  group:developers:rw-p--aARWc--s:f------:allow
            owner@:rwxp--aARWcCos:-------:allow
            group@:r-x---a-R-c--s:-------:allow
         everyone@:r-x---a-R-c--s:-------:allow

So I re-created all of the same files as before and all ACEs are holding true as I wanted and inheritance is working as expected.

Code:
[root@test ~]# getfacl /usr/local/www/website/public_html/test/file-rwtest01
# file: /usr/local/www/website/public_html/test/file-rwtest01
# owner: rwtest
# group: developers
  group:developers:rw-p--aARWc--s:------I:allow
            owner@:rw-p--aARWcCos:-------:allow
            group@:r-----a-R-c--s:-------:allow
         everyone@:r-----a-R-c--s:-------:allow
[root@test ~]# getfacl /usr/local/www/website/public_html/test/dir-rwtest01/
# file: /usr/local/www/website/public_html/test/dir-rwtest01/
# owner: rwtest
# group: developers
  group:developers:rwxp--aARWc--s:-d----I:allow
  group:developers:rw-p--aARWc--s:f-i---I:allow
            owner@:rwxp--aARWcCos:-------:allow
            group@:r-x---a-R-c--s:-------:allow
         everyone@:r-x---a-R-c--s:-------:allow
[root@test ~]# getfacl /usr/local/www/website/public_html/test/dir-rwtest01/file-rwtest02
# file: /usr/local/www/website/public_html/test/dir-rwtest01/file-rwtest02
# owner: rwtest
# group: developers
  group:developers:rw-p--aARWc--s:------I:allow
            owner@:rw-p--aARWcCos:-------:allow
            group@:r-----a-R-c--s:-------:allow
         everyone@:r-----a-R-c--s:-------:allow

Code:
[rwtest@test /usr/local/www/website/public_html/test]$ touch file-rwtest01
[rwtest@test /usr/local/www/website/public_html/test]$ mkdir dir-rwtest01
[rwtest@test /usr/local/www/website/public_html/test]$ touch dir-rwtest01/file-rwtest02
[rwtest@test /usr/local/www/website/public_html/test]$ ls -l
total 1
drwxrwxr-x+ 2 rwtest developers 3 Mar 14 15:54 dir-rwtest01
-rw-rw-r--+ 1 rwtest developers 0 Mar 14 15:33 file-rwtest01
[rwtest@test /usr/local/www/website/public_html/test]$ ls -l dir-rwtest01/
total 1
-rw-rw-r--+ 1 rwtest developers 0 Mar 14 15:54 file-rwtest0

This is great! Thank you both!
 
Back
Top