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.io.crypto.tls;
019
020import java.io.File;
021import java.io.IOException;
022import java.security.Security;
023import java.util.ArrayList;
024import java.util.Collection;
025import java.util.List;
026import org.apache.commons.io.FileUtils;
027import org.apache.hadoop.conf.Configuration;
028import org.apache.hadoop.hbase.HBaseCommonTestingUtil;
029import org.bouncycastle.jce.provider.BouncyCastleProvider;
030import org.junit.After;
031import org.junit.AfterClass;
032import org.junit.Before;
033import org.junit.BeforeClass;
034import org.junit.runners.Parameterized;
035
036/**
037 * Base class for parameterized unit tests that use X509TestContext for testing different X509
038 * parameter combinations (CA key type, cert key type, with/without a password, with/without
039 * hostname verification, etc).
040 * <p/>
041 * This base class takes care of setting up / cleaning up the test environment, and caching the
042 * X509TestContext objects used by the tests.
043 * <p/>
044 * This file has been copied from the Apache ZooKeeper project.
045 * @see <a href=
046 *      "https://github.com/apache/zookeeper/blob/master/zookeeper-server/src/test/java/org/apache/zookeeper/common/BaseX509ParameterizedTestCase.java">Base
047 *      revision</a>
048 */
049public abstract class AbstractTestX509Parameterized {
050
051  private static final HBaseCommonTestingUtil UTIL = new HBaseCommonTestingUtil();
052  private static X509TestContextProvider PROVIDER;
053
054  @Parameterized.Parameter()
055  public X509KeyType caKeyType;
056
057  @Parameterized.Parameter(value = 1)
058  public X509KeyType certKeyType;
059
060  @Parameterized.Parameter(value = 2)
061  public char[] keyPassword;
062
063  @Parameterized.Parameter(value = 3)
064  public Integer paramIndex;
065
066  /**
067   * Default parameters suitable for most subclasses. See example usage in {@link TestX509Util}.
068   * @return an array of parameter combinations to test with.
069   */
070  @Parameterized.Parameters(
071      name = "{index}: caKeyType={0}, certKeyType={1}, keyPassword={2}, paramIndex={3}")
072  public static Collection<Object[]> defaultParams() {
073    List<Object[]> result = new ArrayList<>();
074    int paramIndex = 0;
075    for (X509KeyType caKeyType : X509KeyType.values()) {
076      for (X509KeyType certKeyType : X509KeyType.values()) {
077        for (char[] keyPassword : new char[][] { "".toCharArray(), "pa$$w0rd".toCharArray() }) {
078          result.add(new Object[] { caKeyType, certKeyType, keyPassword, paramIndex++ });
079        }
080      }
081    }
082    return result;
083  }
084
085  /**
086   * Because key generation and writing / deleting files is kind of expensive, we cache the certs
087   * and on-disk files between test cases. None of the test cases modify any of this data so it's
088   * safe to reuse between tests. This caching makes all test cases after the first one for a given
089   * parameter combination complete almost instantly.
090   */
091  protected static Configuration conf;
092
093  protected X509TestContext x509TestContext;
094
095  @BeforeClass
096  public static void setUpBaseClass() throws Exception {
097    Security.addProvider(new BouncyCastleProvider());
098    File dir = new File(UTIL.getDataTestDir(TestX509Util.class.getSimpleName()).toString())
099      .getCanonicalFile();
100    FileUtils.forceMkdir(dir);
101    PROVIDER = new X509TestContextProvider(UTIL.getConfiguration(), dir);
102  }
103
104  @AfterClass
105  public static void cleanUpBaseClass() {
106    Security.removeProvider(BouncyCastleProvider.PROVIDER_NAME);
107    UTIL.cleanupTestDir();
108  }
109
110  @Before
111  public void setUp() throws IOException {
112    x509TestContext = PROVIDER.get(caKeyType, certKeyType, keyPassword);
113    x509TestContext.setConfigurations(KeyStoreFileType.JKS, KeyStoreFileType.JKS);
114    conf = new Configuration(UTIL.getConfiguration());
115  }
116
117  @After
118  public void cleanUp() {
119    x509TestContext.clearConfigurations();
120    x509TestContext.getConf().unset(X509Util.TLS_CONFIG_OCSP);
121    x509TestContext.getConf().unset(X509Util.TLS_CONFIG_CLR);
122    x509TestContext.getConf().unset(X509Util.TLS_CONFIG_PROTOCOL);
123    System.clearProperty("com.sun.net.ssl.checkRevocation");
124    System.clearProperty("com.sun.security.enableCRLDP");
125    Security.setProperty("ocsp.enable", Boolean.FALSE.toString());
126    Security.setProperty("com.sun.security.enableCRLDP", Boolean.FALSE.toString());
127  }
128}