blob: cd4d3a5c152320d76d677d2834c4e7bf860cb1f9 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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.apache.nifi.security.util;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* This interface serves as an immutable domain object (acting as an internal DTO) for
* the various keystore and truststore configuration settings necessary for building
* {@link javax.net.ssl.SSLContext}s.
*/
public interface TlsConfiguration {
String SSL_PROTOCOL = "SSL";
String TLS_PROTOCOL = "TLS";
String TLS_1_0_PROTOCOL = "TLSv1";
String TLS_1_1_PROTOCOL = "TLSv1.1";
String TLS_1_2_PROTOCOL = "TLSv1.2";
String[] LEGACY_TLS_PROTOCOL_VERSIONS = new String[]{TLS_1_0_PROTOCOL, TLS_1_1_PROTOCOL};
String JAVA_8_MAX_SUPPORTED_TLS_PROTOCOL_VERSION = TLS_1_2_PROTOCOL;
String JAVA_11_MAX_SUPPORTED_TLS_PROTOCOL_VERSION = "TLSv1.3";
String[] JAVA_8_SUPPORTED_TLS_PROTOCOL_VERSIONS = new String[]{JAVA_8_MAX_SUPPORTED_TLS_PROTOCOL_VERSION};
String[] JAVA_11_SUPPORTED_TLS_PROTOCOL_VERSIONS = new String[]{JAVA_11_MAX_SUPPORTED_TLS_PROTOCOL_VERSION, JAVA_8_MAX_SUPPORTED_TLS_PROTOCOL_VERSION};
/**
* Returns {@code true} if the provided TlsConfiguration is {@code null} or <em>empty</em>
* (i.e. neither any of the keystore nor truststore properties are populated).
*
* @param tlsConfiguration the container object to check
* @return true if this container is empty or null
*/
static boolean isEmpty(TlsConfiguration tlsConfiguration) {
return tlsConfiguration == null || !(tlsConfiguration.isAnyKeystorePopulated() || tlsConfiguration.isAnyTruststorePopulated());
}
// Getters & setters
String getKeystorePath();
String getKeystorePassword();
/**
* Returns {@code "********"} if the keystore password is populated, {@code "null"} if not.
*
* @return a loggable String representation of the keystore password
*/
String getKeystorePasswordForLogging();
String getKeyPassword();
/**
* Returns {@code "********"} if the key password is populated, {@code "null"} if not.
*
* @return a loggable String representation of the key password
*/
String getKeyPasswordForLogging();
/**
* Returns the "working" key password -- if the key password is populated, it is returned; otherwise the {@link #getKeystorePassword()} is returned.
*
* @return the key or keystore password actually populated
*/
String getFunctionalKeyPassword();
/**
* Returns {@code "********"} if the functional key password is populated, {@code "null"} if not.
*
* @return a loggable String representation of the functional key password
*/
String getFunctionalKeyPasswordForLogging();
KeystoreType getKeystoreType();
String getTruststorePath();
String getTruststorePassword();
/**
* Returns {@code "********"} if the truststore password is populated, {@code "null"} if not.
*
* @return a loggable String representation of the truststore password
*/
String getTruststorePasswordForLogging();
KeystoreType getTruststoreType();
String getProtocol();
// Boolean validators for keystore & truststore
/**
* Returns {@code true} if the necessary properties are populated to instantiate a <strong>keystore</strong>. This does <em>not</em> validate the values (see {@link #isKeystoreValid()}).
*
* @return true if the path, password, and type are present
*/
boolean isKeystorePopulated();
/**
* Returns {@code true} if <em>any</em> of the keystore properties is populated, indicating that the caller expects a valid keystore to be generated.
*
* @return true if any keystore properties are present
*/
boolean isAnyKeystorePopulated();
/**
* Returns {@code true} if the necessary properties are populated and the keystore can be successfully instantiated (i.e. the path is valid and the password(s) are correct).
*
* @return true if the keystore properties are valid
*/
boolean isKeystoreValid();
/**
* Returns {@code true} if the necessary properties are populated to instantiate a <strong>truststore</strong>. This does <em>not</em> validate the values (see {@link #isTruststoreValid()}).
*
* @return true if the path, password, and type are present
*/
boolean isTruststorePopulated();
/**
* Returns {@code true} if <em>any</em> of the truststore properties is populated, indicating that the caller expects a valid truststore to be generated.
*
* @return true if any truststore properties are present
*/
boolean isAnyTruststorePopulated();
/**
* Returns {@code true} if the necessary properties are populated and the truststore can be successfully instantiated (i.e. the path is valid and the password is correct).
*
* @return true if the truststore properties are valid
*/
boolean isTruststoreValid();
/**
* Returns a {@code String[]} containing the keystore properties for logging. The order is
* {@link #getKeystorePath()}, {@link #getKeystorePasswordForLogging()},
* {@link #getFunctionalKeyPasswordForLogging()}, {@link #getKeystoreType()} (using the type or "null").
*
* @return a loggable String[]
*/
String[] getKeystorePropertiesForLogging();
/**
* Returns a {@code String[]} containing the truststore properties for logging. The order is
* {@link #getTruststorePath()}, {@link #getTruststorePasswordForLogging()},
* {@link #getTruststoreType()} (using the type or "null").
*
* @return a loggable String[]
*/
String[] getTruststorePropertiesForLogging();
/**
* Get Enabled TLS Protocol Versions
*
* @return Enabled TLS Protocols
*/
String[] getEnabledProtocols();
/**
* Returns the JVM Java major version based on the System properties (e.g. {@code JVM 1.8.0.231} -> {code 8}).
*
* @return the Java major version
*/
static int getJavaVersion() {
String version = System.getProperty("java.version");
return parseJavaVersion(version);
}
/**
* Returns the major version parsed from the provided Java version string (e.g. {@code "1.8.0.231"} -> {@code 8}).
*
* @param version the Java version string
* @return the major version as an int
*/
static int parseJavaVersion(String version) {
String majorVersion;
if (version.startsWith("1.")) {
majorVersion = version.substring(2, 3);
} else {
Pattern majorVersion9PlusPattern = Pattern.compile("(\\d+).*");
Matcher m = majorVersion9PlusPattern.matcher(version);
if (m.find()) {
majorVersion = m.group(1);
} else {
throw new IllegalArgumentException("Could not detect major version of " + version);
}
}
return Integer.parseInt(majorVersion);
}
/**
* Returns a {@code String[]} of supported TLS protocol versions based on the current Java platform version.
*
* @return the supported TLS protocol version(s)
*/
static String[] getCurrentSupportedTlsProtocolVersions() {
int javaMajorVersion = getJavaVersion();
if (javaMajorVersion < 11) {
return JAVA_8_SUPPORTED_TLS_PROTOCOL_VERSIONS;
} else {
return JAVA_11_SUPPORTED_TLS_PROTOCOL_VERSIONS;
}
}
/**
* Returns the highest supported TLS protocol version based on the current Java platform version.
*
* @return the TLS protocol (e.g. {@code "TLSv1.2"})
*/
static String getHighestCurrentSupportedTlsProtocolVersion() {
int javaMajorVersion = getJavaVersion();
if (javaMajorVersion < 11) {
return JAVA_8_MAX_SUPPORTED_TLS_PROTOCOL_VERSION;
} else {
return JAVA_11_MAX_SUPPORTED_TLS_PROTOCOL_VERSION;
}
}
}