本文继续上一篇Hadoop安全认证方面的内容主题,来简单聊聊Hadoop内部的其它认证体系:Delegation Token(授权令牌认证)和Block Access Token(块访问认证)。主要来聊聊这两者间的差异,顺带也会提及一些Kerberos认证的一点内容。这里不深挖其中的技术细节,整体阐述会比较简单,明了。
Kerberos认证是业界较为成熟的一种认证体系,其中涉及到三方的通信。大致过程可描述为如下两大步骤:
那么这套认证过程会有什么问题呢?主要有以下几点:
第一点,过程比较复杂,认证过程还涉及到第三方服务。
第二点,KDC服务可能存在单点瓶颈问题,尤其当有大量的用户请求需要通过KDC来获取TGT凭证时。
于是乎,一种简单化的认证体系衍生而出了。
这里我们说的Delegation Token指的是一种“授权”认证,它和Kerberos的授权相比,不同的点在于:用户被“授权”了一次之后,可以接着使用“授权令牌”在后续的请求过程中,无须再次“授权”过程。当然,这里会存在令牌过期更新的问题。
Hadoop内部的Delegation Token的产生,初期是由NameNode和用户之间共享的一个安全秘钥,经过一系列的运算,得到。而这个安全秘钥,只允许由用户和NameNode私自保管,是被保护起来的。
每个用户经过初期验证后,会从NN中获取一个授权Token。同时用户需要告知NN它的Token更新者(Renewer)是谁。这样的话,每当令牌失效的时候,NN只允许给定的用户进行更新令牌期限的操作。这个更新者信息也是会被加入到Token信息中。
Delegation Token的具体设计如下:
TokenID = {ownerID, renewerID, issueDate, maxDate, sequenceNumber}
TokenAuthenticator = HMAC-SHA1(masterKey, TokenID)
Delegation Token = {TokenID, TokenAuthenticator}
NN在这里会选择随机的masterKey值来生成Token,并且将这些生成好后的活跃的Token信息保存在内存中,进行后续的请求验证。当用户主动删除Token或者Token过期时,NN会将相应的Token从内存中清除。
当客户端向NN进行请求认证的时候,首先会发送TokenId到NN,TokenId其实代表的就是对应的唯一的Token信息。NN通过保存的masterKey信息和TokenId重新计算出完整Token信息,然后再与客户端的Token信息做彼此验证。这里masterKey的信息是需要被NN持久化出去的。
在早期DataNode中,一个未经认证过的客户端只要提供对应的blockId,是可以随意读写数据到DN上的。因此在这里,我们是否能够提供一个块访问认证的一种机制呢,以此表明用户是被允许访问目标块数据的。同样的,这也是一种令牌凭证信息,不过它会比Delegation Token信息更加轻量级一些。
Block Access Token和Delegation Token有一些方面是类似,过程如下
换句话说,每次客户端会携带着从NN获取的Token信息,做块数据的访问。
在设计上,Block Access Token是更加轻量级并且时效性较短的。Block Access Token的生成采用的是一种对称加密的算法方式。简单来说,NN和DN会共享一个私密的秘钥信息,NN会在DN注册的时候给予其随机生成的秘钥信息。然后通过以下方式,进行Token的生成
TokenID = {expirationDate, keyID, ownerID, blockID, accessModes}
TokenAuthenticator = HMAC-SHA1(key, TokenID)
Block Access Token = {TokenID, TokenAuthenticator}
这里的KeyID即为私密秘钥信息。DN在验证的时候,通过正向运算,以此来比较客户端的Token是否是有效的。
因为Block Access Token没有renew机制,NN采用定期更新的方式来更新它所持有的秘钥信息,并且移除过期的Token信息。新秘钥信息通过心跳的方式传达到各个DN,DN接收到信息后,移除自身内部维护的过期秘钥信息,并加入新的秘钥信息,用于后面的访问验证。通过NN/DN这种内存滚动更新的方式,NN实际也不需要持久化这些秘钥信息了。
[1].https://issues.apache.org/jira/browse/HADOOP-4487
[2].https://issues.apache.org/jira/secure/attachment/12428537/security-design.pdf