图片看不见的请看我的CSDN博客
https://blog.csdn.net/u013332124/article/details/86360756
一、Ranger是什么
ranger大数据领域的一个集中式安全管理框架,它可以对诸如hdfs、hive、kafka、storm等组件进行细粒度的权限控制。比如它可以控制用户读取hdfs文件的权限,甚至可以控制某个用户对hive某个列访问的权限。
ranger目前支持的组件:
[图片上传失败...(image-d3be34-1547276660260)]
二、Ranger的权限模型
Ranger的权限模型一条条的权限策略组成的,权限策略主要由3个方面组成,即用户、资源、权限。
[图片上传失败...(image-5eb124-1547276660260)]
用户:ranger可以对用户进行分组,一个用户可以属于多个分组。Ranger支持对用户或者用户组配置某资源的相关权限。
资源:对于各个不同的组件,资源的表述都不相同。比如在HDFS中,文件路径就是资源,而在Hive中,资源可以指Database、Table甚至Column。
权限:ranger可以对各个资源的读、写、访问进行限制,具体可以配置白名单、白名单排除、黑名单、黑名单排除等条目。
ranger管理员配置好组件的相关策略后,并且将ranger插件安装到具体的大数据组件中,ranger就可以开始生效了。这时用户访问ranger就会进行权限的校验过程了,校验过程如下:
[图片上传失败...(image-536a67-1547276660260)]
当用户要请求某个资源时,会先获取和这个资源有关联的所有配置的策略,之后遍历这些策略,然后根据黑白名单判断该用户是否有权限访问该资源。从上面的流程图可以看出,黑名单、黑名单排除、白名单、白名单排除匹配的优先级如下:
- 黑名单优先级高于白名单
- 黑名单排除的优先级高于黑名单
- 白名单排除的优先级高于白名单
决策下放:
如果没有policy能决策访问,一般情况是认为没有权限拒绝访问,然而Ranger还可以选择将决策下放给系统自身的访问控制层。
三、Ranger架构
[图片上传失败...(image-a4080f-1547276660260)]
Ranger-admin
ranger-admin是基于Jersey+Spring+EclipseLink框框开发的Web服务,对外提供了Restful风格的http服务。Ranger-Admin模块同样内嵌了jsp界面,用于管理员管理用户、资源、权限等信息。同样,我们可以基于它的Restful Api来编写自己的权限管理sdk。
虽然Jersey和SpringMVC同样实现了JAX-RS(javaee6提供Java API for RESTful Web Services)规范,但是jersey更加适合构建restful风格的服务,因为它天生就是为restful而生的。
EclipseLink 是 JPA(Java Persistence Api)的一种实现,是java的一个ORM框架。
Plugin
那么ranger是如何实现对大数据组件的权限控制访问呢?这就和ranger实现的一个个plugin有关系了。
因为几乎所有的大数据组件都有提供一个抽象的验证接口,ranger就是根据这些接口为各个大数据组件实现了对应的plugin,plugin的工作主要是从Ranger-Admin处拉取该组件配置的所有策略,然后缓存到本地,然后当有用户来请求时提供鉴权服务。
Hive Plugin 授权流程
举个Hive Plugin的授权流程的例子。
对于权限模块,Hive提供了几个接口来给开发者来实现自己的授权策略。他们分别是
- org.apache.hadoop.hive.ql.security.authorization.plugin.HiveAuthorizerFactory
- org.apache.hadoop.hive.ql.security.authorization.plugin.HiveAuthorizer
其中HiveAuthorizerFactory用来生成HiveAuthorizer的相关实例,之后Hive在进行编译的时候会调用HiveAuthorizer#checkPrivileges()
方法进行权限校验。
我们要实现自己的授权策略,只需实现这两个接口,然后配置一下相关的配置文件即可。Ranger就是通过实现这两个接口来定制自己的授权流程。Ranger对这两个的实现分别是
- org.apache.ranger.authorization.hive.authorizer.RangerHiveAuthorizerFactory
- org.apache.ranger.authorization.hive.authorizer.RangerHiveAuthorizer
之后配置hiveserver2-site.xml
文件
hive.security.authorization.enabled
true
hive.security.authorization.manager
org.apache.ranger.authorization.hive.authorizer.RangerHiveAuthorizerFactory
重启hiveserver2后生效。
RangerHiveAuthorizer在初始化时会启动一个PolicyRefresher线程定时的从Ranger-admin拉取所有的策略,然后缓存到本地,之后当需要授权时直接根据这些策略进行授权。PolicyRefresher默认是每隔30s拉取一次。
[图片上传失败...(image-f9db74-1547276660260)]
四、一些思考
Ranger的架构其实很简单,主要就是Ranger-Admin和各个组件的Plugin,其代码也大多都是偏业务逻辑的。不过所谓魔鬼在细节,下面探讨一些Ranger在实现上比较有趣或者可以借鉴的地方。
1. 关于组件策略的缓存
由于组件的多样性以及策略的复杂性,在ranger的数据库中,和策略相关的表就多达10来张。也就是说,一个组件要来Ranger-Admin拉取其相关的所有策略时,需要查询这十多张表,然后将其组织成组件需要的数据结构,再转成json返回。这是一个相对耗时较长的操作,另外,不止组件会获取这些策略,web界面或者sdk也可能调用相关接口获取所有策略。
为了提高获取策略的性能,ranger以Service为单位,来缓存这些已经组织好的数据。当数据被缓存起来后,后续的请求只需从内存中获取相关数据即可。—— service可以理解为一个具体的大数据组件
使用缓存会引发另一个问题,怎么判定缓存已经失效?为了解决这个问题,Ranger在Service表中添加了一个字段:policy_version,只要和这个service的策略有关的属性发生了变化,就更新policy_version。当用户请求策略时,发现policy_version和缓存的不一致,就会重新拉取数据,然后更新缓存。
当然,这种缓存策略也很容易引发bug,比如ranger之前有一个bug,它在更新用户组信息时,不会更新该service的policy_version,导致组件拉取到的策略数据还是旧数据。
因此,虽说做这种缓存可以很大程度提高性能,但同时也要格外关注这些缓存的更新问题。
2. 插件类加载器的实现
ranger实现大数据组件的授权接口时,一般需要把打包好的jar包放到对应大数据组件的classpath下供组件加载。同时,ranger在实现授权接口时难免会用到其他的一些第三方库,这时问题就来了:如果把这些第三方库的jar包也放到大数据组件的classpath下,引发的版本冲突该如何解决?
举个例子,比如Hive用到了apache-common-1.0.0,ranger编写hive插件时也用到了apache-common-2.0.0,这时候版本就发生了冲突。如果要完全去兼容hive的第三方库版本是一件很累的事情,同时给hive引入过多的第三方库也会导致一些潜在的隐患。
为了解决这个问题,Ranger定义了自己的一个类加载器,用于加载它使用的那些第三方库。在介绍ranger的自定义类加载器之前,我们先简单回顾一下java中的类加载器的一些概念。
首先我们需要明白一件事,在java中,一个类的唯一性并不是由包名+类名
来决定的,还要根据类加载器。也就是说,比如有一个类com.Test
,分别有两个不同的类加载器加载,那么它们加载出的两个类就不是相等的。
Java中的类加载器
java中常见的类加载器有
启动(Bootstrap)类加载器:负责装载
/lib下面的核心类库或-Xbootclasspath选项指定的jar包。由native方法实现加载过程,程序无法直接获取到该类加载器,无法对其进行任何操作。 另外,java中有规定以 java.*
开头的类必须是BootstrapClassLoader来加载的。扩展(Extension)类加载器:扩展类加载器由sun.misc.Launcher.ExtClassLoader实现的。负责加载
/lib/ext或者由系统变量-Djava.ext.dir指定位置中的类库。程序可以访问并使用扩展类加载器。 系统(System)类加载器:系统类加载器是由sun.misc.Launcher.AppClassLoader实现的,也叫应用程序类加载器。负责加载系统类路径-classpath或-Djava.class.path变量所指的目录下的类库。程序可以访问并使用系统类加载器。
双亲委派类加载机制:
在java世界中,有一个双亲委派机制,是说要加载一个类的时候,先交给父级类加载器加载,父级类加载器无法加载时,自己才能去加载这个类。
[图片上传失败...(image-67e2f0-1547276660260)]
这是我们在实现自己的类加载器时,普遍要遵守的一个机制。但是Ranger实现的类加载器破坏了双亲委派机制,从而将自己使用的第三方库和组件使用的第三方库隔离。由于ranger使用的第三方插件的所有类都是自己定义的类加载器加载的,因此不用担心第三方库冲突的问题。
[图片上传失败...(image-ed570c-1547276660260)]
我们可以看一下安装完ranger插件的hive/lib目录:
只多了两个jar包和一个文件夹
- ranger-plugin-classloader-1.0.1.jar : ranger实现的类加载器的相关代码
- ranger-hive-plugin-shim-1.0.1.jar : 提供了RangerHiveAuthorizerFactory类,用于给hive的类加载器加载
- ranger-hive-plugin-impl : 文件夹,ranger使用的第三方库都放在该目录下,RangerPluginClassLoader加载类时会从该目录下扫描类。
五、总结
虽说ranger是apache的顶级开源项目,覆盖的大数据组件也足够多,但是读过它的部分代码后,觉的ranger代码写的真的挺差的,我们在使用的时候也发现并并修复了一些bug,还针对它的sql做了一些优化。
另外ranger的代码个人感觉业务逻辑偏多,"黑科技"比较少,毕竟只是一个web项目+一些插件实现。不过了解这个项目确实也让我学到了不少东西,还是有一定的价值的,后面打算找一些时间整理一份ranger的安装和使用文档。