维护 setgid 位(在 bower install 或 gulp build 之后)

维护 setgid 位(在 bower install 或 gulp build 之后)

我们在运行 Web 服务器时遇到以下情况:

  1. www-data 用户运行 Web 服务器,并且必须具有对文件的读写权限
  2. deploy 用户部署所有代码
  3. bob 和 alice 用户可以通过 ssh 登录并在本地更改配置

所有用户都必须对 /var/www/mysite 具有读写权限。我们目前通过将 /var/www/site 的组归为 www-data 来实现此目的。然后,我们在该组上设置写入 + setgid 位,以确保所有子目录都具有相同的权限。

现在,这一切都运行良好,但我们在以下场景中遇到了问题:

  1. 我们使用 bower 安装软件包。首次bower install运行的用户拥有该目录,并且未设置 setgid 位bower installpublic/bower_components
  2. 我们使用 gulp 将 JavaScript 从 压缩public/scripts/srcpublic/scripts/dist,并且第一个运行的用户gulp build拥有这些文件

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

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

答案1

Posix ACL 是唯一一种明确而优雅的实现方法,这就是我处理共享读/写资源冲突的方法,尤其是在基于 Web 的系统上。这是一个正在运行的示例。

在我的示例中,我有一个名为 的目录。/var/www/html/share此外,我还有用户alicebobdeploybower

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

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

现在,我已将针对该html组的文件 ACL 添加到该文件夹​​中。

setfacl -m g:html:rwx /var/www/html/share
setfacl -d -m g:html:rwx /var/www/html/share

第二条命令很重要,它导致继承发生。

现在,我们可以测试一下这个行为。

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

乍一看,文件所有权似乎都很简单,不允许一个用户与另一个用户交互。但是,我们可以使用它来检查 ACL,getfacl从而显示更多信息。

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

您可以看到该html组对这些文件具有控制权。

笔记:标准 unix GROUP 权限表示针对权限的掩码。与文件一样,它对于 ACLrw也同样有效,尽管实际授予的权限是。rwrwx

让我们测试其他用户是否可以修改/删除这些文件。

# 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 创建目录时会发生什么?

[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

因为我们传递-dsetfacl它的指示新目录也继承(并将该继承应用于其他子目录)。因此,现在作为用户,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]$ 

答案2

您混淆了 sticky 和 ​​setgid 的语义。

当允许多个用户在目录中创建文件和目录,但只能更改自己创建的内容,而不能更改其他用户创建的内容时,就会使用目录上的粘性位。目录/tmp是此操作的典型用例。

粘性位不会被子目录继承。无需继承即可满足其预期目的。粘性目录中创建的子目录默认禁止除创建者之外的任何人访问。

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

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

但是它不能保证其中的所有内容都可以由组写入。这可以通过 umask 设置来实现。

umask 表示一组位,这些位不能设置在新创建的文件和目录中。umask 的典型值为00020007002200270077。在您的例子中,您希望这些目录对于组来说是可写的,这意味着您希望0002创建的内容对组外的每个人都是可读的,或者0007创建的内容对组外的每个人都是不可访问的。

您需要确保在创建新文件或目录之前设置了 umask。umask 由子进程继承。请留意在该特定目录之外创建的文件,因为 umask 也应用于其他地方,因此在其他地方创建的任何内容仍可由该组写入,即使该组与层次结构中使用的组不同/var/www

答案3

您可以尝试通过仅附加以下内容来增加重置根目录权限的难度聊天室

chattr +a /var/www/mysite

相关内容