# 保护 Apache HBase
> 报告安全漏洞
>
> 为了保护现有的 HBase 安装免受攻击,请**不要**使用 JIRA 报告与安全相关的错误。相反,将您的报告发送到邮件列表 [private@hbase.apache.org](mailto:private@hbase.apache.org) ,允许任何人发送邮件,但限制谁可以阅读它们。该列表中的某个人将与您联系以跟进您的报告。 |
>
> HBase 遵守 Apache Software Foundation 关于报告的漏洞的政策,可在 [http://apache.org/security/](http://apache.org/security/) 上找到。
>
> 如果您希望发送加密报告,可以使用为常规 ASF 安全列表提供的 GPG 详细信息。这可能会增加报告的响应时间。
HBase 提供了保护 HBase 的各种组件和方面的机制,以及它与 Hadoop 基础架构的其余部分以及 Hadoop 之外的客户端和资源的关系。
## 59.对 Web UI 使用安全 HTTP(HTTPS)
默认 HBase 安装为主服务器和区域服务器的 Web UI 使用不安全的 HTTP 连接。要改为启用安全 HTTP(HTTPS)连接,请在 _hbase-site.xml_ 中将`hbase.ssl.enabled`设置为`true`。这不会更改 Web UI 使用的端口。要更改给定 HBase 组件的 Web UI 端口,请在 hbase-site.xml 中配置该端口的设置。这些设置是:
* `hbase.master.info.port`
* `hbase.regionserver.info.port`
> 如果启用 HTTPS,则客户端应避免使用非安全 HTTP 连接。
>
> 如果启用安全 HTTP,客户端应使用`https://` URL 连接到 HBase。使用`http://` URL 的客户端将收到`200`的 HTTP 响应,但不会接收任何数据。记录以下异常:
>
> ```
> javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?
> ```
>
> 这是因为相同的端口用于 HTTP 和 HTTPS。
>
> HBase 将 Jetty 用于 Web UI。如果不修改 Jetty 本身,似乎不可能将 Jetty 配置为在同一主机上将一个端口重定向到另一个端口。有关更多信息,请参阅 Nick Dimiduk 对此 [Stack Overflow](http://stackoverflow.com/questions/20611815/redirect-from-http-to-https-in-jetty) 线程的贡献。如果您知道如何在不打开 HTTPS 的第二个端口的情况下解决这个问题,那么补丁将受到赞赏
## 60.使用 SPNEGO 进行 Web UI 的 Kerberos 身份验证
可以通过使用 _hbase-site.xml_ 中的`hbase.security.authentication.ui`属性配置 SPNEGO 来启用对 HBase Web UI 的 Kerberos 身份验证。启用此身份验证要求 HBase 还配置为对 RPC 使用 Kerberos 身份验证(例如`hbase.security.authentication` = `kerberos`)。
```
<property>
<name>hbase.security.authentication.ui</name>
<value>kerberos</value>
<description>Controls what kind of authentication should be used for the HBase web UIs.</description>
</property>
<property>
<name>hbase.security.authentication</name>
<value>kerberos</value>
<description>The Kerberos keytab file to use for SPNEGO authentication by the web server.</description>
</property>
```
存在许多用于为 Web 服务器配置 SPNEGO 身份验证的属性:
```
<property>
<name>hbase.security.authentication.spnego.kerberos.principal</name>
<value>HTTP/_HOST@EXAMPLE.COM</value>
<description>Required for SPNEGO, the Kerberos principal to use for SPNEGO authentication by the
web server. The _HOST keyword will be automatically substituted with the node's
hostname.</description>
</property>
<property>
<name>hbase.security.authentication.spnego.kerberos.keytab</name>
<value>/etc/security/keytabs/spnego.service.keytab</value>
<description>Required for SPNEGO, the Kerberos keytab file to use for SPNEGO authentication by the
web server.</description>
</property>
<property>
<name>hbase.security.authentication.spnego.kerberos.name.rules</name>
<value></value>
<description>Optional, Hadoop-style `auth_to_local` rules which will be parsed and used in the
handling of Kerberos principals</description>
</property>
<property>
<name>hbase.security.authentication.signature.secret.file</name>
<value></value>
<description>Optional, a file whose contents will be used as a secret to sign the HTTP cookies
as a part of the SPNEGO authentication handshake. If this is not provided, Java's `Random` library
will be used for the secret.</description>
</property>
```
## 61.安全客户端访问 Apache HBase
较新版本的 Apache HBase(&gt; = 0.92)支持客户端的可选 SASL 身份验证。另见 Matteo Bertozzi 关于[了解 Apache HBase 中用户认证和授权的文章](https://blog.cloudera.com/blog/2012/09/understanding-user-authentication-and-authorization-in-apache-hbase/)。
介绍如何设置 Apache HBase 和客户端以连接到安全的 HBase 资源。
### 61.1。先决条件
Hadoop 身份验证配置
要使用强身份验证运行 HBase RPC,必须将`hbase.security.authentication`设置为`kerberos`。在这种情况下,还必须在 core-site.xml 中将`hadoop.security.authentication`设置为`kerberos`。否则,您将对 HBase 使用强身份验证,但不会对底层 HDFS 使用强身份验证,这将取消任何好处。
Kerberos KDC
您需要有一个有效的 Kerberos KDC。
### 61.2。用于安全操作的服务器端配置
首先,请参阅 [security.prerequisites](#security.prerequisites) 并确保您的基础 HDFS 配置是安全的。
将以下内容添加到群集中每台服务器上的`hbase-site.xml`文件中:
```
<property>
<name>hbase.security.authentication</name>
<value>kerberos</value>
</property>
<property>
<name>hbase.security.authorization</name>
<value>true</value>
</property>
<property>
<name>hbase.coprocessor.region.classes</name>
<value>org.apache.hadoop.hbase.security.token.TokenProvider</value>
</property>
```
部署这些配置更改时,需要完全关闭并重新启动 HBase 服务。
### 61.3。用于安全操作的客户端配置
首先,请参阅[先决条件](#security.prerequisites)并确保您的基础 HDFS 配置是安全的。
将以下内容添加到每个客户端上的`hbase-site.xml`文件中:
```
<property>
<name>hbase.security.authentication</name>
<value>kerberos</value>
</property>
```
在 2.2.0 版之前,客户端环境必须通过`kinit`命令从 KDC 或 keytab 登录到 Kerberos,然后才能与 HBase 集群进行通信。
从 2.2.0 开始,客户端可以在`hbase-site.xml`中指定以下配置:
```
<property>
<name>hbase.client.keytab.file</name>
<value>/local/path/to/client/keytab</value>
</property>
<property>
<name>hbase.client.keytab.principal</name>
<value>foo@EXAMPLE.COM</value>
</property>
```
然后,应用程序可以自动执行登录和凭据续订作业,而不会受到客户端干扰。
它是可选功能,客户端升级到 2.2.0,只要保持`hbase.client.keytab.file`和`hbase.client.keytab.principal`未设置,它仍然可以保留旧版本中的登录和凭证更新逻辑。
请注意,如果客户端和服务器端站点文件中的`hbase.security.authentication`不匹配,则客户端将无法与群集通信。
将 HBase 配置为安全 RPC 后,可以选择配置加密通信。为此,请将以下内容添加到每个客户端上的`hbase-site.xml`文件中:
```
<property>
<name>hbase.rpc.protection</name>
<value>privacy</value>
</property>
```
此配置属性也可以基于每个连接进行设置。将其设置在`Table`提供的`Configuration`中:
```
Configuration conf = HBaseConfiguration.create();
Connection connection = ConnectionFactory.createConnection(conf);
conf.set("hbase.rpc.protection", "privacy");
try (Connection connection = ConnectionFactory.createConnection(conf);
Table table = connection.getTable(TableName.valueOf(tablename))) {
.... do your stuff
}
```
对于加密通信,预计性能损失约为 10%。
### 61.4。用于安全操作的客户端配置 - Thrift Gateway
将以下内容添加到每个 Thrift 网关的`hbase-site.xml`文件中:
```
<property>
<name>hbase.thrift.keytab.file</name>
<value>/etc/hbase/conf/hbase.keytab</value>
</property>
<property>
<name>hbase.thrift.kerberos.principal</name>
<value>$USER/_HOST@HADOOP.LOCALDOMAIN</value>
<!-- TODO: This may need to be HTTP/_HOST@<REALM> and _HOST may not work.
You may have to put the concrete full hostname.
-->
</property>
<!-- Add these if you need to configure a different DNS interface from the default -->
<property>
<name>hbase.thrift.dns.interface</name>
<value>default</value>
</property>
<property>
<name>hbase.thrift.dns.nameserver</name>
<value>default</value>
</property>
```
分别用 _$ USER_ 和 _$ KEYTAB_ 替换相应的凭证和密钥表。
为了使用 Thrift API 主体与 HBase 交互,还需要将`hbase.thrift.kerberos.principal`添加到`_acl_`表中。例如,要给 Thrift API 主体,`thrift_server`,管理访问权限,这样的命令就足够了:
```
grant 'thrift_server', 'RWCA'
```
有关 ACL 的更多信息,请参阅[访问控制标签(ACL)](#hbase.accesscontrol.configuration)部分
Thrift 网关将使用提供的凭证对 HBase 进行身份验证。 Thrift 网关本身不会执行任何身份验证。通过 Thrift 网关进行的所有客户端访问都将使用 Thrift 网关的凭证并享有其特权。
### 61.5。配置 Thrift 网关以代表客户端进行身份验证
[安全操作的客户端配置 - Thrift Gateway](#security.client.thrift) 描述了如何使用固定用户对 Thrift 客户端进行 HBase 认证。作为替代方案,您可以将 Thrift 网关配置为代表客户端对 HBase 进行身份验证,并使用代理用户访问 HBase。这在用于 Thrift 1 的 [HBASE-11349](https://issues.apache.org/jira/browse/HBASE-11349) 和用于 Thrift 2 的 [HBASE-11474](https://issues.apache.org/jira/browse/HBASE-11474) 中实施。
> Thrift Framed Transpor 的限制
>
> 如果您使用框架式传输,则无法利用此功能,因为此时 SASL 不适用于 Thrift 框架传输。
要启用它,请执行以下操作。
1. 按照[安全操作的客户端配置 - Thrift Gateway](#security.client.thrift) 中所述的步骤,确保 Thrift 在安全模式下运行。
2. 确保 HBase 配置为允许代理用户,如 [REST 网关模拟配置](#security.rest.gateway)中所述。
3. 在运行 Thrift 网关的每个群集节点的 _hbase-site.xml_ 中,将属性`hbase.thrift.security.qop`设置为以下三个值之一:
* `privacy` - 身份验证,完整性和机密性检查。
* `integrity` - 身份验证和完整性检查
* `authentication` - 仅验证身份验证
4. 重新启动 Thrift 网关进程以使更改生效。如果节点正在运行 Thrift,则`jps`命令的输出将列出`ThriftServer`进程。要在节点上停止 Thrift,请运行命令`bin/hbase-daemon.sh stop thrift`。要在节点上启动 Thrift,请运行命令`bin/hbase-daemon.sh start thrift`。
### 61.6。配置 Thrift 网关以使用`doAs`功能
[配置 Thrift 网关以代表客户端进行身份验证](#security.gateway.thrift)描述如何配置 Thrift 网关以代表客户端对 HBase 进行身份验证,以及如何使用代理用户访问 HBase。此方法的局限性在于,使用一组特定凭据初始化客户端后,它无法在会话期间更改这些凭据。 `doAs`功能提供了一种使用同一客户端模拟多个主体的灵活方式。此功能在 [HBASE-12640](https://issues.apache.org/jira/browse/HBASE-12640) 中针对 Thrift 1 实施,但目前不适用于 Thrift 2。
**要启用`doAs`功能**,请将以下内容添加到每个 Thrift 网关的 _hbase-site.xml_ 文件中:
```
<property>
<name>hbase.regionserver.thrift.http</name>
<value>true</value>
</property>
<property>
<name>hbase.thrift.support.proxyuser</name>
<value>true/value>
</property>
```
**要在使用`doAs`模拟时允许代理用户**,请将以下内容添加到每个 HBase 节点的 _hbase-site.xml_ 文件中:
```
<property>
<name>hadoop.security.authorization</name>
<value>true</value>
</property>
<property>
<name>hadoop.proxyuser.$USER.groups</name>
<value>$GROUPS</value>
</property>
<property>
<name>hadoop.proxyuser.$USER.hosts</name>
<value>$GROUPS</value>
</property>
```
看看[演示客户端](https://github.com/apache/hbase/blob/master/hbase-examples/src/main/java/org/apache/hadoop/hbase/thrift/HttpDoAsClient.java),了解如何在客户端使用此功能。
### 61.7。用于安全操作的客户端配置 - REST 网关
将以下内容添加到每个 REST 网关的`hbase-site.xml`文件中:
```
<property>
<name>hbase.rest.keytab.file</name>
<value>$KEYTAB</value>
</property>
<property>
<name>hbase.rest.kerberos.principal</name>
<value>$USER/_HOST@HADOOP.LOCALDOMAIN</value>
</property>
```
Substitute the appropriate credential and keytab for _$USER_ and _$KEYTAB_ respectively.
REST 网关将使用提供的凭据通过 HBase 进行身份验证。
为了使用 REST API 主体与 HBase 交互,还需要将`hbase.rest.kerberos.principal`添加到`_acl_`表。例如,要给出 REST API 主体,`rest_server`,管理访问权限,这样的命令就足够了:
```
grant 'rest_server', 'RWCA'
```
For more information about ACLs, please see the [Access Control Labels (ACLs)](#hbase.accesscontrol.configuration) section
HBase REST 网关支持 [SPNEGO HTTP 身份验证](https://hadoop.apache.org/docs/stable/hadoop-auth/index.html),以便客户端访问网关。要为客户端访问启用 REST 网关 Kerberos 身份验证,请将以下内容添加到每个 REST 网关的`hbase-site.xml`文件中。
```
<property>
<name>hbase.rest.support.proxyuser</name>
<value>true</value>
</property>
<property>
<name>hbase.rest.authentication.type</name>
<value>kerberos</value>
</property>
<property>
<name>hbase.rest.authentication.kerberos.principal</name>
<value>HTTP/_HOST@HADOOP.LOCALDOMAIN</value>
</property>
<property>
<name>hbase.rest.authentication.kerberos.keytab</name>
<value>$KEYTAB</value>
</property>
<!-- Add these if you need to configure a different DNS interface from the default -->
<property>
<name>hbase.rest.dns.interface</name>
<value>default</value>
</property>
<property>
<name>hbase.rest.dns.nameserver</name>
<value>default</value>
</property>
```
用 _$ KEYTAB_ 替换 HTTP 的密钥表。
HBase REST 网关支持不同的'hbase.rest.authentication.type':simple,kerberos。您还可以通过实现 Hadoop AuthenticationHandler 来实现自定义身份验证,然后将完整的类名指定为“hbase.rest.authentication.type”值。有关更多信息,请参阅 [SPNEGO HTTP 身份验证](https://hadoop.apache.org/docs/stable/hadoop-auth/index.html)。
### 61.8。 REST 网关模拟配置
默认情况下,REST 网关不支持模拟。它代表客户端访问 HBase,就像上一节中配置的用户一样。对于 HBase 服务器,所有请求都来自 REST 网关用户。实际用户不详。您可以打开模拟支持。通过模拟,REST 网关用户是代理用户。 HBase 服务器知道每个请求的实际/真实用户。所以它可以应用适当的授权。
要打开 REST 网关模拟,我们需要配置 HBase 服务器(主服务器和区域服务器)以允许代理用户;配置 REST 网关以启用模拟。
要允许代理用户,请将以下内容添加到每个 HBase 服务器的`hbase-site.xml`文件中:
```
<property>
<name>hadoop.security.authorization</name>
<value>true</value>
</property>
<property>
<name>hadoop.proxyuser.$USER.groups</name>
<value>$GROUPS</value>
</property>
<property>
<name>hadoop.proxyuser.$USER.hosts</name>
<value>$GROUPS</value>
</property>
```
用 _$ USER_ 替换 REST 网关代理用户,用 _$ GROUPS_ 替换允许的组列表。
要启用 REST 网关模拟,请将以下内容添加到每个 REST 网关的`hbase-site.xml`文件中。
```
<property>
<name>hbase.rest.authentication.type</name>
<value>kerberos</value>
</property>
<property>
<name>hbase.rest.authentication.kerberos.principal</name>
<value>HTTP/_HOST@HADOOP.LOCALDOMAIN</value>
</property>
<property>
<name>hbase.rest.authentication.kerberos.keytab</name>
<value>$KEYTAB</value>
</property>
```
Substitute the keytab for HTTP for _$KEYTAB_.
## 62\. Apache HBase 的简单用户访问
Newer releases of Apache HBase (>= 0.92) support optional SASL authentication of clients. See also Matteo Bertozzi’s article on [Understanding User Authentication and Authorization in Apache HBase](https://blog.cloudera.com/blog/2012/09/understanding-user-authentication-and-authorization-in-apache-hbase/).
介绍如何设置 Apache HBase 和客户端,以便用户轻松访问 HBase 资源。
### 62.1。简单与安全访问
以下部分显示如何设置简单用户访问权限。简单的用户访问不是一种安全的 HBase 操作方法。此方法用于防止用户犯错误。它可用于在开发系统上模拟访问控制,而无需设置 Kerberos。
此方法不用于防止恶意或黑客攻击。要使 HBase 对这些类型的攻击安全,您必须配置 HBase 以确保安全操作。请参阅[安全客户端访问 Apache HBase](#hbase.secure.configuration) 部分并完成其中描述的所有步骤。
### 62.2。先决条件
没有
### 62.3。用于简单用户访问操作的服务器端配置
Add the following to the `hbase-site.xml` file on every server machine in the cluster:
```
<property>
<name>hbase.security.authentication</name>
<value>simple</value>
</property>
<property>
<name>hbase.security.authorization</name>
<value>true</value>
</property>
<property>
<name>hbase.coprocessor.master.classes</name>
<value>org.apache.hadoop.hbase.security.access.AccessController</value>
</property>
<property>
<name>hbase.coprocessor.region.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>
```
对于 0.94,将以下内容添加到群集中每台服务器计算机上的`hbase-site.xml`文件中:
```
<property>
<name>hbase.rpc.engine</name>
<value>org.apache.hadoop.hbase.ipc.SecureRpcEngine</value>
</property>
<property>
<name>hbase.coprocessor.master.classes</name>
<value>org.apache.hadoop.hbase.security.access.AccessController</value>
</property>
<property>
<name>hbase.coprocessor.region.classes</name>
<value>org.apache.hadoop.hbase.security.access.AccessController</value>
</property>
```
A full shutdown and restart of HBase service is required when deploying these configuration changes.
### 62.4。用于简单用户访问操作的客户端配置
Add the following to the `hbase-site.xml` file on every client:
```
<property>
<name>hbase.security.authentication</name>
<value>simple</value>
</property>
```
For 0.94, add the following to the `hbase-site.xml` file on every server machine in the cluster:
```
<property>
<name>hbase.rpc.engine</name>
<value>org.apache.hadoop.hbase.ipc.SecureRpcEngine</value>
</property>
```
Be advised that if the `hbase.security.authentication` in the client- and server-side site files do not match, the client will not be able to communicate with the cluster.
#### 62.4.1。简单用户访问操作的客户端配置 - Thrift Gateway
Thrift 网关用户需要访问权限。例如,要给 Thrift API 用户,`thrift_server`,管理访问权限,这样的命令就足够了:
```
grant 'thrift_server', 'RWCA'
```
For more information about ACLs, please see the [Access Control Labels (ACLs)](#hbase.accesscontrol.configuration) section
The Thrift gateway will authenticate with HBase using the supplied credential. No authentication will be performed by the Thrift gateway itself. All client access via the Thrift gateway will use the Thrift gateway’s credential and have its privilege.
#### 62.4.2。用于简单用户访问操作的客户端配置 - REST 网关
REST 网关将使用提供的凭据通过 HBase 进行身份验证。 REST 网关本身不会执行任何身份验证。通过 REST 网关进行的所有客户端访问都将使用 REST 网关的凭证并具有其特权。
REST 网关用户需要访问权限。例如,要给 REST API 用户,`rest_server`,管理访问权限,这样的命令就足够了:
```
grant 'rest_server', 'RWCA'
```
For more information about ACLs, please see the [Access Control Labels (ACLs)](#hbase.accesscontrol.configuration) section
客户端应该可以通过 SPNEGO HTTP 身份验证以传递方式通过 REST 网关对 HBase 群集进行身份验证。这是未来的工作。
## 63.保护对 HDFS 和 ZooKeeper 的访问
安全 HBase 需要安全的 ZooKeeper 和 HDFS,以便用户无法访问和/或修改 HBase 下的元数据和数据。 HBase 使用 HDFS(或配置文件系统)来保存其数据文件以及预写日志(WAL)和其他数据。 HBase 使用 ZooKeeper 存储一些操作元数据(主地址,表锁,恢复状态等)。
### 63.1。保护 ZooKeeper 数据
ZooKeeper 具有可插入的身份验证机制,可以使用不同的方法从客户端进行访问。 ZooKeeper 甚至可以同时允许经过身份验证和未经身份验证的客户端。可以通过为每个 znode 提供访问控制列表(ACL)来限制对 znode 的访问。 ACL 包含两个组件,即身份验证方法和主体。 ACL 不是按层次强制执行的。有关详细信息,请参阅 [ZooKeeper 程序员指南](https://zookeeper.apache.org/doc/r3.3.6/zookeeperProgrammers.html#sc_ZooKeeperPluggableAuthentication)。
HBase 守护进程通过 SASL 和 kerberos 向 ZooKeeper 进行身份验证(请参阅 [SASL 身份验证与 ZooKeeper](#zk.sasl.auth) )。 HBase 设置 znode ACL,以便只有 HBase 用户和配置的 hbase 超级用户(`hbase.superuser`)可以访问和修改数据。如果 ZooKeeper 用于服务发现或与客户端共享状态,HBase 创建的 znode 也将允许任何人(无论身份验证)读取这些 znode(clusterId,主地址,元位置等),但只允许 HBase 用户可以修改它们。
### 63.2。保护文件系统(HDFS)数据
管理中的所有数据都保存在文件系统的根目录下(`hbase.rootdir`)。应限制对文件系统中的数据和 WAL 文件的访问,以便用户无法绕过 HBase 层,并从文件系统中查看底层数据文件。 HBase 假定使用的文件系统(HDFS 或其他)分层次地强制执行权限。如果未提供对文件系统(授权和身份验证)的充分保护,则 HBase 级别授权控制(ACL,可见性标签等)毫无意义,因为用户始终可以从文件系统访问数据。
HBase 将类似 posix 的权限 700(`rwx------`)强制执行到其根目录。这意味着只有 HBase 用户可以读取或写入 FS 中的文件。可以通过在 hbase-site.xml 中配置`hbase.rootdir.perms`来更改默认设置。需要重新启动活动主服务器,以便更改已使用的权限。对于 1.2.0 之前的版本,您可以检查是否已提交 HBASE-13780,如果没有,则可以根据需要手动设置根目录的权限。使用 HDFS,命令将是:
```
sudo -u hdfs hadoop fs -chmod 700 /hbase
```
如果使用其他`hbase.rootdir`,则应更改`/hbase`。
在安全模式下,应配置 SecureBulkLoadEndpoint 并将其用于将从 MR 作业创建的用户文件正确处理到 HBase 守护程序和 HBase 用户。用于批量加载的分布式文件系统中的暂存目录(`hbase.bulkload.staging.dir`,默认为`/tmp/hbase-staging`)应具有(模式 711 或`rwx—x—x`),以便用户可以访问在该父目录下创建的暂存目录,但不能做任何其他操作。有关如何配置 SecureBulkLoadEndPoint 的信息,请参阅[安全批量加载](#hbase.secure.bulkload)。
## 64.保护对数据的访问
在 HBase 客户端和服务器进程和网关之间配置安全身份验证后,您需要考虑数据本身的安全性。 HBase 提供了几种保护数据的策略:
* 基于角色的访问控制(RBAC)使用熟悉的角色范例控制哪些用户或组可以读取和写入给定的 HBase 资源或执行协处理器端点。
* 可见性标签,允许您标记单元格并控制对标记单元格的访问,以进一步限制谁可以读取或写入数据的某些子集。可见性标签存储为标签。有关详细信息,请参阅 [hbase.tags](#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.prerequisites](#security.prerequisites) 和 [SASL 身份验证与 ZooKeeper](#zk.sasl.auth) 中所述。
### 64.1。标签
_ 标签 _ 是 HFile v3 的一个功能。标记是一段元数据,它是单元格的一部分,与键,值和版本分开。标签是一个实现细节,为其他与安全相关的功能(如单元级 ACL 和可见性标签)提供基础。标签存储在 HFiles 本身中。将来,标签可能会用于实现其他 HBase 功能。您不需要了解很多关于标签的信息,以便使用它们启用的安全功能。
#### 64.1.1。实施细节
每个单元格可以包含零个或多个标记。每个标记都有一个类型和实际的标记字节数组。
就像可以对行键,列族,限定符和值进行编码一样(参见 [data.block.encoding.types](#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,则需要为所有可见版本编写新单元。该应用程序完全控制政策演变。
上述规则的例外是`append`和`increment`处理。附加和增量可以在操作中携带 ACL。如果操作中包含一个,则它将应用于`append`或`increment`的结果。否则,将保留要附加或递增的现有单元格的 ACL。
访问级别和范围的组合创建了可以授予用户的可能访问级别的矩阵。在生产环境中,根据执行特定工作所需的内容来考虑访问级别很有用。以下列表描述了一些常见类型的 HBase 用户的适当访问级别。重要的是不要授予比给定用户执行所需任务所需的访问权限更多的访问权限。
* _ 超级用户 _ - 在生产系统中,只有 HBase 用户应具有超级用户访问权限。在开发环境中,管理员可能需要超级用户访问权限才能快速控制和管理群集。但是,这种类型的管理员通常应该是全局管理员而不是超级用户。
* _ 全局管理员 _ - 全局管理员可以执行任务并访问 HBase 中的每个表。在典型的生产环境中,管理员不应对表中的数据具有读取或写入权限。
* 具有管理员权限的全局管理员可以在群集上执行群集范围的操作,例如平衡,分配或取消分配区域,或调用显式主要压缩。这是一个操作角色。
* 具有“创建”权限的全局管理员可以在 HBase 中创建或删除任何表。这更像是 DBA 类型的角色。
在生产环境中,不同用户可能只拥有管理员和创建权限之一。
| |
在当前实现中,具有`Admin`权限的全局管理员可以在表上授予自己`Read`和`Write`权限,并获得对该表数据的访问权限。因此,仅向实际需要它们的受信任用户授予`Global Admin`权限。
另请注意,具有`Create`权限的`Global Admin`可以对 ACL 表执行`Put`操作,模拟`grant`或`revoke`并绕过`Global Admin`权限的授权检查。
由于这些问题,请谨慎授予`Global Admin`权限。
|
* _ 命名空间管理员 _ - 具有`Create`权限的命名空间管理员可以在该命名空间内创建或删除表,并获取和恢复快照。具有`Admin`权限的命名空间管理员可以对该命名空间中的表执行拆分或主要压缩等操作。
* _ 表管理员 _ - 表管理员只能对该表执行管理操作。具有`Create`权限的表管理员可以从该表创建快照或从快照还原该表。具有`Admin`权限的表管理员可以对该表执行拆分或主要压缩等操作。
* _ 用户 _ - 用户可以读取或写入数据,或两者兼而有之。如果给予`Executable`权限,用户还可以执行协处理器端点。
| 职称 | 范围 | 权限 | 描述 |
| --- | --- | --- | --- |
| 高级管理员 | 全球 | 访问,创建 | 管理群集并授予初级管理员访问权限。 |
| 初级管理员 | Global | 创建 | 创建表并提供对表管理员的访问权限。 |
| 表管理员 | 表 | 访问 | 从操作的角度维护表。 |
| 数据分析师 | Table | 读 | 从 HBase 数据创建报告。 |
| Web 应用程序 | Table | 读,写 | 将数据放入 HBase 并使用 HBase 数据执行操作。 |
ACL 矩阵
有关 ACL 如何映射到特定 HBase 操作和任务的更多详细信息,请参阅[附录 acl 矩阵](#appendix_acl_matrix)。
##### 实施细节
单元级 ACL 使用标签实现(参见[标签](#hbase.tags))。要使用单元级 ACL,您必须使用 HFile v3 和 HBase 0.98 或更高版本。
1. HBase 创建的文件由运行 HBase 进程的操作系统用户拥有。要与 HBase 文件进行交互,您应该使用 API或批量加载工具。
2. HBase 不会在 HBase 内部模拟“角色”。相反,可以为组名授予权限。这允许通过组成员身份对角色进行外部建模。通过 Hadoop 组映射服务在 HBase 外部创建和操作组。
##### 服务器端配置
1. 作为先决条件,执行[过程:基本服务器端配置](#security.data.basic.server.side)中的步骤。
2. 通过在 _hbase-site.xml_ 中设置以下属性来安装和配置 AccessController 协处理器。这些属性采用类列表。
> 如果将 AccessController 与 VisibilityController 一起使用,则 AccessController 必须位于列表的第一位,因为两个组件都处于活动状态,VisibilityController 会将其系统表的访问控制委托给 AccessController。有关同时使用两者的示例,请参见[安全配置示例](#security.example.config)。
```
<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.java_ 和 _hbase-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> help "scan"
```
如果需要启用 cell acl,则 hbase-site.xml 中的 hfile.format.version 选项应大于或等于 3,并且 hbase.security.access.early_out 选项应设置为 false。此示例授予读取权限访问“testuser”用户以及“pii”列中与过滤器匹配的单元格上的“开发人员”组的读/写访问权限。
```
hbase> grant 'user', \
{ '@developers' => 'RW', 'testuser' => 'R' }, \
{ COLUMNS => 'pii', FILTER => "(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<Void>() {
@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<String, Permission> 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<Void>() {
@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> user_permission 'user'
hbase> user_permission '.*'
hbase> 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](https://issues.apache.org/jira/browse/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](https://issues.apache.org/jira/browse/HBASE-12470) 。
>
> 可见性标签目前不适用于超级用户。
| 表达 | 解释 |
| --- | --- |
| |
```
fulltime
```
|允许访问与全时标签关联的用户。 | |
```
!public
```
|允许访问与公共标签无关的用户。 | |
```
( secret | topsecret ) & !probationary
```
|允许访问与 secret 或 topsecret 标签关联且与试用标签无关的用户。 |
#### 64.3.1。服务器端配置
1. As a prerequisite, perform the steps in [Procedure: Basic Server-Side Configuration](#security.data.basic.server.side).
2. 通过在 _hbase-site.xml_ 中设置以下属性来安装和配置 VisibilityController 协处理器。这些属性采用类名列表。
```
<property>
<name>hbase.security.authorization</name>
<value>true</value>
</property>
<property>
<name>hbase.coprocessor.region.classes</name>
<value>org.apache.hadoop.hbase.security.visibility.VisibilityController</value>
</property>
<property>
<name>hbase.coprocessor.master.classes</name>
<value>org.apache.hadoop.hbase.security.visibility.VisibilityController</value>
</property>
```
> 如果同时使用 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> add_labels [ 'admin', 'service', 'developer', 'test' ]
```
示例 18\. Java API
```
public static void addLabels() throws Exception {
PrivilegedExceptionAction<VisibilityLabelsResponse> action = new PrivilegedExceptionAction<VisibilityLabelsResponse>() {
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> 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> 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> set_visibility 'user', 'admin|service|developer', { COLUMNS => '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()](https://hbase.apache.org/devapidocs/org/apache/hadoop/hbase/security/visibility/VisibilityClient.html#setAuths-org.apache.hadoop.hbase.client.Connection-java.lang.String:A-java.lang.String-)方法为给定用户设置默认授权集。
您可以在扫描或获取期间通过传递 HBase Shell 中的 AUTHORIZATIONS 选项或 [Scan.setAuthorizations()](https://hbase.apache.org/apidocs/org/apache/hadoop/hbase/client/Scan.html#setAuthorizations-org.apache.hadoop.hbase.security.visibility.Authorizations-)方法(如果使用 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](https://issues.apache.org/jira/browse/HBASE-12466) 中实现的默认实现加载了两个插件,`FeedUserAuthScanLabelGenerator`和`DefinedSetFilterScanLabelGenerator`。参见[用标签读取细胞](#reading_cells_with_labels)。
#### 64.3.5。将可见性标记复制为字符串
如上面部分所述,接口`VisibilityLabelService`可用于实现在单元格中存储可见性表达式的不同方式。启用了复制的群集还必须将可见性表达式复制到对等群集。如果`DefaultVisibilityLabelServiceImpl`用作`VisibilityLabelService`的实现,则所有可见性表达式将根据存储在标签表中的每个可见性标签的序数转换为相应的表达式。在复制期间,可见细胞也复制,基于序数的表达完整。对等群集可能没有相同的`labels`表,其可见性标签具有相同的序数映射。在这种情况下,复制序数是没有意义的。如果复制发生在将可见性表达式作为字符串传输的情况下会更好。要将可见性表达式作为字符串复制到对等集群,请创建`RegionServerObserver`配置,该配置基于`VisibilityLabelService`接口的实现而工作。下面的配置允许将可见性表达式作为字符串复制到对等集群。更多详细信息,请参见 [HBASE-11639](https://issues.apache.org/jira/browse/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 <alias>
```
将 __**__ 替换为密钥库文件的密码,将<alias>替换为 HBase 服务帐户的用户名或任意字符串。如果使用任意字符串,则需要配置 HBase 才能使用它,如下所述。指定适当的密钥大小。不要为密钥指定单独的密码,但在出现提示时按<kbd>返回</kbd>。</alias>
2. 在密钥文件上设置适当的权限,并将其分发给所有 HBase 服务器。
上一个命令在 HBase _conf /_ 目录中创建了一个名为 _hbase.jks_ 的文件。设置此文件的权限和所有权,以便只有 HBase 服务帐户用户可以读取该文件,并将密钥安全地分发给所有 HBase 服务器。
3. 配置 HBase 守护进程。
在区域服务器上的 _hbase-site.xml_ 中设置以下属性,以配置 HBase 守护程序以使用由 KeyStore 文件支持的密钥提供程序或检索集群主密钥。在下面的示例中,用密码替换 __**__。
```
<property>
<name>hbase.crypto.keyprovider</name>
<value>org.apache.hadoop.hbase.io.crypto.KeyStoreKeyProvider</value>
</property>
<property>
<name>hbase.crypto.keyprovider.parameters</name>
<value>jceks:///path/to/hbase/conf/hbase.jks?password=****</value>
</property>
```
默认情况下,HBase 服务帐户名称将用于解析群集主密钥。但是,您可以使用任意别名(在`keytool`命令中)存储它。在这种情况下,请将以下属性设置为您使用的别名。
```
<property>
<name>hbase.crypto.master.key.name</name>
<value>my-alias</value>
</property>
```
您还需要确保您的 HFile 使用 HFile v3,以便使用透明加密。这是 HBase 1.0 以后的默认配置。对于以前的版本,请在 _hbase-site.xml_ 文件中设置以下属性。
```
<property>
<name>hfile.format.version</name>
<value>3</value>
</property>
```
(可选)您可以使用其他密码提供程序,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.provider`和`hbase.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 并且不会使用它们。
```
<property>
<name>hbase.regionserver.hlog.reader.impl</name>
<value>org.apache.hadoop.hbase.regionserver.wal.SecureProtobufLogReader</value>
</property>
<property>
<name>hbase.regionserver.hlog.writer.impl</name>
<value>org.apache.hadoop.hbase.regionserver.wal.SecureProtobufLogWriter</value>
</property>
<property>
<name>hbase.regionserver.wal.encryption</name>
<value>true</value>
</property>
```
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](https://hbase.apache.org/devapidocs/org/apache/hadoop/hbase/security/access/SecureBulkLoadEndpoint.html) 的协处理器实现,该协处理器使用由配置属性`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](https://issues.apache.org/jira/browse/HBASE-19483) ;
```
<property>
<name>hbase.security.authorization</name>
<value>true</value>
</property>
```
## 65.安全配置示例
此配置示例包括对 HFile v3,ACL,可见性标签以及静态和 WAL 数据的透明加密的支持。所有选项都在上面的章节中单独讨论过。
示例 20\. _hbase-site.xml_ 中的示例安全设置
```
<!-- HFile v3 Support -->
<property>
<name>hfile.format.version</name>
<value>3</value>
</property>
<!-- HBase Superuser -->
<property>
<name>hbase.superuser</name>
<value>hbase,admin</value>
</property>
<!-- Coprocessors for ACLs and Visibility Tags -->
<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.visibility.VisibilityController,
org.apache.hadoop.hbase.security.token.TokenProvider</value>
</property>
<property>
<name>hbase.coprocessor.master.classes</name>
<value>org.apache.hadoop.hbase.security.access.AccessController,
org.apache.hadoop.hbase.security.visibility.VisibilityController</value>
</property>
<property>
<name>hbase.coprocessor.regionserver.classes</name>
<value>org.apache.hadoop.hbase.security.access.AccessController</value>
</property>
<!-- Executable ACL for Coprocessor Endpoints -->
<property>
<name>hbase.security.exec.permission.checks</name>
<value>true</value>
</property>
<!-- Whether a user needs authorization for a visibility tag to set it on a cell -->
<property>
<name>hbase.security.visibility.mutations.checkauth</name>
<value>false</value>
</property>
<!-- Secure RPC Transport -->
<property>
<name>hbase.rpc.protection</name>
<value>privacy</value>
</property>
<!-- Transparent Encryption -->
<property>
<name>hbase.crypto.keyprovider</name>
<value>org.apache.hadoop.hbase.io.crypto.KeyStoreKeyProvider</value>
</property>
<property>
<name>hbase.crypto.keyprovider.parameters</name>
<value>jceks:///path/to/hbase/conf/hbase.jks?password=***</value>
</property>
<property>
<name>hbase.crypto.master.key.name</name>
<value>hbase</value>
</property>
<!-- WAL Encryption -->
<property>
<name>hbase.regionserver.hlog.reader.impl</name>
<value>org.apache.hadoop.hbase.regionserver.wal.SecureProtobufLogReader</value>
</property>
<property>
<name>hbase.regionserver.hlog.writer.impl</name>
<value>org.apache.hadoop.hbase.regionserver.wal.SecureProtobufLogWriter</value>
</property>
<property>
<name>hbase.regionserver.wal.encryption</name>
<value>true</value>
</property>
<!-- For key rotation -->
<property>
<name>hbase.crypto.master.alternate.key.name</name>
<value>hbase.old</value>
</property>
<!-- Secure Bulk Load -->
<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>
```
示例 21\. Hadoop _core-site.xml_ 中的示例组映射器
调整这些设置以适合您的环境。
```
<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> <!-- Replace with the actual password -->
</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>
```
- HBase™ 中文参考指南 3.0
- Preface
- Getting Started
- Apache HBase Configuration
- Upgrading
- The Apache HBase Shell
- Data Model
- HBase and Schema Design
- RegionServer Sizing Rules of Thumb
- HBase and MapReduce
- Securing Apache HBase
- Architecture
- In-memory Compaction
- Backup and Restore
- Synchronous Replication
- Apache HBase APIs
- Apache HBase External APIs
- Thrift API and Filter Language
- HBase and Spark
- Apache HBase Coprocessors
- Apache HBase Performance Tuning
- Troubleshooting and Debugging Apache HBase
- Apache HBase Case Studies
- Apache HBase Operational Management
- Building and Developing Apache HBase
- Unit Testing HBase Applications
- Protobuf in HBase
- Procedure Framework (Pv2): HBASE-12439
- AMv2 Description for Devs
- ZooKeeper
- Community
- Appendix