早上好;我有一个 RHEL 5.7 Web 服务器,配置为仅允许特定组使用 SSH/SFTP。我希望内容管理员将内容上传到各自的目录,并让该内容继承目录的用户/组所有权,无论上传方法或应用程序如何。例如:
- John 在群组中“网络”SSH/SFTP 权限和“金融”获取目录权限,并上传到目录“网络内容”通过 SFTP。
- 目录“网络内容”拥有“2760”(rwxrws---)的权限,以及“阿帕奇:财务”。
如果 John 上传了对现有文件的更新“网络内容”,文件的所有权仍为“阿帕奇:财务”。如果 John 上传新文件到“网络内容”,该文件的所有权为“约翰:财务”。
我希望将 John 的任何文件上传到“网络内容”更改为目录的所有者。我尝试设置 setuid 和 setgid,但用户所有权未生效。我在 ServerFault 上看到过使用 ACL 或 chrooted jail 进行 SFTP 的提及,但我尚未配置和测试它们,我不知道它们是否是可行的解决方案(它们可能是,但我不知道,因为我从未做过)。任何想法和帮助都将不胜感激。
答案1
问题是 sftp 以用户 ID 运行 - 首先,sftp 客户端以给定用户的身份通过 ssh 进入目标主机,然后运行 sftp-server。由于 sftp-server 以普通用户身份运行,因此它无法“放弃”文件(更改文件的所有者)。
但是,如果您能够使用 scp,并为每个用户分配一个密钥对,则可以解决这个问题。这涉及将用户的密钥添加到 root 的 ~/.ssh/authorized_keys 文件中,并使用“command=”参数强制它运行一个脚本,该脚本会清理并更改服务器端 scp 程序的参数。我以前曾使用过这种技术来设置一个匿名 scp 投递箱,允许任何人提交文件,并确保没有人可以检索已提交的文件并防止覆盖。
如果您愿意接受这种技术,请告诉我,我将在此帖子中更新一个快速食谱。
编辑:根据评论,这是我最初用来设置匿名 Dropbox 的方法。但它也应该可以用于此目的。
如果您希望 John 写入文件上传到/var/www/webstuff
,并且让任何写入其中的文件归用户 id 所拥有apache
,那么:
1)生成ssh密钥对:
ssh-keygen -t rsa -f john-scp-key
2)编辑公钥文件“john-scp-key.pub”,在开头插入“command=”语句,内容如下:
command="/usr/local/bin/strictscp ^/var/www/webstuff" ssh-rsa AAAA..... (reset
of key follows)
3)将 的内容添加john-scp-key.pub
到~apache/.ssh/authorized_keys
文件(如果文件不存在则创建该文件,并确保 .ssh 目录和 authorized_keys 都归 拥有apache
,并且不能由任何组或世界写入)
4)创建脚本/usr/local/bin/strictscp
如下:
#!/bin/sh
read cmd arg1 arg2 <<EOT
$SSH_ORIGINAL_COMMAND
EOT
if [ "$cmd" = scp -a "$arg1" = -t ] && echo "$arg2" |grep "$1" >/dev/null 2>&1
then
eval $cmd $arg1 $arg2
fi
5)现在将私钥文件john-scp-key
交给 John,并让他将文件复制到您的 Web 服务器,如下所示:
scp -i john-scp-key some_file.html apache@yourserver:/var/www/webstuff/
其工作原理是,当您使用 scp 将文件复制到服务器时,scp 客户端使用 ssh 在服务器上执行“scp -t /path/name”。使用密钥对时,您可以覆盖执行的命令,并在使用该密钥时强制运行特定命令。请求的原始命令及其参数位于环境变量“$SSH_ORIGINAL_COMMAND”中。因此,我们指向COMMAND=
一个检查允许参数的脚本(在本例中,它会验证第三个参数是否是我们要写入内容的特定目录),这样该密钥仅适用于其预期用途,不能用于在服务器上运行任意命令。
strictscp
您可以通过检查目标文件是否存在来进一步锁定脚本,还可以chgrp
在末尾添加命令来设置文件的组所有权(假设apache
是该组的成员)。
希望这会有所帮助 - 如果您有任何问题,请告诉我,我会看看是否可以进一步改进这个答案。