聊聊HDFS中的权限管理
HDFS是一个面向多用户的分布式文件系统。既然是多用户,那么不同用户存储的文件通常需要进行权限隔离,防止被其他用户修改或误删。本文就来聊聊HDFS中的权限管理。
权限校验
要启用权限校验,首先需要在NN中配置开启。
配置项dfs.permissions.enabled控制权限的开关,true表示开启,false表示关闭。
没有开启权限控制时,任何用户都可以对任意文件进行读写删除等操作。
<property>
<name>dfs.permissions.enabled</name>
<value>true</value>
</property>
HDFS中的权限方式和linux文件系统中的权限模型是一样的,均采用UGO模型。
U表示User,G表示Group,O表示Other。每个文件的权限都基于UGO来设置。
而权限又包括可读(r),可写(w),可执行(x),三个为一组,对应UGO分别进行设置。
我们来实际验证下:使用hncscwc用户创建/hncscwc目录,并上传文件到该目录中,然后使用root用户删除该文件。
未开启权限校验之前,root用户可以成功删除文件。
开启权限校验之后,root用户无法删除该文件,并提示没有权限。
那么如果想要让root用户可以删除hncscwc上传的文件,有什么办法呢?一种简单粗暴的方式是通过chmod改变文件的权限。例如上面将目录和文件的权限都设置为777后,root用户就可以成功删除文件了。
但显然这种方式是不友好的,因为几乎和没有开启权限校验一样。因此HDFS同样也是实现了类似linux文件系统中ACL。
ACL
和权限校验一样,ACL的开启有对应的配置项,true表示开启,false表示关闭
<property>
<name>dfs.namenode.acls.enabled</name>
<value>true</value>
</property>
开启ACL之后,可以通过命令设置和获取文件/目录的ACL。
# 获取指定文件/目录的ACL
hdfs dfs -getfacl
-R: 递归列出所有w文件和目录的ACL
# 设置指定文件/目录的ACL
hdfs dfs -setfacl [-R] [-b|-k -m|-x <acl_spec> <path>] [--set <acl_spec <path>]
-b: 删除基本ACL条目之外的所有条目。保留用户、组和其他的条目
-k: 移除默认的ACL
-R: 递归操作所有文件和目录
-m: 修改ACL,将新条目添加到ACL,并保留现有条目
-x: 删除指定的ACL
--set: 完全t替换ACL,acl_spec必须包含用户,组和其他权限信息
acl_spec: 用逗号分隔的ACL列表
path: 需要设置ACL的文件l路径
这里不展开说明命令的细节,详细参考官方文档。
还是按照上面的场景,对/hncscwc/info设置ACL允许root用户写入。
从上图可以看到,文件设置ACL之后,权限后面会多出一个“+”,表示该文件有设置ACL。
通过命令查看该文件的ACL信息:
接着使用root用户追加写入该文件,此时root用户可以成功追加写入,而使用其他用户追加写入时,写入失败并提示没有权限。
由此可见,ACL生效了,也确实达到了我们想要的效果。
超级用户
在HDFS中,有一个超级用户的概念,该用户可以成功执行任意动作而不需要进行权限校验。
超级用户没有固定的值,而是启动NN的用户就是超级用户。
此外,还可以通过配置来指明一个组为超级用户组,在该组中的所有用户均为超级用户,具体配置为:
<property>
<name>dfs.permissions.superusergroup</name>
<value>supergroup</value>
</property>
内部实现
在NN内部,权限校验主要有两个类,部分关键代码如下所示:
public abstract class INodeAttributeProvider
{
//访问控制执行者接口
public interface AccessControlEnforcer {
// 省略了参数列表
public abstract void checkPermission(...)
}
public abstract void start();
public abstract void stop();
public AccessControlEnforcer getExternalAccessControlEnforcer(AccessControlEnforcer defaultEnforcer) {
return defaultEnforcer;
}
}
该类为抽象类,用于HDFS委派授权,该类中定义了一个接口AccessControlEnforcer,并定义方法checkPermission,该方法需要实现类重写,以实现最终的权限校验逻辑。
class FSPermissionChecker implements AccessControlEnforcer {
private AccessControlEnforcer getAccessControlEnforcer() {
// 这里的attributeProvider就是上面抽象类的具体实现类
// 如果attributeProvider 则使用自身
return (attributeProvider != null) ?
attributeProvider.getExternalAccessControlEnforcer(this) : this;
}
// 外部调用接口, 省略了参数列表
void checkPermission(...) {
AccessControlEnforcer enforcer = getAccessControlEnforcer();
enforcer.checkPermission(...)
}
// 实现AccessControlEnforcer接口的方法实现
public void checkPermission(...) {
}
}
简单总结下鉴权流程,如下图所示:
从流程可以看出,通过编写INodeAttributeProvider继承类,和接口AccessControlEnforcer实现,HDFS可以支持外部以插件的方式实现定制的权限控制。而实际上,开源的大数据权限管理项目Ranger,sentry就是利用了这一点,以插件的方式扩展实现了权限校验。
好了,本文就介绍到这里了,原创不易,点赞,在看,分享是最好的支持, 谢谢~