
# MRS组件应用安全认证说明
#### Kerberos认证说明
开启了Kerberos认证的安全模式集群，进行应用开发时需要进行安全认证。使用Kerberos的系统在设计上采用"客户端/服务器"结构与AES等加密技术，并且能够进行相互认证（即客户端和服务器端均可对对方进行身份认证）。可以用于防止窃听、防止replay攻击、保护数据完整性等场合，是一种应用对称密钥体制进行密钥管理的系统。
图1Kerberos原理架构   
![](https://support.huaweicloud.com/devg-lts-mrs/zh-cn_image_0000001918070244.png "点击放大")
表1Kerberos模块说明 
| 模块                 | 说明                          |
|:---|:---|
| Application Client | 应用客户端，通常是需要提交任务（或者作业）的应用程序。 |
| Application Server | 应用服务端，通常是应用客户端需要访问的应用程序。    |
| Kerberos           | 提供安全认证的服务。                  |
| KerberosAdmin      | 提供认证用户管理的进程。                |
| KerberosServer     | 提供认证票据分发的进程。                |
   
应用客户端（Application Client）可以是集群内某个服务，也可以是客户二次开发的一个应用程序，应用程序可以向应用服务提交任务或者作业。
1. 应用程序在提交任务或者作业前，需要向Kerberos服务申请TGT（Ticket-Granting Ticket），用于建立和Kerberos服务器的安全会话。
2. Kerberos服务在收到TGT请求后，会解析其中的参数来生成对应的TGT，使用客户端指定的用户名的密钥进行加密响应消息。
3. 应用客户端收到TGT响应消息后，解析获取TGT，此时，再由应用客户端（通常是rpc底层）向Kerberos服务获取应用服务端的ST（Server Ticket）。
4. Kerberos服务在收到ST请求后，校验其中的TGT合法后，生成对应的应用服务的ST，再使用应用服务密钥将响应消息进行加密处理。
5. 应用客户端收到ST响应消息后，将ST打包到发给应用服务的消息里面传输给对应的应用服务端（Application Server）。
6. 应用服务端收到请求后，使用本端应用服务对应的密钥解析其中的ST，并校验成功后，本次请求合法通过。
 
#### 安全认证基本概念
本文以HDFS组件应用的安全认证为例介绍安全认证相关的常见基本概念，可以帮助用户减少学习Kerberos框架所花费的时间，有助于更好地理解Kerberos业务。
**TGT**
票据授权票据（Ticket-Granting Ticket），由Kerberos服务生成，提供给应用程序与Kerberos服务器建立认证安全会话，该票据的默认有效期为24小时，24小时后该票据自动过期。
TGT申请方式(以HDFS为例)：
- 通过HDFS提供的接口获取。
  ```
  /**
    * 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
      System.setProperty("java.security.krb5.conf", PATH_TO_KRB5_CONF);
          
      UserGroupInformation.setConfiguration(conf);
      UserGroupInformation.loginUserFromKeytab(PRINCIPAL_NAME, PATH_TO_KEYTAB);        
    }
  ```
  
- 通过MRS集群客户端以**kinit** 方式获取。
  1. 登录MRS集群客户端所在节点，进入客户端安装目录。 **cd** *{客户端安装目录}*
     
  
  2. 执行以下命令配置环境变量。 **source bigdata_env**
     
  
  3. 执行以下命令进行用户认证。 **kinit** *MRS* *集群业务用户*
     
   
**ST**
服务票据（Server Ticket），由Kerberos服务生成，提供给应用程序与应用服务建立安全会话，该票据一次性有效。
ST的生成在MRS中，基于hadoop-rpc通信，由rpc底层自动向Kerberos服务端提交请求，由Kerberos服务端生成。
#### Kerberos认证代码示例
```
package com.huawei.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 static String PATH_TO_HDFS_SITE_XML = KerberosTest.class.getClassLoader().getResource("hdfs-site.xml")
            .getPath();
    private static String PATH_TO_CORE_SITE_XML = KerberosTest.class.getClassLoader().getResource("core-site.xml")
            .getPath();
    private static String PATH_TO_KEYTAB = KerberosTest.class.getClassLoader().getResource("user.keytab").getPath();
    private static String PATH_TO_KRB5_CONF = KerberosTest.class.getClassLoader().getResource("krb5.conf").getPath();
    private static String PRINCIPAL_NAME = "develop";
    private FileSystem fs;
    private Configuration conf;
    
    /**
     * initialize Configuration
     */
    private void initConf() {
        conf = new Configuration();
        
        // add configuration files
        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
        System.setProperty("java.security.krb5.conf", PATH_TO_KRB5_CONF);
        
        UserGroupInformation.setConfiguration(conf);
        UserGroupInformation.loginUserFromKeytab(PRINCIPAL_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();       
    }
}
```
![](https://support.huaweicloud.com/devg-lts-mrs/public_sys-resources/note_3.0-zh-cn.png)
- Kerberos认证时需要配置Kerberos认证所需要的文件参数，主要包含keytab文件路径、Kerberos认证的用户名称、Kerberos认证所需要的客户端配置"krb5.conf"文件。
- login()方法为调用hadoop的接口执行Kerberos认证，生成TGT票据。
- doSth()方法调用hadoop的接口访问文件系统，此时底层RPC会自动携带TGT去Kerberos认证，生成ST票据。
- 以上代码可在安全模式下的HDFS二次开发样例工程中创建KerberosTest.java，运行并查看调测结果，具体操作过程请参考[HDFS开发指南（安全模式）](https://support.huaweicloud.com/devg-lts-mrs/mrs_07_090000.html)。
 
