HDFS集成kerberos认证

1. DataNode的安全配置

1.1 前言

由于DataNode数据传输走的不是rpc,而是http。所以DataNode无法使用kerberos的方式进行认证。为了解决这个问题,有两种方式的配置,来实现DataNode数据传输的安全性

  • JSVC

  • TLS/SSL

    JSVC方式的大体原理是使用JSVC工具,让datanode能够使用特权端口启动,所谓特权端口是指1024以下的端口,这种安全配置假定攻击者无法获取root权限,所以也就无法操作datanode来实现。hadoop 2.6.0以前,只能使用这种方式,配置较为复杂,本次调研暂时采用的就是JSVC的方式(放在配置模块一起细述)。

    hadoop 2.6.0以后引入了SASL方式,通过TLS/SSL来实现数据的安全传输,下面详细介绍这种方式

1.2 JSVC配置

1.2.1 下载及编译
wget https://downloads.apache.org//commons/daemon/source/commons-daemon-1.2.4-src.tar.gz
tar -xzvf commons-daemon-1.2.4-src.tar.gz
cd commons-daemon-1.2.4-src/src/native/unix/
./configure --with-java=/opt/tools/jdk1.8.0_181

# 编译
make

# 编译之后目录下会生成一个jsvc的指令
# 验证
./jsvc --help
  • 如果make指令找不到,则执行以下命令安装插件,然后重试

    yum group install "Development Tools" -y
    
    1.2.2 安装
  • 将编译后的jsvc 指令 复制到 ${HADOOP_HOME}/libexec 目录下

    cp jsvc ${HADOOP_HOME}/libexec/
    
  • 首先确认 ${HADOOP_HOME}/share/hadoop/hdfs/lib目录下 没有jar包 : commons-daemon-*.jar , 如果有,删除!!!

  • 将编译后或者下载的文件找到commons-daemon-1.2.4.jar 放到 ${HADOOP_HOME}/share/hadoop/hdfs/lib目录下

    1.3 TLS/SSL配置

    1.3.1 证书生成和安装

    TLS/SSL相关原理见文档 ,这里粘贴地址

    首先保证机器上已经安装好了openssl。下面是详细的配置。核心思想是,做一个私有的CA,然后通过这个私有的CA证书给所有的其它证书签名,通过将私有CA的证书安装到各机器的信任区里,实现一个各机器间的TLS/SSL通信

    然后在集群中随便找一台机器,先生成CA证书,这里在Master这台机器上操作

 openssl req -new -x509 -keyout ca_private.key -out ca_cert -days 9999 -subj '/C=CN/ST=chengdu/L=chengdu/O=bigdata/OU=bigdata/CN=master'

将上述的CA私钥跟更要证书拷贝到各个机器。然后再各机器上做如下操作,当然如果我们在生成证书时,用的密码完全一样也可以在一个机器上做,最后把相关的keystore和truststore分发到所有的机器。

//生成自己的公私秘钥对
keytool -keystore keystore -alias localhost -validity 9999 -genkey -keyalg RSA -keysize 2048 -dname "CN=slave2, OU=bigdata, O=bigdata, L=chengdu, ST=chengdu, C=CN"

//将上述的CA公钥证书导入本机的信任区truststore
keytool -keystore truststore -alias CARoot -import -file ca_cert 

//将上述的CA公钥导入本机的keystore中
keytool -keystore keystore -alias CARoot -import -file ca_cert 

//将本机的公钥证书导出
keytool -certreq -alias localhost -keystore keystore -file local_cert

//对CA私钥,对本机的公钥证书进行签名
openssl x509 -req -CA hd_ca_cert -CAkey ca_private.key -in local_cert -out local_cert_signed -days 9999 -CAcreateserial 

//将签名后的证书导入的自己的Keystore
keytool -keystore keystore -alias localhost -import -file local_cert_signed
1.3.2 hdfs-site.xml的重点配置
  • 配置dfs.http.policy的value为HTTPS_ONLY

  • 配置dfs.data.transfer.protection的value为authenticationintegrityprivacy任意一种。一般内部集群用authentication即可

    • authentication ,只认证签名
    • integrity 除了认证签名外,还验证数据是否被篡改
    • privacy,数据除了上述的认证和完整性验证之外还要加密传输
1.3.3 ssl-client.xml 和 ssl-server.xml配置

hadoop在在跟core-site.xml同级目录下一般有ssl-client.xml.example和ssl-server.xml.example两个模板文件,我们可以直接去掉template来后作为配置文件来配置。他们是用来配置当前组件作为服务端时,自己的证书kestore位置,和作为客户端时,自己的信任证书truststore位置

  • ssl-client.xml配置如下
  <configuration>                                                                                                                 

<property> <name>ssl.client.truststore.location</name>  
 <value>/opt/ssl_store/truststore</value>  
 <description>Truststore to be used by clients like distcp. Must be  
 specified.  
 </description> </property>

<property> <name>ssl.client.truststore.password</name>  
 <value>123456</value>  
 <description>Optional. Default value is "".  
 </description> </property>

<property> <name>ssl.client.truststore.type</name>  
 <value>jks</value>  
 <description>Optional. The keystore file format, default value is "jks".  
 </description> </property>

<property> <name>ssl.client.truststore.reload.interval</name>  
 <value>10000</value>  
 <description>Truststore reload check interval, in milliseconds.  
 Default value is 10000 (10 seconds).  
 </description> </property>

<property> <name>ssl.client.keystore.location</name>  
 <value>/opt/ssl_store/keystore</value>  
 <description>Keystore to be used by clients like distcp. Must be  
 specified.  
 </description> </property>  
<property> <name>ssl.client.keystore.password</name>
 <value>123456</value>
 <description>Optional. Default value is "".
 </description></property>

<property>
  <name>ssl.client.keystore.keypassword</name>
  <value>123456</value>
  <description>Optional. Default value is "".
  </description>
</property>

<property>
  <name>ssl.client.keystore.type</name>
  <value>jks</value>
  <description>Optional. The keystore file format, default value is "jks".
  </description>
</property>

</configuration>
  • ssl-server.xml
<property>
  <name>ssl.server.keystore.password</name>
  <value>123456</value>
  <description>Must be specified.
  </description>
</property>
  
<property>
  <name>ssl.server.keystore.keypassword</name>
  <value>123456</value>
  <description>Must be specified.
  </description>
</property>

<property>
  <name>ssl.server.keystore.type</name>
  <value>jks</value>
  <description>Optional. The keystore file format, default value is "jks".
  </description>
</property>

<property>
  <name>ssl.server.exclude.cipher.list</name>
  <value>TLS_ECDHE_RSA_WITH_RC4_128_SHA,SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA,
  SSL_RSA_WITH_DES_CBC_SHA,SSL_DHE_RSA_WITH_DES_CBC_SHA,
  SSL_RSA_EXPORT_WITH_RC4_40_MD5,SSL_RSA_EXPORT_WITH_DES40_CBC_SHA,
  SSL_RSA_WITH_RC4_128_MD5</value>
  <description>Optional. The weak security cipher suites that you want excluded
  from SSL communication.</description>
</property>

</configuration>

上述配置的123456是我们在做证书时使用的密码

1.3.4 yarn(详见Yarn集成Kerberos认证)

  • 整体配置

    <property>
          <name>yarn.resourcemanager.principal</name>
          <value>rm/_HOST@TEST.COM</value>
      </property>
    <property>
          <name>yarn.resourcemanager.keytab</name>
          <value>/opt/keytab_store/rm.service.keytab</value>
      </property>
    <property>
          <name>yarn.nodemanager.principal</name>
          <value>nm/_HOST@TEST.COM</value>
      </property>
    <property>
          <name>yarn.nodemanager.keytab</name>
          <value>/opt/keytab_store/nm.service.keytab</value>
      </property>
    <property>
          <!--安全集群必须使用下面的LinuxContainerExecutor-->
          <name>yarn.nodemanager.container-executor.class</name>
          <value>org.apache.hadoop.yarn.server.nodemanager.LinuxContainerExecutor</value>
      </property>
    <property>
          <name>yarn.nodemanager.linux-container-executor.group</name>
          <value>hadoop</value>
      </property>
    <property>
          <name>yarn.nodemanager.linux-container-executor.path</name>
          <value>/opt/hadoop-3.1.3/bin/container-executor</value>
      </property>
    
    1.3.5 container-executor
  • build LinuxContainerExecutor

    上述yarn.nodemanager.linux-container-executor.path指定了LinuxContainerExecutor对应的可执行文件container-executor的路径。
    hadoop发行包在bin路径下,一般就已经有这个文件了。
    这个文件执行需要一个配置,container-executor.cfg 。其默认加载的是$HADOOP_HOME/etc/hadoop/container-executor.cfg这个路径的配置文件。

    但由于这个路径本身又有hadoop的其它配置文件,而container-executor又要求container-executor.cfg所在路径所有层级权限都只能root访问。这会导致我们其它组件启动出现各种奇奇古怪的问题。

    所以我们需要另外指定container-executor.cfg文件的位置。但问题是container-executor这个二进制文件在构建时,已经写死了文件路径。如果我们需要重指定配置文件路径,需要重新打包container-executor。构建步骤为

  • 首先下载同版本的hadoop源码

  • 进入到源码包的路径hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager

  • 使用命令mvn package -DskipTests=true -Dcontainer-executor.conf.dir=/etc/hadoop/ 构建,container-executor.conf.dir参数即指定新的container-executor.cfg文件路径

  • 构建完成后,在构建路径下的target/native/target/usr/local/bin路径即可找到新构建的container-executor,将其拷贝到$HADOOP_HOME/bin下,替换原来的程序即可

    1.3.5.1 配置container-executor.cfg
  • 在/etc/hadoop/中,创建container-executor.cfg,其配置内容如下

    yarn.nodemanager.linux-container-executor.group=hadoop
    banned.users=hdfs,yarn,mapred,bin
    min.user.id=1000
    allowed.system.users=
    feature.tc.enabled=false
    

    注意配置每行不要有空格,yarn.nodemanager.linux-container-executor.group这个配置值同yarn-site.xml中的一致

  • 总结权限配置需要配置的项
    在这里插入图片描述

1.3.6 文件权限修改
chown root:hadoop /opt/hadoop-3.1.3/bin/container-executor
chmod 6050 /opt/hadoop-3.1.3/bin/container-executor
chown root:hadoop /etc/hadoop/container-executor.cfg
chmod 400 /etc/hadoop/container-executor.cfg

假设在yarn-site.xml的中yarn.nodemanager.local-dirs 配置 路径为/home/var/data/hadoop/nodemanager/data
yarn.nodemanager.log-dirs配置路径为 /home/var/data/hadoop/nodemanager/log,还需要做以下权限配置

chown yarn:hadoop /home/var/data/hadoop/nodemanager/data 
chown yarn:hadoop /home/var/data/hadoop/nodemanager/log  
chmod 755 /home/var/data/hadoop/nodemanager/data
chmod 755 /home/var/data/hadoop/nodemanager/log
1.3.7 mapreduce
 <property>
        <name>mapreduce.jobhistory.keytab</name>
        <value>/opt/keytab_store/jhs.service.keytab</value>
    </property>
 <property>
        <name>mapreduce.jobhistory.principal</name>
        <value>jhs/_HOST@TEST.COM</value>
    </property>
1.3.8 启动
  • 配置完后,按原来的方式启动即可。只是由于hdfs开起了SSL/TLS ,其原来的9870端口,变成了9871, 且需要通过https访问。比如我们这地址为:https://master:9871

2. 创建HDFS的principal

2.1 在kerberos服务端节点进入kadmin.local

kadmin.local:  addprinc experiment/node135
kadmin.local:  addprinc experiment/node136
kadmin.local:  addprinc experiment/node137

kadmin.local: ktadd -norandkey -k /opt/keytab/experiment.keytab experiment/node135
kadmin.local: ktadd -norandkey -k /opt/keytab/experiment.keytab experiment/node136
kadmin.local: ktadd -norandkey -k /opt/keytab/experiment.keytab experiment/node137
2.2 分发密钥文件至对应节点
scp /opt/keytab/experiment.keytab node136:/opt/keytab
scp /opt/keytab/experiment.keytab node137:/opt/keytab

3. 配置HDFS的kerberos相关配置项(以下配置在namenode节点配置完成后需同步至其它节点)

3.1 core-site.xml配置

<!-- 新增kerberos认证管理  -->
    <property>
     <name>hadoop.security.authentication</name>
     <value>kerberos</value>
   </property>
   <property>
     <name>hadoop.security.authorization</name>
     <value>true</value>
   </property>

   <property>
     <name>hadoop.rpc.protection</name>
     <value>authentication</value>
     <description>authentication : authentication only (default); integrity : integrity check in addition to authentication; privacy : data encryption in addition to integrity</description>
   </property>
    <property>
      <name>hadoop.proxyuser.root.hosts</name>
      <value>*</value>
   </property>
   <property>
      <name>hadoop.proxyuser.root.groups</name>
      <value>*</value>
   </property>
   <property>
      <name>hadoop.proxyuser.hdfs.hosts</name>
      <value>*</value>
   </property>

   <property>
      <name>hadoop.proxyuser.hdfs.groups</name>
      <value>*</value>
   </property>
   <property>
      <name>hadoop.proxyuser.yarn.hosts</name>
      <value>*</value>
   </property>

   <property>
      <name>hadoop.proxyuser.yarn.groups</name>
      <value>*</value>
   </property>

   <property>
      <name>hadoop.proxyuser.hive.hosts</name>
      <value>*</value>
   </property>

   <property>
      <name>hadoop.proxyuser.hive.groups</name>
      <value>*</value>
   </property>

3.2 hdfs-site.xml配置

<!-- 新增kerberos认证管理  -->
<property>
    <name>dfs.block.access.token.enable</name>
    <value>true</value>
</property>
    <property>
        <name>dfs.permissions.supergroup</name>
        <value>hadoop</value>
    </property>
<property>
    <name>dfs.namenode.kerberos.principal</name>
    <value>experiment/node136@HC.CN</value>
</property>
<property>
    <name>dfs.namenode.keytab.file</name>
    <value>/opt/keytab/experiment.keytab</value>
</property>
<property>
    <name>dfs.namenode.kerberos.internal.spnego.principal</name>
    <value>experiment/node136@HC.CN</value>
</property>
<property>
        <name>dfs.journalnode.kerberos.principal</name>
        <value>experiment/node136@HC.CN</value>
    </property>
<property>
        <name>dfs.journalnode.keytab.file</name>
        <value>/opt/keytab/experiment.keytab</value>
    </property>
<property>
        <name>dfs.journalnode.kerberos.internal.spnego.principal</name>
        <value>${dfs.web.authentication.kerberos.principal}</value>
    </property>
<property>
    <name>dfs.namenode.kerberos.internal.spnego.keytab</name>
    <value>experiment/node136@HC.CN</value>
</property>
<property>
    <name>dfs.web.authentication.kerberos.principal</name>
    <value>experiment/node136@HC.CN</value>
</property>
<property>
    <name>dfs.web.authentication.kerberos.keytab</name>
    <value>/opt/keytab/experiment.keytab</value>
</property>
    <property>
        <name>dfs.encrypt.data.transfer</name>
        <value>true</value>
        <description>数据传输协议激活数据加密</description>
    </property>
<property>
    <name>dfs.datanode.kerberos.principal</name>
    <value>experiment/node136@HC.CN</value>
</property>
<property>
    <name>dfs.datanode.keytab.file</name>
<value>/opt/keytab/experiment.keytab</value>
</property>
    <property>
        <name>dfs.datanode.data.dir.perm</name>
        <value>700</value>
    </property>
    <property>
        <name>dfs.datanode.address</name>
        <value>0.0.0.0:1004</value>
        <description>[重要]安全数据节点必须使用特权端口,以确保服务器安全启动。这意味着服务器必须通过jsvc启动。 或者,如果使用SASL对数据传输协议进行身份验证,则必须将其设置为非特权端口. (See dfs.data.transfer.protection.)</description>
    </property>
    <property>
        <name>dfs.datanode.http.address</name>
        <value>0.0.0.0:1006</value>
        <description>[重要]安全数据节点必须使用特权端口,以确保服务器安全启动。这意味着服务器必须通过jsvc启动。</description>
    </property>

3.3 yarn-site.xml配置(详见Yarn集成Kerberos认证)

 <!-- 新增kerberos认证管理  -->
<property>
    <name>yarn.resourcemanager.principal</name>
    <value>experiment/node136@HC.CN</value>
</property>
<property>
    <name>yarn.resourcemanager.keytab</name>
    <value>/opt/keytab/experiment.keytab</value>
</property>
<property>
    <name>yarn.nodemanager.keytab</name>
    <value>/opt/keytab/experiment.keytab</value>
</property>
<property>
    <name>yarn.nodemanager.principal</name>
    <value>experiment/node136@HC.CN</value>
</property>

3.4 hadoop-env.sh配置

#新增/修改参数
export HDFS_DATANODE_SECURE_USER=experiment
export JSVC_HOME=/home/experiment/workspace/hadoop/libexec

4. HDFS启动

4.1 experiment用户使用./start-dfs.sh启动除datanode服务外的其它服务

4.2 root用户使用./start-secure-dns.sh启动datanode服务

4.3 每个节点需在命令行使用HDFS时,使用如下命令验证kerberos权限

kinit -kt /opt/keytab/experiment.keytab experiment/node137@HC.CN

5 JavaAPI使用kerberos服务

5.1 将 core-site.xml/hdfs-site.xml/krb5.conf/experiment.keytab 放置在maven项目的resources目录下

5.2 pom.xml添加以下配置

        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-common</artifactId>
            <version>3.1.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-hdfs</artifactId>
            <version>3.1.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-hdfs-client</artifactId>
            <version>3.1.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-nfs</artifactId>
            <version>3.1.1</version>
        </dependency>
4.4.3 Java代码编写
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.security.UserGroupInformation;
import java.io.IOException;


public class HDFSKerberos {
    public static void test1(String user, String keytab, String dir) throws Exception {
        Configuration conf = new Configuration();
        conf.set("hadoop.security.authentication", "Kerberos");
        conf.addResource(new Path("E:\\tmp\\hbasetest1\\src\\main\\resources\\hdfs-site.xml"));
        conf.addResource(new Path("E:\\tmp\\hbasetest1\\src\\main\\resources\\core-site.xml"));
        System.setProperty("java.security.krb5.conf", "E:\\tmp\\hbasetest1\\src\\main\\resources\\krb5.conf");
        UserGroupInformation.setConfiguration(conf);
        UserGroupInformation.loginUserFromKeytab(user, keytab);
        listDir(conf, dir);
    }

    public static void listDir(Configuration conf, String dir) throws IOException {
        FileSystem fs = FileSystem.get(conf);
        FileStatus files[] = fs.listStatus(new Path(dir));
        for (FileStatus file : files) {
            System.out.println(file.getPath());
        }
    }

    public static void main(String[] args) {
        // user为kerberos密钥对应的用户
        String user = "experiment/node137@HC.CN";
        // 提前在kerberos服务端生成好的keytab密钥
        String keytab = "E:\\tmp\\hbasetest1\\src\\main\\resources\\experiment.keytab";
        String dir = "hdfs://hdfsha/kbtest";
        try {
            test1(user, keytab, dir);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

今天写代码了没

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值