HDFS内部的认证机制

前言


数据的安全性是一直被大家所重视的.对于一个存有大规模数据量的成熟企业来说,如何做到数据不丢失,不损坏,不窃取就显得格外重要了.而HDFS恰恰满足了”海量数据规模”的特点,所以如果我们用HDFS存储大量的非结构化的数据,我们如何保证其中数据的安全性呢?在之前的文章中,有提到过一个”Encryption Zone”数据加密空间的概念.Encryption Zone可以保证用户在指定的加密空间路径下,数据是被加/解密的,而且对于用户来说完全透明.详细信息可点击HDFS数据加密空间.但是其实再仔细分析数据加密空间的原理,你会发现他其实是一个局部数据安全处理的过程.因为他有一个路径空间的限制.而且我要每次创建我想要加密的特定路径.那么在HDFS中是否还有其他的安全认证机制,可以弥补这点,做到全局的数据验证呢?本文就带大家了解HDFS中2大验证体系BlockToken验证和Sasl认证.

BlockToken验证


首先介绍的验证机制是BlockToken验证,因为相比较而言,BlockToken验证比Sasl确实也要简单一些.而且BlockToken在Sasl中也会被用到.细看BlockToken这个词,可以被拆分为2个词,Block,Token.我们可以得出以下2点关键信息.

1.BlockToken是针对Block块级别的验证.
2.Token的意思是令牌的意思,基本是用做访问时的验证.

OK,大体有了这么一个理解之后,继续来看一下BlockToken如何做具体的验证的,要解决这个问题,需要弄清楚下面3个问题:

  • BlockToken如何生成的?
  • BlockToken在哪里被验证?
  • BlockToken如何被验证的?

在下面的阐述中,将会一一揭开这些答案.

BlockToken的结构分析


BlockToken的体系结构分析可以帮助我们了解他是如何产生的.如果你仔细观察,查找的话,应该很容易就找到相关类,就是BlockPoolTokenSecretManager.BlockToken就是由这个类调用产生的.但是真正产生BlockToken的操作其实是由其存储的BlockTokenSecretManager做的.所以这里就有一层关系:

BlockPoolTokenSecretManager包含BlockTokenSecretManager,并且每一个blockPool对应一个BlockTokenSecretManager

最终是如下的map存储关系.

private final Map<String, BlockTokenSecretManager> map = 
    new HashMap<String, BlockTokenSecretManager>();

可能会有人有疑问了,为什么按照BlockPool分出这么多的BlockTokenSecretManager,全局维护一个Manager不是更好吗?我的个人看法是HDFS这么做还是想做隔离,blockPool是在每次NameNode做format时产生的,代表着独立的存储空间.所有的Block在各自所属的BlockPool下是全局唯一的.HDFS中是可以有多个BlockPool的..回到前面说的过程,重新来看一下BlockToken的生成调用过程.

  /**
   * See {@link BlockTokenSecretManager#generateToken(ExtendedBlock, EnumSet)}
   */
  public Token<BlockTokenIdentifier> generateToken(ExtendedBlock b,
      EnumSet<AccessMode> of) throws IOException {
    // 选择block所属的BlockPool去生成Token
    return get(b.getBlockPoolId()).generateToken(b, of);
  }

然后进行实际调用方法

  /** Generate an block token for current user */
  public Token<BlockTokenIdentifier> generateToken(ExtendedBlock block,
      EnumSet<BlockTokenIdentifier.AccessMode> modes) throws IOException {
    UserGroupInformation ugi = UserGroupInformation.getCurrentUser();
    String userID = (ugi == null ? null : ugi.getShortUserName());
    return generateToken(userID, block, modes);
  }

  /** Generate a block token for a specified user */
  public Token<BlockTokenIdentifier> generateToken(String userId,
      ExtendedBlock block, EnumSet<BlockTokenIdentifier.AccessMode> modes) throws IOException {
    // 将block相关信息,用户信息,访问模式信息设置入对象中,并返回
    BlockTokenIdentifier id = new BlockTokenIdentifier(userId, block
        .getBlockPoolId(), block.getBlockId(), modes);
    return new Token<BlockTokenIdentifier>(id, this);
  }

blockToken在创建block块的时候,会被构建

  private LocatedBlock createLocatedBlock(final BlockInfo blk, final long pos,
    final AccessMode mode) throws IOException {
    final LocatedBlock lb = createLocatedBlock(blk, pos);
    // 设置blockToken
    if (mode != null) {
      setBlockToken(lb, mode);
    }
    return lb;
  }

进入setBlockToken方法

  public void setBlockToken(final LocatedBlock b,
      final AccessMode mode) throws IOException {
    // 如果开启了BlockToken验证功能
    if (isBlockTokenEnabled()) {
      // Use cached UGI if serving RPC calls.
      if (b.isStriped()) {
        Preconditions.checkState(b instanceof LocatedStripedBlock);
        LocatedStripedBlock sb = (LocatedStripedBlock) b;
        byte[] indices = sb.getBlockIndices();
        Token<BlockTokenIdentifier>[] blockTokens = new Token[indices.length];
        ExtendedBlock internalBlock = new ExtendedBlock(b.getBlock());
        for (int i = 0; i < indices.length; i++) {
          internalBlock.setBlockId(b.getBlock().getBlockId() + indices[i]);
          // 生成blockToken对象
          blockTokens[i] = blockTokenSecretManager.generateToken(
              NameNode.getRemoteUser().getShortUserName(),
              internalBlock, EnumSet.of(mode));
        }
        sb.setBlockTokens(blockTokens);
      } else {
        // // 生成blockToken对象并设置到block中
        b.setBlockToken(blockTokenSecretManager.generateToken(
            NameNode.getRemoteUser().getShortUserName(),
            b.getBlock(), EnumSet.of(mode)));
      }
    }    
  }

这就是blockToken从产

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值