001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.security;
019
020import java.io.File;
021import java.security.Security;
022import java.util.ArrayList;
023import java.util.List;
024import java.util.stream.Stream;
025import org.apache.commons.io.FileUtils;
026import org.apache.hadoop.conf.Configuration;
027import org.apache.hadoop.hbase.HBaseParameterizedTestTemplate;
028import org.apache.hadoop.hbase.io.crypto.tls.KeyStoreFileType;
029import org.apache.hadoop.hbase.io.crypto.tls.X509KeyType;
030import org.apache.hadoop.hbase.io.crypto.tls.X509TestContext;
031import org.apache.hadoop.hbase.io.crypto.tls.X509TestContextProvider;
032import org.apache.hadoop.hbase.io.crypto.tls.X509Util;
033import org.apache.hadoop.hbase.ipc.NettyRpcClient;
034import org.apache.hadoop.hbase.ipc.NettyRpcServer;
035import org.apache.hadoop.hbase.ipc.RpcClient;
036import org.apache.hadoop.hbase.ipc.RpcClientFactory;
037import org.apache.hadoop.hbase.ipc.RpcServer;
038import org.apache.hadoop.hbase.ipc.RpcServerFactory;
039import org.apache.hadoop.hbase.testclassification.LargeTests;
040import org.apache.hadoop.hbase.testclassification.SecurityTests;
041import org.bouncycastle.jce.provider.BouncyCastleProvider;
042import org.junit.jupiter.api.AfterAll;
043import org.junit.jupiter.api.AfterEach;
044import org.junit.jupiter.api.BeforeAll;
045import org.junit.jupiter.api.BeforeEach;
046import org.junit.jupiter.api.Tag;
047import org.junit.jupiter.params.provider.Arguments;
048
049@Tag(SecurityTests.TAG)
050@Tag(LargeTests.TAG)
051@HBaseParameterizedTestTemplate(name = "{index}: caKeyType={0}, certKeyType={1}, keyPassword={2},"
052  + " acceptPlainText={3}, clientTlsEnabled={4}")
053public class TestSaslTlsIPC extends AbstractTestSecureIPC {
054
055  private static X509TestContextProvider PROVIDER;
056
057  private X509KeyType caKeyType;
058
059  private X509KeyType certKeyType;
060
061  private char[] keyPassword;
062
063  private boolean acceptPlainText;
064
065  private boolean clientTlsEnabled;
066
067  public TestSaslTlsIPC(X509KeyType caKeyType, X509KeyType certKeyType, char[] keyPassword,
068    boolean acceptPlainText, boolean clientTlsEnabled) {
069    this.caKeyType = caKeyType;
070    this.certKeyType = certKeyType;
071    this.keyPassword = keyPassword;
072    this.acceptPlainText = acceptPlainText;
073    this.clientTlsEnabled = clientTlsEnabled;
074  }
075
076  private X509TestContext x509TestContext;
077
078  public static Stream<Arguments> parameters() {
079    List<Arguments> params = new ArrayList<>();
080    for (X509KeyType caKeyType : X509KeyType.values()) {
081      for (X509KeyType certKeyType : X509KeyType.values()) {
082        for (char[] keyPassword : new char[][] { "".toCharArray(), "pa$$w0rd".toCharArray() }) {
083          // do not accept plain text
084          params.add(Arguments.of(caKeyType, certKeyType, keyPassword, false, true));
085          // support plain text and client enables tls
086          params.add(Arguments.of(caKeyType, certKeyType, keyPassword, true, true));
087          // support plain text and client disables tls
088          params.add(Arguments.of(caKeyType, certKeyType, keyPassword, true, false));
089        }
090      }
091    }
092    return params.stream();
093  }
094
095  @BeforeAll
096  public static void setUpBeforeClass() throws Exception {
097    Security.addProvider(new BouncyCastleProvider());
098    File dir = new File(TEST_UTIL.getDataTestDir(TestSaslTlsIPC.class.getSimpleName()).toString())
099      .getCanonicalFile();
100    FileUtils.forceMkdir(dir);
101    initKDCAndConf();
102    Configuration conf = TEST_UTIL.getConfiguration();
103    // server must enable tls
104    conf.setBoolean(X509Util.HBASE_SERVER_NETTY_TLS_ENABLED, true);
105    // only netty support tls
106    conf.setClass(RpcClientFactory.CUSTOM_RPC_CLIENT_IMPL_CONF_KEY, NettyRpcClient.class,
107      RpcClient.class);
108    conf.setClass(RpcServerFactory.CUSTOM_RPC_SERVER_IMPL_CONF_KEY, NettyRpcServer.class,
109      RpcServer.class);
110    PROVIDER = new X509TestContextProvider(conf, dir);
111  }
112
113  @AfterAll
114  public static void tearDownAfterClass() throws InterruptedException {
115    stopKDC();
116    Security.removeProvider(BouncyCastleProvider.PROVIDER_NAME);
117    TEST_UTIL.cleanupTestDir();
118  }
119
120  @BeforeEach
121  public void setUp() throws Exception {
122    x509TestContext = PROVIDER.get(caKeyType, certKeyType, keyPassword);
123    x509TestContext.setConfigurations(KeyStoreFileType.JKS, KeyStoreFileType.JKS);
124    Configuration conf = TEST_UTIL.getConfiguration();
125    conf.setBoolean(X509Util.HBASE_SERVER_NETTY_TLS_SUPPORTPLAINTEXT, acceptPlainText);
126    conf.setBoolean(X509Util.HBASE_CLIENT_NETTY_TLS_ENABLED, clientTlsEnabled);
127    setUpPrincipalAndConf();
128  }
129
130  @AfterEach
131  public void tearDown() {
132    x509TestContext.clearConfigurations();
133    x509TestContext.getConf().unset(X509Util.TLS_CONFIG_OCSP);
134    x509TestContext.getConf().unset(X509Util.TLS_CONFIG_CLR);
135    x509TestContext.getConf().unset(X509Util.TLS_CONFIG_PROTOCOL);
136    System.clearProperty("com.sun.net.ssl.checkRevocation");
137    System.clearProperty("com.sun.security.enableCRLDP");
138    Security.setProperty("ocsp.enable", Boolean.FALSE.toString());
139    Security.setProperty("com.sun.security.enableCRLDP", Boolean.FALSE.toString());
140  }
141}