保持setgid位(在bower安装或gulp构build之后)

我们运行Web服务器,我们有以下情况:

  1. www-data用户运行Web服务器,并且必须具有对文件的读写访问权限
  2. 部署用户部署所有代码
  3. bob和alice用户可能通过sshlogin并在本地更改configuration

所有用户必须具有对/ var / www / mysite的读写权限。 我们目前通过拥有/ var / www / site到www-data这个组来完成这个任务。 然后我们在组上设置write + setgid位,以确保所有子目录具有相同的权限。

现在,这一切都运行良好一段时间,但我们有以下scheme的问题:

  1. 我们使用凉亭安装与bower install包。 运行bower install的用户第一次bower installpublic/bower_components目录,并且没有设置setgid位
  2. 我们使用gulp将public/scripts/src javascript缩小为public/scripts/dist并且第一个运行gulp build用户拥有这些文件

在这两种情况下, find path/to/dir -type d -exec chmod g+ws {} \; 是否缓解了这个问题,但是有可能首先解决这个问题吗? 我们已经在/var/www/mysite目录中设置了setgid位,那么为什么bower install不能遵循这个权限设置?

如果没有,是否有更好的方法来解决这个问题? 我们曾想过在部署自动化过程中设置一些位,但是如果用户忘记了setgid位,我们认为自动化部署也可能会陷入困境。

Posix ACL是唯一明确的优雅方式,这是我处理共享读/写资源冲突的方式,尤其是在基于Web的系统上。 这是一个运行的例子。

在我的例子中,我有一个名为/var/www/html/share 。 另外我有用户alicebobdeploybower

首先,我创build了一个名为html的组,然后将用户添加到该组中。

 groupadd html for i in alice bob deploy bower; do usermod -a -G html $user; done 

现在,我已经添加了一个文件ACL对这个html组到该文件夹​​。

 setfacl -mg:html:rwx /var/www/html/share setfacl -d -mg:html:rwx /var/www/html/share 

第二个命令很重要,它会导致inheritance的发生。

现在,我们可以testing这个的行为。

 # 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]# 

乍看起来,文件的所有权似乎都很简单,并且不允许一个用户与另一个用户进行交互。 但是,我们可以使用getfacl来查看ACL,其中显示了更多信息。

 # 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::rx #effective:r-- group:html:rwx #effective:rw- mask::rw- other::r-- 

你可以看到, html组有控制这些文件。

注意:标准的unix GROUP权限表示针对权限的掩码。 由于它是rw文件,对于ACL也是有效的,尽piperwx授予了实际的权限。

让其他用户可以修改/删除这些文件。

 # 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 

最后,棘手的一点。 当爱丽丝做一个目录时会发生什么?

 [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::rx group:html:rwx mask::rwx other::rx default:user::rwx default:group::rx default:group:html:rwx default:mask::rwx default:other::rx 

因为我们将-d传递给setfacl它指示新的目录也inheritance(并将inheritance应用到更多的子目录)。 所以,现在作为用户deploy我们可以添加和编辑该新子目录内的现有文件。

 [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]$ 

你混淆了sticky和setgid的语义。

当多个用户被允许在该目录中创build文件和目录时,会使用目录上的粘性位,但只允许更改他们自己创build的那些内容,不允许混淆其他用户创build的内容。 /tmp目录是这个典型的用例。

粘性位不被子目录inheritance。 为了达到预期的目的,没有必要inheritance它。 除了创build者之外,在粘性目录中创build的子目录默认情况下都是禁止的。

目录上的setgid位表示在该目录内创build的文件和目录从该目录inheritance组,而不是获取创build它的当前用户组。 setgid位由在setgid目录内创build的新目录inheritance。

setgid位可以实现您尝试实现的一部分目标。 它将实现目录和文件的整个层次结构将具有相同组的部分(除非明确地被重写)。

但是,这并不能保证所有内容都可以被小组写入。 这可以通过umask设置来实现。

umask表示一组位,不能在新创build的文件和目录中设置。 umask的典型值是0077 。 在你的情况下,你希望这些目录是可写的,这意味着你想要0002 ,这意味着创build的内容对于组外的每个人都是可读的,或者说0007 ,这意味着创build的内容对于组外的每个人都是不可访问的。

您需要确保umask在创build新文件或目录之前的某个时间点被设置。 umask由subprocessinheritance。 注意在特定目录之外创build的文件,因为umask也在其他地方应用,所以在其他地方创build的任何东西仍然可以由组写入,即使这是与/var/www层次结构中使用的不同的组。

您可以尝试通过使其仅附加到chattr来重置根目录的权限:

 chattr +a /var/www/mysite