数据安全一直是企业的一个重要的工程,很多企业都有自己的一套安全认证框架,如何将第三方的安全认证框架集成到Flink on Yarn实现中呢?目前Flink on Kerberos Yarn的实现方案是通过客户端将keytab提交到Hadoop集群,再通过YARN分发keytab给AM和其他运行TaskManager的worker container,每个container使用相同的Keytab重复地向KDC进行认证授权与刷新token,给KDC带来了很大负担,并且Hadoop proxy user目前(Flink 1.10)也无法使用.针对这些问题,Flink社区对Flink on Yarn的Security流程提出了改进方案。
Security采用Service Provider模式
目前Flink的安全认证方式是在任务提交前通过各个SecurityModule实现的,Flink客户端在提交任务前会根据配置文件初始化所需的SecurityModule并调用其install方法来认证用户权限。然而这种安全机制在实际应用中受到了很大限制
- 一方面Flink本身实现的SecurityModule数量有限,把所有的安全认证解决方案都集成进来将使系统变得太重且可能破坏现有的架构;
- 另一很多企业甚至自己开发了一套独立的数据安全框架,并不是开源的,更不可能集成到Flink代码中了。
在改进提案中,使用了Service Provider模式,主要涉及以下几个类。
- SecurityFactoryService:安全认证的核心API接口,类似于原来的SecurityUtils类。
- SecurityModuleFactory:基于用户配置安装或卸载相应的security module。
- SecurityModule:用于执行具体的安全认证,例如获取HDFS的访问权限,并且还要负责在具体的security context中实例化数据Connector与StateManager。
- SecurityContextFactory:用于实例化SecurityContext。
- SecurityContext:调用安全请求的上下文环境,使得用户代码代码在许可的权限范围内执行.
在启动Flink任务时,会加载所有用户JAR,SecurityFactoryService会基于Service Provider模式查找所有需要实例化的类。由用户配置来控制具体哪些SecurityContext与SecurityModule需要实例化与动态加载。
这样就可以将client 端、AM 端和普通 container端的认证方法通过SecurityFactoryService来解耦,因此用户可以灵活定制三者的认证方法。对于第三方认证方法,可以通过实现SecurityModule接口,并将该实现的jar包添加到容器的classpath,就将这种第三方安全认证集成到flink任务了。
使用Hadoop Delegation Token进行认证
该提案从提交到AM初始化地过程与原方案一样,只是TaskManager不再使用keytab进行身份认证,而是使用Hadoop的delegation token,减少了对KDC的访问,具体步骤如下。
- Flink客户端在提交任务时,将keytab上传至HDFS,将其作为AM需要本地化的资源。
- AM container初始化时NodeManager将keytab拷贝至container的资源目录,然后再AM启动时通过
UserGroupInformation.loginUserFromKeytab()
来重新认证。 - AM申请container运行TaskManager时并不再将keytab列本地化资源,而是请求container需要的delegation token(比如基础的 HDFS_DELEGATION_TOKEN)并将这些 token 作为 ContainerLaunchContext的安全凭证。
- 为了防止token过期,container后续定期从AM获取新的token。
支持超级用户Impersonation
Impersonation的本义是扮演,所谓超级用户Impersonation就是以一个超级用户superuser身份去提交flink任务,任务提交到集群中后,以另外一个普通用户去访问HDFS资源。这可以让一个没有kerberos证书的hadoop用户在flink客户端提交flink任务。
其实现原理是让Flink客户端以superuser的证书进行,然后使用UserGroupInformation.createProxyUser创建代理用户的ugi对象,再用ugi.doAs方法代理操作。其中代理用户的username可以通过flink配置或者环境变量HADOOP_PROXY_USER传入(与Hadoop类似)。
这种方法存在一个潜在风险,Flink客户端运行了用户代码的main方法,这就使得用户可以获取superuser的keytab。解决方案是让Jobmanager支持像Flink客户端一样运行用户代码的main方法来生成Flink任务的JobGraph。
对于长时间运行的任务,需要以实现个提案为基础,即使用Hadoop Delegation Token进行认证,才能支持长时间的Impersonation。将superuser设置为Hadoop超级用户,那么superuser这样他就可以申请到代理用户的delagtion token,再以代理用户的delegation token来提交作业或访问其他资源文件。后续Flink需要以这种提案的认证方式持续刷新delegation token。