kerberos解决了认证的问题,sentry解决了授权的问题。但是sentry的授权是按照角色和组来的,不支持按用户。所以我们还需要解决用户和组的映射问题。使用哪种映射方式由hadoop的hadoop.security.group.mapping参数决定。该参数默认为org.apache.hadoop.security.ShellBasedUnixGroupsMapping即基于操作系统的用户和组映射。
在linux上由NameNode所在服务器执行bash -c groups命令决定。
详见https://hadoop.apache.org/docs/r2.8.0/hadoop-project-dist/hadoop-common/GroupsMapping.html
在开发环境,还可以直接在配置文件中使用hadoop.user.group.static.mapping.overrides参数来指定指定用户和组的映射关系,例如:user1=group1,group2;user2=;user3=group2.如果在此处配置了用户和组的关系,会覆盖group mapping service provider提供的组映射。对于在此处存在的用户和组关系会直接返回,而无需进一步查询group mapping service provider。
而在生产环境中,通常采用LdapGroupsMapping。
本文以OpenLDAP为例,讲述配置过程。
有关LDAP的安装及配置,后续有机会在分享,现在大家请自行解决。
在切换为LdapGroupsMapping之前,我们必须将CDH集群已有的服务帐号(例如hive/hdfs/mapred等)导入LDAP中,否则相关服务无法正常工作。
好在我们可以使用migrationtools来导入,方法如下(需要root帐号或者拥有sudo权限的帐号):
安装软件包
#yum install migrationtools -y
修改默认域名
根据实际情况修改/usr/share/migrationtools/migrate_common.ph
# Default DNS domain
$DEFAULT_MAIL_DOMAIN = "xxx.com";
# Default base
$DEFAULT_BASE = "dc=bi,dc=xxx,dc=com";
导出NameNode所在服务器的操作系统用户和组列表
#cat /etc/passwd > people
#cat /etc/group > group
然后删除不需要的用户,只保留和CDH集群相关的用户,具体参见
https://www.cloudera.com/documentation/enterprise/5-10-x/topics/cm_sg_ldap_grp_mappings.html
生成用户和组ldif文件
/usr/share/migrationtools/migrate_passwd.pl people people.ldif
/usr/share/migrationtools/migrate_group.pl group group.ldif
最终people.ldif中的内容如下:
dn: uid=mapred,ou=People,dc=bi,dc=xxx,dc=com
uid: mapred
cn: Hadoop MapReduce
objectClass: account
objectClass: posixAccount
objectClass: top
userPassword: {crypt}x
loginShell: /bin/bash
uidNumber: 491
gidNumber: 489
homeDirectory: /var/lib/hadoop-mapreduce
gecos: Hadoop MapReduce
可以看到用户的objectClass为posixAccount,组的objectClass为posixGroup
接下来将用户和组的ldif文件导入OpenLDAP中
将people.ldif和group.ldif文件上传到OpenLDAP所在服务器,然后使用root或者拥有sudo权限的帐号执行
#ldapadd -x -W -D "cn=admin,dc=bi,dc=xxx,dc=com" -f people.ldif
#ldapadd -x -W -D "cn=admin,dc=bi,dc=xxx,dc=com" -f group.ldif
其中-D参数为LDAP管理员的DN
使用管理员帐号登录cloudera manager管理界面,然后执行如下操作
点击HDFS-Configuration-Security,然后修改如下配置项
Hadoop User Group Mapping Implementation: org.apache.hadoop.security.LdapGroupsMapping
Hadoop User Group Mapping LDAP URL: ldap://hdpdev17.xxx.com
Hadoop User Group Mapping LDAP Bind User Distinguished Name: cn=admin,dc=bi,dc=xxx,dc=com
Hadoop User Group Mapping LDAP Bind User Password: 输入密码
Hadoop User Group Mapping Search Base: dc=bi,dc=xxx,dc=com
Hadoop User Group Mapping LDAP User Search Filter: (&(objectClass=posixAccount)(uid={0}))
Hadoop User Group Mapping LDAP Group Search Filter: (objectClass=posixGroup)
Hadoop User Group Mapping LDAP Group Membership Attribute: memberUid
Hadoop User Group Mapping LDAP Group Name Attribute: cn注:LDAP的默认端口为389,如果不是该端口URL应为: ldap://hdpdev17.xxx.com:端口
Bind User是指LDAP管理员帐号,或者有查询权限的帐号
Search Base是指在哪个节点下面搜索用户和组
User Search Filter的意思是指通过uid属性来查询posixAccount类,以确认用户是否在LDAP中存在。
注:有关filter的语法,详见https://social.technet.microsoft.com/wiki/contents/articles/5392.active-directory-ldap-syntax-filters.aspx?Sort=MostUseful&Sort=MostUseful
只有在用户存在的情况下,才去获取用户所属的组。
Group Search Filter用于限定组的类型
posixGroup使用memberUid属性来维护成员列表(groupOfNames则是使用的member属性),所以 Group Membership Attribute应该设置memberUid
修改完之后保存,并重启HDFS服务。
登录集群中任意一台服务器,执行
hdfs groups mapred
你会发现只会得mapred的一个组mapred,然而mapred应该是有hadoop和mapred两个组的。这是为什么呢?
通过查看hadoop-2.6.0-cdh5.10.0-src中\hadoop-common-project\hadoop-common\src\main\java\org\apache\hadoop\security\LdapGroupsMapping.java得知,由于memberUid中存的是uid而不是uidNumber,所以我们需要设置
hadoop.security.group.mapping.ldap.posix.attr.uid.name=uid来解决这个问题。
方法如下:
登录cloudera manager管理界面,HDFS-Configuration
在Cluster-wide Advanced Configuration Snippet (Safety Valve) for core-site.xml中设置,保存重启即可。
然后在执行
hdfs groups mapred ,你应该能得到如下输出:
mapred : hadoop mapred
后续如果有在LDAP中更改了用户的组,而hdfs groups 命令却没有生效的情况(因为有缓存)可以执行
hdfs dfsadmin -refreshUserToGroupsMappings命令来刷新
至此,GroupMapping配置结束了,但是有一个问题值得我们思考,迁移的帐号和组我们使用posixAccount和posixGroup没有问题。但是之后新增用户和组时,我们没必要使用posixGroup和posixAccount了呀;假设我们使用account和groupOfNames那么我们上面的配置就有问题了。怎么解决,大家可以结合源代码自行思考一下。
最后给大家推荐一个LDAP客户端,ApacheDirectoryStudio,可以方便的完成LDAP的增删改查操作。