将目录下的所有文件设为只读而不更改权限?

将目录下的所有文件设为只读而不更改权限?

首先,一些背景:

  • /dev/md1 是用作主文件存储的 RAID-0 阵列。它安装到/var/smb。
  • /dev/md2 是另一个 RAID-0 阵列,存储从 /dev/md1 获取的备份快照。它安装到 /var/smb/snapshots。
  • 通过 Samba 提供三个目录:/var/smb/files(公共共享文件)、/var/smb/private(私有文件)和 /var/smb/snapshots(提供对备份快照的只读访问)。

仅允许 smbusers 组中的用户访问文件和快照共享;同样,只有 smbprivate 组中的用户才可以访问私有文件。此外,Linux 权限禁止不在相应组中的用户访问本地系统上和 Samba 共享快照中的文件和私有目录。

这很棒,因为这意味着我们拥有一个功能齐全的文件服务器,具有自助“从备份恢复”选项(用户可以简单地访问快照共享并检索他们想要自行恢复的文件),但是到目前为止,我缺少一个关键要素:本地系统上对 /var/smb/snapshots 目录的非 root 访问权限。

快照必须对所有普通用户严格只读,但是当然文件系统必须以读写方式安装才能进行备份操作。目前这些目录的权限是:

root@odin:/var/smb# ll
total 40
drwxrwxr-x  7 root   root        4096 2011-04-11 15:18 ./
drwxr-xr-x 14 root   root        4096 2011-04-10 19:07 ../
drwxrwx--- 15 kromey smbusers    4096 2010-12-07 13:09 files/
drwxrwx---  7 kromey smbprivate  4096 2010-04-07 07:08 private/
drwxrwx---  3 root   root        4096 2011-04-11 15:16 snapshots/

现在,我想要的是向非 root 用户提供对快照目录的访问,但以严格只读的方式。不过,我无法以只读方式挂载 /dev/md2,因为我必须将其读写才能运行备份;我不能简单地将其重新挂载为可读写备份,然后将其重新挂载为只读,因为这提供了另一个用户可以写入备份的时间窗口。

以前,我通过将快照目录设置为只读 NFS 导出(仅限本地主机)并在本地安装(原始安全目录位于缺乏非 root 用户遍历权限的目录下)来实现此目的,但这感觉像是一种黑客行为,并且似乎就像应该有更好的方法来实现这一目标。我确实尝试了该mount --bind选项,但它似乎缺乏在两个目录上具有不同访问级别(即只读与读写)的能力(除非我错过了一些东西:)mount -r --bind dir1 dir2

有什么想法可以在没有 NFS 的情况下完成此任务,或者这是我的最佳选择?

长话短说:如何使文件系统的内容可供选定用户读写,但对其其他人严格只读,同时保留备份到该文件系统的文件的原始权限和所有权?

答案1

@Gilles 非常接近,只是对于 Ubuntu 10.10 来说有点偏离目标(我没有任何理由怀疑他是否适合 Debian Squeeze,可能还有其他人)。通过将我的读写快照目录安装在其他用户无法访问的文件夹下(例如 /var/smb/hidden/snapshots,其中 /var/smb/hidden 具有权限 770 并且由 root:root 所有),我可以保护来自其他用户的读写挂载。然后我可以使用mount --bind后面的mount -o remount,ro将安装绑定到可访问的位置,然后将其设置为只读。

(相反的(将原始文件系统挂载为只读,然后将其绑定为读写)不起作用;同样,将原始文件系统挂载为只读,然后将其绑定为只读,然后重新挂载原始读写使得绑定目录也是可读写的。)

回顾一下,解决方案如下:

mkdir /var/smb/hidden
chown root:root /var/smb/hidden
chmod 770 /var/smb/hidden
mkdir /var/smb/hidden/snapshots
mksdir /var/smb/snapshots
mount /dev/md2 /var/smb/hidden/snapshots
mount --bind /var/smb/hidden/snapshots /var/smb/snapshots
mount -o remount,ro /var/smb/snapshots

因此,有一个短暂的时间窗口,其中备份是可读写的并且通常可以访问,但它足够小,可以满足我的需要。如果这些短暂的毫秒窗口太大,那么 /var/smb 上的权限的一些技巧可以在这个短暂的窗口期间保护它(即使其不可遍历,然后绑定挂载,然后再次使其可遍历)。

现在我只需要将这些全部放在一个脚本中即可。也许在安装完所有内容后将其插入启动过程,这应该可以避免由于 Samba 尝试共享我绑定到的目录而可能引起的任何冲突。

笔记:如果您的发行版支持mount -o bind,roGilles 发布的版本,我会为您推荐该解决方案;我的解决方案在这里应该仅有的由 Ubuntu 或其他发行版上的用户使用,这些发行版不允许您在绑定到另一个目录时更改安装选项。

答案2

这个答案适用于 Debian(在 lenny 和挤压上测试)。经过调查,它似乎只能通过 Debian 补丁才能工作;其他发行版(例如 Ubuntu)的用户可能就不那么幸运了。

您可以使用mount --bind。将“真实”文件系统安装在不可公开访问的目录下。创建一个更易于访问的只读绑定安装。为您想要通过读写访问公开的部分进行读写绑定安装。

mkdir /media/hidden /media/hidden/sdz99
chmod 700 /media/hidden
mount /dev/sdz99 /media/hidden/sdz99
mount -o bind,ro /media/hidden/sdz99/world-readable /media/world-readable
mount -o bind /media/hidden/sdz99/world-writable /media/world-writable

在你的用例中,我认为你可以这样做:

mkdir /var/smb/hidden
mv /var/smb/snapshot /var/smb/hidden
mkdir /var/smb/snapshot
chmod 700 /var/smb/hidden
chmod 755 /var/smb/hidden/snapshot
mount -o bind,ro /var/smb/hidden/snapshot /var/smb/hidden/snapshot

即把真实snapshot目录放在受限目录下,但给snapshot每个人读取权限。它无法直接访问,因为它的父级访问受到限制。将其以只读方式绑定安装在可访问的位置,以便每个人都可以通过该路径读取它。

(只读绑定挂载在引入绑定挂载几年后才成为可能,所以你可能还记得它们不起作用的时候。我不知道它们何时起作用,但它们已经在 Debian lenny 中起作用了(即现在是旧稳定)。)

相关内容