Hadoop分布式文件系统(HDFS)实现了共享大部分POSIX模型的文件和目录的权限模型。每个文件和目录都与所有者和组相关联。对于作为所有者的用户,作为该组成员的其他用户以及所有其他用户,该文件或目录具有单独的权限。对于文件,需要r权限才能读取文件,并且需要w权限才能写入或附加到文件。对于目录,需要r权限列出目录的内容,创建或删除文件或目录需要w权限,访问目录子项需要x权限。

与POSIX模型相比,文件没有setuid或setgid位,因为没有可执行文件的概念。对于目录,没有setuid或setgid位目录作为简化。可以在目录上设置粘滞位,防止除超级用户,目录所有者或文件所有者之外的任何人删除或移动目录中的文件。设置文件的粘滞位无效。总的来说,文件或目录的权限是其模式。通常,将使用用于表示和显示模式的Unix习惯,包括在本说明书中使用八进制数字。创建文件或目录时,其所有者是客户端进程的用户标识,其组是父目录的组(BSD规则)。

HDFS还为POSIX ACL(访问控制列表)提供可选支持,以使用针对特定命名用户或命名组的更细粒度规则来增强文件权限。ACL将在本文档后面详细讨论。

访问HDFS的每个客户端进程都有一个由用户名和组列表组成的由两部分组成的标识。每当HDFS必须对客户端进程访问的文件或目录foo执行权限检查时,

  • 如果用户名与foo的所有者匹配,则测试所有者权限;
  • 否则,如果foo组与组列表中的任何成员匹配,则测试组权限;
  • 否则,将测试foo的其他权限。

如果权限检查失败,则客户端操作将失败。

用户身份

从Hadoop 0.22开始,Hadoop支持两种不同的操作模式来确定用户的身份,由hadoop.security.authentication属性指定:

  • 简单

    <p><span style="color:#000000;"><span style="color:#000000;">在这种操作模式中,客户端进程的标识由主机操作系统确定。在类Unix系统上,用户名相当于`whoami`。</span></span></p>
    </li>
    <li>
    <p><span style="color:#000000;"><span style="color:#000000;"><strong>Kerberos的</strong></span></span></p>
    
    <p><span style="color:#000000;"><span style="color:#000000;">在Kerberized操作中,客户端进程的标识由其Kerberos凭据确定。例如,在Kerberized环境中,用户可以使用kinit实用程序获取Kerberos票证授予票证(TGT)并使用klist来确定其当前主体。将Kerberos主体映射到HDFS用户名时,将删除除主服务器之外的所有组件。例如,主体<a class="externalLink" href="mailto:todd/foobar@CORP.COMPANY.COM" rel="nofollow" target="_blank">todd/foobar@CORP.COMPANY.COM</a>将作为HDFS上的简单用户名todd。</span></span></p>
    </li>
    

无论操作模式如何,用户身份机制对于HDFS本身来说都是外在的。HDFS中没有用于创建用户身份,建立组或处理用户凭据的规定。

组映射

一旦如上所述确定了用户名,则组列表由组映射服务确定,由hadoop.security.group.mapping属性配置。有关详细信息,请参阅Hadoop组映射

许可检查

每个HDFS操作都要求用户具有通过文件所有权,组成员身份或其他权限授予的特定权限(READ,WRITE和EXECUTE的某种组合)。操作可以在路径的多个组件上执行许可检查,而不仅仅是最终组件。此外,某些操作依赖于检查路径的所有者。

所有操作都需要遍历访问。遍历访问需要路径的所有现有组件的EXECUTE权限,但最终路径组件除外。例如,对于访问/ foo / bar / baz的任何操作,调用者必须对/,/ foo和/ foo / bar具有EXECUTE权限。

下表描述了HDFS对路径的每个组件执行的权限检查。

  • Ownership是否检查呼叫者是否是路径的所有者。通常,更改所有权或权限元数据的操作要求调用者是所有者。
  • Parent请求的路径的父目录。例如,对于路径/ foo / bar / baz,父级是/ foo / bar。
  • Ancestor请求路径的最后一个现有组件。例如,对于路径/ foo / bar / baz,如果/ foo / bar存在,则祖先路径为/ foo / bar。如果/ foo存在但/ foo / bar不存在,则祖先路径为/ foo。
  • Final:所请求路径的最后一个组成部分。例如,对于路径/ foo / bar / baz,最终路径组件是/ foo / bar / baz。
  • Sub-tree对于作为目录的路径,目录本身及其所有子子目录,递归。例如,对于路径/foo/bar/baz,它有2个名为buz和boo的子目录,子树是/foo/bar/baz,/foo/bar/baz/buz和/foo/bar/baz/boo.
OperationOwnershipParentAncestorFinalSub-tree
appendNON/AN/AWRITEN/A
concatNO [2]WRITE (sources)N/AREAD (sources), WRITE (destination)N/A
createNON/AWRITEWRITE [1]N/A
createSnapshotYESN/AN/AN/AN/A
deleteNO [2]WRITEN/AN/AREAD, WRITE, EXECUTE
deleteSnapshotYESN/AN/AN/AN/A
getAclStatusNON/AN/AN/AN/A
getBlockLocationsNON/AN/AREADN/A
getContentSummaryNON/AN/AN/AREAD, EXECUTE
getFileInfoNON/AN/AN/AN/A
getFileLinkInfoNON/AN/AN/AN/A
getLinkTargetNON/AN/AN/AN/A
getListingNON/AN/AREAD, EXECUTEN/A
getSnapshotDiffReportNON/AN/AREADREAD
getStoragePolicyNON/AN/AREADN/A
getXAttrsNON/AN/AREADN/A
listXAttrsNOEXECUTEN/AN/AN/A
mkdirsNON/AWRITEN/AN/A
modifyAclEntriesYESN/AN/AN/AN/A
removeAclYESN/AN/AN/AN/A
removeAclEntriesYESN/AN/AN/AN/A
removeDefaultAclYESN/AN/AN/AN/A
removeXAttrNO [2]N/AN/AWRITEN/A
renameNO [2]WRITE (source)WRITE (destination)N/AN/A
renameSnapshotYESN/AN/AN/AN/A
setAclYESN/AN/AN/AN/A
setOwnerYES [3]N/AN/AN/AN/A
setPermissionYESN/AN/AN/AN/A
setReplicationNON/AN/AWRITEN/A
setStoragePolicyNON/AN/AWRITEN/A
setTimesNON/AN/AWRITEN/A
setXAttrNO [2]N/AN/AWRITEN/A
truncateNON/AN/AWRITE

 

[1] 只有在调用使用覆盖选项并且路径中存在现有文件时,才需要在创建期间对最终路径组件进行WRITE访问。

[2]如果设置了粘滞位,任何检查父目录的WRITE权限的操作也会检查所有权。[1] 只有在调用使用覆盖选项并且路径中存在现有文件时,才需要在创建期间对最终路径组件进行WRITE访问。

[3]调用setOwner来更改拥有文件的用户需要HDFS超级用户访问权限。更改组不需要HDFS超级用户访问,但调用者必须是文件的所有者和指定组的成员。

了解实施

每个文件或目录操作都将完整路径名传递给NameNode,并在每个操作的路径中应用权限检查。客户端框架将隐式地将用户身份与NameNode的连接相关联,从而减少了对现有客户端API的更改的需要。一直是这样的情况:当文件上的一个操作成功时,操作可能在重复时失败,因为文件或路径上的某个目录不再存在。例如,当客户端首次开始读取文件时,它向NameNode发出第一个请求,以发现文件的第一个块的位置。为查找其他块而发出的第二个请求可能会失败。另一方面,删除文件不会撤消已经知道文件块的客户端的访问权限。通过添加权限,客户端对文件的访问权限可以在请求之间撤消。同样,更改权限不会撤消已经知道文件块的客户端的访问权限。

对文件系统API的更改

如果权限检查失败,则使用path参数的所有方法都将抛出AccessControlException。

新方法:

  • public FSDataOutputStream create(Path f,FsPermission permission,boolean overwrite,int bufferSize,short replication,long blockSize,Progressable progress)抛出IOException;
  • public boolean mkdirs(Path f,FsPermission permission)抛出IOException;
  • public void setPermission(Path p,FsPermission permission)抛出IOException;
  • public void setOwner(Path p,String username,String groupname)抛出IOException;
  • public FileStatus getFileStatus(Path f)抛出IOException; 另外还将返回与路径关联的用户,组和模式。

新文件或目录的模式受umask设置为配置参数的限制。当使用现有的create(path,...)方法(没有permission参数)时,新文件的模式为0666&^ umask。当使用新的create(path,permission,...)方法(具有权限参数P)时,新文件的模式是P&^ umask&0666。使用现有的mkdirs(path)方法(没有permission参数)创建新目录时,新目录的模式为0777&^ umask。当使用新的mkdirs(路径,权限)方法(使用权限参数P)时,新目录的模式为P&^ umask&0777。

对应用程序外壳的更改

新业务:

  • chmod [-R]模式文件...

    <p><span style="color:#000000;">仅允许文件的所有者或超级用户更改文件的模式。</span></p>
    </li>
    <li>
    <p><span style="color:#000000;">chgrp [-R]组文件...</span></p>
    
    <p><span style="color:#000000;">调用chgrp的用户必须属于指定的组,并且是该文件的所有者,或者是超级用户。</span></p>
    </li>
    <li>
    <p><span style="color:#000000;">chown [-R] [owner] [:[group]]文件......</span></p>
    
    <p><span style="color:#000000;">文件的所有者只能由超级用户更改。</span></p>
    </li>
    <li>
    <p><span style="color:#000000;">ls文件...</span></p>
    </li>
    <li>
    <p><span style="color:#000000;">lsr文件...</span></p>
    
    <p><span style="color:#000000;">输出重新格式化以显示所有者,组和模式。</span></p>
    </li>
    

超级用户

超级用户是与NameNode进程本身具有相同标识的用户。很简单,如果你启动了NameNode,那么你就是超级用户。超级用户可以做任何事情,超级用户的权限检查永远不会失败。没有人认为谁是超级用户; 当NameNode启动时,进程标识现在确定谁是超级用户。HDFS超级用户不必是NameNode主机的超级用户,也不必所有群集都具有相同的超级用户。此外,在个人工作站上运行HDFS的实验者可以方便地成为该安装的超级用户而无需任何配置。

另外,管理员可以使用配置参数来识别区分组。如果设置,该组的成员也是超级用户。

Web服务器

默认情况下,Web服务器的标识是配置参数。也就是说,NameNode没有真实用户身份的概念,但Web服务器的行为就好像它具有管理员选择的用户的身份(用户和组)。除非所选标识与超级用户匹配,否则Web服务器可能无法访问名称空间的某些部分。

ACL(访问控制列表)

除了传统的POSIX权限模型外,HDFS还支持POSIX ACL(访问控制列表)。ACL对于实现与用户和组的自然组织层次结构不同的权限要求非常有用。ACL提供了一种为特定命名用户或命名组设置不同权限的方法,而不仅仅是文件所有者和文件组。

默认情况下,禁用对ACL的支持,NameNode不允许创建ACL。要启用ACL支持,请在NameNode配置中将dfs.namenode.acls.enabled设置为true。

ACL由一组ACL条目组成。每个ACL条目命名特定用户或组,并授予或拒绝该特定用户或组的读取,写入和执行权限。例如:

   user::rw-
   user:bruce:rwx                  #effective:r--
   group::r-x                      #effective:r--
   group:sales:rwx                 #effective:r--
   mask::r--
   other::r--

ACL条目由类型,可选名称和权限字符串组成。出于显示目的,':'用作每个字段之间的分隔符。在此示例ACL中,文件所有者具有读写访问权限,文件组具有读取 - 执行访问权限,而其他文件组具有读取访问权限。到目前为止,这相当于将文件的权限位设置为654。

此外,指定用户bruce和命名组销售有2个扩展ACL条目,两者都被授予完全访问权限。掩码是一个特殊的ACL条目,用于过滤授予所有命名用户条目和命名组条目的权限,以及未命名的组条​​目。在该示例中,掩码仅具有读取权限,并且我们可以看到已相应地过滤了多个ACL条目的有效权限。

每个ACL都必须有一个掩码。如果用户在设置ACL时未提供掩码,则通过计算将由掩码过滤的所有条目的权限联合自动插入掩码。

在具有ACL的文件上运行chmod实际上会更改掩码的权限。由于掩码充当过滤器,因此这有效地约束了所有扩展ACL条目的权限,而不是仅更改组条目并可能缺少其他扩展ACL条目。

该模型还区分“访问ACL”和“默认ACL”,后者定义了在权限检查期间强制执行的规则,“ACL”定义了新子文件或子目录在创建期间自动接收的ACL条目。例如:

   user::rwx
   group::r-x
   other::r-x
   default:user::rwx
   default:user:bruce:rwx          #effective:r-x
   default:group::r-x
   default:group:sales:rwx         #effective:r-x
   default:mask::r-x
   default:other::r-x

只有目录可能具有默认ACL。创建新文件或子目录时,它会自动将其父级的默认ACL复制到其自己的访问ACL中。新的子目录还会将其复制到自己的默认ACL。通过这种方式,当创建新的子目录时,将通过文件系统树的任意深层级向下复制默认ACL。

新子访问ACL中的确切权限值受模式参数的筛选。考虑到默认的umask为022,新目录通常为755,新文件为644。mode参数过滤未命名用户(文件所有者),掩码和其他用户的复制权限值。使用此特定示例ACL,并使用755为模式创建新的子目录,此模式筛选对最终结果没有影响。但是,如果我们考虑为模式创建644的文件,则模式过滤会导致新文件的ACL接收未命名用户(文件所有者)的读写,读取掩码并读取其他用户。此掩码还表示仅读取指定用户bruce和命名组销售的有效权限。

请注意,副本在创建新文件或子目录时发生。对父级默认ACL的后续更改不会更改现有子级。

默认ACL必须具有所有必需的最低ACL条目,包括未命名用户(文件所有者),未命名组(文件组)和其他条目。如果用户在设置默认ACL时未提供其中一个条目,则通过从访问ACL复制相应的权限自动插入条目,如果没有访问ACL,则为权限位。默认ACL也必须具有掩码。如上所述,如果未指定掩码,则通过计算将由掩码过滤的所有条目的权限的并集来自动插入掩码。

在考虑具有ACL的文件时,权限检查的算法更改为:

  • 如果用户名与文件所有者匹配,则测试所有者权限;

  • 否则,如果用户名与其中一个指定用户条目中的名称匹配,则会测试这些权限,并通过掩码权限进行过滤;

  • 否则,如果文件组匹配组列表的任何成员,并且如果这些权限通过掩码授予访问权限,则使用这些权限;

  • 否则,如果存在与组列表成员匹配的命名组条目,并且如果这些权限通过掩码授予访问权限进行过滤,则使用这些权限;

  • 否则,如果文件组或任何命名的组条​​目与组列表的成员匹配,但未通过任何这些权限授予访问权限,则拒绝访问;

  • 否则,将测试文件的其他权限。

最佳做法是依靠传统的权限位来实现大多数权限要求,并定义较少数量的ACL以使用一些例外规则来扩充权限位。与仅具有权限位的文件相比,具有ACL的文件在NameNode中的内存中产生额外成本。

ACL文件系统API

新方法:

  • public void modifyAclEntries(Path path,List <AclEntry> aclSpec)抛出IOException;
  • public void removeAclEntries(Path path,List <AclEntry> aclSpec)抛出IOException;
  • public void public void removeDefaultAcl(Path path)抛出IOException;
  • public void removeAcl(Path path)抛出IOException;
  • public void setAcl(Path path,List <AclEntry> aclSpec)抛出IOException;
  • public AclStatus getAclStatus(Path path)抛出IOException;

ACL Shell命令

  • hdfs dfs -getfacl [-R] <path>

    <p><span style="color:#000000;"><span style="color:#000000;">显示文件和目录的访问控制列表(ACL)。如果目录具有默认ACL,则getfacl还会显示默认ACL。</span></span></p>
    </li>
    <li>
    <p><span style="color:#000000;"><span style="color:#000000;">hdfs dfs -setfacl [-R] [-b | -k -m | -x &lt;acl_spec&gt; &lt;path&gt;] | [ - set &lt;acl_spec&gt; &lt;path&gt;]</span></span></p>
    
    <p><span style="color:#000000;"><span style="color:#000000;">设置文件和目录的访问控制列表(ACL)。</span></span></p>
    </li>
    <li>
    <p><span style="color:#000000;"><span style="color:#000000;">hdfs dfs -ls &lt;args&gt;</span></span></p>
    
    <p><span style="color:#000000;"><span style="color:#000000;">ls的输出会将“+”字符附加到具有ACL的任何文件或目录的权限字符串。</span></span></p>
    
    <p><span style="color:#000000;"><span style="color:#000000;">有关这些命令的完整内容,请参阅<a href="https://hadoop.apache.org/docs/r3.2.0/hadoop-project-dist/hadoop-common/FileSystemShell.html" rel="nofollow" target="_blank">文件系统Shell</a>文档。</span></span></p>
    </li>
    

配置参数

  • dfs.permissions.enabled = true

    <p><span style="color:#000000;"><span style="color:#000000;">如果是,请使用此处所述的权限系统。如果不是,则关闭权限检查,但所有其他行为都保持不变。从一个参数值切换到另一个参数值不会更改模式,所有者或文件或目录组。无论权限是打开还是关闭,chmod,chgrp,chown和setfacl始终检查权限。这些函数仅在权限上下文中有用,因此不存在向后兼容性问题。此外,这允许管理员在打开常规权限检查之前可靠地设置所有者和权限。</span></span></p>
    </li>
    <li>
    <p><span style="color:#000000;"><span style="color:#000000;">dfs.web.ugi = webuser,webgroup</span></span></p>
    
    <p><span style="color:#000000;"><span style="color:#000000;">Web服务器要使用的用户名。将此设置为超级用户的名称允许任何Web客户端查看所有内容。将此更改为其他未使用的标识允许Web客户端仅使用“其他”权限查看可见的内容。可以将其他组添加到逗号分隔列表中。</span></span></p>
    </li>
    <li>
    <p><span style="color:#000000;"><span style="color:#000000;">dfs.permissions.superusergroup = supergroup</span></span></p>
    
    <p><span style="color:#000000;"><span style="color:#000000;">超级用户组的名称。</span></span></p>
    </li>
    <li>
    <p><span style="color:#000000;"><span style="color:#000000;">fs.permissions.umask-mode = 0022</span></span></p>
    
    <p><span style="color:#000000;"><span style="color:#000000;">创建文件和目录时使用的umask。对于配置文件,可以使用十进制值18。</span></span></p>
    </li>
    <li>
    <p><span style="color:#000000;"><span style="color:#000000;">dfs.cluster.administrators = ACL-for-admins</span></span></p>
    
    <p><span style="color:#000000;"><span style="color:#000000;">指定为ACL的集群的管理员。这可以控制谁可以访问HDFS中的默认servlet等。</span></span></p>
    </li>
    <li>
    <p><span style="color:#000000;"><span style="color:#000000;">dfs.namenode.acls.enabled = true</span></span></p>
    
    <p><span style="color:#000000;"><span style="color:#000000;">设置为true以启用对HDFS ACL(访问控制列表)的支持。默认情况下,禁用ACL。禁用ACL时,NameNode拒绝所有设置ACL的尝试。</span></span></p>
    </li>
    <li>
    <p><span style="color:#000000;"><span style="color:#000000;">dfs.namenode.posix.acl.inheritance.enabled</span></span></p>
    
    <p><span style="color:#000000;"><span style="color:#000000;">设置为true以启用POSIX样式ACL继承。默认情况下启用。启用它并且创建请求来自兼容客户端时,NameNode将从父目录应用默认ACL到创建模式,并忽略客户端umask。如果未找到默认ACL,则它将应用客户端umask。</span></span></p>
    </li>
    

 

原文链接: https://hadoop.apache.org/docs/r3.2.0/

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐