如何为HttpFS服务配置SSL

2018-04-01 20:57:34 浏览数 (1)

温馨提示:要看高清无码套图,请使用手机打开并单击图片放大查看。 Fayson的github:https://github.com/fayson/cdhproject 提示:代码块部分可以左右滑动查看噢

1.文档编写目的


前面Fayson也介绍过《如何在集群外节点跨网段向HDFS写数据》和《如何使用Java代码访问HDFS》。在非Kerberos的环境中,使用HttpFS是不需要输入用户密码的,为了集群数据安全考虑可以考虑配置HttpFS的SSL。本篇文章主要介绍如何为HttpFS服务配置SSL。但Fayson依旧建议在开启HttpFS服务的集群里必须开启Kerberos。

  • 内容概述

1.生成Keystore文件

2.配置HttpFS服务SSL并验证

3.Java客户端访问及测试

4.总结

  • 测试环境

1.CentOS7.2

  • 前置条件

1.集群未启用Kerberos

2.生成KeyStore文件


在keystore里,包含两种数据:

  • 密钥实体(Key entity)——密钥(secret key)又或者是私钥和配对公钥(采用非对称加密)
  • 可信任的证书实体(trusted certificate entries)——只包含公钥

这里我们使用Java提供的Keytool证书管理工具来生成一个Keystore文件。

在部署了HttpFS服务的节点上,执行如下命令生成KeyStore文件

代码语言:txt复制
[root@cdh01 ~]# sudo -u httpfs /usr/java/jdk1.7.0_67-cloudera/bin/keytool -genkey -alias tomcat -keyalg RSA
Enter keystore password:  (输入密码)
Re-enter new password: (再次输入密码)
What is your first and last name?
  [Unknown]:  cdh01.macro.com
What is the name of your organizational unit?
  [Unknown]:  fayson
What is the name of your organization?
  [Unknown]:  fayson
What is the name of your City or Locality?
  [Unknown]:  fayson
What is the name of your State or Province?
  [Unknown]:  fayson
What is the two-letter country code for this unit?
  [Unknown]:  fason
Is CN=fayson, OU=cloudera, O=cloudera, L=shanghai, ST=shanghai, C=shanghai correct?
  [no]:  yes
Enter key password for <tomcat>
        (RETURN if same as keystore password):  (输入密码)
Re-enter new password: (再次输入密码)
[root@cdh01 ~]# 

(可左右滑动)

这里需要注意几个地方,需要输入密码和CN(CN必须为HttpFS服务所在节点的hostname)。

执行成功后证书文件默认生成在/var/lib/hadoop-httpfs目录下的 .keystore文件:

完成证书文件的生成后,接下来通过ClouderaManager界面为HttpFS服务配置SSL。

3.配置SSL


1.使用管理员用户登录Cloudera Manager的WEB界面

进入HDFS服务配置页面,范围选择“HttpFS”,类别选择“安全性”

2.配置启用SSL和Keystore文件

保存配置,回到CM主页根据提示重启相应服务。

4.验证配置是否生效


1.浏览器验证是否能正常访问HDFS文件列表,查看HDFS根目录下所有文件

请求成功,使用的是https

2.通过curl查看是否正常访问

代码语言:txt复制
[root@cdh01 ~]# curl -k "https://192.168.10.4:14000/webhdfs/v1/?op=liststatus&user.name=hdfs"

(可左右滑动)

5.Java客户端访问


1.将HttpFS服务器上的.keystore证书下载至本地命名为httpfs.keystore

2.使用Maven创建一个java工程,pom.xml文件中增加如下依赖

代码语言:txt复制
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.4</version>
</dependency>
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpmime</artifactId>
    <version>4.5.4</version>
</dependency>

(可左右滑动)

3.编写访问HttpFS的示例代码

代码语言:txt复制
package com.cloudera.hdfs.nonekerberos;
import javax.net.ssl.SSLContext;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
/**
 * package: com.cloudera.hdfs.nonekerberos
 * describe: Java使用HttpClient访问启用SSL的HttpFS服务
 * creat_user: Fayson
 * email: htechinfo@163.com
 * creat_date: 2018/1/13
 * creat_time: 下午9:56
 * 公众号:Hadoop实操
 */
public class HttpFSSSLDemo {
    private static String HTTPFS_HOST = "cdh01.macro.com";
    public static void main(String[] args) {
        try{
            SSLContext sslcontext = SSLContexts.custom()
                    .loadTrustMaterial(new File("/Volumes/Transcend/keytab/ssl/httpfs-server.keystore"), "123456".toCharArray(), new TrustSelfSignedStrategy()).build();
            // Allow TLSv1 protocol only
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                    sslcontext,
                    new String[] { "TLSv1" },
                    null,
                    SSLConnectionSocketFactory.getDefaultHostnameVerifier());
            CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
            System.out.println("===========Case No.1  List resources==========");
            String getRequest =  "https://"   HTTPFS_HOST   ":14000/webhdfs/v1/?op=liststatus&user.name=hdfs";
            HttpGet httpget = new HttpGet(getRequest);
            System.out.println("executing request "   httpget.getRequestLine());
            CloseableHttpResponse response = httpclient.execute(httpget);
            System.out.println("----------------------------------------");
            System.out.println(response.getStatusLine());
            HttpEntity entity = response.getEntity();
            BufferedReader br =
                    new BufferedReader(new InputStreamReader((entity.getContent())));
            String output;
            while ((output = br.readLine()) != null) {
                System.out.println(output);
            }
            EntityUtils.consume(entity);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

(可左右滑动)

4.示例运行结果

6.常见问题


运行时报如下异常

代码语言:txt复制
javax.net.ssl.SSLPeerUnverifiedException: Certificate for <114.119.11.142> doesn't match any of the subject alternative names: []
   at org.apache.http.conn.ssl.SSLConnectionSocketFactory.verifyHostname(SSLConnectionSocketFactory.java:467)
   at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:397)
   at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:355)
   at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:142)
   at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:373)
   at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:381)
   at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:237)
   at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:185)
   at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89)
   at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:111)
   at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185)
   at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)
   at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:108)
   at com.cloudera.hdfs.nonekerberos.HttpFSSSLDemo.main(HttpFSSSLDemo.java:50)
   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
   at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
   at java.lang.reflect.Method.invoke(Method.java:483)
   at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)

(可左右滑动)

异常原因:

1.在生成keystore文件时未指定CN为HttpFS服务所在节点的hostname

2.直接访问HttpFS服务的IP地址导致,需要配置hosts文件

7.总结


  • 在生成HttpFS服务的keystore文件时CN信息必须为该服务的hostsname,否则会报错
  • 在访问时需要配置本地的hosts文件

GitHub地址:

https://github.com/fayson/cdhproject/blob/master/hdfsdemo/src/main/java/com/cloudera/hdfs/nonekerberos/HttpFSSSLDemo.java

提示:代码块部分可以左右滑动查看噢 为天地立心,为生民立命,为往圣继绝学,为万世开太平。 温馨提示:要看高清无码套图,请使用手机打开并单击图片放大查看。

推荐关注Hadoop实操,第一时间,分享更多Hadoop干货,欢迎转发和分享。

原创文章,欢迎转载,转载请注明:转载自微信公众号Hadoop实操

0 人点赞