Apache Ranger对HDFS的访问权限控制的原理分析(一)
介绍
Aapche Ranger是以插件的形式集成到HDFS中,由Ranger Admin管理访问策略,Ranger插件定期轮询Admin更新策略到本地,并根据策略信息进行用户访问权限的判定。其中提供管理员管理策略、插件的Ranger web和Ranger Plugin,与Admin之间的通信是基于HTTP的RESTful架构。Ranger集成HDFS的架构图如下:
Ranger对HDFS访问控制的实现原理
HDFS本身是有访问控制机制的,即在身份认证机制之后通过查询ACLs来对用户的权限检查,该权限检查的实现代码是INodeAttributeProvider抽象类中接口AccessControlEnforcer的checkPermission方法。Ranger将HDFS NameNode 的Inode attribute的提供类即INodeAttributeProvider抽象类修改为Ranger自己写的类,该类继承了INodeAttributeProvider抽象类。即在hdfs-site.xml文件中修改如下配置项。
<name>dfs.namenode.inode.attributes.provider.class</name>
<value>org.apache.ranger.authorization.hadoop.RangerHdfsAuthorizer</value>
Ranger 插件的初始化过程
动态加载类
在Namenode启动过程中编译RangerHdfsAuthorizerorizer类(包名为ranger-hdfs-plugin-shim),将RangerHdfs的相关类动态加载进虚拟机,并实例化具体实现类RangerHdfsAuthorizerorizer(包名为ranger-hdfs-plugin)。
rangerPluginClassLoader = RangerPluginClassLoader.getInstance(RANGER_PLUGIN_TYPE, this.getClass());
@SuppressWarnings("unchecked")
Class<INodeAttributeProvider> cls = (Class<INodeAttributeProvider>) Class.forName(RANGER_HDFS_AUTHORIZER_IMPL_CLASSNAME, true, rangerPluginClassLoader);
activatePluginClassLoader();
rangerHdfsAuthorizerImpl = cls.newInstance();
插件初始化
初始化RangerPlugin,如上面的类图可知,RangerHdfsPlugin是RangerBasePlugin类的子类,其具体的初始化是由父类的初始化方法来实现的。该方法主要完成了以下几个功能:
(1)调用cleanup()方法,主要完成清空了refresher、serviceName、policyEngine这三个变量的值。
(2)读取配置文件,并设置以下变量的初始值。
- serviceType:Ranger提供访问控制服务的类型。
- serviceName:Ranger提供访问控制服务的名称。
- appId:由Ranger提供服务的组件ID。
- propertyPrefix:Ranger插件的属性前缀。
- pollingIntervalMs:刷新器定期更新策略的轮询间隔时间。Ranger 插件会定期从Ranger Admin拉取新的策略信息,并保存在Hdfs缓存中。
- cacheDir:从Ranger Admin拉取策略到Hdfs插件的临时存放目录。
(3)设置PangerPolicyEngineOptions类的成员变量值。
- evaluatorType:评估器的类型。在Ranger对Hdfs的访问权限的鉴权阶段需要策略评估器根据策略判断是否具有访问权限。
- cacheAuditResults:是否缓存审计。
- disableContextEnrichers:是否使用上下文增强器。
- disableCustomConditions:是否使用自定义条件。在Ranger0.5版本之后加入上下文增强器和用户自定义条件这样的“钩子”函数以增加授权策略的可扩展性。
- disableTagPolicyEvaluation:是否使用基于标签的策略评估。在Ranger0.6版本以后,Ranger不仅仅支持基于资源的策略,还支持基于标签的策略,该策略的优点是资源分类与访问授权的分离,标记的单个授权策略可用于授权跨各种Hadoop组件访问资源。
(4)调用createAdminClient(),创建RangerAdmin与RangerPlugin通信的客户端。这里使用的基于RESTful的通信风格,所以创建RangerAdminClient类的实例对象。
(5)创建PolicyRefresher类的对象,调用startRefresher()开启策略刷新器,根据轮询间隔时间定期从Ranger Admin 拉取更新的策略。
策略更新
Ranger插件更新策略的流程图如下:
这部分主要讲Ranger插件如何通过调用Ranger定义好的API获取策略。这里使用了jersey来构建RESTful服务。
(1)Jersey客户端的实现
RangerAdminRESTClient # getServicePoliciesIfUpdated()
if (isSecureMode) {
PrivilegedAction<ClientResponse> action = new PrivilegedAction<ClientResponse>() {
public ClientResponse run() {
// 创建WebResource实例,并根据URI和查询参数(lastKnownVersion、pluginId)构建URL
WebResource secureWebResource = createWebResource(RangerRESTUtils.REST_URL_POLICY_GET_FOR_SECURE_SERVICE_IF_UPDATED + serviceName)
.queryParam(RangerRESTUtils.REST_PARAM_LAST_KNOWN_POLICY_VERSION, Long.toString(lastKnownVersion))
.queryParam(RangerRESTUtils.REST_PARAM_PLUGIN_ID, pluginId);
// 发送GET请求,并且mime类型为Json
return secureWebResource.accept(RangerRESTUtils.REST_MIME_TYPE_JSON).get(ClientResponse.class);
};
};
response = user.doAs(action);
}else{
WebResource webResource = createWebResource(RangerRESTUtils.REST_URL_POLICY_GET_FOR_SERVICE_IF_UPDATED + serviceName)
.queryParam(RangerRESTUtils.REST_PARAM_LAST_KNOWN_POLICY_VERSION, Long.toString(lastKnownVersion))
.queryParam(RangerRESTUtils.REST_PARAM_PLUGIN_ID, pluginId);
response = webResource.accept(RangerRESTUtils.REST_MIME_TYPE_JSON).get(ClientResponse.class);
}
if(response != null && response.getStatus() == 200) { //200:请求成功
ret = response.getEntity(ServicePolicies.class);
} else if(response != null && response.getStatus() == 304) { // 304:未修正
// no change
}
在RangerRESTUtils类中定义了参数的值:
public static final String REST_URL_POLICY_GET_FOR_SERVICE_IF_UPDATED = "/service/plugins/policies/download/";
public static final String SERVICE_NAME_PARAM = "serviceName";
public static final String LAST_KNOWN_TAG_VERSION_PARAM = "lastKnownVersion";
public static final String REST_MIME_TYPE_JSON = "application/json" ;
(2)服务端的实现
ServiceREST # getServicePolicesIfUpdate()
@GET
@Path("/policies/download/{serviceName}")
@Produces({ "application/json", "application/xml" })
public ServicePolicies getServicePoliciesIfUpdated(@PathParam("serviceName") String serviceName, @QueryParam("lastKnownVersion") Long lastKnownVersion, @QueryParam("pluginId") String pluginId, @Context HttpServletRequest request) throws Exception {
ServicePolicies ret = null;
int httpCode = HttpServletResponse.SC_OK;
String logMsg = null;
RangerPerfTracer perf = null; if (serviceUtil.isValidateHttpsAuthentication(serviceName, request)) {
if(lastKnownVersion == null) {
lastKnownVersion = Long.valueOf(-1);
}
try {
ServicePolicies servicePolicies = svcStore.getServicePoliciesIfUpdated(serviceName, lastKnownVersion); // 从数据库获取更新策略的过程
if(servicePolicies == null) {
httpCode = HttpServletResponse.SC_NOT_MODIFIED;
logMsg = "No change since last update";
} else {
ret = filterServicePolicies(servicePolicies);
httpCode = HttpServletResponse.SC_OK;
logMsg = "Returning " + (ret.getPolicies() != null ? ret.getPolicies().size() : 0) + " policies. Policy version=" + ret.getPolicyVersion();
}
}
}
return ret;
}
Apache Ranger对HDFS的访问权限控制的原理分析(一)的更多相关文章
- MongoDB 安全和访问权限控制
MongoDB的访问控制能够有效保证数据库的安全,访问控制是指绑定Application监听的IP地址,设置监听端口,使用账户和密码登录 一,访问控制的参数 1,绑定IP地址 mongod 参数:-- ...
- (转)浅析Java中的访问权限控制
原文地址: http://www.cnblogs.com/dolphin0520/p/3734915.html 今天我们来一起了解一下Java语言中的访问权限控制.在讨论访问权限控制之前,先来讨论一下 ...
- 使用nginx和iptables做访问权限控制(IP和MAC)
之前配置的服务器,相当于对整个内网都是公开的 而且,除了可以通过80端口的nginx来间接访问各项服务,也可以绕过nginx,直接ip地址加端口访问对应服务 这是不对的啊,所以我们要做一些限制 因为只 ...
- [THINKING IN JAVA]访问权限控制
6 访问权限控制 6.1 包:库单元 package.import.import *.import static: 修改classpath环境变量可以将自己写的类库添加至环境变量并在任何java程序中 ...
- Java成员的访问权限控制
Java中的访问权限控制包含两个部分: 类的访问权限控制 类成员的访问权限控制 对类来说,访问权限控制修饰符可以是public或者无修饰符(默认的包访问权限): 对于类成员来说,访问权限控制修饰符可以 ...
- 浅析Java中的访问权限控制
浅析Java中的访问权限控制 今天我们来一起了解一下Java语言中的访问权限控制.在讨论访问权限控制之前,先来讨论一下为何需要访问权限控制.考虑两个场景: 场景1:工程师A编写了一个类ClassA,但 ...
- redis密码设置、访问权限控制等安全设置
redis作为一个高速数据库,在互联网上,必须有对应的安全机制来进行保护,方法有2,如下. 1.比较安全的办法是采用绑定IP的方式来进行控制. 请在redis.conf文件找到如下配置 # If y ...
- JAVA访问权限控制[zhuan]
Java的访问权限控制修饰符,从最大权限到最小权限依次是:public.protected.包访问权限(默认,没有关键字)和private.对于类的访问权限只能是:public和包访问权限(但内部类可 ...
- C++中public/protect/private三种访问权限控制
一.成员访问权限控制 1.public (1)public成员变量可以被成员函数访问 [访问性] (2)public成员可以被实体对象访问 [访问性] (3)public成员可以成为子类成员 [ ...
随机推荐
- HTML超文本标记语言-基础标签整理
第一章 <META>标签: <meta http-equiv="Content-Type" Content="text/html;charset=gb2 ...
- python 接口自动化测试--代码实现(七)
数据库还原脚本: #! /usr/bin/python # coding:utf-8 import time from Engine.SqlEngine import MSSQL COUNT=1 de ...
- 【转】请求处理机制其三:view层与模板解析
进入 View 了 如果处理过程这时候还在继续的话,处理器会调用 view function.Django 中的 Views 不很严格因为它只需要满足几个条件: 必须可以被调用. 必须接受 djan ...
- windows phone 8.1开发:socket通信聊天
本例用WPF程序做服务器端,windows phone程序做客户端.我们使用基于UDP协议的Socket通信.更多关于socket信息请查看:http://msdn.microsoft.com/zh- ...
- calendar.js(日历组件封装)
最近一直闲来无事,便寻思着做一下自己的个人项目,也想说能使用现在比较流行的一些mvvm框架来做,于是就选用了这样的一个技术栈vue2.0+vue-router+vuex+webpack来做,做得也是多 ...
- 安装vnc远程连接CentOS桌面
1.查看本机是否有安装vnc(centOS5默认有安装vnc) rpm -q vnc vnc-server 如果显示结果为: package vnc is not installedvnc-serve ...
- CSS常见兼容性问题总结
原文链接:渔人码头 http://www.cnblogs.com/imwtr/p/4340010.html?utm_source=tuicool&utm_medium=referral 浏览器 ...
- require include 一个隐藏的用法:作用域。
最近在研究php底层框架,奇怪的一点.控制器里为什么要把从model里获取的数据 需要$this->assign('items', $items); 这种形式模板文件里才可以调用到这个变量.控制 ...
- MySQL(Navicat)运行.sql文件时报错[Err] 2006 - MySQL server has gone away 的解决方法
在my.ini里加上 max_allowed_packet=16M
- Android中启动页ViewPager和ViewFlipper带指示器
版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] 首先我们来分析一下,想要实现启动页的功能,大家第一个想到的就是使用ViewPager,使用ViewPager确实是一种比 ...