在 HBase 客户端和服务器进程和网关之间配置安全身份验证后,您需要考虑数据本身的安全性。 HBase 提供了几种保护数据的策略:

  • 基于角色的访问控制(RBAC)使用熟悉的角色范例控制哪些用户或组可以读取和写入给定的 HBase 资源或执行协处理器端点。

  • 可见性标签,允许您标记单元格并控制对标记单元格的访问,以进一步限制谁可以读取或写入数据的某些子集。可见性标签存储为标签。有关详细信息,请参阅 hbase.tags

  • 在 HFiles 和 WAL 中对底层文件系统上的静态数据进行透明加密。这可以保护您的静态数据免受可以访问底层文件系统的攻击者的攻击,而无需更改客户端的实现。它还可以防止来自不正确处理的磁盘的数据泄漏,这对于法律和法规合规性而言非常重要。

下面讨论每个功能的服务器端配置,管理和实现细节,以及任何性能权衡。最后给出了一个示例安全配置,以显示所有这些功能一起使用,因为它们可能位于真实场景中。

HBase 的所有安全方面都在积极发展并迅速发展。您应采用任何策略来保护数据的安全性。此外,其中一些功能仍处于开发的实验阶段。要利用其中的许多功能,您必须运行 HBase 0.98+并使用 HFile v3 文件格式。

保护敏感文件

本节中的几个过程要求您在群集节点之间复制文件。复制密钥,配置文件或包含敏感字符串的其他文件时,请使用安全方法(如ssh)以避免泄露敏感数据。

过程:基本服务器端配置

  1. 通过在 hbase-site.xml 中将hfile.format.version设置为 3 来启用 HFile v3。这是 HBase 1.0 和更新版本的默认值。

    <property>
      <name>hfile.format.version</name>
      <value>3</value>
    </property> 
    
  2. 为 RPC 和 ZooKeeper 启用 SASL 和 Kerberos 身份验证,如 security.prerequisitesSASL 身份验证与 ZooKeeper 中所述。

64.1。标签

_ 标签 _ 是 HFile v3 的一个功能。标记是一段元数据,它是单元格的一部分,与键,值和版本分开。标签是一个实现细节,为其他与安全相关的功能(如单元级 ACL 和可见性标签)提供基础。标签存储在 HFiles 本身中。将来,标签可能会用于实现其他 HBase 功能。您不需要了解很多关于标签的信息,以便使用它们启用的安全功能。

64.1.1。实施细节

每个单元格可以包含零个或多个标记。每个标记都有一个类型和实际的标记字节数组。

就像可以对行键,列族,限定符和值进行编码一样(参见 data.block.encoding.types ),也可以对标记进行编码。您可以在列族的级别启用或禁用标记编码,默认情况下启用它。使用HColumnDescriptor#setCompressionTags(boolean compressTags)方法管理列族的编码设置。您还需要为列族启用 DataBlockEncoder,以使标记的编码生效。

如果还启用了 WAL 压缩,则可以通过在 hbase-site.xml 中将hbase.regionserver.wal.tags.enablecompression的值设置为true来启用 WAL 中每个标记的压缩。标签压缩使用字典编码。

在 RegionServers 上运行服务器端的协处理器可以对单元标记执行 get 和 set 操作。在发送读取响应之前,标记在 RPC 层被剥离,因此客户端不会看到这些标记。使用 WAL 加密时不支持标记压缩。

64.2。访问控制标签(ACL)

64.2.1。这个怎么运作

HBase 中的 ACL 基于用户在组中的成员资格或从组中排除,以及给定组访问给定资源的权限。 ACL 实现为名为 AccessController 的协处理器。

HBase 不维护专用组映射,但依赖于 _Hadoop 组映射器 _,它映射目录(如 LDAP 或 Active Directory)和 HBase 用户之间的实体。任何受支持的 Hadoop 组映射器都可以使用。然后,用户将被授予针对资源(全局,名称空间,表,单元或端点)的特定权限(读取,写入,执行,创建,管理)。

启用 Kerberos 和访问控制后,将对 HBase 的客户端访问进行身份验证,并且除非已明确授予访问权限,否则用户数据将为私有。

HBase 比关系数据库具有更简单的安全模型,尤其是在客户端操作方面。例如,插入(新记录)和更新(现有记录)之间没有区别,因为两者都折叠为 Put。

了解访问级别

HBase 访问级别彼此独立地授予,并允许在给定范围内的不同类型的操作。

  • Read(R) - 可以读取给定范围内的数据

  • _ 写(W)_ - 可以在给定范围内写入数据

  • _ 执行(X)_ - 可以在给定范围内执行协处理器端点

  • Create(C) - 可以在给定范围内创建表或删除表(甚至是那些他们没有创建的表)

  • Admin(A) - 可以执行集群操作,例如平衡集群或在给定范围内分配区域

可能的范围是:

  • _ 超级用户 _ - 超级用户可以在任何资源上执行 HBase 中可用的任何操作。在群集上运行 HBase 的用户是超级用户,分配给 HMaster 上 hbase-site.xml 中的配置属性hbase.superuser的任何主体也是如此。

  • Global - 在 global 范围内授予的权限允许管理员在集群的所有表上运行。

  • _ 命名空间 _ - 在 _ 命名空间 _ 范围内授予的权限适用于给定命名空间内的所有表。

  • _ 表 _ - 在 _ 表 _ 范围内授予的权限适用于给定表中的数据或元数据。

  • ColumnFamily - 在 ColumnFamily 范围内授予的权限适用于该 ColumnFamily 中的单元格。

  • Cell - 在 _ 单元格 _ 范围内授予的权限适用于该确切的单元格坐标(键,值,时间戳)。这允许政策演变以及数据。

    要更改特定单元格上的 ACL,请使用新 ACL 将更新的单元格写入原始的精确坐标。

    如果您具有多版本架构并且想要更新所有可见版本上的 ACL,则需要为所有可见版本编写新单元。该应用程序完全控制政策演变。

    上述规则的例外是appendincrement处理。附加和增量可以在操作中携带 ACL。如果操作中包含一个,则它将应用于appendincrement的结果。否则,将保留要附加或递增的现有单元格的 ACL。

访问级别和范围的组合创建了可以授予用户的可能访问级别的矩阵。在生产环境中,根据执行特定工作所需的内容来考虑访问级别很有用。以下列表描述了一些常见类型的 HBase 用户的适当访问级别。重要的是不要授予比给定用户执行所需任务所需的访问权限更多的访问权限。

  • _ 超级用户 _ - 在生产系统中,只有 HBase 用户应具有超级用户访问权限。在开发环境中,管理员可能需要超级用户访问权限才能快速控制和管理群集。但是,这种类型的管理员通常应该是全局管理员而不是超级用户。

  • _ 全局管理员 _ - 全局管理员可以执行任务并访问 HBase 中的每个表。在典型的生产环境中,管理员不应对表中的数据具有读取或写入权限。

  • 具有管理员权限的全局管理员可以在群集上执行群集范围的操作,例如平衡,分配或取消分配区域,或调用显式主要压缩。这是一个操作角色。

  • 具有“创建”权限的全局管理员可以在 HBase 中创建或删除任何表。这更像是 DBA 类型的角色。

    在生产环境中,不同用户可能只拥有管理员和创建权限之一。

    | |

    在当前实现中,具有Admin权限的全局管理员可以在表上授予自己ReadWrite权限,并获得对该表数据的访问权限。因此,仅向实际需要它们的受信任用户授予Global Admin权限。

    另请注意,具有Create权限的Global Admin可以对 ACL 表执行Put操作,模拟grantrevoke并绕过Global Admin权限的授权检查。

    由于这些问题,请谨慎授予Global Admin权限。

    |

  • _ 命名空间管理员 _ - 具有Create权限的命名空间管理员可以在该命名空间内创建或删除表,并获取和恢复快照。具有Admin权限的命名空间管理员可以对该命名空间中的表执行拆分或主要压缩等操作。

  • _ 表管理员 _ - 表管理员只能对该表执行管理操作。具有Create权限的表管理员可以从该表创建快照或从快照还原该表。具有Admin权限的表管理员可以对该表执行拆分或主要压缩等操作。

  • _ 用户 _ - 用户可以读取或写入数据,或两者兼而有之。如果给予Executable权限,用户还可以执行协处理器端点。

职称 范围 权限 描述
高级管理员 全球 访问,创建 管理群集并授予初级管理员访问权限。
初级管理员 Global 创建 创建表并提供对表管理员的访问权限。
表管理员 访问 从操作的角度维护表。
数据分析师 Table 从 HBase 数据创建报告。
Web 应用程序 Table 读,写 将数据放入 HBase 并使用 HBase 数据执行操作。

ACL 矩阵

有关 ACL 如何映射到特定 HBase 操作和任务的更多详细信息,请参阅附录 acl 矩阵

实施细节

单元级 ACL 使用标签实现(参见标签)。要使用单元级 ACL,您必须使用 HFile v3 和 HBase 0.98 或更高版本。

  1. HBase 创建的文件由运行 HBase 进程的操作系统用户拥有。要与 HBase 文件进行交互,您应该使用 API​​或批量加载工具。

  2. HBase 不会在 HBase 内部模拟“角色”。相反,可以为组名授予权限。这允许通过组成员身份对角色进行外部建模。通过 Hadoop 组映射服务在 HBase 外部创建和操作组。

服务器端配置
  1. 作为先决条件,执行过程:基本服务器端配置中的步骤。

  2. 通过在 hbase-site.xml 中设置以下属性来安装和配置 AccessController 协处理器。这些属性采用类列表。

    > 如果将 AccessController 与 VisibilityController 一起使用,则 AccessController 必须位于列表的第一位,因为两个组件都处于活动状态,VisibilityController 会将其系统表的访问控制委托给 AccessController。有关同时使用两者的示例,请参见安全配置示例

    <property>
      <name>hbase.security.authorization</name>
      <value>true</value>
    </property>
    <property>
      <name>hbase.coprocessor.region.classes</name>
      <value>org.apache.hadoop.hbase.security.access.AccessController, org.apache.hadoop.hbase.security.token.TokenProvider</value>
    </property>
    <property>
      <name>hbase.coprocessor.master.classes</name>
      <value>org.apache.hadoop.hbase.security.access.AccessController</value>
    </property>
    <property>
      <name>hbase.coprocessor.regionserver.classes</name>
      <value>org.apache.hadoop.hbase.security.access.AccessController</value>
    </property>
    <property>
      <name>hbase.security.exec.permission.checks</name>
      <value>true</value>
    </property> 
    

    (可选)您可以通过将hbase.rpc.protection设置为privacy来启用传输安全性。这需要 HBase 0.98.4 或更高版本。

  3. 在 Hadoop namenode 的 core-site.xml 中设置 Hadoop 组映射器。这是一个 Hadoop 文件,而不是 HBase 文件。根据您网站的需求进行自定义。以下是一个例子。

    <property>
      <name>hadoop.security.group.mapping</name>
      <value>org.apache.hadoop.security.LdapGroupsMapping</value>
    </property>
    
    <property>
      <name>hadoop.security.group.mapping.ldap.url</name>
      <value>ldap://server</value>
    </property>
    
    <property>
      <name>hadoop.security.group.mapping.ldap.bind.user</name>
      <value>Administrator@example-ad.local</value>
    </property>
    
    <property>
      <name>hadoop.security.group.mapping.ldap.bind.password</name>
      <value>****</value>
    </property>
    
    <property>
      <name>hadoop.security.group.mapping.ldap.base</name>
      <value>dc=example-ad,dc=local</value>
    </property>
    
    <property>
      <name>hadoop.security.group.mapping.ldap.search.filter.user</name>
      <value>(&(objectClass=user)(sAMAccountName={0}))</value>
    </property>
    
    <property>
      <name>hadoop.security.group.mapping.ldap.search.filter.group</name>
      <value>(objectClass=group)</value>
    </property>
    
    <property>
      <name>hadoop.security.group.mapping.ldap.search.attr.member</name>
      <value>member</value>
    </property>
    
    <property>
      <name>hadoop.security.group.mapping.ldap.search.attr.group.name</name>
      <value>cn</value>
    </property> 
    
  4. (可选)启用早期评估策略。在 HBase 0.98.0 之前,如果未授予用户访问列族或至少列限定符的权限,则会抛出 AccessDeniedException。 HBase 0.98.0 删除了此异常,以便允许单元级别的特殊授权。要恢复 HBase 0.98.0-0.98.6 中的旧行为,请在 hbase-site.xml 中将hbase.security.access.early_out设置为true。在 HBase 0.98.6 中,默认值已返回到true

  5. 分发配置并重新启动群集以使更改生效。

  6. 要测试您的配置,请以给定用户身份登录 HBase Shell,并使用whoami命令报告您的用户所属的组。在此示例中,用户被报告为services组的成员。

    hbase> whoami
    service (auth:KERBEROS)
        groups: services 
    
管理

管理任务可以从 HBase Shell 或通过 API 执行。

API 示例

下面的许多 API 示例都来自源文件 hbase-server / src / test / java / org / apache / hadoop / hbase / security / access / TestAccessController.javahbase-server / src / test / java / org / apache / hadoop / hbase / security / access / SecureTestUtil.java

这些示例以及它们的源文件都不是公共 HBase API 的一部分,仅供参考。有关使用说明,请参阅官方 API。

  1. 用户和组管理

    用户和组在您的目录中维护在 HBase 外部。

  2. 授予对命名空间,表,列族或单元格的访问权限

    grant 语句有几种不同类型的语法。第一个,也是最熟悉的,如下所示,表和列族是可选的:

    grant 'user', 'RWXCA', 'TABLE', 'CF', 'CQ' 
    

    组和用户以相同的方式被授予访问权限,但组的前缀为@符号。同样,表和名称空间以相同的方式指定,但名称空间以@符号为前缀。

    也可以在单个语句中为同一资源授予多个权限,如本示例所示。第一个子句将用户映射到 ACL,第二个子子句指定资源。

    > HBase Shell 支持在单元级别授予和撤销访问权限,用于测试和验证支持,不应用于生产用途,因为它不会将权限应用于尚不存在的单元格。应用单元级权限的正确方法是在存储值时在应用程序代码中执行此操作。

    ACL 粒度和评估顺序

    ACL 从最小粒度到最细粒度进行评估,当达到授予权限的 ACL 时,评估将停止。这意味着单元 ACL 不会以较小的粒度覆盖 ACL。

    例 14. HBase Shell

    • 全球:

      hbase> grant '@admins', 'RWXCA' 
      
    • 命名空间:

      hbase> grant 'service', 'RWXCA', '@test-NS' 
      
    • 表:

      hbase> grant 'service', 'RWXCA', 'user' 
      
    • 专栏系列:

      hbase> grant '@developers', 'RW', 'user', 'i' 
      
    • 列限定符:

      hbase> grant 'service, 'RW', 'user', 'i', 'foo' 
      
    • 细胞:

      授予单元 ACL 的语法使用以下语法:

      grant <table>, \
        { '<user-or-group>' => \
          '<permissions>', ... }, \
        { <scanner-specification> } 
      
    • 是用户名或组名,如果是组,则以@为前缀。

    • 是包含任何或所有“RWXCA”的字符串,但只有 R 和 W 在细胞范围内有意义。

    • <scanner-specification></scanner-specification> 是'scan'hell 命令使用的扫描器规范语法和约定。有关扫描程序规范的一些示例,请发出以下 HBase Shell 命令。

      hbase&gt; help "scan" 
      

      如果需要启用 cell acl,则 hbase-site.xml 中的 hfile.format.version 选项应大于或等于 3,并且 hbase.security.access.early_out 选项应设置为 false。此示例授予读取权限访问“testuser”用户以及“pii”列中与过滤器匹配的单元格上的“开发人员”组的读/写访问权限。

      hbase&gt; grant 'user', \
        { '@developers' =&gt; 'RW', 'testuser' =&gt; 'R' }, \
        { COLUMNS =&gt; 'pii', FILTER =&gt; "(PrefixFilter ('test'))" } 
      

      shell 将运行具有给定条件的扫描程序,使用新 ACL 重写找到的单元格,并将它们存储回其精确坐标。

    例 15. API

    以下示例显示如何在表级别授予访问权限。

    public static void grantOnTable(final HBaseTestingUtility util, final String user,
        final TableName table, final byte[] family, final byte[] qualifier,
        final Permission.Action... actions) throws Exception {
      SecureTestUtil.updateACLs(util, new Callable&lt;Void&gt;() {
        @Override
        public Void call() throws Exception {
          try (Connection connection = ConnectionFactory.createConnection(util.getConfiguration());
               Table acl = connection.getTable(AccessControlLists.ACL_TABLE_NAME)) {
            BlockingRpcChannel service = acl.coprocessorService(HConstants.EMPTY_START_ROW);
            AccessControlService.BlockingInterface protocol =
              AccessControlService.newBlockingStub(service);
            AccessControlUtil.grant(null, protocol, user, table, family, qualifier, false, actions);
          }
          return null;
        }
      });
    } 
    

    要在单元级别授予权限,可以使用Mutation.setACL方法:

    Mutation.setACL(String user, Permission perms)
    Mutation.setACL(Map&lt;String, Permission&gt; perms) 
    

    具体来说,此示例为特定 Put 操作中包含的任何单元格上的user1用户提供读取权限:

    put.setACL(“user1”, new Permission(Permission.Action.READ)) 
    
  3. 从命名空间,表,列系列或单元格撤消访问控制

    revoke命令和 API 是 grant 命令和 API 的双胞胎,语法完全相同。唯一的例外是您无法在单元级别撤消权限。您只能撤消先前已授予的访问权限,并且revoke语句与显式拒绝资源不同。

    > HBase Shell 对授予和撤销访问权限的支持用于测试和验证支持,不应用于生产用途,因为它不会将权限应用于尚不存在的单元格。应用单元级权限的正确方法是在存储值时在应用程序代码中执行此操作。

    示例 16.撤销对表的访问

    public static void revokeFromTable(final HBaseTestingUtility util, final String user,
        final TableName table, final byte[] family, final byte[] qualifier,
        final Permission.Action... actions) throws Exception {
      SecureTestUtil.updateACLs(util, new Callable&lt;Void&gt;() {
        @Override
        public Void call() throws Exception {
          Configuration conf = HBaseConfiguration.create();
          Connection connection = ConnectionFactory.createConnection(conf);
          Table acl = connection.getTable(util.getConfiguration(), AccessControlLists.ACL_TABLE_NAME);
          try {
            BlockingRpcChannel service = acl.coprocessorService(HConstants.EMPTY_START_ROW);
            AccessControlService.BlockingInterface protocol =
                AccessControlService.newBlockingStub(service);
            ProtobufUtil.revoke(protocol, user, table, family, qualifier, actions);
          } finally {
            acl.close();
          }
          return null;
        }
      });
    } 
    
  4. 显示用户的有效权限

    HBase Shell

    hbase&gt; user_permission 'user'
    
    hbase&gt; user_permission '.*'
    
    hbase&gt; user_permission JAVA_REGEX 
    

例 17. API

public static void verifyAllowed(User user, AccessTestAction action, int count) throws Exception {
  try {
    Object obj = user.runAs(action);
    if (obj != null && obj instanceof List<?>) {
      List<?> results = (List<?>) obj;
      if (results != null && results.isEmpty()) {
        fail("Empty non null results from action for user '" ` user.getShortName() ` "'");
      }
      assertEquals(count, results.size());
    }
  } catch (AccessDeniedException ade) {
    fail("Expected action to pass for user '" ` user.getShortName() ` "' but was denied");
  }
} 

64.3。可见性标签

可见性标签控件可用于仅允许与给定标签关联的用户或主体读取或访问具有该标签的单元。例如,您可以标记单元格top-secret,并仅将该标签的访问权限授予managers组。可见性标签使用标签实现,标签是 HFile v3 的一项功能,允许您按单元格存储元数据。标签是一个字符串,标签可以通过使用逻辑运算符(&amp;,|或!)并使用括号进行分组来组合成表达式。 HBase 不会对基本格式良好的表达式进行任何形式的验证。可见性标签本身没有任何意义,可用于表示敏感度级别,权限级别或任何其他任意语义含义。

如果用户的标签与单元格的标签或表达式不匹配,则拒绝用户访问该单元格。

在 HBase 0.98.6 及更新版本中,可见性标签和表达式支持 UTF-8 编码。使用org.apache.hadoop.hbase.security.visibility.VisibilityClient类提供的addLabels(conf, labels)方法创建标签并通过 Scan 或 Get 在 Authorizations 中传递标签时,标签可以包含 UTF-8 字符,以及通常在可见性标签中使用的逻辑运算符,具有普通的 Java 表示法,无需任何转义方法。但是,当您通过 Mutation 传递 CellVisibility 表达式时,如果使用 UTF-8 字符或逻辑运算符,则必须使用CellVisibility.quote()方法将表达式括起来。参见TestExpressionParser和源文件 hbase-client / src / test / java / org / apache / hadoop / hbase / client / TestScan.java

用户在 Put 操作期间向单元格添加可见性表达式。在默认配置中,用户无需访问标签即可使用标签标记单元格。此行为由配置选项hbase.security.visibility.mutations.checkauths控制。如果将此选项设置为true,则用户正在修改的标签必须与用户关联,否则突变将失败。在获取或扫描期间确定用户是否被授权读取标记的单元格,并且过滤掉用户不被允许读取的结果。这会导致相同的 I / O 损失,就像返回结果一样,但会降低网络负载。

在删除操作期间也可以指定可见性标签。有关可见性标签和删除的详细信息,请参阅 HBASE-10885

当 RegionServer 首次收到请求时,用户的有效标签集将构建在 RPC 上下文中。用户与标签关联的方式是可插入的。默认插件通过添加到“获取”或“扫描”的“授权”中指定的标签,并根据主叫用户的经过身份验证的标签列表检查这些标签。当客户端传递未对用户进行身份验证的标签时,默认插件会删除它们。您可以通过Get#setAuthorizations(Authorizations(String,…​))Scan#setAuthorizations(Authorizations(String,…​));方法传递用户身份验证标签的子集。

可以以与用户相同的方式向组授予可见性标签。组以@符号为前缀。在检查用户的可见性标签时,服务器将包括用户所属的组的可见性标签以及用户自己的标签。当使用 API​​ VisibilityClient#getAuths或 Shell 命令get_auths为用户检索可见性标签时,我们将返回专门为该用户添加的标签,而不是组级标签。

可见性标签访问检查由 VisibilityController 协处理器执行。您可以使用接口VisibilityLabelService提供自定义实现和/或控制可见性标签与单元格一起存储的方式。有关示例,请参阅源文件 hbase-server / src / test / java / org / apache / hadoop / hbase / security / visibility / TestVisibilityLabelsWithCustomVisLabService.java

可见性标签可与 ACL 一起使用。

必须先明确定义标签,然后才能在可见性标签中使用它们。请参阅下面的示例,了解如何执行此操作。

目前无法确定哪些标签已应用于单元格。有关详细信息,请参见 HBASE-12470

可见性标签目前不适用于超级用户。

表达 解释
fulltime 

|允许访问与全时标签关联的用户。 | |

!public 

|允许访问与公共标签无关的用户。 | |

( secret &#124; topsecret ) & !probationary 

|允许访问与 secret 或 topsecret 标签关联且与试用标签无关的用户。 |

64.3.1。服务器端配置

  1. As a prerequisite, perform the steps in Procedure: Basic Server-Side Configuration.

  2. 通过在 hbase-site.xml 中设置以下属性来安装和配置 VisibilityController 协处理器。这些属性采用类名列表。

    &lt;property&gt;
      &lt;name&gt;hbase.security.authorization&lt;/name&gt;
      &lt;value&gt;true&lt;/value&gt;
    &lt;/property&gt;
    &lt;property&gt;
      &lt;name&gt;hbase.coprocessor.region.classes&lt;/name&gt;
      &lt;value&gt;org.apache.hadoop.hbase.security.visibility.VisibilityController&lt;/value&gt;
    &lt;/property&gt;
    &lt;property&gt;
      &lt;name&gt;hbase.coprocessor.master.classes&lt;/name&gt;
      &lt;value&gt;org.apache.hadoop.hbase.security.visibility.VisibilityController&lt;/value&gt;
    &lt;/property&gt; 
    

    > 如果同时使用 AccessController 和 VisibilityController 协处理器,则 AccessController 必须位于列表的第一位,因为两个组件都处于活动状态,VisibilityController 会将其系统表的访问控制委托给 AccessController。

  3. 调整配置

    默认情况下,用户可以使用任何标签标记单元格,包括与之无关的标签,这意味着用户可以放置他无法读取的数据。例如,即使用户未与该标签相关联,用户也可以用(假设的)'topsecret'标签标记单元格。如果您只希望用户能够使用与之关联的标签标记单元格,请将hbase.security.visibility.mutations.checkauths设置为true。在这种情况下,如果使用与用户无关的标签,则突变将失败。

  4. Distribute your configuration and restart your cluster for changes to take effect.

64.3.2。管理

可以使用 HBase Shell 或 Java API 执行管理任务。为了定义可见性标签列表并将标签与用户关联,HBase Shell 可能更简单。

API Examples

本节中的许多 Java API 示例都来自源文件 hbase-server / src / test / java / org / apache / hadoop / hbase / security / visibility / TestVisibilityLabels.java 。有关更多上下文,请参阅该文件或 API 文档。

这些示例以及它们的源文件都不是公共 HBase API 的一部分,仅供参考。有关使用说明,请参阅官方 API。

  1. 定义可见性标签列表

    HBase Shell

    hbase&gt; add_labels [ 'admin', 'service', 'developer', 'test' ] 
    

    示例 18. Java API

    public static void addLabels() throws Exception {
      PrivilegedExceptionAction&lt;VisibilityLabelsResponse&gt; action = new PrivilegedExceptionAction&lt;VisibilityLabelsResponse&gt;() {
        public VisibilityLabelsResponse run() throws Exception {
          String[] labels = { SECRET, TOPSECRET, CONFIDENTIAL, PUBLIC, PRIVATE, COPYRIGHT, ACCENT,
              UNICODE_VIS_TAG, UC1, UC2 };
          try {
            VisibilityClient.addLabels(conf, labels);
          } catch (Throwable t) {
            throw new IOException(t);
          }
          return null;
        }
      };
      SUPERUSER.runAs(action);
    } 
    
  2. 将标签与用户关联

    HBase Shell

    hbase&gt; set_auths 'service', [ 'service' ] 
    
hbase> set_auths 'testuser', [ 'test' ] 
hbase> set_auths 'qa', [ 'test', 'developer' ] 
hbase> set_auths '@qagroup', [ 'test' ] 
  • .Java API
public void testSetAndGetUserAuths() throws Throwable {
  final String user = "user1";
  PrivilegedExceptionAction<Void> action = new PrivilegedExceptionAction<Void>() {
    public Void run() throws Exception {
      String[] auths = { SECRET, CONFIDENTIAL };
      try {
        VisibilityClient.setAuths(conf, auths, user);
      } catch (Throwable e) {
      }
      return null;
    }
    ... 
  1. 清除用户标签

    HBase Shell

    hbase&gt; clear_auths 'service', [ 'service' ] 
    
hbase> clear_auths 'testuser', [ 'test' ] 
hbase> clear_auths 'qa', [ 'test', 'developer' ] 
hbase> clear_auths '@qagroup', [ 'test', 'developer' ] 
  • .Java API
...
auths = new String[] { SECRET, PUBLIC, CONFIDENTIAL };
VisibilityLabelsResponse response = null;
try {
  response = VisibilityClient.clearAuths(conf, auths, user);
} catch (Throwable e) {
  fail("Should not have failed");
  ...
} 
  1. 将标签或表达式应用于单元格

    标签仅在写入数据时应用。标签与给定版本的单元格相关联。

    HBase Shell

    hbase&gt; set_visibility 'user', 'admin|service|developer', { COLUMNS =&gt; 'i' } 
    
hbase> set_visibility 'user', 'admin|service', { COLUMNS => 'pii' } 
hbase> set_visibility 'user', 'test', { COLUMNS => [ 'i', 'pii' ], FILTER => "(PrefixFilter ('test'))" } 
  • 注意:HBase Shell 支持对单元格应用标签或权限,用于测试和验证支持,不应用于生产用途,因为它不会将标签应用于尚不存在的单元格。应用单元格级别标签的正确方法是在存储值时在应用程序代码中执行此操作。

  • .Java API

static Table createTableAndWriteDataWithLabels(TableName tableName, String... labelExps)
    throws Exception {
  Configuration conf = HBaseConfiguration.create();
  Connection connection = ConnectionFactory.createConnection(conf);
  Table table = NULL;
  try {
    table = TEST_UTIL.createTable(tableName, fam);
    int i = 1;
    List<Put> puts = new ArrayList<Put>();
    for (String labelExp : labelExps) {
      Put put = new Put(Bytes.toBytes("row" + i));
      put.add(fam, qual, HConstants.LATEST_TIMESTAMP, value);
      put.setCellVisibility(new CellVisibility(labelExp));
      puts.add(put);
      i++;
    }
    table.put(puts);
  } finally {
    if (table != null) {
      table.flushCommits();
    }
  } 

64.3.3。用标签读取单元格

当您发出扫描或获取时,HBase 使用您的默认授权集来过滤掉您无权访问的单元格。超级用户可以使用set_auths HBase Shell 命令或 VisibilityClient.setAuths()方法为给定用户设置默认授权集。

您可以在扫描或获取期间通过传递 HBase Shell 中的 AUTHORIZATIONS 选项或 Scan.setAuthorizations()方法(如果使用 API​​)指定其他授权。此授权将与您的默认设置组合作为附加过滤器。它将进一步过滤您的结果,而不是给您额外的授权。

HBase Shell

hbase> get_auths 'myUser'
hbase> scan 'table1', AUTHORIZATIONS => ['private'] 

示例 19. Java API

...
public Void run() throws Exception {
  String[] auths1 = { SECRET, CONFIDENTIAL };
  GetAuthsResponse authsResponse = null;
  try {
    VisibilityClient.setAuths(conf, auths1, user);
    try {
      authsResponse = VisibilityClient.getAuths(conf, user);
    } catch (Throwable e) {
      fail("Should not have failed");
    }
  } catch (Throwable e) {
  }
  List<String> authsList = new ArrayList<String>();
  for (ByteString authBS : authsResponse.getAuthList()) {
    authsList.add(Bytes.toString(authBS.toByteArray()));
  }
  assertEquals(2, authsList.size());
  assertTrue(authsList.contains(SECRET));
  assertTrue(authsList.contains(CONFIDENTIAL));
  return null;
}
... 

64.3.4。实现您自己的可见性标签算法

解释为给定的 get / scan 请求验证的标签是可插入的算法。

您可以使用属性hbase.regionserver.scan.visibility.label.generator.class指定自定义插件或插件。第一个ScanLabelGenerator的输出将是下一个的输出,直到列表的结尾。

HBASE-12466 中实现的默认实现加载了两个插件,FeedUserAuthScanLabelGeneratorDefinedSetFilterScanLabelGenerator。参见用标签读取细胞

64.3.5。将可见性标记复制为字符串

如上面部分所述,接口VisibilityLabelService可用于实现在单元格中存储可见性表达式的不同方式。启用了复制的群集还必须将可见性表达式复制到对等群集。如果DefaultVisibilityLabelServiceImpl用作VisibilityLabelService的实现,则所有可见性表达式将根据存储在标签表中的每个可见性标签的序数转换为相应的表达式。在复制期间,可见细胞也复制,基于序数的表达完整。对等群集可能没有相同的labels表,其可见性标签具有相同的序数映射。在这种情况下,复制序数是没有意义的。如果复制发生在将可见性表达式作为字符串传输的情况下会更好。要将可见性表达式作为字符串复制到对等集群,请创建RegionServerObserver配置,该配置基于VisibilityLabelService接口的实现而工作。下面的配置允许将可见性表达式作为字符串复制到对等集群。更多详细信息,请参见 HBASE-11639

<property>
  <name>hbase.security.authorization</name>
  <value>true</value>
</property>
<property>
  <name>hbase.coprocessor.regionserver.classes</name>
  <value>org.apache.hadoop.hbase.security.visibility.VisibilityController$VisibilityReplication</value>
</property> 

64.4。静态数据的透明加密

HBase 提供了一种机制,用于保护静态数据,HFiles 和 WAL,它们驻留在 HDFS 或其他分布式文件系统中。双层体系结构用于灵活且非侵入式的密钥轮换。 “透明”意味着客户端不需要进行任何实现更改。写入数据时,会对其进行加密。读取时,按需解密。

64.4.1。这个怎么运作

管理员为群集配置主密钥,该密钥存储在每个受信任的 HBase 进程可访问的密钥提供程序中,包括管理工作站上的 HMaster,RegionServers 和客户端(如 HBase Shell)。默认密钥提供程序与 Java KeyStore API 以及支持它的任何密钥管理系统集成在一起。其他自定义密钥提供程序实现是可能密钥检索机制在 hbase-site.xml 配置文件中配置。主密钥可以存储在集群服务器上,受安全 KeyStore 文件保护,或者存储在外部密钥服务器上,或者存储在硬件安全模块中。 HBase 进程通过配置的密钥提供程序根据需要解析此主密钥。

接下来,可以在每个列族的模式中指定加密使用,方法是创建或修改列描述符以包含两个附加属性:要使用的加密算法的名称(当前仅支持“AES”),还可以选择数据密钥使用群集主密钥包装(加密)。如果没有为 ColumnFamily 显式配置数据密钥,HBase 将为每个 HFile 创建一个随机数据密钥。这提供了替代方案的安全性的逐步改进。除非您需要提供显式数据密钥,例如在使用给定数据密钥生成用于批量导入的加密 HFile 的情况下,否则仅在 ColumnFamily 模式元数据中指定加密算法,并让 HBase 按需创建数据密钥。每列族键有助于低影响增量键旋转,并减少关键材料的任何外部泄漏范围。包装的数据密钥存储在 ColumnFamily 模式元数据中,并存储在列系列的每个 HFile 中,使用集群主密钥加密。在列系列配置为加密后,任何新的 HFile 都将被加密写入。要确保加密所有 HFile,请在启用此功能后触发主要压缩。

当 HFile 打开时,数据密钥从 HFile 中提取,用集群主密钥解密,并用于解密 HFile 的其余部分。如果主密钥不可用,HFile 将无法读取。如果远程用户以某种方式获得对 HFile 数据的访问,因为 HDFS 权限有所失效,或者来自不适当的丢弃媒体,则无法解密数据密钥或文件数据。

也可以加密 WAL。即使 WAL 是瞬态的,在基础文件系统受到损害的情况下,有必要加密 WALEdits 以避免绕过加密列族的 HFile 保护。启用 WAL 加密后,无论相关的 HFile 是否加密,所有 WAL 都会被加密。

64.4.2。服务器端配置

此过程假定您使用的是默认的 Java 密钥库实现。如果您使用的是自定义实现,请检查其文档并进行相应调整。

  1. 使用keytool实用程序为 AES 加密创建适当长度的密钥。

    $ keytool -keystore /path/to/hbase/conf/hbase.jks \
      -storetype jceks -storepass **** \
      -genseckey -keyalg AES -keysize 128 \
      -alias &lt;alias&gt; 
    

    ** 替换为密钥库文件的密码,将<alias>替换为 HBase 服务帐户的用户名或任意字符串。如果使用任意字符串,则需要配置 HBase 才能使用它,如下所述。指定适当的密钥大小。不要为密钥指定单独的密码,但在出现提示时按<kbd>返回</kbd>。</alias>

  2. 在密钥文件上设置适当的权限,并将其分发给所有 HBase 服务器。

    上一个命令在 HBase conf / 目录中创建了一个名为 hbase.jks 的文件。设置此文件的权限和所有权,以便只有 HBase 服务帐户用户可以读取该文件,并将密钥安全地分发给所有 HBase 服务器。

  3. 配置 HBase 守护进程。

    在区域服务器上的 hbase-site.xml 中设置以下属性,以配置 HBase 守护程序以使用由 KeyStore 文件支持的密钥提供程序或检索集群主密钥。在下面的示例中,用密码替换 **

    &lt;property&gt;
      &lt;name&gt;hbase.crypto.keyprovider&lt;/name&gt;
      &lt;value&gt;org.apache.hadoop.hbase.io.crypto.KeyStoreKeyProvider&lt;/value&gt;
    &lt;/property&gt;
    &lt;property&gt;
      &lt;name&gt;hbase.crypto.keyprovider.parameters&lt;/name&gt;
      &lt;value&gt;jceks:///path/to/hbase/conf/hbase.jks?password=****&lt;/value&gt;
    &lt;/property&gt; 
    

    默认情况下,HBase 服务帐户名称将用于解析群集主密钥。但是,您可以使用任意别名(在keytool命令中)存储它。在这种情况下,请将以下属性设置为您使用的别名。

    &lt;property&gt;
      &lt;name&gt;hbase.crypto.master.key.name&lt;/name&gt;
      &lt;value&gt;my-alias&lt;/value&gt;
    &lt;/property&gt; 
    

    您还需要确保您的 HFile 使用 HFile v3,以便使用透明加密。这是 HBase 1.0 以后的默认配置。对于以前的版本,请在 hbase-site.xml 文件中设置以下属性。

    &lt;property&gt;
      &lt;name&gt;hfile.format.version&lt;/name&gt;
      &lt;value&gt;3&lt;/value&gt;
    &lt;/property&gt; 
    

    (可选)您可以使用其他密码提供程序,Java Cryptography Encryption(JCE)算法提供程序或自定义 HBase 密码实现。

    • JCE:

      • 安装签名的 JCE 提供程序(支持 128 位密钥的AES/CTR/NoPadding模式)

      • 将它以最高优先级添加到 JCE 站点配置文件 _ $ JAVA HOME / lib / security / java.security

      • 更新 hbase-site.xml 中的hbase.crypto.algorithm.aes.providerhbase.crypto.algorithm.rng.provider选项。

    • 自定义 HBase 密码:

      • 实施org.apache.hadoop.hbase.io.crypto.CipherProvider

      • 将实现添加到服务器类路径。

      • 更新 hbase-site.xml 中的hbase.crypto.cipherprovider

  4. 配置 WAL 加密。

    通过设置以下属性,在每个 RegionServer 的 hbase-site.xml 中配置 WAL 加密。您也可以将这些包含在 HMaster 的 hbase-site.xml 中,但是 HMaster 没有 WAL 并且不会使用它们。

    &lt;property&gt;
      &lt;name&gt;hbase.regionserver.hlog.reader.impl&lt;/name&gt;
      &lt;value&gt;org.apache.hadoop.hbase.regionserver.wal.SecureProtobufLogReader&lt;/value&gt;
    &lt;/property&gt;
    &lt;property&gt;
      &lt;name&gt;hbase.regionserver.hlog.writer.impl&lt;/name&gt;
      &lt;value&gt;org.apache.hadoop.hbase.regionserver.wal.SecureProtobufLogWriter&lt;/value&gt;
    &lt;/property&gt;
    &lt;property&gt;
      &lt;name&gt;hbase.regionserver.wal.encryption&lt;/name&gt;
      &lt;value&gt;true&lt;/value&gt;
    &lt;/property&gt; 
    
  5. 配置 hbase-site.xml 文件的权限。

    由于密钥库密码存储在 hbase-site.xml 中,因此您需要确保只有 HBase 用户可以使用文件所有权和权限读取 hbase-site.xml 文件。

  6. 重新启动群集。

    将新配置文件分发到所有节点并重新启动群集。

64.4.3。管理

管理任务可以在 HBase Shell 或 Java API 中执行。

Java API

本节中的 Java API 示例取自源文件 hbase-server / src / test / java / org / apache / hadoop / hbase / util / TestHBaseFsckEncryption.java 。 。

这些示例以及它们的源文件都不是公共 HBase API 的一部分,仅供参考。有关使用说明,请参阅官方 API。

在列族上启用加密

要在列族上启用加密,可以使用 HBase Shell 或 Java API。启用加密后,触发主要压缩。当主要压缩完成时,HFiles 将被加密。

旋转数据键

要旋转数据键,首先更改列描述符中的 ColumnFamily 键,然后触发主要压缩。压缩完成后,将使用新数据密钥重新加密所有 HFile。在压缩完成之前,旧的 HFiles 仍然可以使用旧密钥读取。

在使用随机数据密钥和指定密钥之间切换

如果您将列族配置为使用特定键,并且希望返回使用该列系列的随机生成的键的默认行为,请使用 Java API 更改HColumnDescriptor,以便不会发送任何值。键ENCRYPTION_KEY

旋转万能钥匙

要旋转主密钥,请先生成并分发新密钥。然后更新 KeyStore 以包含新的主密钥,并使用不同的别名将旧主密钥保留在 KeyStore 中。接下来,配置回退到 hbase-site.xml 文件中的旧主密钥。

64.5。安全批量加载

安全模式下的批量加载比正常设置要多一些,因为客户端必须将 MapReduce 作业生成的文件的所有权转移到 HBase。安全批量加载由名为 SecureBulkLoadEndpoint 的协处理器实现,该协处理器使用由配置属性hbase.bulkload.staging.dir配置的暂存目录,默认为 / tmp / hbase-staging /

安全批量加载算法

  • 仅限一次,创建一个可由世界遍历并且由运行 HBase 的用户拥有的暂存目录(模式 711 或rwx—​x—​x)。此目录的列表将类似于以下内容:

    $ ls -ld /tmp/hbase-staging
    drwx--x--x  2 hbase  hbase  68  3 Sep 14:54 /tmp/hbase-staging 
    
  • 用户将数据写入该用户拥有的安全输出目录。例如, / user / foo / data

  • 在内部,HBase 创建一个全局可读/可写的秘密登台目录(-rwxrwxrwx, 777)。例如, / tmp / hbase-staging / averylongandrandomdirectoryname 。此目录的名称和位置不会向用户公开。 HBase 管理此目录的创建和删除。

  • 用户使数据具有全局可读性和全局可写性,将其移动到随机登台目录中,然后调用SecureBulkLoadClient#bulkLoadHFiles方法。

安全性的强度在于秘密目录的长度和随机性。

要启用安全批量加载,请将以下属性添加到 hbase-site.xml

<property>
  <name>hbase.security.authorization</name>
  <value>true</value>
</property>
<property>
  <name>hbase.bulkload.staging.dir</name>
  <value>/tmp/hbase-staging</value>
</property>
<property>
  <name>hbase.coprocessor.region.classes</name>
  <value>org.apache.hadoop.hbase.security.token.TokenProvider,
  org.apache.hadoop.hbase.security.access.AccessController,org.apache.hadoop.hbase.security.access.SecureBulkLoadEndpoint</value>
</property> 

64.6。安全启用

在 hbase-2.x 之后,默认的'hbase.security.authorization'发生了变化。在 hbase-2.x 之前,它默认为 true,在后来的 HBase 版本中,默认值为 false。因此,要启用 hbase 授权,必须在 hbase-site.xml 中配置以下属性。见 HBASE-19483 ;

<property>
  <name>hbase.security.authorization</name>
  <value>true</value>
</property>