本文作者为中国移动云能力中心大数据团队软件开发工程师徐海辉,本篇内容主要包括如下三个部分:
Apache Ranger总体框架
Ranger对HDFS鉴权的实现原理
HDFS细粒度权限实践及思考
Apache Ranger简介
Apache Ranger是一个Hadoop集群数据安全管理的框架,提供集中式的授权管理及日志审计。它可以对Hadoop生态的组件如HDFS、Yarn、Hive、HBase、Kafka、Storm、Presto、Kylin等进行细粒度的数据访问控制。通过操作Ranger
Admin控制台,管理员可以轻松地通过配置策略来控制用户或用户组访问数据的权限。
Apache Ranger总体架构
Ranger的总体架构图如下图所示,主要由Ranger Admin、Ranger Usersync及Ranger-xx-Plugin三个部分构成,下面分别介绍三个部分的功能。
1、Ranger Admin
核心组件,是一个独立的进程,提供RESTFUL接口来对用户及用户组、服务、策略等进行增删改查,并提供WebUI界面可以方便用户进行操作管理,下图即Ranger Admin web 界面,主要包括以下几个模块:
(1)服务管理(service manager):目前支持的服务有HDFS、Yarn、Hive、HBase、Kafka、Storm、Knox、Solr、Nifi等服务;
(2) 服务(service):通过某一个服务管理如HDFS,创建一个服务service,如hadoopdev,通过这个服务,ranger控制台和具体环境的hdfs相关联;
(3)策略(policy):有了某个服务后,如hadoopdev,可以用这个服务创建相关的策略来管理权限;
(4)审计管理(audit):对所做的操作及权限进行审计,通过界面可以看到操作日志信息;
(5)用户和用户组管理(users and groups):可以增加删除修改用户或用户组信息以便对这些用户或用户组设置权限。
2、Ranger-xx-plugin
xx代表HDFS、Yarn、Hive、HBase、Kafka、Storm等服务组件,此插件是轻量级的java程序,嵌入到各个服务组件的进程中,定期轮询拉取策略及定期记录访问审计日志。
3、Ranger-UserSync
用户及用户组同步组件。该组件是个独立的进程,将Linux(Unix)、LDAP及AD(windows的用户域)的用户及用户组信息同步到
Ranger数据库中,进而可以对这些用户及用户组进行授权。
HDFS鉴权实现原理
HDFS本身提供了对访问控制列表(ACL)的支持,通过ACL,可以为特定的用户或者用户组提供文件权限控制。ACL是不同于用户和组的自然组织层次的有用的权限控制方式,可以为特定的用户和组设置不同的权限,而不仅仅是文件的拥有者和文件所属的组。
HDFS鉴权过程是在身份认证机制(如Simple、Kerberos、BCID)之后通过查询ACLs来对用户或用户组的权限匹配。
注:BCID是一种中国移动云能力中心自主开发的认证机制。
1、开启权限控制
开启Ranger对HDFS鉴权,需要修改hdfs-site.xml的配置项,即:
<property>
<name>dfs.namenode.inode.attributes.provider.class</name>
<value>org.apache.ranger.authorization.hadoop.RangerHdfsAuthorizer</value>
</property>
其中RangerHdfsAuthorizer类是ranger中的类,该类继承了INodeAttributeProvider类。即Ranger-hdfs-plugin将NameNode 的Inode Attribute的提供的抽象类INodeAttributeProvider修改为自身实现的RangerHdfsAuthorizer类,同时实现类中的接口AccessControlEnforcer的checkPermission方法。通过checkPermission匹配用户或用户组的权限。
2、插件工作过程分析
在Namenode启动过程中加载包ranger-hdfs-plugin-shim下的RangerHdfsAuthorizerorizer类,将Ranger HDFS插件的相关类动态加载到虚拟机,并实例化具体实现类ranger-hdfs-plugin包下的RangerHdfsAuthorizerorizer。
类加载代码如下图所示:
通过RangerHdfsPlugin类进行初始化hdfs插件,RangerHdfsPlugin是RangerBasePlugin类的子类,如下图所示,其具体的初始化是由父类的初始化方法来实现的。
a、调用cleanup()方法,设置refresher、serviceName、policyEngine这三个变量的值为null。
b、读取配置文件,并设置变量的初始值,同时设置PangerPolicyEngineOptions类的成员变量值。
c、调用createAdminClient(),创建RangerAdmin与RangerPlugin通信的客户端。这里使用的基于RESTful的通信风格,所以创建RangerAdminClient类的实例对象。
d、创建PolicyRefresher类的对象,调用startRefresher()开启策略刷新器,
初始化之后,通过RangerAdminClient类的实例对象与Ranger Admin进程通信,使用PolicyRefresher类的对象,根据轮询间隔时间定期从Ranger Admin 拉取更新的策略,同时记录审计日志。
3、插件安装过程分析
Ranger鉴权本质上是通过读取安装ranger插件时生成的配置文件以及插件自带的jar包,通过实现可扩展接口或代码注入方式来实现逻辑嵌入到各个服务组件,达到权限管理。在安装服务组件插件过程中,当执行./enable-xxx-plugin.sh时,主要执行了以下三个步骤:
(1)将插件自带的conf更新到安装的服务组件conf目录下,并修改相应的服务conf属性;
(2)将插件自带的lib更新到安装的服务组件lib目录下;
(3)将install.properties生成.xml文件,更新到安装的服务组件conf目录下。
4、鉴权过程分析
通过插件安装,即开启ranger hdfs插件;然后重启namenode服务,在重启服务过程中,会加载类、初始化相关配置、变量和RangerAdminClient类及PolicyRefresher类的对象,这时
Ranger对hdfs的权限控制开始工作。
假设用户的请求是要读写一个hdfs文件,下图是
Ranger对此请求的hdfs鉴权流程。其中从HDFS进入ranger中的入口点是RagnerHdfsAuthorizer类,通过此类的内部类RangerAccessControlEnforcer的checkPermission()方法判断是用户是否有权限访问,最终调用的是isAccessAllowed()方法,此方法根据请求的参数,判断
Ranger中的policy是否匹配,若匹配,则允许访问,否则拒绝访问;同时插件会记录此过程的审计日志。
HDFS细粒度权限实践
现有的HDFS服务权限模型(AccessType)如下表:
组件 (Service) |
资源 (Resource) |
权限模型 (AccessType) |
HDFS
|
Path
|
Read,Write,Execute
|
在一些大数据平台的安全性要求较高的场景中,上述支持的HDFS组件权限模型粒度较大,不满足“权限明确,最小权限”原则。例如某用户对HDFS Path路径(假设是文件)具有write写权限,那么这个用户可以对此文件进行重命名、截断、删除等操作,这样用户可能会有误操作的情况;原本可能只授予用户下载此文件的权限,结果权限模糊或权限扩大,导致可能恶意访问数据的问题发生。
为此我们对HDFS权限模型进一步细化,定义更加细粒度的权限模型,使其数据访问控制遵循“权限明确,最小权限”原则,这样解决了权限模糊或权限扩大,进而导致恶意访问数据的问题。
1、细粒度权限模型定义
细粒度授权是为用户或用户组赋予大数据平台中访问数据的操作权限。细粒度授权应可以从不同的数据粒度为用户或用户组赋予可执行的操作。根据数据操作权限必须按需分配,遵循最小化的原则,定义的细粒度权限模型如下:
组件 (Service) |
资源 (Resource) |
权限模型 (AccessType) |
说明
|
HDFS
|
Path
|
mkdir |
创建文件夹 |
rename
|
重命名/移动
|
delete |
删除
|
list |
查看
|
create |
创建文件
|
upload
|
上传
|
download
|
下载 |
append |
追加
|
truncate
|
截断 |
open
|
读取
|
2、细粒度权限实现
(1)模型支持
首先对ApacheRanger的HDFS组件ServiceDefinition数据模型做了扩展,支持定义的细粒度权限模型,具体涉及到ranger-admin模块改造。
(2)鉴权支持
这里提供两种方案:
方案一:namenode侧细化权限。从 namenode进程角度看,客户端请求到达namenode服务端后,需要解析并区分客户端具体请求的操作(delete or move等),进而把具体的请求操作封装后调用Ranger HDFS-plugin中的方法,再检查是否具有权限。
方案二:Ranger HDFS-plugin侧细化权限。客户端请求到达namenode服务端后,请求调用Ranger HDFS-plugin中的方法,其中namenode的Inode Attribute封装了客户端请求的参数,在HDFS-plugin侧进行进一步区分,经过和已有权限策略的对比,检测是否有权限。
在实际开发过程中我
们采用了方案一,即对namenode代码进行了改造。在实践过程中,我们有如下两点思考:
(1)是否可以在HDFS客户端请求到达namenode校验逻辑之前进行预校验,实现PRC的限流?
HDFS客户端经过参数解析后,预先请求调用ranger-admin服务进行预校验,通过后再请求namenode服务。这样做对于namenode服务负载过高的场景,可以减少namenode压力,提升rpc性能。
(2)是否可以定义可扩展权限模型?
在实际应用场景中,有些用户可能会恶意触发一些“重”操作(如递归删除一些大文件目录)的行为,这种操作会导致namenode rpc请求负载升高,所以有必要定义可扩展的权限模型限制这种操作场景。基于Ranger HDFS组件定义的细粒度权限模型,例如可以定义如下可扩展权限模型:
组件 (Service) |
资源 (Resource) |
权限模型 (AccessType) |
说明
|
HDFS |
Path |
heavy
|
重操作
|
light
|
轻操作
|
这里定义heavy包含delete、rename两种权限模型。假设有HDFS目录 /user/dir1/dir2/dir3,用户bch已经通过了自身身份认证,满足的策略条件有:
a)用户bch对目录 /user/dir1/dir2/dir3有open,delete,rename三种权限;
b)用户bch对目录/user/dir1/dir2/dir3有heavy权限
当只有同时满足策略条件a、b时,用户bch才能进行“重”操作,从而增加此类操作的安全性。
关于本周文章如果大家有疑问,或者有其他感兴趣的大数据内容,欢迎大家在评论区留言,后续会持续分享大数据领域的干货知识~