天天看点

gitlab 将管理员权限移交给ldap账户_HDFS权限管理

概述

作为分布式文件系统,HDFS实现了一套兼容POSIX的文件权限模型,包括粗粒度的POSIX UGO模型和细粒度的POSIX ACLs协议。

客户端在每次进行文件操作时,HDFS会从用户身份认证、用户组映射和数据访问鉴权三个环节进行验证: 客户端的操作请求会首先从本地系统获取用户名,然后服务端将用户名匹配上组信息,最后查看所访问的数据是否已经授权给该用户。一旦这个流程中的某个环节出现异常,客户端的操作请求便会失败。

本文以Hadoop 3.1.1版本为例,介绍 HDFS 权限管理的相关内容以及权限分配的应用实践。

用户身份认证

用户身份认证并不属于HDFS的范畴,也就是说HDFS并不负责用户身份的合法性检查,它只是会依赖相关系统来获取用户身份,从而用于后续的鉴权。而对于身份认证,完全取决于其采用的认证系统。目前HDFS有支持两种用户身份认证:简单认证和kerberos认证。

简单认证

基于客户端进程所在的Linux/Unix系统的当前用户名来进行认证。只要用户能正常登录操作系统就认证成功。这样客户端与NameNode交互时,会将用户的登录账号(与whoami命令输出一致)作为合法用户名传给Namenode。 这样的认证机制存在恶意用户可以伪造其他人的用户名的风险,对数据安全造成极大的隐患,线上生产环境一般不会使用。

kerberos认证

kerberos是一个网络认证协议,其使用密钥加密技术为客户端和服务端应用提供强认证功能。它有一个管理端(AdminServer)用于管理所有需要认证的账号信息,另外还有若干的密钥分发服务器(KDC)用于提供认证和分发密钥服务。 用户从 Kerberos 管理员处获取对应的 Kerberos 账号名或者密钥文件,然后通过 kinit 等方式认证Kerberos,拿到TGT(ticket-granting-ticket)票据。客户端会将TGT信息传输到NN端,NN在获取到认证信息后,将principle首部截取出来作为客户端的用户名。例如使用 todd/[email protected]认证成功后, da作为principle的首部会作为该客户端的用户名使用。 使用Kerberos可以极大增强HDFS的安全性,特别是在多租户的生产环境下。

用户组映射

因为HDFS采用与Linux/Unix系统类似的文件权限模型,也就是UGO模型,分成用户、组和其他,所以在拿到用户名后,NN会通过获取该用户所对应的组列表。HDFS中组的获取是通过外部Group Mapping服务来获取,目前社区对用户到组的映射有主要有两种实现方式:1)使用系统自带的方案(即NameNode服务器上的用户组系统),2)使用三方服务如LDAP,通过参数hadoop.security.group.mapping来进行设置。下面重点讲解下这两种实现方式。

基于Linux/Unix系统的用户和组实现

Linux/Unix 系统上的用户和用户组信息存储在/etc/passwd 和 /etc/group 文件中。默认情况下,HDFS 会使用org.apache.hadoop.security.ShellBasedUnixGroupsMapping服务,其原理是在NN上调用Shell 命令groups来获取用户的组列表。 此方案的优点在于组映射服务十分稳定,不易受外部服务的影响。但是用户和用户组管理需要root权限,同时会在服务器上生成大量的用户组,后续管理,特别是自动化运维方面会有较大影响。

基于LDAP数据库的用户和组实现

OpenLDAP是一个开源LDAP的数据库,可以通过phpLDAPadmin等管理工具或相关接口方便地添加用户和修改用户组。HDFS通过配置org.apache.hadoop.security.LdapGroupsMapping来使用 LDAP 服务,可以通过接口来直接获取到某个用户的组列表。使用LDAP的不足在于需要保障LDAP服务的可用性和性能。

数据授权(数据权限管理)

UGO权限管理
  • HDFS的文件权限与Linux/Unix系统的UGO模型类似,我们使用FS Shell查看目录,可以看到如下内容:
drwxrwxrwt   - yarn   hadoop          0 2020-01-20 15:42 /app-logs
drwxr-xr-x   - yarn   hadoop          0 2020-01-20 15:40 /ats
drwxr-xr-x   - hdfs   hdfs            0 2020-01-20 15:40 /hdp
drwxr-xr-x   - mapred hdfs            0 2020-01-20 15:40 /mapred
drwxrwxrwx   - mapred hadoop          0 2020-01-20 15:40 /mr-history
drwxrwxrwx   - hdfs   hdfs            0 2020-01-20 15:41 /tmp
drwxr-xr-x   - hdfs   hdfs            0 2020-01-20 15:40 /user
drwxr-xr-x   - hdfs   hdfs            0 2020-01-20 15:40 /warehouse
           
  • 但是与传统的POSIX模式相比,HDFS没有setuid和setgid实现
  • 与Linux/Uninx类似,HDFS在目录中也可以设置粘连位(Sticky bit)。 通过设置粘连位可以让不同的用户共享特定目录的读写权限,而只有子目录的属主才有删除权限。类似linux下/tmp目录一般设置粘连位,hdfs也应该将/tmp目录设置粘连位来共享读写而限制随便删除,通过hdfs dfs -chmod o+t /tmp设置后如下:
drwxrwxrwt   - hdfs      hdfs          0 2016-10-11 05:14 /tmp
           

/tmp下面的一些子目录的权限如下:

drwxr-xr-x   - hdfs  hdfs          0 2020-02-12 15:47 /tmp/entity-file-history
drwxr-x---   - hive  hdfs          0 2020-02-14 22:30 /tmp/hive
drwxr-x---   - spark hdfs          0 2020-02-14 22:28 /tmp/spark
           
  • 与Linux/Unix类似,HDFS也提供了umask掩码,用于设置在HDFS中默认新建的文件和目录权限位。为了配合用户组的权限限制,建议将其设置成027。配置如下:
<property>
   
           

注意:这个umask配置是客户端可以配置的,即客户端自己主宰创建文件或目录的权限。

关于022和027的解释:如果umask是022(默认值),那么新文件的模式就是644,新目录的模式就是755,即umask擦除掉了group和other的写权限。如果umask是027,那么新文件的模式就是650,新目录的模式就是750,即umask擦除掉了group的写权限,以及other的读写执行权限。

  • HDFS也有与linux/uinx系统root账号类似的超级用户。默认来说,只有启动Namenode进程的用户才有超级用户权限,也就是hdfs用户。但很多操作实际上都需要超级用户的权限(如fsck等),故HDFS也可以配置超级用户组,除了部分操作(如hdfs dfsadmin -report命令)对用户名有限制之外,所有在该用户组里面的用户都可以以超级用户权限来操作HDFS。开启超级用户组的参数如下:
<property>
    
           

注意:必须在NN节点上将用户添加到superusergroup。

UGO 权限相关操作
  1. hadoop fs -chmod 750 /user/dw_dev/foo
  2. hadoop fs -chown dw_dev:hdfs /user/dw_dev/foo
  3. hadoop fs -chgrp hdfs /user/dw_dev/foo
ACLs权限管理

除了支持传统的POSIX权限模型之外,HDFS还支持POSIX ACLs (Access Control Lists)。ACLs增强了传统的权限模型,通过为特定的用户或组设置不同的权限来控制对HDFS文件的访问,即可以做到更加灵活和细粒度的权限控制:允许用户为用户和组的任意组合定义访问控制,而不是单个用户(所有者)或单个组。

默认情况下对ACLs的支持是关闭的,可以通过设置dfs.namenode.acls.enabled为true来打开。

ACLs应用场景

HDFS使用UGO这种用户组的权限管理模型可以满足大多数场景的安全性要求,但对于一些复杂场景无法胜任,实际企业应用中存在如下问题:

对于一个目录,可能会有两种权限需求,一种是只读,一种是读写,但用户组权限只能设定为其中之一;
           
ACL规则定义

一条ACL规则由若干ACL条目组成,每个条目指定一个用户或用户组的权限位。ACL条目由类型名,可选名称和权限字符串组成,以:为分隔符。

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

第一部分由固定的类型名构成,有user,group,other,mask,default等选项。mask条目会过滤掉所有命名的用户和用户组,以及未命名的用户组权限。第二部分可以指定类型名称,如用户名,用户组名等(other类型不需要名称),这部分是可选项,若不指定特定的用户名或用户组,则表示只对该文件属主或目录的用户组生效。第三部分就是权限位。 若该条规则应用到foo文件,foo文件的属主有读写权限,foo文件的用户组有只读和执行权限(对于目录),其他用户也是只读权限;但bruce用户的权限经过mask过滤后只有只读权限,sales组也是只读权限。

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
           

default类型是一个特殊的类型,且只应用在目录上,用于在创建子目录和文件时为其应用该默认的ACL规则。权限复制发生在文件产生之时,在这之后对父级目录的ACL操作,不会影响子目录已存在的ACL规则。 另外每个ACL规则都有mask条目,如果用户在设置ACL时没有显式声明,那么系统会自动地添加一条mask规则。在含有ACL规则的文件上通过chmod变更权限会改变mask值。因为mask要作为一个过滤器来更有效地限制所有的扩展ACL条目,如果仅仅改变组条目,这会导致Other部分的ACL规则出现缺漏。

当设置了ACL规则之后,目录或文件的权限位后面会出现一个“+”号,如下:

drwxrwx---+  - hive hadoop          0 2020-02-13 03:12 /warehouse/tablespace/managed/hive
           

ACL相关操作

1.查看目录权限

hadoop fs -setfacl /user/dw_dev
           

2.为目录添加访问权限

hadoop fs -setfacl -m user:public:r-x /user/dw_dev
           

3.为目录添加可继承的权限

hadoop fs -setfacl -m default:user:public:r-x,default:group:public:r-x,default:other::r-x /user/dw_dev
           

4.删除目录权限

hdfs dfs -setfacl -b /user/dw_dev
           

5.删除特定权限,保留其他权限

hdfs dfs -setfacl -x user:public:r-x /user/dw_dev
           

数据鉴权(数据访问权限检查)

以HDFS Client为例,来分析下HDFS鉴权的过程

gitlab 将管理员权限移交给ldap账户_HDFS权限管理

在hdfs client分析:hdfs dfs -ls一文中,我们已经知道client在创建出FileSystem对象后,就会去调用fs.listStatus方法去列取目录信息。listStatus底层是通过RPC调用到NameNode的listStatus方法,那么ls的鉴权肯定就是在NameNode的listStatus方法中进行的了。

进入DistributedFileSystem.listStatus方法

//DistributedFileSystem.java
           

再进入listStatusInternal(p)

//DistributedFileSystem.java
           

再进入dfs.listPaths(src, HdfsFileStatus.EMPTY_NAME)

//DFSClient.java 
           

再进入listPaths(src, startAfter, false)

//DFSClient.java
           

namenode.getListing最终是调用到了NameNodeRPCServer端了

//NameNodeRpcServer.java
           

进入namesystem.getListing

DirectoryListing 
           

终于看到AccessControlException出现了,看来getListingInt

static 
           

先来看下fsd.getPermissionChecker()

FSPermissionChecker 
           

看到remoteUser信息是从RPC连接中获取到的。

接下来看鉴权的过程fsd.isPermissionEnabled()

在NameNodeServer端获取到了remoteUGI后,就是和path的ugi信息做匹配了,很简单,就不一步步的分析了。

参考文档

HDFS Permissions Guide

Hadoop Groups Mapping

【Linux】理解setuid()、setgid()和sticky位 - puyangsky - 博客园

Linux SetUID(SUID)文件特殊权限用法详解

Linux SetGID(SGID)文件特殊权限用法详解

Linux Stick BIT(SBIT)文件特殊权限用法详解

HDFS Extended ACLs

继续阅读