报告安全漏洞
为了保护现有的HBase安装免受攻击,请不要使用JIRA报告与安全相关的错误。相反,将您的报告发送到邮件列表 private@hbase.apache.org ,允许任何人发送邮件,但限制谁可以阅读它们。该列表中的某个人将与您联系以跟进您的报告。 |
HBase遵守Apache Software Foundation关于报告的漏洞的政策,可在 http://apache.org/security/ 上找到。
如果您希望发送加密报告,可以使用为常规ASF安全列表提供的GPG详细信息。这可能会增加报告的响应时间。
HBase提供了保护HBase的各种组件和方面的机制,以及它与Hadoop基础架构的其余部分以及Hadoop之外的客户端和资源的关系。
默认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 线程的贡献。如果您知道如何在不打开HTTPS的第二个端口的情况下解决这个问题,那么补丁将受到赞赏
可以通过使用 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>
较新版本的Apache HBase(&gt; = 0.92)支持客户端的可选SASL身份验证。另见Matteo Bertozzi关于了解Apache HBase中用户认证和授权的文章。
介绍如何设置Apache HBase和客户端以连接到安全的HBase资源。
Hadoop身份验证配置
要使用强身份验证运行HBase RPC,必须将hbase.security.authentication设置为kerberos。在这种情况下,还必须在core-site.xml中将hadoop.security.authentication设置为kerberos。否则,您将对HBase使用强身份验证,但不会对底层HDFS使用强身份验证,这将取消任何好处。
Kerberos KDC
您需要有一个有效的Kerberos KDC。
首先,请参阅 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服务。
首先,请参阅先决条件并确保您的基础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%。
将以下内容添加到每个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)部分
Thrift网关将使用提供的凭证对HBase进行身份验证。 Thrift网关本身不会执行任何身份验证。通过Thrift网关进行的所有客户端访问都将使用Thrift网关的凭证并享有其特权。
安全操作的客户端配置 - Thrift Gateway 描述了如何使用固定用户对Thrift客户端进行HBase认证。作为替代方案,您可以将Thrift网关配置为代表客户端对HBase进行身份验证,并使用代理用户访问HBase。这在用于Thrift 1的 HBASE-11349 和用于Thrift 2的 HBASE-11474 中实施。
Thrift Framed Transpor的限制
如果您使用框架式传输,则无法利用此功能,因为此时SASL不适用于Thrift框架传输。
要启用它,请执行以下操作。
-
按照安全操作的客户端配置 - Thrift Gateway 中所述的步骤,确保Thrift在安全模式下运行。
-
确保HBase配置为允许代理用户,如 REST网关模拟配置中所述。
-
在运行Thrift网关的每个群集节点的 hbase-site.xml 中,将属性
hbase.thrift.security.qop设置为以下三个值之一:-
privacy- 身份验证,完整性和机密性检查。 -
integrity- 身份验证和完整性检查 -
authentication- 仅验证身份验证
-
-
重新启动Thrift网关进程以使更改生效。如果节点正在运行Thrift,则
jps命令的输出将列出ThriftServer进程。要在节点上停止Thrift,请运行命令bin/hbase-daemon.sh stop thrift。要在节点上启动Thrift,请运行命令bin/hbase-daemon.sh start thrift。
配置Thrift网关以代表客户端进行身份验证描述如何配置Thrift网关以代表客户端对HBase进行身份验证,以及如何使用代理用户访问HBase。此方法的局限性在于,使用一组特定凭据初始化客户端后,它无法在会话期间更改这些凭据。 doAs功能提供了一种使用同一客户端模拟多个主体的灵活方式。此功能在 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>
看看演示客户端,了解如何在客户端使用此功能。
将以下内容添加到每个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) section
HBase REST网关支持 SPNEGO HTTP身份验证,以便客户端访问网关。要为客户端访问启用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身份验证。
默认情况下,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.
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.
介绍如何设置Apache HBase和客户端,以便用户轻松访问HBase资源。
以下部分显示如何设置简单用户访问权限。简单的用户访问不是一种安全的HBase操作方法。此方法用于防止用户犯错误。它可用于在开发系统上模拟访问控制,而无需设置Kerberos。
此方法不用于防止恶意或黑客攻击。要使HBase对这些类型的攻击安全,您必须配置HBase以确保安全操作。请参阅安全客户端访问Apache HBase 部分并完成其中描述的所有步骤。
没有
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.
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.
Thrift网关用户需要访问权限。例如,要给Thrift API用户,thrift_server,管理访问权限,这样的命令就足够了:
grant 'thrift_server', 'RWCA'
For more information about ACLs, please see the Access Control Labels (ACLs) 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.
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) section
客户端应该可以通过SPNEGO HTTP身份验证以传递方式通过REST网关对HBase群集进行身份验证。这是未来的工作。
安全HBase需要安全的ZooKeeper和HDFS,以便用户无法访问和/或修改HBase下的元数据和数据。 HBase使用HDFS(或配置文件系统)来保存其数据文件以及预写日志(WAL)和其他数据。 HBase使用ZooKeeper存储一些操作元数据(主地址,表锁,恢复状态等)。
ZooKeeper具有可插入的身份验证机制,可以使用不同的方法从客户端进行访问。 ZooKeeper甚至可以同时允许经过身份验证和未经身份验证的客户端。可以通过为每个znode提供访问控制列表(ACL)来限制对znode的访问。 ACL包含两个组件,即身份验证方法和主体。 ACL不是按层次强制执行的。有关详细信息,请参阅 ZooKeeper程序员指南。
HBase守护进程通过SASL和kerberos向ZooKeeper进行身份验证(请参阅 SASL身份验证与ZooKeeper )。 HBase设置znode ACL,以便只有HBase用户和配置的hbase超级用户(hbase.superuser)可以访问和修改数据。如果ZooKeeper用于服务发现或与客户端共享状态,HBase创建的znode也将允许任何人(无论身份验证)读取这些znode(clusterId,主地址,元位置等),但只允许HBase用户可以修改它们。
管理中的所有数据都保存在文件系统的根目录下(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客户端和服务器进程和网关之间配置安全身份验证后,您需要考虑数据本身的安全性。 HBase提供了几种保护数据的策略:
-
基于角色的访问控制(RBAC)使用熟悉的角色范例控制哪些用户或组可以读取和写入给定的HBase资源或执行协处理器端点。
-
可见性标签,允许您标记单元格并控制对标记单元格的访问,以进一步限制谁可以读取或写入数据的某些子集。可见性标签存储为标签。有关详细信息,请参阅 hbase.tags 。
-
在HFiles和WAL中对底层文件系统上的静态数据进行透明加密。这可以保护您的静态数据免受可以访问底层文件系统的攻击者的攻击,而无需更改客户端的实现。它还可以防止来自不正确处理的磁盘的数据泄漏,这对于法律和法规合规性而言非常重要。
下面讨论每个功能的服务器端配置,管理和实现细节,以及任何性能权衡。最后给出了一个示例安全配置,以显示所有这些功能一起使用,因为它们可能位于真实场景中。
HBase的所有安全方面都在积极发展并迅速发展。您应采用任何策略来保护数据的安全性。此外,其中一些功能仍处于开发的实验阶段。要利用其中的许多功能,您必须运行HBase 0.98+并使用HFile v3文件格式。
保护敏感文件
本节中的几个过程要求您在群集节点之间复制文件。复制密钥,配置文件或包含敏感字符串的其他文件时,请使用安全方法(如
ssh)以避免泄露敏感数据。
过程:基本服务器端配置
-
通过在 hbase-site.xml 中将
hfile.format.version设置为3来启用HFile v3。这是HBase 1.0和更新版本的默认值。<property> <name>hfile.format.version</name> <value>3</value> </property> -
为RPC和ZooKeeper启用SASL和Kerberos身份验证,如 security.prerequisites 和 SASL身份验证与ZooKeeper 中所述。
_标签_是HFile v3的一个功能。标记是一段元数据,它是单元格的一部分,与键,值和版本分开。标签是一个实现细节,为其他与安全相关的功能(如单元级ACL和可见性标签)提供基础。标签存储在HFiles本身中。将来,标签可能会用于实现其他HBase功能。您不需要了解很多关于标签的信息,以便使用它们启用的安全功能。
每个单元格可以包含零个或多个标记。每个标记都有一个类型和实际的标记字节数组。
就像可以对行键,列族,限定符和值进行编码一样(参见 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加密时不支持标记压缩。
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矩阵。
单元级ACL使用标签实现(参见标签)。要使用单元级ACL,您必须使用HFile v3和HBase 0.98或更高版本。
-
HBase创建的文件由运行HBase进程的操作系统用户拥有。要与HBase文件进行交互,您应该使用API或批量加载工具。
-
HBase不会在HBase内部模拟“角色”。相反,可以为组名授予权限。这允许通过组成员身份对角色进行外部建模。通过Hadoop组映射服务在HBase外部创建和操作组。
-
作为先决条件,执行过程:基本服务器端配置中的步骤。
-
通过在 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或更高版本。 -
在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> -
(可选)启用早期评估策略。在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。 -
分发配置并重新启动群集以使更改生效。
-
要测试您的配置,请以给定用户身份登录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。
-
用户和组管理
用户和组在您的目录中维护在HBase外部。
-
授予对命名空间,表,列族或单元格的访问权限
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)) -
-
从命名空间,表,列系列或单元格撤消访问控制
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; } }); } -
显示用户的有效权限
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");
}
}
可见性标签控件可用于仅允许与给定标签关联的用户或主体读取或访问具有该标签的单元。例如,您可以标记单元格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 | topsecret ) & !probationary
|允许访问与secret或topsecret标签关联且与试用标签无关的用户。 |
-
As a prerequisite, perform the steps in Procedure: Basic Server-Side Configuration.
-
通过在 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。
-
调整配置
默认情况下,用户可以使用任何标签标记单元格,包括与之无关的标签,这意味着用户可以放置他无法读取的数据。例如,即使用户未与该标签相关联,用户也可以用(假设的)'topsecret'标签标记单元格。如果您只希望用户能够使用与之关联的标签标记单元格,请将
hbase.security.visibility.mutations.checkauths设置为true。在这种情况下,如果使用与用户无关的标签,则突变将失败。 -
Distribute your configuration and restart your cluster for changes to take effect.
可以使用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。
-
定义可见性标签列表
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); } -
将标签与用户关联
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;
}
...
-
清除用户标签
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");
...
}
-
将标签或表达式应用于单元格
标签仅在写入数据时应用。标签与给定版本的单元格相关联。
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();
}
}
当您发出扫描或获取时,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;
}
...
解释为给定的get / scan请求验证的标签是可插入的算法。
您可以使用属性hbase.regionserver.scan.visibility.label.generator.class指定自定义插件或插件。第一个ScanLabelGenerator的输出将是下一个的输出,直到列表的结尾。
在 HBASE-12466 中实现的默认实现加载了两个插件,FeedUserAuthScanLabelGenerator和DefinedSetFilterScanLabelGenerator。参见用标签读取细胞。
如上面部分所述,接口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>
HBase提供了一种机制,用于保护静态数据,HFiles和WAL,它们驻留在HDFS或其他分布式文件系统中。双层体系结构用于灵活且非侵入式的密钥轮换。 “透明”意味着客户端不需要进行任何实现更改。写入数据时,会对其进行加密。读取时,按需解密。
管理员为群集配置主密钥,该密钥存储在每个受信任的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都会被加密。
此过程假定您使用的是默认的Java密钥库实现。如果您使用的是自定义实现,请检查其文档并进行相应调整。
-
使用
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>
-
在密钥文件上设置适当的权限,并将其分发给所有HBase服务器。
上一个命令在HBase conf / 目录中创建了一个名为 hbase.jks 的文件。设置此文件的权限和所有权,以便只有HBase服务帐户用户可以读取该文件,并将密钥安全地分发给所有HBase服务器。
-
配置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。
-
-
-
配置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> -
配置 hbase-site.xml 文件的权限。
由于密钥库密码存储在hbase-site.xml中,因此您需要确保只有HBase用户可以使用文件所有权和权限读取 hbase-site.xml 文件。
-
重新启动群集。
将新配置文件分发到所有节点并重新启动群集。
管理任务可以在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 文件中的旧主密钥。
安全模式下的批量加载比正常设置要多一些,因为客户端必须将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>
在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>
此配置示例包括对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>