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

Kro*_*mey 9 linux permissions mount

首先介绍一下背景:

  • /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/
Run Code Online (Sandbox Code Playgroud)

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

以前,我通过将我的快照目录设为只读 NFS 导出(仅到本地主机)并将其安装在本地(原始保护在一个目录下,没有非 root 用户的遍历权限)来做到这一点,但这感觉就像一个黑客,似乎就像应该有更好的方法来实现这一点。我确实尝试过该mount --bind选项,但它似乎缺乏对两个目录具有不同访问级别(即只读与读写)的能力(除非我遗漏了某些内容:)mount -r --bind dir1 dir2

任何想法如何在没有 NFS 的情况下完成此操作,或者这是我的最佳选择?

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

Kro*_*mey 7

@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
Run Code Online (Sandbox Code Playgroud)

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

现在我只需要将所有这些放在一个脚本中。也许在所有东西都挂载后立即将其插入启动过程,这应该可以避免因 Samba 尝试共享我绑定到的目录而可能引起的任何冲突。

注意:如果您的发行版支持mount -o bind,roGilles 发布的版本,我建议您使用该解决方案;我的解决方案应该只供Ubuntu 或其他发行版上的人使用,这些发行版不允许您在绑定到另一个目录时更改挂载选项。

  • 我在 Ubuntu 10.04 上观察到与您相同(相当令人困惑!)的行为。 (2认同)

Gil*_*il' 6

这个答案适用于 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
Run Code Online (Sandbox Code Playgroud)

在您的用例中,我认为您可以执行以下操作:

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
Run Code Online (Sandbox Code Playgroud)

即把真正的snapshot目录放在一个受限目录下,但给snapshot每个人读权限。它不能直接访问,因为它的父级访问受限。在可访问的位置以只读方式绑定挂载它,以便每个人都可以通过该路径读取它。

(只读绑定安装在引入绑定安装几年后才成为可能,所以你可能记得它们不起作用的时候。我不知道它们从什么时候开始工作,但它们已经在 Debian lenny 中工作了(即现在旧稳定))