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 static org.apache.hadoop.hbase.ipc.TestProtobufRpcServiceImpl.SERVICE;
021import static org.hamcrest.MatcherAssert.assertThat;
022import static org.hamcrest.Matchers.instanceOf;
023import static org.junit.jupiter.api.Assertions.assertThrows;
024
025import java.io.File;
026import java.io.IOException;
027import java.net.InetSocketAddress;
028import java.security.Security;
029import java.util.ArrayList;
030import java.util.List;
031import java.util.stream.Stream;
032import org.apache.commons.io.FileUtils;
033import org.apache.hadoop.conf.Configuration;
034import org.apache.hadoop.hbase.HBaseCommonTestingUtil;
035import org.apache.hadoop.hbase.exceptions.ConnectionClosedException;
036import org.apache.hadoop.hbase.io.crypto.tls.KeyStoreFileType;
037import org.apache.hadoop.hbase.io.crypto.tls.X509KeyType;
038import org.apache.hadoop.hbase.io.crypto.tls.X509TestContext;
039import org.apache.hadoop.hbase.io.crypto.tls.X509TestContextProvider;
040import org.apache.hadoop.hbase.io.crypto.tls.X509Util;
041import org.apache.hadoop.hbase.ipc.FifoRpcScheduler;
042import org.apache.hadoop.hbase.ipc.NettyRpcClient;
043import org.apache.hadoop.hbase.ipc.NettyRpcServer;
044import org.apache.hadoop.hbase.ipc.RpcClient;
045import org.apache.hadoop.hbase.ipc.RpcClientFactory;
046import org.apache.hadoop.hbase.ipc.RpcServer;
047import org.apache.hadoop.hbase.ipc.RpcServerFactory;
048import org.bouncycastle.jce.provider.BouncyCastleProvider;
049import org.junit.jupiter.api.AfterEach;
050import org.junit.jupiter.api.BeforeEach;
051import org.junit.jupiter.api.TestTemplate;
052import org.junit.jupiter.params.provider.Arguments;
053
054import org.apache.hbase.thirdparty.com.google.common.collect.Lists;
055import org.apache.hbase.thirdparty.com.google.common.io.Closeables;
056import org.apache.hbase.thirdparty.com.google.protobuf.ServiceException;
057
058import org.apache.hadoop.hbase.shaded.ipc.protobuf.generated.TestProtos.EchoRequestProto;
059import org.apache.hadoop.hbase.shaded.ipc.protobuf.generated.TestRpcServiceProtos.TestProtobufRpcProto.BlockingInterface;
060
061public abstract class AbstractTestTlsRejectPlainText {
062
063  protected static HBaseCommonTestingUtil UTIL;
064
065  protected static File DIR;
066
067  protected static X509TestContextProvider PROVIDER;
068
069  protected X509KeyType caKeyType;
070
071  protected X509KeyType certKeyType;
072
073  protected char[] keyPassword;
074
075  private X509TestContext x509TestContext;
076
077  protected RpcServer rpcServer;
078
079  protected RpcClient rpcClient;
080
081  public static Stream<Arguments> parameters() {
082    List<Arguments> params = new ArrayList<>();
083    for (X509KeyType caKeyType : X509KeyType.values()) {
084      for (X509KeyType certKeyType : X509KeyType.values()) {
085        for (char[] keyPassword : new char[][] { "".toCharArray(), "pa$$w0rd".toCharArray() }) {
086          params.add(Arguments.of(caKeyType, certKeyType, keyPassword));
087        }
088      }
089    }
090    return params.stream();
091  }
092
093  protected AbstractTestTlsRejectPlainText(X509KeyType caKeyType, X509KeyType certKeyType,
094    char[] keyPassword) {
095    this.caKeyType = caKeyType;
096    this.certKeyType = certKeyType;
097    this.keyPassword = keyPassword;
098  }
099
100  protected static void initialize() throws IOException {
101    Security.addProvider(new BouncyCastleProvider());
102    DIR =
103      new File(UTIL.getDataTestDir(AbstractTestTlsRejectPlainText.class.getSimpleName()).toString())
104        .getCanonicalFile();
105    FileUtils.forceMkdir(DIR);
106    Configuration conf = UTIL.getConfiguration();
107    conf.setClass(RpcClientFactory.CUSTOM_RPC_CLIENT_IMPL_CONF_KEY, NettyRpcClient.class,
108      RpcClient.class);
109    conf.setClass(RpcServerFactory.CUSTOM_RPC_SERVER_IMPL_CONF_KEY, NettyRpcServer.class,
110      RpcServer.class);
111    conf.setBoolean(X509Util.HBASE_SERVER_NETTY_TLS_ENABLED, true);
112    conf.setBoolean(X509Util.HBASE_SERVER_NETTY_TLS_SUPPORTPLAINTEXT, false);
113    conf.setBoolean(X509Util.HBASE_CLIENT_NETTY_TLS_ENABLED, false);
114    PROVIDER = new X509TestContextProvider(conf, DIR);
115  }
116
117  protected static void cleanUp() {
118    Security.removeProvider(BouncyCastleProvider.PROVIDER_NAME);
119    UTIL.cleanupTestDir();
120  }
121
122  @BeforeEach
123  public void setUp() throws Exception {
124    x509TestContext = PROVIDER.get(caKeyType, certKeyType, keyPassword);
125    x509TestContext.setConfigurations(KeyStoreFileType.JKS, KeyStoreFileType.JKS);
126    Configuration conf = UTIL.getConfiguration();
127    rpcServer = new NettyRpcServer(null, "testRpcServer",
128      Lists.newArrayList(new RpcServer.BlockingServiceAndInterface(SERVICE, null)),
129      new InetSocketAddress("localhost", 0), conf, new FifoRpcScheduler(conf, 1), true);
130    rpcServer.start();
131    rpcClient = new NettyRpcClient(conf);
132  }
133
134  @AfterEach
135  public void tearDown() throws IOException {
136    if (rpcServer != null) {
137      rpcServer.stop();
138    }
139    Closeables.close(rpcClient, true);
140    x509TestContext.clearConfigurations();
141    x509TestContext.getConf().unset(X509Util.TLS_CONFIG_OCSP);
142    x509TestContext.getConf().unset(X509Util.TLS_CONFIG_CLR);
143    x509TestContext.getConf().unset(X509Util.TLS_CONFIG_PROTOCOL);
144    System.clearProperty("com.sun.net.ssl.checkRevocation");
145    System.clearProperty("com.sun.security.enableCRLDP");
146    Security.setProperty("ocsp.enable", Boolean.FALSE.toString());
147    Security.setProperty("com.sun.security.enableCRLDP", Boolean.FALSE.toString());
148  }
149
150  protected abstract BlockingInterface createStub() throws Exception;
151
152  @TestTemplate
153  public void testReject() throws Exception {
154    BlockingInterface stub = createStub();
155    ServiceException se = assertThrows(ServiceException.class,
156      () -> stub.echo(null, EchoRequestProto.newBuilder().setMessage("hello world").build()));
157    assertThat(se.getCause(), instanceOf(ConnectionClosedException.class));
158  }
159}