深度解析 JuiceFS 权限管理:Linux 多种安全机制全兼容

在多用户和高安全性要求的系统中,文件与目录权限控制是实现资源隔离与系统安全的基础机制。Linux 操作系统的文件权限模型提供了灵活强大的权限控制机制,通过对用户、组和其他用户的权限设置,确保系统资源的安全性和合规性。

作为一款支持 Linux 系统的分布式文件系统,JuiceFS 需要与 Linux 权限管理模型兼容,以实现一致的访问控制和数据安全。本文将深入探讨 JuiceFS 在实际应用中的权限管理实践,帮助用户更好地理解和应用。

01 访问控制模型:DAC 和 MAC

访问控制是系统安全的重要组成部分,旨在管理对资源(如文件、网络服务等)的访问。Linux上常见的访问控制模型有 DAC(Discretionary Access Control,自主访问控制)和 MAC(Mandatory Access Control,强制访问控制)。这两种模型有不同的授权机制和应用场景。

二者的区别如下:

特性 DAC(分散式机制,用户自主访问控制) MAC(中心化机制,管理员强制访问控制)
控制主体 资源所有者 系统级策略
权限分配 资源所有者自主分配 中央管理员统一管理
灵活性 高(用户自主控制) 低(严格策略限制)
安全等级 中等(依赖用户决策) 高(适用于敏感环境)
修改权限 资源所有者可随时修改 只能由管理员修改

常用的 Unix Permission 和 POSIX ACL 实现了自主访问控制 (DAC),允许资源所有者自由管理文件和目录的访问权限,而 SELinux 和 AppArmor 实现了强制访问控制(MAC),通过系统定义的安全策略来限制访问权限,从而提供更为严格的安全控制。

在下面的内容中,我们会展开介绍这些机制的细节和在 JuiceFS 的相关使用。

02 Unix Permission

Unix Permission 是从 Unix 系统中继承的一种权限管理机制,用于控制文件和目录的访问权限。 该机制简单总结如下:

主体(Subject)对客体(Object)的行为根据规则进行控制。

  • 主体:操作者是用户或者说进程,划分为三类(ugo)
    • u: 文件所有者(Owner)
    • g: 文件所属组(Owner Group)
    • o: 其他用户(Other)
  • 客体:操作对象是文件或者目录
  • 规则:三种权限(rwx),对于文件和目录有不同的含义
    • r:读取权限
      • 文件:读取文件内容,拓展属性,symlink等
      • 目录: 列出目录内列表等
    • w:写入权限
      • 文件:修改文件内容,拓展属性等
      • 目录:创建,删除,移动文件或目录
    • x:执行权限
      • 文件:执行文件
      • 目录:切换目录,查看内部文件属性等

特殊权限位

简单的 ugo+rwx 权限模型,是大家比较熟悉的。在这基础上,还有一些拓展的特殊权限位:

  • SUID: 当一个文件被赋予了 SUID 权限,其他用户在执行这个文件时,其权限会暂时提升到该文件所有者的权限。
  • SGID: SGID 权限与 SUID 类似,但它影响的是文件的组权限而不是所有者权限。当一个文件被赋予了 SGID 权限,其他用户在执行这个文件时,其权限会暂时提升到该文件所属组的权限。
  • SBIT: Sticky Bit 是一种特殊的目录权限。当一个目录被赋予了 Sticky Bit 权限,用户只能删除自己拥有的文件,即使他们对这个目录有写和执行权限。这个权限通常用在临时文件目录(如/tmp),以防止用户删除其他用户的文件。

JuiceFS 的权限校验

JuiceFS 是基于 FUSE 的用户态文件系统,默认情况下,JuiceFS 会开启 default_permissions 配置,即启用内核的权限检查。文件操作请求到达 JuiceFS 用户态前,内核会根据文件属性中的 mode 先进行 Unix Permission 的权限校验,通过后再交给 JuiceFS 处理。

此外,JuiceFS 本身在用户态也实现了兼容的权限校验逻辑,用于处理一些特殊的权限场景。

  1. SDK 访问: 一个是 JuiceFS 提供了多种 SDK 访问方式,这些 SDK 请求不经过内核,所以 JuiceFS 需要自己实现权限校验;

  2. Squash 功能:当启用 squash 功能时,JuiceFS 会将某些用户映射为指定的用户,在这种情况下,无法依赖内核权限校验,因此 JuiceFS 会启用用户态的权限校验。

下面简单介绍一下 squash 两种模式:

  1. root-squash (Root 降权映射)

root-squash 模式用于将本地 root 用户映射为其他用户,从而增强系统安全性。在该模式下,即使操作系统中的 root 用户,执行文件操作时也会受到权限控制,无法随意修改其他用户的文件。

shell 复制代码
# root in /tmp/jfs
$ ll /tmp/jfs/f1    
-rw------- 1 user2 user2 0  2月  19 16:26 /tmp/jfs/f1
# 读取用户user2的文件,可以直接读取
$ cat /tmp/jfs/f1
hello

映射后

shell 复制代码
# root用户映射为普通用户user1(uid=1001,gid=1001)
./juicefs mount sqlite3://test.db /tmp/jfs -o allow_other -root-squash=1001:1001
# 读取user2的文件,权限不足
$ cat /tmp/jfs/f1
cat: /tmp/jfs/f1: Permission denied
  1. all-squash (所有用户映射为指定用户)

在 all-squash 模式下,系统将所有用户映射为指定的用户(例如 user1),此模式通常用于统一权限管理,所有操作都会以指定用户的身份进行。该功能将在 JuiceFS 社区 1.3 版本发布。

shell 复制代码
# 所有用户映射为user1(uid=1001,gid=1001)
$ ./juicefs mount sqlite3://test.db /tmp/jfs -o allow_other -all-squash=1001:1001
# user2 创建文件
$ whoami
user2
$ touch f1
# user3 创建文件
$ whoami
user3
$ touch f2
# 最后文件拥有者都是user1
$ ls -l .
total 0
-rw-rw-r-- 1 user1 user1 0  2月 19 14:10 f1
-rw-rw-r-- 1 user1 user1 0  2月 19 14:11 f2

03 POSIX ACL

Unix Permission 已经能够满足大部分的权限管理需求,但是在某些场景下,我们需要更加细粒度的权限控制。比如需要单独为某个用户开放文件权限的时候,这时候就可以用 ACL 做精细控制。 POSIX ACL(Access Control List)是一种扩展的权限控制机制,虽然没有统一的标准,但是草案《POSIX 1003.1e draft 17》是被广泛接受的。基于这个草案的实现,在 2002 年 11 月被添加到 Linux 内核的 2.5.46 版本中。

传统的 Unix Permission 只对主体做了三种分类(owner、group、other),而 POSIX ACL 在此基础上,对主体进行了更细致的分类,可以对任意的用户/组分配 rwx 权限。所有的用户权限定义在 ACL 中可以抽象成一条 entry 定义。每一条 entry,包含用户 id,以及他的权限定义,结构定义如下:

go 复制代码
type Permission struct {
    Owner Mode
    Group Mode
    Other Mode
}

type ACL struct {
    Owner Mode
    Group Mode
    Other Mode
    Mask Mode // 权限上界
    NamedUsers  Entry // 新增指定用户权限定义
    NamedGroups Entry // 新增指定用户组权限定义
}

type Entry struct {
    Uid uint32
    Perm Mode
}

POSIX ACL 新增了指定用户(NamedUsers)和指定用户组(NamedGroup)的权限。从定义上看,我们可以把 POSIX ACL 新增的 entry(包括 Mask)划分到 group class,将 group class 的定义从原来所在组的权限,扩展到 group class 中所有 entry 的权限上界。

分组 entry 项 文本格式
owner class owner user::rwx
group class named user user:name:rwx
group class owning group group::rwx
group class named group group:name:rwx
group class mask mask::rwx
other class others other::rwx

当没有配置额外的 named user 和 named group 时,称之为 Minimal ACL, 与 Unix Permission 等价。

  • Minimal ACL:等同于普通 unix permission
  • Extended ACL:配置了任意 named user 或 named group 项

下面操作展示了 POSIX ACL 与 Unix Permission 之间的关联性。

shell 复制代码
# 查看权限
$ ls -l
drwxr-xr-x 2 root root 4.0K  4月 12 09:32 d1

# 通过setfacl设置d1目录的group1组权限
$ setfacl -m g:group1:rwx d1

# 再次查看权限
$ ls -l
drwxrwxr-x+ 2 root root 4.0K  4月 12 09:32 d1

设置了 ACL 之后,文件的 group class 也发生了变化, 增加了 "w" 权限。这是因为 ACL 拓展了 group class(请参考表格 1 中的分组)。

unix permission 中的 group class 仅代表了 owner group 的权限,但 POSIX ACL 中代表 group class 所有条目的权限上界。因此 group class 的权限位也会随条目变动而变化.

ACL 新增条目:Mask

上文提到 ACL 中新增的条目 "mask" ,该条目用于表示 group class 的动态权限变化。设置了 ACL 后,permission mode 的 group class 显示就是 mask。

通过 setfacl 设置 ACL, 默认会自动计算出 mask。比如上文所示, mask = owner group entry | group1 entry, 取并集"rwx"; 也可以独立设置 mask, 则 group class 中 entry 项的最终权限需要与 mask 取交集. 如下文:

  • owner group 最终生效的权限为:"r-x" & "-wx" = "--x"
  • group1 权限为:"rwx" & "-wx" = "-wx"
shell 复制代码
# 接上文操作, 设置mask为"-wx"
$ setfacl -m m::-wx d1

# 查看ACL
$ getfacl d1 --omit-header
user::rwx
group::r-x                      #effective:--x
group:group1:rwx                #effective:-wx
mask::-wx
other::r-x

ACL 类别

ACL 分为两种类别,Access ACL 和 Default ACL。

  • Access ACL: 用于权限定义和检查, 适用于文件和目录,定义如上面章节所述。
  • Default ACL:结构与 Access ACL 相同,但仅应用于目录。子文件/子目录的 Access ACL将继承自父目录的 Default ACL。(继承后的权限,结合创建文件对象的系统调用的mode 参数生成最终的 Access ACL, 其中 owner/mask/other与mode 取交集)。
shell 复制代码
# 设置access acl
$ setfacl -m u:user1:rwx d1
# 设置default acl (with -d flag)
setfacl -d -m u:user1:rwx d1
# 查看acl
$ getfacl -c d1
# 前5项是access acl配置
user::rwx
user:user1:rwx
group::rwx
mask::rwx
other::r-x
# 后面5项是default acl配置
default:user::rwx
default:user:user1:rwx
default:group::rwx
default:mask::rwx
default:other::r-x

Access ACL 权限判断规则

进程请求访问文件对象,权限判断规则如下:

  • 首先找到一条最匹配的 ACL entry
    • entry按照以下顺序查找:
      1. owner
      2. named users
      3. owning or named groups
      4. others
    • 一个进程可能属于多个组,有多条group class entry匹配(上面第3项),那么取拥有权限的那条entry。如果有匹配的group class entry,但都不满足权限要求,那么请求被拒绝。
  • 检查这条 entry 的权限要求是否满足请求

如果对细节感兴趣,可以参考 JuiceFS 社区版 pkg/acl/acl.go 中的实现。

JuiceFS 的 ACL

JuiceFS 通过将 ACL 和扩展属性(xattr)解耦来优化 ACL 的存储。每个文件不再单独保存一份 ACL,而是将 ACL 存储在一个独立的元数据结构中,并通过全局唯一的 ACL ID 来引用相同的 ACL 配置。这种方法显著减少了重复数据存储需求,并提高了性能,特别是在使用 Default ACL 的目录下创建文件时,减少了存储 ACL 请求的频率。详情,请参考文章:ACL 功能全解析,更精细的权限控制;配置参考文档:POSIX ACLJuiceFS POSIX ACL 权限管理上手指南

04 Capability,细分权限能力,降低系统安全风险

传统的 unix 权限只区分了两种类别进程,特权 (root) 和非特权。 root 进程拥有系统的所有权限, 比如前面所述的 unix permission 和 acl 权限检查对其无效,可以任意访问/修改文件对象。

从 Linux 内核 2.2 版本之后,加入了 Capability 机制,将权限细分成不同能力。这样可以给非特权进程赋予部分特权,降低了系统的安全风险

二进制文件的 capability 集合是记录在命名空间 security 下的拓展属性的。可以通过 getcap 和setcap 命令查看和设置 capability。

如果在 JuiceFS中(1.3版本)使用的话,需要同时开启拓展属性(挂载参数 --enable-xattr)和capability (挂载参数 --enable-cap) 支持。默认 capability 是关闭的,因为一般场景比较少使用到,开启后会增加许多对拓展属性的元数据请求,影响性能。

shell 复制代码
# 挂载, 需要启动xattr和cap
$ ./juicefs mount sqlite3://test.db /tmp/jfs --enable-cap --enable-xattr
# 设置capability:普通用户执行bin二进制,可以拥有修改文件owner的权限
$ sudo setcap 'cap_chown=+ep' bin
# 查看capability
$ getcap bin
bin cap_chown=ep

05 SELinux:增强 Linux 系统安全的内核模块

前面讲述 DAC 与 MAC 两种模型的原理与区别,DAC 比较灵活但不严格,有一定的安全隐患。在 DAC 的访问控制机制中,传统 Linux 由于 root 权限的"权力"过大而存在安全威胁。

MAC 模型则能解决这个问题,它是一种强制访问控制机制,由系统管理员配置策略,严格执行。SElinux 是实现 MAC 模型的一个安全增强的 Linux 内核模块,它控制了无限的 root 权限

虽然 SELinux 和 AppArmor 都是 Linux 上的实现 MAC 的安全模块。但是使用和实现上有一些区别。不同 Linux 发行版默认使用不同,SELiunx 主要用于 RHEL/Fedora,AppArmor主要用于 Ubuntu 和 SUSE。这里主要介绍 SELinux。

在启用了 SELinux 的 Linux 操作系统中,系统权限管理要先通过 DAC 机制的检测, 再检测 SELinux 的安全策略。在 SELinux 中,每个对象(比如文件)都有一个 安全上下文(Security Context),通过文件拓展属性,记载着该对象具有的权限(SELinux 定义的权限)。

如果在 JuiceFS 中(1.3 版本)使用的话,需要同时开启拓展属性(挂载参数--enable-xattr)和SELinux (挂载参数--enable-selinux)支持。默认 ``--enable-selinux` 也是关闭的。

06 小结

本文全面梳理了 Linux 文件权限管理模型,并探讨了 JuiceFS 在此基础上的权限管理实现。作为一款基于 FUSE 的用户态分布式文件系统,JuiceFS 不仅兼容传统的 Unix 权限机制,还通过用户态权限校验、root-squash 和 all-squash 等特殊功能,提供了更加灵活的访问控制策略。这些功能使得 JuiceFS 能够在多种权限管理需求下稳定运行,特别适用于需要高安全性和复杂用户管理的环境。

通过灵活配置权限管理,JuiceFS 能有效提高数据的安全性、合规性,并确保在多用户环境中提供稳定和高效的数据存取服务,帮助企业应对更复杂的存储和安全挑战。

相关推荐
白露与泡影12 分钟前
springboot + nacos + k8s 优雅停机
spring boot·后端·kubernetes
菜鸟谢30 分钟前
windows xp 下载 sp0 sp1 sp2 sp3 sp4
后端
AirMan32 分钟前
你真的懂 MySQL 的一致性读和当前读的区别吗?
后端·面试
运维成长记33 分钟前
阿里云实践创建实例步骤
linux·运维·服务器·阿里云·云计算
David爱编程38 分钟前
容器性能优化实战指南——防止“吃爆”服务器就靠这些招!
后端·docker·容器
Android洋芋41 分钟前
GitHub项目部署的终极指南:从零到一掌握Docker实战
后端
THe CHallEnge of THe BrAve1 小时前
Linux检验库是否安装成功
linux·运维·服务器
Hello.Reader1 小时前
NGINX 四层 SSL/TLS 支持ngx_stream_ssl_module
运维·nginx·ssl
林太白1 小时前
Next.js超简洁完整篇
前端·后端·react.js
前端付豪1 小时前
汇丰登录风控体系拆解:一次 FaceID 被模拟攻击的调查纪实
前端·后端·架构