功能
开启了 Kerberos认证的安全模式集群,进行应用开发时需要进行安全认证。
Kerberos这一名词来源于希腊神话“三个头的狗——地狱之门守护者”,后来沿用作为安全认证的概念,使用Kerberos的系统在设计上采用“客户端/服务器”结构与AES等加密技术,并且能够进行相互认证(即客户端和服务器端均可对对方进行身份认证)。可以用于防止窃听、防止replay攻击、保护数据完整性等场合,是一种应用对称密钥体制进行密钥管理的系统。
原理
Kerberos的原理架构和各模块的说明如下图所示:
原理架构
模块说明
- App Client:应用客户端,通常是需要提交任务(或者作业)的应用程序。
- App Server:应用服务端,通常是应用客户端需要访问的应用程序。
- Key Distribution Center(KDC):提供安全认证的服务。
- Database:存储Principal数据。
- Authentication Server(AS):认证服务器,认证客户端身份,发放客户访问TGS的票据授权票据(TGT)。
- Ticket Granting Server(TGS):票据授予服务器,发放应用客户端访问应用服务端所需的服务票据(ST)。
步骤原理说明
应用客户端(App Client)可以是集群内某个服务,也可以是客户二次开发的一个应用程序,应用程序可以向应用服务提交任务或者作业。
- AS_REQ:App Client在提交任务或者作业前,需要向AS申请TGT,用于建立和TGS的安全会话。
- AS_REP:AS在收到TGT请求后,会解析其中的参数来生成对应的TGT,使用App Client指定的用户名的密钥进行加密响应消息。
- TGS_REQ:App Client收到TGT响应消息后,解析获取TGT,此时,再由App Client(通常是RPC底层)向TGS获取应用服务端的ST。
- TGS_REP:TGS在收到ST请求后,校验其中的TGT合法后,生成对应的App Server的ST,再使用App Server密钥将响应消息进行加密处理。
- AP_REQ:App Client收到ST响应消息后,将ST打包到发给App Server的消息里面传输给对应的App Server。
- AP_REP:App Server端收到请求后,使用App Server对应的密钥解析其中的ST,并校验成功后,本次请求合法通过。
说明
Kerberos认证时需要配置Kerberos认证所需要的文件参数,主要包含keytab路径,Kerberos认证的principal,Kerberos认证所需要的客户端配置krb5.conf文件。
方法login()为调用的UserGroupInformation的方法执行Kerberos认证,生成TGT票据。
方法doSth()调用hadoop的接口访问文件系统,此时底层RPC会自动携带TGT去Kerberos认证,生成ST票据。
基本概念
- 票据授权票据(Ticket-Granting Ticket,TGT):由AS生成,提供给应用程序与TGS建立认证安全会话,该票据的默认有效期为24小时,24小时后该票据自动过期。
- 服务票据(Server Ticket,ST):由TGS生成,提供给应用程序与应用服务建立安全会话,该票据一次性有效。
- 用户身份(Principal):用于标识用户或者服务,格式一般为<用户名或服务名>/<主机名>,例如hdfs/host1, user/host2。
样例
以HDFS为例,前提:HDFS集群已经开启Kerberos认证。
通过UserGroupInformation
package bigdata.hdfs.examples;
import java.io.IOException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileStatus; import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.security.UserGroupInformation;
public class KerberosTest {
private FileSystem fs;
private Configuration conf;
/**
* initialize Configuration
*/
private void initConf() {
conf = new Configuration();
//add configuration files
//PATH_TO_HDFS_SITE_XML是hdfs-site.xml的路径
//PATH_TO_CORE_SITE_XML是core-site.xml的路径
conf.addResource(new Path(PATH_TO_HDFS_SITE_XML));
conf.addResource(new Path(PATH_TO_CORE_SITE_XML));
}
/**
* login Kerberos to get TGT, if the cluster is in security mode
* @throws IOException if login is failed
*/
private void login() throws IOException {
// not security mode, just return
if (! "kerberos".equalsIgnoreCase(conf.get("hadoop.security.authentication"))) {
return;
}
//security mode
//PATH_TO_KRB5_CONF是krb5.conf的路径
System.setProperty("java.security.krb5.conf", PATH_TO_KRB5_CONF);
UserGroupInformation.setConfiguration(conf);
//PATH_TO_KEYTAB是keytab的路径
//PRNCIPAL_NAME是pincipal名称
UserGroupInformation.loginUserFromKeytab(PRNCIPAL_NAME, PATH_TO_KEYTAB);
}
/**
* initialize FileSystem, and get ST from Kerberos
* @throws IOException
*/
private void initFileSystem() throws IOException {
fs = FileSystem.get(conf);
}
/**
* An example to access the HDFS
* @throws IOException
*/
private void doSth() throws IOException {
Path path = new Path("/tmp");
FileStatus fStatus = fs.getFileStatus(path);
System.out.println("Status of " + path + " is " + fStatus);
//other thing
}
public static void main(String[] args) throws Exception {
KerberosTest test = new KerberosTest();
test.initConf();
test.login();
test.initFileSystem();
test.doSth();
}
}
通过kinit命令,执行hadoop命令
kinit -kt /etc/security/keytabs/hdfs.keytab hdfs/host1
hadoop fs -ls /tmp