在生产环境中保护Apache HBase
HBase是模仿Google BigTable的流行分布式键值存储。 HBase可以支持极快的查找,高写入吞吐量和强大的一致性,使其适用于从用例数据存储(如Facebook消息传递)到分析用例(如Yahoo Flurry)的各种用例。 HBase将数据存储在HDFS上,以提供线性缩放和容错能力。
与HDFS相似,Kerberos集成通过在需要有效SPN进行身份验证的HBase协议中添加基于SASL的身份验证层而起作用。 另外,HBase本身在存储数据时使用Kerberos对HDFS进行身份验证。 HBase支持单元级别的访问控制,提供了非常精细的授权层。
在现有的HDP群集上使用Kerberos安装Apache HBase
您可以在HDP群集上安装启用了Kerberos的Apache HBase。
在你开始之前
•您必须具有启用了Kerberos的可运行HDP群集。
•您必须具有Kerberos管理员访问权限。
请按照以下步骤安装启用了Kerberos的HBase:
程序
1.登录到Ambari。
2.从“操作”菜单中,单击“添加服务”。
3.从服务列表中,选择HBase,然后单击“下一步”。
4.选择安装HBase Master的位置。
5.选择要安装HBase区域服务器的节点。
6.查看配置详细信息,然后根据您的性能调整需求对其进行修改,然后单击“下一步”。
您也可以稍后自定义服务。
7.检查将为HBase部署创建的Kerberos服务主体名称(SPN),然后单击“下一步”。
8.查看配置详细信息,然后单击“部署”。
如果在HDFS上启用Kerberos时未存储Kerberos管理员凭据,则Ambari会提示您输入
凭证再次。
9.输入凭据后,单击“保存”。
10.等待安装完成。
11.查看安装期间遇到的任何错误,然后单击“下一步”。
验证是否为HBase启用了kerberos
请遵循以下步骤来验证是否为Apache HBase启用了kerberos:
程序
1.登录到安装了HBase客户端的Ambari节点。
2.启动HBase Shell。
3.在HBase Master主机上,执行status命令:
在此示例中,该命令失败并带有堆栈跟踪,因为没有TGT。 因此无法使用Kerberos向HBase进行身份验证。
4.获取票证授予票证(TGT)。
以下示例显示了运行kinit操作时用于创建本地TGT的输入和输出。
在第一个示例中,您首先在命令行上运行“ kinit”,然后运行应用程序。 第二个示例通过密钥表自动获取TGT。
安全客户端的示例1:
package com.hortonworks.hbase.examples;
import java.io.IOException;
import java.util.Objects;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.Admin;
import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder;
import org.apache.hadoop.hbase.client.Connection;
import org.apache.hadoop.hbase.client.ConnectionFactory;
import org.apache.hadoop.hbase.client.Get;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.Table;
import org.apache.hadoop.hbase.client.TableDescriptorBuilder;
import org.apache.hadoop.hbase.util.Bytes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Write and read data from HBase, expects HBASE_CONF_DIR and
HADOOP_CONF_DIR on the classpath and a valid Kerberos
* ticket in a ticket cache (e.g. kinit).
*/
public class ExampleSecureClient implements Runnable {
private static final Logger LOG =
LoggerFactory.getLogger(ExampleSecureClient.class);
private static final TableName TABLE_NAME =
TableName.valueOf("example_secure_client");
private static final byte[] CF = Bytes.toBytes("f1");
private final Configuration conf;
public ExampleSecureClient(Configuration conf) {
this.conf = Objects.requireNonNull(conf);
}
@Override public void run() {
try (Connection conn = ConnectionFactory.createConnection(conf)) {
writeAndRead(conn, TABLE_NAME, CF);
LOG.info("Success!");
} catch (Exception e) {
LOG.error("Uncaught exception running example", e);
throw new RuntimeException(e);
}
}
void writeAndRead(Connection conn, TableName tn, byte[] family) throws
IOException {
final Admin admin = conn.getAdmin();
// Delete the table if it already exists
if (admin.tableExists(tn)) {
admin.disableTable(tn);
admin.deleteTable(tn);
}
// Create our table
admin.createTable(TableDescriptorBuilder.newBuilder(tn).setColumnFamily(
ColumnFamilyDescriptorBuilder.of(family)).build());
final Table table = conn.getTable(tn);
Put p = new Put(Bytes.toBytes("row1"));
p.addColumn(family, Bytes.toBytes("q1"), Bytes.toBytes("value"));
LOG.info("Writing update: row1 -> value");
table.put(p);
Result r = table.get(new Get(Bytes.toBytes("row1")));
assert r.size() == 1;
LOG.info("Read row1: {}", r);
}
public static void main(String[] args) {
final Configuration conf = HBaseConfiguration.create();
new ExampleSecureClient(conf).run();
}
}
票证缓存输出示例1:
2018-06-12 13:44:40,144 WARN [main] util.NativeCodeLoader: Unable to load
native-hadoop library for your platform... using builtin-java classes
where applicable
2018-06-12 13:44:40,975 INFO [main] zookeeper.ReadOnlyZKClient: Connect
0x62e136d3 to my.fqdn:2181 with session timeout=90000ms, retries 6, retry
interval 1000ms, keepAlive=60000ms
2018-06-12 13:44:42,806 INFO [main] client.HBaseAdmin: Started disable of
example_secure_client
2018-06-12 13:44:44,159 INFO [main] client.HBaseAdmin: Operation:
DISABLE, Table Name: default:example_secure_client completed
2018-06-12 13:44:44,590 INFO [main] client.HBaseAdmin: Operation: DELETE,
Table Name: default:example_secure_client completed
2018-06-12 13:44:46,040 INFO [main] client.HBaseAdmin: Operation: CREATE,
Table Name: default:example_secure_client completed
2018-06-12 13:44:46,041 INFO [main] examples.ExampleSecureClient: Writing
update: row1 -> value
2018-06-12 13:44:46,183 INFO [main] examples.ExampleSecureClient: Read
row1: keyvalues={row1/f1:q1/1528825486175/Put/vlen=5/seqid=0}
2018-06-12 13:44:46,183 INFO [main] examples.ExampleSecureClient:
Success!
2018-06-12 13:44:46,183 INFO [main] client.ConnectionImplementation:
Closing master protocol: MasterService
2018-06-12 13:44:46,183 INFO [main] zookeeper.ReadOnlyZKClient: Close
zookeeper connection 0x62e136d3 to my.fqdn:2181
- 通过通过principal和keytab登录再次执行status命令。
使用keytab登录的安全客户端的示例2:
package com.hortonworks.hbase.examples;
import java.io.File;
import java.security.PrivilegedAction;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.security.UserGroupInformation;
public class ExampleSecureClientWithKeytabLogin {
public static void main(String[] args) throws Exception {
final Configuration conf = HBaseConfiguration.create();
final String principal = "myself@EXAMPLE.COM";
final File keytab = new File("/etc/security/keytabs/myself.keytab");
assert keytab.isFile() : "Provided keytab '" + keytab + "' is not a
regular file.";
UserGroupInformation.setConfiguration(conf);
UserGroupInformation ugi =
UserGroupInformation.loginUserFromKeytabAndReturnUGI(
principal, keytab.getAbsolutePath());
ugi.doAs(new PrivilegedAction<Void>() {
@Override public Void run() {
new ExampleSecureClient(conf).run();
return null;
}
});
}
}
以下示例显示了通过keytab登录产生的输出:
2018-06-12 13:29:23,057 WARN [main] util.NativeCodeLoader: Unable to load
native-hadoop library for your platform... using builtin-java classes
where applicable
2018-06-12 13:29:23,574 INFO [main] zookeeper.ReadOnlyZKClient: Connect
0x192d43ce to my.fqdn:2181 with session timeout=90000ms, retries 6, retry
interval 1000ms, keepAlive=60000ms
2018-06-12 13:29:29,172 INFO [main] client.HBaseAdmin: Started disable of
example_secure_client
2018-06-12 13:29:30,456 INFO [main] client.HBaseAdmin: Operation:
DISABLE, Table Name: default:example_secure_client completed
2018-06-12 13:29:30,702 INFO [main] client.HBaseAdmin: Operation: DELETE,
Table Name: default:example_secure_client completed
2018-06-12 13:29:33,005 INFO [main] client.HBaseAdmin: Operation: CREATE,
Table Name: default:example_secure_client completed
2018-06-12 13:29:33,006 INFO [main] examples.ExampleSecureClient: Writing
update: row1 -> value
2018-06-12 13:29:33,071 INFO [main] examples.ExampleSecureClient: Read
row1: keyvalues={row1/f1:q1/1528824573066/Put/vlen=5/seqid=0}
2018-06-12 13:29:33,071 INFO [main] examples.ExampleSecureClient:
Success!
2018-06-12 13:29:33,071 INFO [main] client.ConnectionImplementation:
Closing master protocol: MasterService
2018-06-12 13:29:33,071 INFO [main] zookeeper.ReadOnlyZKClient: Close
zookeeper connection 0x192d43ce to my.fqdn:2181
使用Java客户端访问启用Kerberos的HBase群集
您可以使用Java客户端访问启用了Kerberos的HBase群集。
在你开始之前
•启用了Kerberos的HDP群集。
•您正在Java 8,Maven 3和Eclipse开发环境中工作。
•您具有Kerberos KDC的管理员访问权限。
执行以下任务,以使用Java客户端连接到HBase,并对表执行简单的Put操作。
程序
1.“下载配置”
2.“设置客户帐户”
3.“使用Java客户端访问启用Kerberos的HBase群集”
下载配置
请按照以下步骤下载所需的配置:
程序
1.从Ambari,将HBase和HDFS文件提取到conf目录,这将保存所有配置详细信息。
这些文件必须在$ HBASE_CONF_DIR目录下提取,其中$ HBASE_CONF_DIR是用于存储HBase配置文件的目录。 例如,/ etc / hbase / conf。
2.从KDC,从/etc/krb5.con下载krb5.conf文件。 您还可以将配置摘要放置在目录中。
includedir /etc/krb5.conf.d/
[logging]
default = FILE:/var/log/krb5libs.log
kdc = FILE:/var/log/krb5kdc.log
admin_server = FILE:/var/log/kadmind.log
[libdefaults]
dns_lookup_realm = false
ticket_lifetime = 24h
renew_lifetime = 7d
forwardable = true
rdns = false
default_realm = HWFIELD.COM
default_ccache_name = KEYRING:persistent:%{uid}
[realms]
HWFIELD.COM = {
kdc = ambud-hdp-3.field.hortonworks.com
admin_server = ambud-hdp-3.field.hortonworks.com
}
[domain_realm]
.hwfield.com = HWFIELD.COM
hwfield.com = HWFIELD.COM
设置客户帐号
请按照以下步骤为客户端设置一个kerberos帐户,并向HBase中的该帐户授予权限,因此
您可以创建,读取和写入表。
程序
1.登录到KDC。
2.切换到根目录。
3.运行kadmin.local:
$ sudo kadmin.local
kadmin.local: addprinc myself
WARNING: no policy specified for myself@EXAMPLE.COM; defaulting to no
policy
Enter password for principal "myself@EXAMPLE.COM":
Re-enter password for principal "myself@EXAMPLE.COM":
Principal "myself@EXAMPLE.COM" created.
kadmin.local: xst -k /etc/security/keytabs/myself.keytab -norandkey
myself
Entry for principal myself with kvno 1, encryption type aes256-cts-hmacsha1-96 added to keytab
WRFILE:/etc/security/keytabs/myself.keytab.
Entry for principal myself with kvno 1, encryption type aes128-cts-hmacsha1-96 added to keytab
WRFILE:/etc/security/keytabs/myself.keytab.
- 将密钥表文件复制到conf目录。
- 在HBase中授予权限。 有关更多信息,请参见为访问控制列表(ACL)配置HBase。
klist -k /etc/security/keytabs/hbase.headless.keytab
可选步骤:您应该保护keytab文件安全,以便只有HBase进程才能访问keytab。 这可以通过运行命令来完成。
$>sudo chmod 700 /etc/security/keytabs/hbase.headless.keytab
$ kinit -kt /etc/security/keytabs/hbase.headless.keytab hbase
$ hbase shell
hbase(main):001:0> status
1 active master, 0 backup masters, 4 servers, 1 dead, 1.2500 average load
- 向用户授权管理员权限。 您也可以自定义此选项,以限制该帐户的访问权限。 有关更多信息,请参见https://hbase.apache.org/0.94/book/ hbase.accesscontrol.configuration.html#d1984e4744
例子
hbase(main):001:0> grant 'myself', 'C'
创建Java客户端
请按照以下步骤创建Java客户端:
程序
1.启动Eclipse。
2.创建一个简单的Maven项目。
3.添加hbase-client和hadoop-auth依赖项。
客户端使用Hadoop UGI实用程序类使用keytab文件执行Kerberos身份验证。 它设置了上下文,以便所有操作都在hbase-user2安全上下文下执行。 然后,它执行所需的HBase操作,即检查/创建表以及执行放置和获取操作。
<dependencies>
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-client</artifactId>
<version>${hbase.version}</version>
<exclusions>
<exclusion>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-aws</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-auth</artifactId>
<version>${hadoop.version}</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>${hadoop.version}</version>
</dependency>
<dependency>
4.从可以反向DNS解析的节点上执行HBase Java客户端代码。
这是Kerberos身份验证的一部分。 因此,从不与HDP群集共享同一DNS基础结构的计算机上运行它会导致身份验证失败。
5.要验证Kerberos身份验证/ keytab /主体是否确实有效,您还可以从Java执行简单的Kerberos身份验证。 这使您对Java JAAS和Kerberos的工作方式有一些了解。
强烈建议您使用Maven Shade插件或Maven Jar插件将依赖项自动打包到胖客户端JAR中。 您也可以使用Eclipse导出功能,但是不建议在生产代码库中使用此功能。