Skip to content

Commit

Permalink
Add SSL Configuration Library (#37287)
Browse files Browse the repository at this point in the history
This introduces a new ssl-config library that can parse
and validate SSL/TLS settings and files.

It supports the standard configuration settings as used in the
Elastic Stack such as "ssl.verification_mode" and
"ssl.certificate_authorities" as well as all file formats used
in other parts of Elasticsearch security (such as PEM, JKS,
PKCS#12, PKCS#8, et al).
  • Loading branch information
tvernum authored Jan 16, 2019
1 parent 023bb2f commit 6d99e79
Show file tree
Hide file tree
Showing 70 changed files with 5,044 additions and 1 deletion.
42 changes: 42 additions & 0 deletions libs/ssl-config/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

dependencies {
compile "org.elasticsearch:elasticsearch-core:${version}"

if (isEclipse == false || project.path == ":libs:ssl-config-tests") {
testCompile("org.elasticsearch.test:framework:${version}") {
exclude group: 'org.elasticsearch', module: 'elasticsearch-ssl-config'
}
}

testCompile "com.carrotsearch.randomizedtesting:randomizedtesting-runner:${versions.randomizedrunner}"
testCompile "junit:junit:${versions.junit}"
testCompile "org.hamcrest:hamcrest-all:${versions.hamcrest}"
}

forbiddenApisMain {
replaceSignatureFiles 'jdk-signatures'
}
forbiddenPatterns {
exclude '**/*.key'
exclude '**/*.pem'
exclude '**/*.p12'
exclude '**/*.jks'
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.elasticsearch.common.ssl;

import org.elasticsearch.common.Nullable;

import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509ExtendedTrustManager;
import java.io.IOException;
import java.nio.file.Path;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.function.BiFunction;

/**
* This class represents a trust configuration that corresponds to the default trusted CAs of the JDK
*/
final class DefaultJdkTrustConfig implements SslTrustConfig {

private final BiFunction<String, String, String> systemProperties;
private final char[] trustStorePassword;

/**
* Create a trust config that uses System properties to determine the TrustStore type, and the relevant password.
*/
DefaultJdkTrustConfig() {
this(System::getProperty);
}

/**
* Create a trust config that uses supplied {@link BiFunction} to determine the TrustStore type, and the relevant password.
*/
DefaultJdkTrustConfig(BiFunction<String, String, String> systemProperties) {
this(systemProperties, isPkcs11Truststore(systemProperties) ? getSystemTrustStorePassword(systemProperties) : null);
}

/**
* @param trustStorePassword the password for the truststore. It applies only when PKCS#11 tokens are used, is null otherwise
*/
DefaultJdkTrustConfig(BiFunction<String, String, String> systemProperties, @Nullable char[] trustStorePassword) {
this.systemProperties = systemProperties;
this.trustStorePassword = trustStorePassword;
}

@Override
public X509ExtendedTrustManager createTrustManager() {
try {
return KeyStoreUtil.createTrustManager(getSystemTrustStore(), TrustManagerFactory.getDefaultAlgorithm());
} catch (GeneralSecurityException e) {
throw new SslConfigException("failed to initialize a TrustManager for the system keystore", e);
}
}

/**
* When a PKCS#11 token is used as the system default keystore/truststore, we need to pass the keystore
* password when loading, even for reading certificates only ( as opposed to i.e. JKS keystores where
* we only need to pass the password for reading Private Key entries ).
*
* @return the KeyStore used as truststore for PKCS#11 initialized with the password, null otherwise
*/
private KeyStore getSystemTrustStore() {
if (isPkcs11Truststore(systemProperties) && trustStorePassword != null) {
try {
KeyStore keyStore = KeyStore.getInstance("PKCS11");
keyStore.load(null, trustStorePassword);
return keyStore;
} catch (GeneralSecurityException | IOException e) {
throw new SslConfigException("failed to load the system PKCS#11 truststore", e);
}
}
return null;
}

private static boolean isPkcs11Truststore(BiFunction<String, String, String> systemProperties) {
return systemProperties.apply("javax.net.ssl.trustStoreType", "").equalsIgnoreCase("PKCS11");
}

private static char[] getSystemTrustStorePassword(BiFunction<String, String, String> systemProperties) {
return systemProperties.apply("javax.net.ssl.trustStorePassword", "").toCharArray();
}

@Override
public Collection<Path> getDependentFiles() {
return Collections.emptyList();
}

@Override
public String toString() {
return "JDK-trusted-certs";
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
final DefaultJdkTrustConfig that = (DefaultJdkTrustConfig) o;
return Arrays.equals(this.trustStorePassword, that.trustStorePassword);
}

@Override
public int hashCode() {
return Arrays.hashCode(trustStorePassword);
}
}
Loading

0 comments on commit 6d99e79

Please sign in to comment.