Hadoop分布式文件系统(HDFS)为共享大部分POSIX模型的文件和目录实现权限模型。每个文件和目录都与一个所有者和一个组相关联。该文件或目录对作为所有者的用户,作为该组成员的其他用户以及对所有其他用户具有单独的权限。对于文件,需要r权限才能读取文件,而w权限才需要写入或附加到文件。对于目录,需要r权限才能列出目录的内容,需要w权限来创建或删除文件或目录,并且需要x权限来访问目录的子级。
与POSIX模型相比,文件没有setuid或setgid位,因为没有可执行文件的概念。对于目录,没有setuid或setgid bits目录来简化。可以在目录上设置粘滞位,以防止除超级用户,目录所有者或文件所有者以外的任何人删除或移动目录中的文件。设置文件的粘性位无效。总而言之,文件或目录的权限就是其模式。通常,将使用用于表示和显示模式的Unix习惯,包括在此描述中使用八进制数字。创建文件或目录时,其所有者是客户端进程的用户身份,其组是父目录的组(BSD规则)。
HDFS还提供对POSIX ACL(访问控制列表)的可选支持,以针对特定命名用户或命名组的更细粒度的规则来扩展文件权限。本文档后面将详细讨论ACL。
每个访问HDFS的客户端进程都有一个由用户名和组列表组成的两部分身份。每当HDFS必须对客户端进程访问的文件或目录foo进行权限检查时,
如果权限检查失败,则客户端操作将失败。
从Hadoop 0.22开始,Hadoop支持两种不同的操作模式来确定用户的身份,该模式由hadoop.security.authentication属性指定:
简单
在这种操作模式下,客户端进程的身份由主机操作系统确定。在类似Unix的系统上,用户名等效于“ whoami”。
kerberos
在Kerberized操作中,客户端进程的身份由其Kerberos凭据确定。例如,在以Kerberized环境中,用户可以使用kinit实用程序来获取Kerberos票证授予票证(TGT),并使用klist来确定其当前主体。当将Kerberos主体映射到HDFS用户名时,除主要组件外的所有组件均被删除。例如,委托人todd/foobar@CORP.COMPANY.COM将充当HDFS上的简单用户名todd。
无论操作模式如何,用户标识机制都是HDFS本身固有的。HDFS内没有用于创建用户身份,建立组或处理用户凭据的规定。
如上所述确定了用户名后,组列表将由hadoop.security.group.mapping属性配置的组映射服务确定。有关详细信息,请参见Hadoop组映射。
每个HDFS操作都要求用户具有特定的权限(通过文件所有权,组成员身份或其他权限来授予特定权限(READ,WRITE和EXECUTE的某种组合)。一个操作可能会在路径的多个组件上执行权限检查,而不仅仅是最终组件。此外,某些操作取决于对路径所有者的检查。
所有操作都需要遍历访问。遍历访问需要对路径的所有现有组件(最终路径组件除外)具有EXECUTE权限。例如,对于任何访问/ foo / bar / baz的操作,调用者必须对/,/ foo和/ foo / bar具有EXECUTE权限。
下表描述了HDFS对路径的每个组件执行的权限检查。
运作方式 | 所有权 | 父母 | 祖先 | 最后 | 子树 |
---|---|---|---|---|---|
附加 | 没有 | 不适用 | 不适用 | 写 | 不适用 |
康卡特 | 否[2] | 写(来源) | 不适用 | READ(源),WRITE(目标) | 不适用 |
创建 | 没有 | 不适用 | 写 | 写[1] | 不适用 |
createSnapshot | 是 | 不适用 | 不适用 | 不适用 | 不适用 |
删除 | 否[2] | 写 | 不适用 | 不适用 | 读,写,执行 |
deleteSnapshot | 是 | 不适用 | 不适用 | 不适用 | 不适用 |
getAclStatus | 没有 | 不适用 | 不适用 | 不适用 | 不适用 |
getBlockLocations | 没有 | 不适用 | 不适用 | 读 | 不适用 |
getContentSummary | 没有 | 不适用 | 不适用 | 不适用 | 读取,执行 |
getFileInfo | 没有 | 不适用 | 不适用 | 不适用 | 不适用 |
getFileLinkInfo | 没有 | 不适用 | 不适用 | 不适用 | 不适用 |
getLinkTarget | 没有 | 不适用 | 不适用 | 不适用 | 不适用 |
getListing | 没有 | 不适用 | 不适用 | 读取,执行 | 不适用 |
getSnapshotDiffReport | 没有 | 不适用 | 不适用 | 读 | 读 |
getStoragePolicy | 没有 | 不适用 | 不适用 | 读 | 不适用 |
getXAttrs | 没有 | 不适用 | 不适用 | 读 | 不适用 |
listXAttrs | 没有 | 执行 | 不适用 | 不适用 | 不适用 |
mkdirs | 没有 | 不适用 | 写 | 不适用 | 不适用 |
ModifyAclEntries | 是 | 不适用 | 不适用 | 不适用 | 不适用 |
removeAcl | 是 | 不适用 | 不适用 | 不适用 | 不适用 |
removeAclEntries | 是 | 不适用 | 不适用 | 不适用 | 不适用 |
removeDefaultAcl | 是 | 不适用 | 不适用 | 不适用 | 不适用 |
removeXAttr | 否[2] | 不适用 | 不适用 | 写 | 不适用 |
改名 | 否[2] | 写(来源) | 写(目的地) | 不适用 | 不适用 |
重命名快照 | 是 | 不适用 | 不适用 | 不适用 | 不适用 |
setAcl | 是 | 不适用 | 不适用 | 不适用 | 不适用 |
setOwner | 是[3] | 不适用 | 不适用 | 不适用 | 不适用 |
setPermission | 是 | 不适用 | 不适用 | 不适用 | 不适用 |
setReplication | 没有 | 不适用 | 不适用 | 写 | 不适用 |
setStoragePolicy | 没有 | 不适用 | 不适用 | 写 | 不适用 |
setTimes | 没有 | 不适用 | 不适用 | 写 | 不适用 |
setXAttr | 否[2] | 不适用 | 不适用 | 写 | 不适用 |
截短 | 没有 | 不适用 | 不适用 | 写 | 不适用 |
[1] 仅当调用使用覆盖选项并且路径上存在现有文件时,才需要在创建过程中对最终路径组件进行WRITE访问。
[2]如果设置了sticky位,则检查父目录上的WRITE权限的任何操作也会检查所有权。
[3]调用setOwner更改拥有文件的用户需要HDFS超级用户访问权限。更改组不需要HDFS超级用户访问权限,但调用者必须是文件的所有者,并且是指定组的成员。
每个文件或目录操作将完整路径名传递给NameNode,并且权限检查沿每个操作的路径应用。客户端框架将隐式地将用户身份与与NameNode的连接关联起来,从而减少了对现有客户端API进行更改的需要。一直存在这样的情况:对文件的一项操作成功后,重复操作可能会失败,因为该文件或路径中的某些目录已不存在。例如,当客户端第一次开始读取文件时,它会向NameNode发出第一个请求,以发现文件的第一个块的位置。查找其他块的第二个请求可能会失败。另一方面,删除文件不会撤消已经知道文件块的客户端的访问。除了权限,客户可以在两次请求之间撤消对文件的访问。同样,更改权限不会撤消已经知道该文件块的客户端的访问。
如果权限检查失败,则所有使用path参数的方法都将引发AccessControlException。
新方法:
新文件或目录的模式受设置为配置参数的umask限制。当使用现有的create(path,…)方法(不带权限参数)时,新文件的模式为0666&^ umask。当使用新的create(path,Permission,...)方法(具有权限参数P)时,新文件的模式为P&^ umask&0666。使用现有的mkdirs(path)方法创建新目录时(不具有permission参数),新目录的模式为0777&^ umask。当使用新的mkdirs(path,Permission)方法(具有权限参数P)时,新目录的模式为P&^ umask&0777。
新操作:
chmod [-R]模式文件...
仅文件的所有者或超级用户被允许更改文件的模式。
chgrp [-R]组文件...
调用chgrp的用户必须属于指定的组,并且是文件的所有者,或者是超级用户。
chown [-R] [owner] [:[group]]文件...
文件的所有者只能由超级用户更改。
ls文件...
lsr文件...
重新格式化输出以显示所有者,组和模式。
超级用户是与NameNode进程本身具有相同标识的用户。宽松地,如果您启动了NameNode,那么您就是超级用户。超级用户可以执行任何操作,因为超级用户的权限检查永远不会失败。谁是超级用户并没有持久的观念。当NameNode启动时,进程标识将确定谁是当前的超级用户。HDFS超级用户不必是NameNode主机的超级用户,也不必所有群集都具有相同的超级用户。而且,在个人工作站上运行HDFS的实验人员可以方便地成为该安装的超级用户,而无需进行任何配置。
另外,管理员可以使用配置参数来识别专有组。如果设置,则该组的成员也是超级用户。
默认情况下,Web服务器的身份是配置参数。也就是说,NameNode不具有真实用户身份的概念,但是Web服务器的行为就像它具有管理员选择的用户的身份(用户和组)一样。除非所选择的身份与超级用户匹配,否则Web服务器可能无法访问部分名称空间。
除了传统的POSIX权限模型外,HDFS还支持POSIX ACL(访问控制列表)。ACL可用于实施与用户和组的自然组织层次结构不同的权限要求。ACL提供了一种为特定的命名用户或命名组设置不同权限的方法,而不仅仅是文件的所有者和文件的组。
默认情况下,禁用对ACL的支持,并且NameNode禁止创建ACL。要启用对ACL的支持,请在NameNode配置中将dfs.namenode.acls.enabled设置为true。
ACL由一组ACL条目组成。每个ACL条目都为一个特定的用户或组命名,并授予或拒绝对该特定用户或组的读取,写入和执行权限。例如:
用户:: rw- 用户:bruce:rwx#有效:r-- 组:: RX#有效:R-- 组:销售:rwx#有效:r-- 面具:: r-- 其他:: r--
ACL条目由类型,可选名称和权限字符串组成。出于显示目的,“:”用作每个字段之间的分隔符。在此示例ACL中,文件所有者具有读写访问权限,文件组具有读取执行访问权限,其他用户具有读取访问权限。到目前为止,这等效于将文件的权限位设置为654。
此外,还有2个扩展的ACL条目,分别用于已授予完全访问权限的命名用户bruce和命名组sales。掩码是一个特殊的ACL条目,它过滤授予所有已命名用户条目和已命名组条目以及未命名组条目的权限。在该示例中,掩码仅具有读取权限,并且我们可以看到已经相应过滤了多个ACL条目的有效权限。
每个ACL必须有一个掩码。如果用户在设置ACL时未提供掩码,则将通过计算将被掩码过滤的所有条目的权限并集来自动插入掩码。
在具有ACL的文件上运行chmod实际上会更改掩码的权限。由于掩码充当过滤器,因此有效地限制了所有扩展ACL条目的权限,而不是仅更改组条目并可能丢失其他扩展ACL条目。
该模型还区分了“访问ACL”和“默认ACL”,“访问ACL”定义了权限检查期间要执行的规则,“默认ACL”定义了新子文件或子目录在创建过程中自动接收的ACL条目。例如:
用户:: rwx 组:: RX 其他:: rx 默认值:user :: rwx 默认值:user:bruce:rwx#有效:rx 默认值:group :: rx 默认值:组:销售:rwx#有效:rx 默认值:mask :: rx 默认值:other :: RX
只有目录可以具有默认的ACL。创建新文件或子目录后,它将自动将其父级的默认ACL复制到其自己的访问ACL中。新的子目录还将其复制到其自己的默认ACL。这样,当创建新的子目录时,将通过文件系统树的任意深层次向下复制默认ACL。
新子级访问ACL中的确切许可权值受mode参数过滤。考虑到默认umask 022,对于新目录,这通常是755,对于新文件,通常是644。模式参数过滤未命名用户(文件所有者),掩码和其他用户的复制的权限值。使用此特定示例ACL,并为模式创建带有755的新子目录,此模式过滤对最终结果没有影响。但是,如果考虑为该模式创建带有644的文件,则模式过滤会导致新文件的ACL对未命名用户(文件所有者)进行读写操作,对掩码进行读取,对其他用户进行读取。此掩码还意味着仅读取命名用户布鲁斯和命名组销售的有效权限。
请注意,复制发生在创建新文件或子目录时。对父级默认ACL的后续更改不会更改现有子级。
默认ACL必须具有所有最低要求的ACL条目,包括未命名的用户(文件所有者),未命名的组(文件组)和其他条目。如果用户在设置默认ACL时未提供这些条目之一,则将通过复制访问ACL中的相应权限(如果没有访问ACL,则复制权限位)来自动插入条目。默认ACL还必须具有掩码。如上所述,如果未指定掩码,则通过计算将被掩码过滤的所有条目的权限并集,自动插入掩码。
考虑具有ACL的文件时,权限检查算法更改为:
如果用户名与文件的所有者匹配,则将测试所有者权限;否则,将进行测试。
否则,如果用户名与命名的用户条目之一中的名称匹配,则将测试这些许可权,并通过掩码许可权进行过滤;否则,将对这些许可权进行测试。
否则,如果文件组与组列表中的任何成员匹配,并且如果由掩码过滤的这些权限授予访问权限,则将使用这些权限;否则,将使用这些权限。
否则,如果存在与组列表成员匹配的命名组条目,并且如果这些权限由掩码授予访问权限过滤,则将使用这些权限;否则,将使用这些权限。
否则,如果文件组或任何命名的组条目与组列表的成员匹配,但是任何这些权限均未授予访问权限,则访问被拒绝;
否则,将测试文件的其他权限。
最佳实践是依靠传统的权限位来实现大多数权限要求,并定义较少数量的ACL以通过一些例外规则来扩展权限位。与仅具有权限位的文件相比,具有ACL的文件在NameNode中的内存中会产生额外的开销。
新方法:
hdfs dfs -getfacl [-R] <路径>
显示文件和目录的访问控制列表(ACL)。如果目录具有默认ACL,则getfacl还将显示默认ACL。
hdfs dfs -setfacl [-R] [-b | -k -m | -x <acl_spec> <path>] | [-set <acl_spec> <path>]
设置文件和目录的访问控制列表(ACL)。
hdfs dfs -ls <参数>
ls的输出将在带有ACL的任何文件或目录的权限字符串后附加一个'+'字符。
有关这些命令的完整说明,请参见文件系统外壳程序文档。
dfs.permissions.enabled = true
如果是,请按照此处所述使用权限系统。如果否,则关闭权限检查,但其他所有行为均保持不变。从一个参数值切换到另一个参数值不会更改模式,所有者或文件或目录组。不管权限是打开还是关闭,chmod,chgrp,chown和setfacl都会始终检查权限。这些功能仅在权限上下文中有用,因此没有向后兼容性问题。此外,这允许管理员在打开常规权限检查之前可靠地设置所有者和权限。
dfs.web.ugi = webuser,webgroup
Web服务器要使用的用户名。将此设置为超级用户的名称将允许任何Web客户端查看所有内容。将其更改为其他方式未使用的身份,可使Web客户端仅查看使用“其他”权限可见的内容。可以将其他组添加到以逗号分隔的列表中。
dfs.permissions.superusergroup =超级组
超级用户组的名称。
fs.permissions.umask-mode = 0022
创建文件和目录时使用的umask。对于配置文件,可以使用十进制值18。
dfs.cluster.administrators =管理员专用ACL
指定为ACL的群集的管理员。这控制着谁可以访问HDFS中的默认servlet等。
dfs.namenode.acls.enabled = true
设置为true以启用对HDFS ACL(访问控制列表)的支持。默认情况下,禁用ACL。禁用ACL时,NameNode拒绝所有设置ACL的尝试。
dfs.namenode.posix.acl.inheritance.enabled
设置为true以启用POSIX样式ACL继承。默认启用。启用该选项后,当创建请求来自兼容的客户端时,NameNode会将父目录中的默认ACL应用于创建模式,并忽略客户端umask。如果未找到默认ACL,它将应用客户端umask。