Ranger的中文释义是“园林管理员”。正如其名,Apache Ranger很好的承担了Hadoop这个大园林的管理员职责。Ranger提供了一个集中式的安全管理框架,用户可以通过操作Ranger控制台来配置各种策略,从而实现对Hadoop生态组件如HDFS、Hive、HBase、Yarn等进行细粒度的数据访问控制。
根据Apache Ranger官网所述,Ranger主要实现以下功能:
(1)通过统一的中心化管理界面或者REST接口来管理所有安全任务,从而实现集中化的安全管理;
(2)通过统一的中心化管理界面,对Hadoop组件/工具的操作/行为进行细粒度级别的控制;
(3)提供了统一的、标准化的授权方式;
(4)支持基于角色的访问控制、基于属性的访问控制等多种访问控制手段;
(5)支持对用户访问和(与安全相关的)管理操作的集中审计。
目前,Ranger的最新版本是2.1.0,广泛使用的版本是1.2.0。
(一)Ranger的架构
Ranger主要由以下三个组件构成:
(1)Ranger Admin:Ranger Admin是Ranger的核心模块,它内置了一个Web管理页面,用户可以通过这个Web管理界面或者REST接口来制定安全策略。
(2)Agent Plugin:Agent Plugin是嵌入到Hadoop生态组件中的插件,它定期从Ranger Admin拉取策略并执行,同时记录操作记录以供审计。
(3)User Sync:User Sync将操作系统用户/属组(Users/Groups)的权限数据同步到Ranger的数据库中。
它们之间的关系如下图所示:
(二)Ranger的工作流程
Ranger Admin是Apache Ranger和用户交互的主要界面。当用户登录Ranger Admin时,可以针对不同的Hadoop组件制定不同的安全策略;当策略制定好并保存之后,Agent Plugin定期(默认是30秒)从Ranger Admin拉取该组件配置的所有策略,并缓存到本地。这样,当有用户来请求Hadoop组件的数据服务时,Agent Plugin就提供鉴权服务,并将鉴权结果反馈给相应的组件,从而实现了数据服务的权限控制功能。当用户在Ranger Admin中修改配置策略后,Agent Plugin会拉取新策略并更新;如果用户在Ranger Admin中删除了配置策略,那么Agent Plugin的鉴权服务也无法继续使用。
以Hive为例。Hive提供了2个接口给开发者实现自己的授权策略,分别是org.apache.hadoop.hive.ql.security.authorization.plugin.HiveAuthorizerFactory和org.apache.hadoop.hive.ql.security.authorization.plugin.HiveAuthorizer。其中,HiveAuthorizerFactory用来生成HiveAuthorizer的相关实例。HiveAuthorizer在初始化时,会启动一个PolicyRefresher线程定时的从Ranger Admin拉取所有Hive相关的策略,写入本地临时json文件并更新缓存,当需要授权时直接根据缓存的策略进行授权。具体流程如下图所示:
(三)Ranger运维实战
人员,角色和权限一直是系统设计和运维重点关注的领域。如果不建立一套完善的人员、角色和权限关系,那么一个“非法用户”就有可能轻易地访问甚至篡改系统的资源和数据。相比于Unix/Linux系统简单的用“用户/用户组”来设定权限,Apache Ranger提供了界面更友好的、操作更方便的Web页面来建立一套完善的人员、角色和权限关系,让经过授权的用户可以合法地访问已授权的资源和数据,而将那些未经授权的“非法用户”彻底“拒之门外”。
此外Ranger还支持临时策略创建,实现对其他用户的临时授权。当临时授权的用户完成相关操作后,再删除这些临时策略,从而方便、快捷地实现用户的临时授权。
以HDFS为例。我们在Ranger Admin中选择Services Manager,然后再点击HDFS组件,就能进入HDFS策略编辑页面。如下图所示:
点击Add New Policy按钮,就可以开始制定安全策略了。在实际生产环境上,我们制定的一个具体安全策略如下图所示:
从上图可以看到,这个策略是允许应用系统的admin、test0822-2等用户,访问HDFS组件的/user、/user/rangerpath/、/user/rangerpath/data、/user/rangerpath/data/allday等路径、并在路径下执行命令的策略。需要注意的是,由于我们在制定策略时未打开recursive(递归)开关,所以用户能访问/user目录,并不能保证他有权限访问该目录的下一层目录。因此我们依次指定了这些用户能访问的具体目录。
在Audit标签,我们可以很清晰的看到审计和状态信息,如系统登录记录、策略鉴权记录、Agent Plugin状态等,如下图所示:
Ranger对Hive的支持也非常完善。它不仅支持表级的访问控制,还能细化到字段级的访问控制。同时,Ranger还支持字段级的加密和行级别的过滤。这些手段非常适合临时授权时,限制临时用户的访问权限。
制定Hive策略的方式与HDFS基本一致。我们制定的访问策略如下图所示:
在Masking标签页,可以制定字段级的加密策略。如下图所示:
在上图中,我们制定的策略是:不让Hadoop属组的damp用户,看到foodmart数据库customer表lname字段的真实数据。这个字段的数据,将以hash值的方式展现给damp用户。当damp访问这张表时,他查询的结果如下图所示:
在Row Level Filter标签页,我们可以制定行级的过滤策略。我们制定了一个简单的策略:不让damp用户,看到customer表fname是Sheri的记录,如下图所示:
此时,damp用户无法看到customer表fname=’Sheri’的记录:
需要注意的是,Ranger通过Usersync组件,将操作系统的用户同步到了hive组件中。因此在配置Hive组件的策略时,需要用hive管理员对应的操作系统账号登录Ranger Admin,才能配置成功。否则会提示:
(四)Ranger策略的批量操作
随着信息化进程的加快和深入,信息系统的应用范围逐步拓宽,信息系统的使用人员也越来越多,对用户权限的需求也越来越多。此外,大数据思维逐渐深入人心,对数据的临时访问需求也随之增多。如果用传统手工的方式逐一添加安全策略,会造成极大的人力浪费,也很容易发生错误。针对这一场景,我们用java程序,对Ranger的安全策略进行批量的增、删、改、查,极大的提升了运维效率。
我们先实现一个访问Ranger Api的基础类,代码如下所示:
public ApiResult execRangerApi(String url, String method, String requestBody) {
HadoopConfig.Ranger ranger = this.hadoop.getRanger();
String baseUrl = ranger.getApiBaseUrl();
String user = ranger.getUser();
String password = ranger.getPassword();
String fullUrl = baseUrl + url;
String auth = user + ":" + password;
String authInfo = DatatypeConverter.printBase64Binary(auth.getBytes());
HttpRequest request = null;
if (method.equalsIgnoreCase("GET")) {
request = HttpRequest.get(fullUrl);
} else if (method.equalsIgnoreCase("POST")) {
request = HttpRequest.post(fullUrl);
} else if (method.equalsIgnoreCase("PUT")) {
request = HttpRequest.put(fullUrl);
} else if (method.equalsIgnoreCase("DELETE")) {
request = HttpRequest.delete(fullUrl);
}
((HttpRequest)((HttpRequest)((HttpRequest)request.header("Authorization", "Basic " + authInfo))
.header("Accept", "application/json"))
.header("Content-Type", "application/json"))
.header("X-XSRF-HEADER", "valid");
if (requestBody != null && !requestBody.isEmpty())
request.body(requestBody);
HttpResponse response = request.execute();
ApiResult result = new ApiResult(this);
result.setHttpCode(response.getStatus());
result.setBodyRaw(response.body());
return result;
}
基于这个基础类,我们可以进一步设计出增加、删除、修改和查询Ranger策略的实现类,基础代码如下:
public void savePolicy(String policyName, List<String> paths, boolean isPathAdd, String appUser, List<PolicyAccess> accesses, boolean isReclusive) {
ApiResult result = null;
Policy policy = getPolicyByName(policyName);
......
Gson gson = new Gson();
if (isNewPolicy) {
logger.info("create policy, content:" + gson.toJson(policy));
result = execRangerApi("/public/v2/api/policy/", "POST", gson.toJson(policy));
if (result.getHttpCode() != 200)
throw new DMCException(String.format("create policy failed! ranger return : %d, %s", new Object[] { Integer.valueOf(result.getHttpCode()), result.getBodyRaw() }));
logger.info("create policy ok! " + policyName);
} else {
logger.info("edit policy, content:" + gson.toJson(policy));
result = execRangerApi("/public/v2/api/policy/" + policy.getId(), "PUT", gson.toJson(policy));
if (result.getHttpCode() != 200)
throw new DMCException(String.format("edit policy failed! ranger return : %d, %s", new Object[] { Integer.valueOf(result.getHttpCode()), result.getBodyRaw() }));
logger.info("edit policy ok! " + policyName);
}
}
最后,我们可以通过curl命令,将我们制定的安全策略传给Ranger Admin,从而实现安全策略的批量处理。参考命令如下所示:
curl -H "Content-Type:application/json" -H "X-Token:token-name" -X POST "http://web-url&appUser=user-name" -d"[\"ranger-policy"]"
综上所述,Apache Ranger提供了丰富的Hadoop组件,帮助我们更好地实现各种安全策略。同时,Ranger策略的定制方便快捷、简单易懂,并且可以“用后即焚”,非常适用于临时授权的场景。我们有理由相信,随着Hadoop生态圈的不断扩大,Ranger会受到越来越多运维人员的青睐和使用。
参考资料:
1.http://ranger.apache.org/
2.ZTE中兴,Ranger培训材料