BlockToken原理剖析

本文深入探讨了Hadoop中BlockToken的原理和实现,它用于认证HDFS的数据读写请求。BlockToken通过HMAC算法确保消息完整性和来源合法性,涉及NN、DN和客户端的角色交互。NN生成并分发BlockToken,DN在接收数据请求时进行校验。BlockToken的生命周期管理解决了key同步和过期问题,确保HA和联邦模式下的安全性。性能方面,虽然计算HMAC会增加一定开销,但在大数据读写场景下影响较小。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【简介】


Hadoop安全需要解决两个问题:一个是认证,即解决用户身份合法性验证问题;另一个是授权,即解决认证用户的操作范围问题。

对于认证,Hadoop设计了Security特性和BlockToken方案;对于授权,设计了ACL机制。

本文重点讲述BlockToken相关的知识原理。

【BlockToken流程概述】


BlockToken方案使用HMAC(Hash Message Authentication Code)技术实现对合法请求的访问认证检查。

HMAC算法流程为:

1. 消息传递前,Alice和Bob约定共享密钥和HASH函数

2. Alice把要发送的消息使用共享密钥计算出HMAC值,然后将消息和HMAC发送给Bob

3. Bob接收到消息和HMAC值后,使用共享密钥独立计算消息本身的HMAC值,与接受到的HMAC值对比。

4. 如果二者的HMAC值相同,说明接收到的消息是完整的,并且是Alice发送的。

对于HDFS而言,NN就相当于上面的Alice,DN就相当于上面的Bob,而客户端在其中扮演数据中转的角色,具体流程为:

1. NN启动后进行初始化,生成共享密钥(下面都称为key)

2. DN在向NN注册时,NN将key信息同步给DN。

3. 客户端在进行文件读写时,需要先向NN请求获取block的信息,NN在处理请求时,生成对应的BlockToken,其中包含了通过key计算出的HMAC值。

4. 接下来,client继续向DN建立连接并进行实际block数据的读写请求,读写请求中会携带从NN中获取的BlockToken。

5. DN进行处理block读写请求前,对BlockToken进行校验,具体包括从BlockToken中获取用户、blockpoolid、blockID、以及访问权限,然后与实际请求的用户、读写的blockID、访问动作进行对比看是否相符;然后根据从NN获取的key计算出HMAC,并与传递过来的HMAC比较是否相等。

【BlockToken的相关实现】


从代码实现的流程来看,最关键的一个数据结构是LocatedBlock类,该类的成员除了包含block的相关信息(blockID、时间戳、副本信息等)、在文件中的偏移量、副本存储的位置(DN)信息外,还包含关键的BlockToken信息。

具体类代码如下所示:

665fdaf15eff8d418c1071e4fdb29feb.png

Token类的代码如下所示:

bf2079448541c1bb1bbaf202dc54035b.png

  • kind为token的类型,对于BlockToken为常量"HDFS_BLOCK_TOKEN";

  • service用来表述请求的服务,通常为服务的"host:port",对于BlockToken则为空;

  • TokenRenewer是客户端生命周期内的renewer,防止token过期而进行的定期更新,对于BlockToken一般不设置,即BlockToken只在固定有效期内生效。

  • identifier是BlockTokenIdentifier的序列化结果。

  • password则是使用key通过MAC算法对identifier计算得到的密码(对应于HMAC)

BlockTokenIdentifier类信息如下代码所示:

d09c69a63e50f5243c5ec2f042ef9fe6.png

包括用户ID,blockPool的ID,block的ID,访问类型,使用的key的ID,以及过期时间。

NN在处理读写block请求时,最终会调用BlockTokenSecretManager的generateToken方法生成BlockToken,相关代码如下:

6b46a2eb90439f36b06242bb8ec29b64.png

在Token的构造方法中,会调用BlockTokenSecretManager的createPassword方法完成密码(对应于HMAC)的计算:

9d08750d6900a21fdb224372e4b6ff43.png

c3d38cf8d52f8331f6d2b3ef298f0c3a.png

34898feec8cfb543e39435d0e510c0c9.png

DN在处理block数据的读写请求前,最终调用BlockTokenSecretManager的checkaccess方法完成blocktoken的校验工作,具体代码为:

33f2d47d2468cfb7c802d70ae4bfbc72.png

在retrievePassword方法中根据key计算出密码。

179b43204423b60e9f09afc7d09a8453.png

到这里就完成了BlockToken的全部流程。

【key的同步与过期处理】


从上面的代码中可以看出,NN和DN对序列化的identifier能计算出同一个password的关键在于使用同一个key。

然而key并不是固定不变的,而是有一定的有效期(默认10小时),超过有效期后,NN会进行更新,DN则通过定时的心跳从NN获取key完成与NN的同步。

但这里会存在问题。考虑这么一个场景,NN对key更新后,DN的心跳还未触发,客户端进行读写请求,此时的密码是NN新的key产生的,而DN中还未来得及更新key,这就会出现key不一致而导致BlockToken无法校验通过。

为了解决上述问题,NN中同时维护了3份key,每个key都有唯一的ID,这些key存放在一个map中。内部定时检测key是否过期,如果过期,则生成新的key添加到map中并滚动向前激活当前的key。

对应代码如下所示:

相关类成员:

b8c39179e90a589b6cf64c5a43042a22.png

初始化生成key(注意初始化时,当前key和nextkey的过期时间设置)

7c7359e431ddaf4178145de6815eb211.png

更新key:

0dec8dc6797460e6607d09c7dd954652.png

DN向NN注册时,获取全量的key并保存,同样,每次心跳从NN获取的key也保存在map中。

另外,NN生成BlockToken时,将key的ID存放在identifier中,DN对BlockToken进行校验时,从identifier中获取key的ID并在内存中找到对应的key。如此一来,就可以保证NN和DN使用同一个key进行密码的计算了。

key的过期问题通过存3份可以解决,那么在HA模式下,如果ANN异常了,SNN接管成为新的ANN,此时key不一致的问题如何解决呢?

对此,hadoop的解决办法是让DN同时保存来自NN和SNN的key。

由于DN会同时向ANN和SNN注册,并发送心跳。这样,DN就会从ANN和SNN分别拿到3份key。因此,只要BlockToken中的key是来自NN的,不管是ANN还是SNN,都能保证使用相同的key进行密码的计算。

此外,在联邦模式下,DN会按照blockpool分别存储多个NN的key信息,保证来自不同NN的BlockToken都能使用对应的key正确计算出密码。

【性能考虑】


NN的性能考虑:

在NN中维护3份key,也就需要对3份key都定时检测是否过期,但是由于时间间隔很长,默认的检测间隔和过期时间都为10小时,因此内存中维护多份key不存在性能问题。

而读写block时需要先有BlockToken,BlockToken的生成和校验都需要计算密码,因此读写耗时的性能整体会有一定的损耗。实测发现,文件大小越小,读写耗时的损耗就越明显;而文件越大,由于读写耗时的基数本身相对较大,这样,因计算密码带来的损耗也就越来越不明显。

总结下,本文对BlockToken的概念进行了简单描述,然后从原理流程、源码实现讲述了BlockToken的鉴权流程,以及key过期的处理,最后以实际测试的经验对性能损耗做了一定的分析。

好了,本文就介绍到这里,原创不易,点赞,在看,分享是最好的支持, 谢谢~

fc9d4c6c94be4daba01fb1a87ff606e0.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值