diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle index 854b81852dcf6..934990a1dbc52 100644 --- a/buildSrc/build.gradle +++ b/buildSrc/build.gradle @@ -200,6 +200,7 @@ if (project != rootProject) { exclude '**/*.p12' // the file that actually defines nocommit exclude '**/ForbiddenPatternsTask.java' + exclude '**/*.bcfks' } testingConventions { diff --git a/buildSrc/src/main/groovy/org/elasticsearch/gradle/BuildPlugin.groovy b/buildSrc/src/main/groovy/org/elasticsearch/gradle/BuildPlugin.groovy index c085952cc0be8..aeda4494f6124 100644 --- a/buildSrc/src/main/groovy/org/elasticsearch/gradle/BuildPlugin.groovy +++ b/buildSrc/src/main/groovy/org/elasticsearch/gradle/BuildPlugin.groovy @@ -26,13 +26,12 @@ import groovy.transform.CompileStatic import org.apache.commons.io.IOUtils import org.elasticsearch.gradle.info.BuildParams import org.elasticsearch.gradle.info.GlobalBuildInfoPlugin -import org.elasticsearch.gradle.info.GlobalInfoExtension -import org.elasticsearch.gradle.info.JavaHome import org.elasticsearch.gradle.precommit.DependencyLicensesTask import org.elasticsearch.gradle.precommit.PrecommitTasks import org.elasticsearch.gradle.test.ErrorReportingTestListener import org.elasticsearch.gradle.testclusters.ElasticsearchCluster import org.elasticsearch.gradle.testclusters.TestClustersPlugin +import org.elasticsearch.gradle.tool.Boilerplate import org.gradle.api.Action import org.gradle.api.GradleException import org.gradle.api.InvalidUserDataException @@ -138,31 +137,50 @@ class BuildPlugin implements Plugin { configureTestTasks(project) configurePrecommit(project) configureDependenciesInfo(project) - configureFips140(project) } - public static void configureFips140(Project project) { - // Need to do it here to support external plugins - GlobalInfoExtension globalInfo = project.rootProject.extensions.getByType(GlobalInfoExtension) - // wait until global info is populated because we don't know if we are running in a fips jvm until execution time - globalInfo.ready { - // Common config when running with a FIPS-140 runtime JVM - if (BuildParams.inFipsJvm) { - project.tasks.withType(Test).configureEach { Test task -> - task.systemProperty 'javax.net.ssl.trustStorePassword', 'password' - task.systemProperty 'javax.net.ssl.keyStorePassword', 'password' - } - project.pluginManager.withPlugin("elasticsearch.testclusters") { - NamedDomainObjectContainer testClusters = project.extensions.findByName(TestClustersPlugin.EXTENSION_NAME) as NamedDomainObjectContainer - if (testClusters != null) { - testClusters.all { ElasticsearchCluster cluster -> - cluster.systemProperty 'javax.net.ssl.trustStorePassword', 'password' - cluster.systemProperty 'javax.net.ssl.keyStorePassword', 'password' - } - } + static void configureFips140(Project project) { + // Common config when running with a FIPS-140 runtime JVM + if (inFipsJvm()) { + ExportElasticsearchBuildResourcesTask buildResources = project.tasks.getByName('buildResources') as ExportElasticsearchBuildResourcesTask + File securityProperties = buildResources.copy("fips_java.security") + File securityPolicy = buildResources.copy("fips_java.policy") + File bcfksKeystore = buildResources.copy("cacerts.bcfks") + // This configuration can be removed once system modules are available + Boilerplate.maybeCreate(project.configurations, 'extraJars') { + project.dependencies.add('extraJars', "org.bouncycastle:bc-fips:1.0.1") + project.dependencies.add('extraJars', "org.bouncycastle:bctls-fips:1.0.9") + } + project.pluginManager.withPlugin("elasticsearch.testclusters") { + NamedDomainObjectContainer testClusters = project.extensions.findByName(TestClustersPlugin.EXTENSION_NAME) as NamedDomainObjectContainer + testClusters.all { ElasticsearchCluster cluster -> + for (File dep : project.getConfigurations().getByName("extraJars").getFiles()){ + cluster.extraJarFile(dep) } + cluster.extraConfigFile("fips_java.security", securityProperties) + cluster.extraConfigFile("fips_java.policy", securityPolicy) + cluster.extraConfigFile("cacerts.bcfks", bcfksKeystore) + cluster.systemProperty('java.security.properties', '=${ES_PATH_CONF}/fips_java.security') + cluster.systemProperty('java.security.policy', '=${ES_PATH_CONF}/fips_java.policy') + cluster.systemProperty('javax.net.ssl.trustStore', '${ES_PATH_CONF}/cacerts.bcfks') + cluster.systemProperty('javax.net.ssl.trustStorePassword', 'password') + cluster.systemProperty('javax.net.ssl.keyStorePassword', 'password') + cluster.systemProperty('javax.net.ssl.keyStoreType', 'BCFKS') } + } + project.tasks.withType(Test).configureEach { Test task -> + task.dependsOn(buildResources) + task.systemProperty('javax.net.ssl.trustStorePassword', 'password') + task.systemProperty('javax.net.ssl.keyStorePassword', 'password') + task.systemProperty('javax.net.ssl.trustStoreType', 'BCFKS') + // Using the key==value format to override default JVM security settings and policy + // see also: https://docs.oracle.com/javase/8/docs/technotes/guides/security/PolicyFiles.html + task.systemProperty('java.security.properties', String.format(Locale.ROOT, "=%s", securityProperties.toString())) + task.systemProperty('java.security.policy', String.format(Locale.ROOT, "=%s", securityPolicy.toString())) + task.systemProperty('javax.net.ssl.trustStore', bcfksKeystore.toString()) + } + } } @@ -623,15 +641,13 @@ class BuildPlugin implements Plugin { project.mkdir(heapdumpDir) project.mkdir(test.workingDir) - if (BuildParams.inFipsJvm) { - nonInputProperties.systemProperty('runtime.java', "${-> BuildParams.runtimeJavaVersion.majorVersion}FIPS") - } else { - nonInputProperties.systemProperty('runtime.java', "${-> BuildParams.runtimeJavaVersion.majorVersion}") - } //TODO remove once jvm.options are added to test system properties test.systemProperty ('java.locale.providers','SPI,COMPAT') } - + if (inFipsJvm()) { + project.dependencies.add('testRuntimeOnly', "org.bouncycastle:bc-fips:1.0.1") + project.dependencies.add('testRuntimeOnly', "org.bouncycastle:bctls-fips:1.0.9") + } test.jvmArgumentProviders.add(nonInputProperties) test.extensions.add('nonInputProperties', nonInputProperties) @@ -775,4 +791,8 @@ class BuildPlugin implements Plugin { }) } } + + private static inFipsJvm(){ + return Boolean.parseBoolean(System.getProperty("tests.fips.enabled")); + } } diff --git a/buildSrc/src/main/java/org/elasticsearch/gradle/info/GenerateGlobalBuildInfoTask.java b/buildSrc/src/main/java/org/elasticsearch/gradle/info/GenerateGlobalBuildInfoTask.java index cbe61a54ae9ad..9dba3fbe907ec 100644 --- a/buildSrc/src/main/java/org/elasticsearch/gradle/info/GenerateGlobalBuildInfoTask.java +++ b/buildSrc/src/main/java/org/elasticsearch/gradle/info/GenerateGlobalBuildInfoTask.java @@ -147,9 +147,7 @@ public void generate() { runtimeJavaVersionDetails = findJavaVersionDetails(runtimeJavaHome); runtimeJavaVersionEnum = JavaVersion.toVersion(findJavaSpecificationVersion(runtimeJavaHome)); - // We don't expect Gradle to be running in a FIPS JVM - String inFipsJvmScript = "print(java.security.Security.getProviders()[0].name.toLowerCase().contains(\"fips\"));"; - inFipsJvm = Boolean.parseBoolean(runJavaAsScript(runtimeJavaHome, inFipsJvmScript)); + inFipsJvm = Boolean.parseBoolean(System.getProperty("tests.fips.enabled")); } else { throw new RuntimeException("Runtime Java home path of '" + compilerJavaHome + "' does not exist"); } diff --git a/buildSrc/src/main/java/org/elasticsearch/gradle/testclusters/ElasticsearchCluster.java b/buildSrc/src/main/java/org/elasticsearch/gradle/testclusters/ElasticsearchCluster.java index 60c6e02bc44bc..a3cf70a70ef92 100644 --- a/buildSrc/src/main/java/org/elasticsearch/gradle/testclusters/ElasticsearchCluster.java +++ b/buildSrc/src/main/java/org/elasticsearch/gradle/testclusters/ElasticsearchCluster.java @@ -334,6 +334,11 @@ public void extraConfigFile(String destination, File from, PropertyNormalization nodes.all(node -> node.extraConfigFile(destination, from, normalization)); } + @Override + public void extraJarFile(File from) { + nodes.all(node -> node.extraJarFile(from)); + } + @Override public void user(Map userSpec) { nodes.all(node -> node.user(userSpec)); diff --git a/buildSrc/src/main/java/org/elasticsearch/gradle/testclusters/ElasticsearchNode.java b/buildSrc/src/main/java/org/elasticsearch/gradle/testclusters/ElasticsearchNode.java index 66cd77ddb8e20..65beedc1860f7 100644 --- a/buildSrc/src/main/java/org/elasticsearch/gradle/testclusters/ElasticsearchNode.java +++ b/buildSrc/src/main/java/org/elasticsearch/gradle/testclusters/ElasticsearchNode.java @@ -128,6 +128,7 @@ public class ElasticsearchNode implements TestClusterConfiguration { private final LazyPropertyMap environment = new LazyPropertyMap<>("Environment", this); private final LazyPropertyList jvmArgs = new LazyPropertyList<>("JVM arguments", this); private final LazyPropertyMap extraConfigFiles = new LazyPropertyMap<>("Extra config files", this, FileEntry::new); + private final LazyPropertyList extraJarFiles = new LazyPropertyList<>("Extra jar files", this); private final List> credentials = new ArrayList<>(); final LinkedHashMap defaultConfig = new LinkedHashMap<>(); @@ -454,6 +455,8 @@ public synchronized void start() { copyExtraConfigFiles(); + copyExtraJars(); + if (isSettingTrue("xpack.security.enabled")) { if (credentials.isEmpty()) { user(Collections.emptyMap()); @@ -530,6 +533,25 @@ private void copyExtraConfigFiles() { }); } + /** + * Copies extra jars to the `/lib` directory. + * //TODO: Remove this when system modules are available + */ + private void copyExtraJars() { + if (extraJarFiles.isEmpty() == false){ + logToProcessStdout("Setting up " + extraJarFiles.size() + " additional jar dependencies"); + } + extraJarFiles.forEach(from -> { + Path destination = getDistroDir().resolve("lib").resolve(from.getName()); + try { + Files.copy(from.toPath(), destination, StandardCopyOption.REPLACE_EXISTING); + LOGGER.info("Added extra jar {} to {}", from.getName(), destination); + } catch (IOException e) { + throw new UncheckedIOException("Can't copy extra jar dependency " + from.getName() + " to " + destination.toString(), e); + } + }); + } + private void installModules() { if (testDistribution == TestDistribution.INTEG_TEST) { logToProcessStdout("Installing " + modules.size() + "modules"); @@ -576,6 +598,14 @@ public void extraConfigFile(String destination, File from, PropertyNormalization extraConfigFiles.put(destination, from, normalization); } + @Override + public void extraJarFile(File from) { + if (from.toString().endsWith(".jar") == false) { + throw new IllegalArgumentException("extra jar file " + from.toString() + " doesn't appear to be a JAR"); + } + extraJarFiles.add(from); + } + @Override public void user(Map userSpec) { Set keys = new HashSet<>(userSpec.keySet()); diff --git a/buildSrc/src/main/java/org/elasticsearch/gradle/testclusters/TestClusterConfiguration.java b/buildSrc/src/main/java/org/elasticsearch/gradle/testclusters/TestClusterConfiguration.java index 585b62890c83d..651ab0fae6170 100644 --- a/buildSrc/src/main/java/org/elasticsearch/gradle/testclusters/TestClusterConfiguration.java +++ b/buildSrc/src/main/java/org/elasticsearch/gradle/testclusters/TestClusterConfiguration.java @@ -92,6 +92,8 @@ public interface TestClusterConfiguration { void extraConfigFile(String destination, File from, PropertyNormalization normalization); + void extraJarFile(File from); + void user(Map userSpec); String getHttpSocketURI(); diff --git a/buildSrc/src/main/resources/cacerts.bcfks b/buildSrc/src/main/resources/cacerts.bcfks new file mode 100644 index 0000000000000..9c3863eda60c5 Binary files /dev/null and b/buildSrc/src/main/resources/cacerts.bcfks differ diff --git a/buildSrc/src/main/resources/fips_java.policy b/buildSrc/src/main/resources/fips_java.policy new file mode 100644 index 0000000000000..4ef62e03c2546 --- /dev/null +++ b/buildSrc/src/main/resources/fips_java.policy @@ -0,0 +1,16 @@ +grant { + permission java.security.SecurityPermission "putProviderProperty.BCFIPS"; + permission java.security.SecurityPermission "putProviderProperty.BCJSSE"; + permission java.lang.RuntimePermission "getProtectionDomain"; + permission java.util.PropertyPermission "java.runtime.name", "read"; + permission org.bouncycastle.crypto.CryptoServicesPermission "tlsAlgorithmsEnabled"; + //io.netty.handler.codec.DecoderException + permission java.lang.RuntimePermission "accessClassInPackage.sun.security.internal.spec"; + //java.security.InvalidAlgorithmParameterException: Cannot process GCMParameterSpec + permission java.lang.RuntimePermission "accessDeclaredMembers"; + permission java.util.PropertyPermission "intellij.debug.agent", "read"; + permission java.util.PropertyPermission "intellij.debug.agent", "write"; + permission org.bouncycastle.crypto.CryptoServicesPermission "exportSecretKey"; + permission org.bouncycastle.crypto.CryptoServicesPermission "exportPrivateKey"; + permission java.io.FilePermission "${javax.net.ssl.trustStore}", "read"; +}; diff --git a/buildSrc/src/main/resources/fips_java.security b/buildSrc/src/main/resources/fips_java.security new file mode 100644 index 0000000000000..6c59c35b4560f --- /dev/null +++ b/buildSrc/src/main/resources/fips_java.security @@ -0,0 +1,50 @@ +security.provider.1=org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider +security.provider.2=org.bouncycastle.jsse.provider.BouncyCastleJsseProvider fips:BCFIPS +security.provider.3=SUN +securerandom.source=file:/dev/urandom +securerandom.strongAlgorithms=NativePRNGBlocking:SUN,DRBG:SUN +securerandom.drbg.config= +login.configuration.provider=sun.security.provider.ConfigFile +policy.provider=sun.security.provider.PolicyFile +policy.expandProperties=true +policy.allowSystemProperty=true +policy.ignoreIdentityScope=false +keystore.type=BCFKS +keystore.type.compat=true +package.access=sun.misc.,\ + sun.reflect. +package.definition=sun.misc.,\ + sun.reflect. +security.overridePropertiesFile=true +ssl.KeyManagerFactory.algorithm=PKIX +ssl.TrustManagerFactory.algorithm=PKIX +networkaddress.cache.negative.ttl=10 +krb5.kdc.bad.policy = tryLast +jdk.certpath.disabledAlgorithms=MD2, MD5, SHA1 jdkCA & usage TLSServer, \ + RSA keySize < 1024, DSA keySize < 1024, EC keySize < 224 +jdk.jar.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \ + DSA keySize < 1024 +jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 1024, \ + EC keySize < 224, DES40_CBC, RC4_40, 3DES_EDE_CBC +jdk.tls.legacyAlgorithms= \ + K_NULL, C_NULL, M_NULL, \ + DH_anon, ECDH_anon, \ + RC4_128, RC4_40, DES_CBC, DES40_CBC, \ + 3DES_EDE_CBC +jdk.tls.keyLimits=AES/GCM/NoPadding KeyUpdate 2^37 +crypto.policy=unlimited +jdk.xml.dsig.secureValidationPolicy=\ + disallowAlg http://www.w3.org/TR/1999/REC-xslt-19991116,\ + disallowAlg http://www.w3.org/2001/04/xmldsig-more#rsa-md5,\ + disallowAlg http://www.w3.org/2001/04/xmldsig-more#hmac-md5,\ + disallowAlg http://www.w3.org/2001/04/xmldsig-more#md5,\ + maxTransforms 5,\ + maxReferences 30,\ + disallowReferenceUriSchemes file http https,\ + minKeySize RSA 1024,\ + minKeySize DSA 1024,\ + minKeySize EC 224,\ + noDuplicateIds,\ + noRetrievalMethodLoops +jceks.key.serialFilter = java.base/java.lang.Enum;java.base/java.security.KeyRep;\ + java.base/java.security.KeyRep$Type;java.base/javax.crypto.spec.SecretKeySpec;!* diff --git a/distribution/tools/launchers/src/main/java/org/elasticsearch/tools/launchers/JvmOptionsParser.java b/distribution/tools/launchers/src/main/java/org/elasticsearch/tools/launchers/JvmOptionsParser.java index 43f30eb090ab3..e14390c57645c 100644 --- a/distribution/tools/launchers/src/main/java/org/elasticsearch/tools/launchers/JvmOptionsParser.java +++ b/distribution/tools/launchers/src/main/java/org/elasticsearch/tools/launchers/JvmOptionsParser.java @@ -31,6 +31,8 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Locale; @@ -87,8 +89,13 @@ public void accept(final int lineNumber, final String line) { .filter(Predicate.not(String::isBlank)) .collect(Collectors.toUnmodifiableList())); } + final Map substitutions = new HashMap<>(); + substitutions.put("ES_TMPDIR", System.getenv("ES_TMPDIR")); + if (null != System.getenv("ES_PATH_CONF")){ + substitutions.put("ES_PATH_CONF", System.getenv("ES_PATH_CONF")); + } final List substitutedJvmOptions = - substitutePlaceholders(jvmOptions, Map.of("ES_TMPDIR", System.getenv("ES_TMPDIR"))); + substitutePlaceholders(jvmOptions, Collections.unmodifiableMap(substitutions)); final List ergonomicJvmOptions = JvmErgonomics.choose(substitutedJvmOptions); final List systemJvmOptions = SystemJvmOptions.systemJvmOptions(); final List finalJvmOptions = diff --git a/libs/ssl-config/src/main/java/org/elasticsearch/common/ssl/SslConfiguration.java b/libs/ssl-config/src/main/java/org/elasticsearch/common/ssl/SslConfiguration.java index 52c1e8151f49d..f95f350143103 100644 --- a/libs/ssl-config/src/main/java/org/elasticsearch/common/ssl/SslConfiguration.java +++ b/libs/ssl-config/src/main/java/org/elasticsearch/common/ssl/SslConfiguration.java @@ -24,6 +24,7 @@ import javax.net.ssl.X509ExtendedTrustManager; import java.nio.file.Path; import java.security.GeneralSecurityException; +import java.security.NoSuchAlgorithmException; import java.util.Collection; import java.util.Collections; import java.util.HashSet; @@ -51,7 +52,12 @@ public class SslConfiguration { static final Map ORDERED_PROTOCOL_ALGORITHM_MAP; static { LinkedHashMap protocolAlgorithmMap = new LinkedHashMap<>(); - protocolAlgorithmMap.put("TLSv1.3", "TLSv1.3"); + try { + SSLContext.getInstance("TLSv1.3"); + protocolAlgorithmMap.put("TLSv1.3", "TLSv1.3"); + } catch (NoSuchAlgorithmException e) { + // ignore since we support JVMs using BCJSSE in FIPS mode which doesn't support TLSv1.3 + } protocolAlgorithmMap.put("TLSv1.2", "TLSv1.2"); protocolAlgorithmMap.put("TLSv1.1", "TLSv1.1"); protocolAlgorithmMap.put("TLSv1", "TLSv1"); diff --git a/libs/ssl-config/src/main/java/org/elasticsearch/common/ssl/SslConfigurationLoader.java b/libs/ssl-config/src/main/java/org/elasticsearch/common/ssl/SslConfigurationLoader.java index dd5a9e0b8dd02..4c2b1bc3891c9 100644 --- a/libs/ssl-config/src/main/java/org/elasticsearch/common/ssl/SslConfigurationLoader.java +++ b/libs/ssl-config/src/main/java/org/elasticsearch/common/ssl/SslConfigurationLoader.java @@ -24,12 +24,15 @@ import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.TrustManagerFactory; import java.nio.file.Path; +import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.function.Function; import java.util.stream.Collectors; import static org.elasticsearch.common.ssl.KeyStoreUtil.inferKeyStoreType; +import static org.elasticsearch.common.ssl.SslConfiguration.ORDERED_PROTOCOL_ALGORITHM_MAP; import static org.elasticsearch.common.ssl.SslConfigurationKeys.CERTIFICATE; import static org.elasticsearch.common.ssl.SslConfigurationKeys.CERTIFICATE_AUTHORITIES; import static org.elasticsearch.common.ssl.SslConfigurationKeys.CIPHERS; @@ -66,7 +69,9 @@ */ public abstract class SslConfigurationLoader { - static final List DEFAULT_PROTOCOLS = List.of("TLSv1.3", "TLSv1.2", "TLSv1.1"); + static final List DEFAULT_PROTOCOLS = Collections.unmodifiableList( + ORDERED_PROTOCOL_ALGORITHM_MAP.containsKey("TLSv1.3") ? + Arrays.asList("TLSv1.3", "TLSv1.2", "TLSv1.1") : Arrays.asList("TLSv1.2", "TLSv1.1")); private static final List JDK11_CIPHERS = List.of( // TLSv1.3 cipher has PFS, AEAD, hardware support diff --git a/test/framework/src/main/java/org/elasticsearch/test/ESIntegTestCase.java b/test/framework/src/main/java/org/elasticsearch/test/ESIntegTestCase.java index e855636af15a1..b9eee256da597 100644 --- a/test/framework/src/main/java/org/elasticsearch/test/ESIntegTestCase.java +++ b/test/framework/src/main/java/org/elasticsearch/test/ESIntegTestCase.java @@ -145,7 +145,6 @@ import java.net.URL; import java.nio.file.Files; import java.nio.file.Path; -import java.security.Security; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -2086,6 +2085,6 @@ public static Index resolveIndex(String index) { } public static boolean inFipsJvm() { - return Security.getProviders()[0].getName().toLowerCase(Locale.ROOT).contains("fips"); + return Boolean.parseBoolean(System.getProperty(FIPS_SYSPROP)); } } diff --git a/test/framework/src/main/java/org/elasticsearch/test/ESTestCase.java b/test/framework/src/main/java/org/elasticsearch/test/ESTestCase.java index feb8f9e4cde79..e538790f871b0 100644 --- a/test/framework/src/main/java/org/elasticsearch/test/ESTestCase.java +++ b/test/framework/src/main/java/org/elasticsearch/test/ESTestCase.java @@ -118,7 +118,6 @@ import java.io.IOException; import java.io.InputStream; import java.nio.file.Path; -import java.security.Security; import java.time.ZoneId; import java.util.ArrayList; import java.util.Arrays; @@ -192,6 +191,8 @@ public static void resetPortCounter() { public static final String DEFAULT_TEST_WORKER_ID = "--not-gradle--"; + public static final String FIPS_SYSPROP = "tests.fips.enabled"; + static { TEST_WORKER_VM_ID = System.getProperty(TEST_WORKER_SYS_PROPERTY, DEFAULT_TEST_WORKER_ID); setTestSysProps(); @@ -1341,7 +1342,7 @@ private static boolean isUnusableLocale() { } public static boolean inFipsJvm() { - return Security.getProviders()[0].getName().toLowerCase(Locale.ROOT).contains("fips"); + return Boolean.parseBoolean(System.getProperty(FIPS_SYSPROP)); } /** diff --git a/test/framework/src/main/java/org/elasticsearch/test/junit/listeners/ReproduceInfoPrinter.java b/test/framework/src/main/java/org/elasticsearch/test/junit/listeners/ReproduceInfoPrinter.java index b94c8551562ed..7d1b8411c01ac 100644 --- a/test/framework/src/main/java/org/elasticsearch/test/junit/listeners/ReproduceInfoPrinter.java +++ b/test/framework/src/main/java/org/elasticsearch/test/junit/listeners/ReproduceInfoPrinter.java @@ -174,8 +174,7 @@ private ReproduceErrorMessageBuilder appendESProperties() { appendOpt("tests.distribution", System.getProperty("tests.distribution")); appendOpt("compiler.java", System.getProperty("compiler.java")); appendOpt("runtime.java", System.getProperty("runtime.java")); - appendOpt("javax.net.ssl.keyStorePassword", System.getProperty("javax.net.ssl.keyStorePassword")); - appendOpt("javax.net.ssl.trustStorePassword", System.getProperty("javax.net.ssl.trustStorePassword")); + appendOpt(ESTestCase.FIPS_SYSPROP, System.getProperty(ESTestCase.FIPS_SYSPROP)); return this; } diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/XPackSettings.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/XPackSettings.java index d5d1b5440daea..82e9f2553c3ed 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/XPackSettings.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/XPackSettings.java @@ -6,6 +6,7 @@ package org.elasticsearch.xpack.core; +import org.apache.logging.log4j.LogManager; import org.elasticsearch.bootstrap.JavaVersion; import org.elasticsearch.common.settings.Setting; import org.elasticsearch.common.settings.Setting.Property; @@ -16,8 +17,10 @@ import org.elasticsearch.xpack.core.ssl.VerificationMode; import javax.crypto.SecretKeyFactory; +import javax.net.ssl.SSLContext; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Locale; @@ -183,7 +186,20 @@ private XPackSettings() { } }, Setting.Property.NodeScope); - public static final List DEFAULT_SUPPORTED_PROTOCOLS = List.of("TLSv1.3", "TLSv1.2", "TLSv1.1"); + public static final List DEFAULT_SUPPORTED_PROTOCOLS; + + static { + boolean supportsTLSv13 = false; + try { + SSLContext.getInstance("TLSv1.3"); + supportsTLSv13 = true; + } catch (NoSuchAlgorithmException e) { + // BCJSSE in FIPS mode doesn't support TLSv1.3 yet. + LogManager.getLogger(XPackSettings.class).debug("TLSv1.3 is not supported", e); + } + DEFAULT_SUPPORTED_PROTOCOLS = supportsTLSv13 ? + Arrays.asList("TLSv1.3", "TLSv1.2", "TLSv1.1") : Arrays.asList("TLSv1.2", "TLSv1.1"); + } public static final SSLClientAuth CLIENT_AUTH_DEFAULT = SSLClientAuth.REQUIRED; public static final SSLClientAuth HTTP_CLIENT_AUTH_DEFAULT = SSLClientAuth.NONE; diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/KeyConfig.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/KeyConfig.java index a0aeac73107d0..d7225deef9685 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/KeyConfig.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/KeyConfig.java @@ -10,6 +10,7 @@ import org.elasticsearch.env.Environment; import org.elasticsearch.xpack.core.ssl.cert.CertificateInfo; +import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.X509ExtendedKeyManager; import javax.net.ssl.X509ExtendedTrustManager; @@ -17,7 +18,12 @@ import java.nio.file.AccessDeniedException; import java.nio.file.Path; import java.security.AccessControlException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; +import java.security.UnrecoverableKeyException; +import java.security.cert.CertificateException; import java.util.Collection; import java.util.Collections; import java.util.List; @@ -27,7 +33,15 @@ abstract class KeyConfig extends TrustConfig { static final KeyConfig NONE = new KeyConfig() { @Override X509ExtendedKeyManager createKeyManager(@Nullable Environment environment) { - return null; + try { + KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); + keyStore.load(null, null); + KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + keyManagerFactory.init(keyStore, null); + return (X509ExtendedKeyManager) keyManagerFactory.getKeyManagers()[0]; + } catch (IOException | CertificateException | NoSuchAlgorithmException | UnrecoverableKeyException | KeyStoreException e) { + throw new ElasticsearchException("failed to initialize SSL KeyManager", e); + } } @Override diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/SSLService.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/SSLService.java index ec9f7a2d5a8f3..fb70e42ca8aa4 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/SSLService.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/SSLService.java @@ -22,7 +22,6 @@ import org.elasticsearch.xpack.core.watcher.WatcherField; import javax.net.ssl.HostnameVerifier; -import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLParameters; @@ -30,7 +29,6 @@ import javax.net.ssl.SSLSessionContext; import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; -import javax.net.ssl.TrustManagerFactory; import javax.net.ssl.X509ExtendedKeyManager; import javax.net.ssl.X509ExtendedTrustManager; import java.io.IOException; @@ -38,7 +36,6 @@ import java.net.Socket; import java.security.GeneralSecurityException; import java.security.KeyManagementException; -import java.security.KeyStore; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.Arrays; @@ -58,6 +55,8 @@ import java.util.function.Supplier; import java.util.stream.Collectors; +import static org.elasticsearch.xpack.core.XPackSettings.DEFAULT_SUPPORTED_PROTOCOLS; + /** * Provides access to {@link SSLEngine} and {@link SSLSocketFactory} objects based on a provided configuration. All * configurations loaded by this service must be configured on construction. @@ -74,7 +73,9 @@ public class SSLService { private static final Map ORDERED_PROTOCOL_ALGORITHM_MAP; static { LinkedHashMap protocolAlgorithmMap = new LinkedHashMap<>(); - protocolAlgorithmMap.put("TLSv1.3", "TLSv1.3"); + if (DEFAULT_SUPPORTED_PROTOCOLS.contains("TLSv1.3")) { + protocolAlgorithmMap.put("TLSv1.3", "TLSv1.3"); + } protocolAlgorithmMap.put("TLSv1.2", "TLSv1.2"); protocolAlgorithmMap.put("TLSv1.1", "TLSv1.1"); protocolAlgorithmMap.put("TLSv1", "TLSv1"); @@ -619,36 +620,18 @@ synchronized void reload() { private void reloadSslContext() { try { - X509ExtendedKeyManager loadedKeyManager = Optional.ofNullable(keyConfig.createKeyManager(env)). - orElse(getEmptyKeyManager()); - X509ExtendedTrustManager loadedTrustManager = Optional.ofNullable(trustConfig.createTrustManager(env)). - orElse(getEmptyTrustManager()); + X509ExtendedKeyManager loadedKeyManager = keyConfig.createKeyManager(env); + X509ExtendedTrustManager loadedTrustManager = trustConfig.createTrustManager(env); SSLContext loadedSslContext = SSLContext.getInstance(sslContextAlgorithm(sslConfiguration.supportedProtocols())); loadedSslContext.init(new X509ExtendedKeyManager[]{loadedKeyManager}, new X509ExtendedTrustManager[]{loadedTrustManager}, null); supportedCiphers(loadedSslContext.getSupportedSSLParameters().getCipherSuites(), sslConfiguration.cipherSuites(), false); this.context = loadedSslContext; - } catch (GeneralSecurityException | IOException e) { + } catch (GeneralSecurityException e) { throw new ElasticsearchException("failed to initialize the SSLContext", e); } } - X509ExtendedKeyManager getEmptyKeyManager() throws GeneralSecurityException, IOException { - KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); - keyStore.load(null, null); - KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); - keyManagerFactory.init(keyStore, null); - return (X509ExtendedKeyManager) keyManagerFactory.getKeyManagers()[0]; - } - - X509ExtendedTrustManager getEmptyTrustManager() throws GeneralSecurityException, IOException { - KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); - keyStore.load(null, null); - TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("X509"); - trustManagerFactory.init(keyStore); - return (X509ExtendedTrustManager) trustManagerFactory.getTrustManagers()[0]; - } - public void addReloadListener(Runnable listener) { this.reloadListeners.add(listener); } diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/XPackSettingsTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/XPackSettingsTests.java index 9f430819225a4..1ff99fc82a805 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/XPackSettingsTests.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/XPackSettingsTests.java @@ -56,7 +56,12 @@ public void testPasswordHashingAlgorithmSettingValidation() { } public void testDefaultSupportedProtocols() { - assertThat(XPackSettings.DEFAULT_SUPPORTED_PROTOCOLS, contains("TLSv1.3", "TLSv1.2", "TLSv1.1")); + if (inFipsJvm()) { + assertThat(XPackSettings.DEFAULT_SUPPORTED_PROTOCOLS, contains("TLSv1.2", "TLSv1.1")); + } else { + assertThat(XPackSettings.DEFAULT_SUPPORTED_PROTOCOLS, contains("TLSv1.3", "TLSv1.2", "TLSv1.1")); + + } } private boolean isSecretkeyFactoryAlgoAvailable(String algorithmId) { diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/RestrictedTrustManagerTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/RestrictedTrustManagerTests.java index 109722c37c086..7f19b9356a4ef 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/RestrictedTrustManagerTests.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/RestrictedTrustManagerTests.java @@ -33,6 +33,8 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; +import static org.elasticsearch.test.ESIntegTestCase.inFipsJvm; + public class RestrictedTrustManagerTests extends ESTestCase { private X509ExtendedTrustManager baseTrustManager; @@ -132,7 +134,8 @@ public void testThatDelegateTrustManagerIsRespected() throws Exception { if (cert.endsWith("/ca")) { assertTrusted(trustManager, cert); } else { - assertNotValid(trustManager, cert, "PKIX path building failed.*"); + assertNotValid(trustManager, cert, inFipsJvm() ? "unable to process certificates: Unable to find certificate chain.": + "PKIX path building failed.*"); } } } diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/SSLConfigurationReloaderTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/SSLConfigurationReloaderTests.java index 16b668080a545..a8625bef51c1d 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/SSLConfigurationReloaderTests.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/SSLConfigurationReloaderTests.java @@ -154,15 +154,16 @@ public void testReloadingKeyStore() throws Exception { * Tests the reloading of SSLContext when a PEM key and certificate are used. */ public void testPEMKeyConfigReloading() throws Exception { + assumeFalse("https://github.com/elastic/elasticsearch/issues/49094", inFipsJvm()); Path tempDir = createTempDir(); Path keyPath = tempDir.resolve("testnode.pem"); - Path updatedKeyPath = tempDir.resolve("testnode_updated.pem"); Path certPath = tempDir.resolve("testnode.crt"); + Path updatedKeyPath = tempDir.resolve("testnode_updated.pem"); Path updatedCertPath = tempDir.resolve("testnode_updated.crt"); Files.copy(getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.pem"), keyPath); + Files.copy(getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt"), certPath); Files.copy(getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_updated.pem"), updatedKeyPath); Files.copy(getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_updated.crt"), updatedCertPath); - Files.copy(getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt"), certPath); MockSecureSettings secureSettings = new MockSecureSettings(); secureSettings.setString("xpack.security.transport.ssl.secure_key_passphrase", "testnode"); final Settings settings = Settings.builder() @@ -266,15 +267,14 @@ public void testReloadingTrustStore() throws Exception { * Test the reloading of SSLContext whose trust config is backed by PEM certificate files. */ public void testReloadingPEMTrustConfig() throws Exception { + assumeFalse("https://github.com/elastic/elasticsearch/issues/49094", inFipsJvm()); Path tempDir = createTempDir(); Path serverCertPath = tempDir.resolve("testnode.crt"); Path serverKeyPath = tempDir.resolve("testnode.pem"); - Path updatedCert = tempDir.resolve("updated.crt"); - //Our keystore contains two Certificates it can present. One build from the RSA keypair and one build from the EC keypair. EC is - // used since it keyManager presents the first one in alias alphabetical order (and testnode_ec comes before testnode_rsa) + Path updatedCertPath = tempDir.resolve("updated.crt"); Files.copy(getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt"), serverCertPath); Files.copy(getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.pem"), serverKeyPath); - Files.copy(getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_updated.crt"), updatedCert); + Files.copy(getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_updated.crt"), updatedCertPath); Settings settings = baseKeystoreSettings(tempDir, null) .put("xpack.security.transport.ssl.enabled", true) .putList("xpack.security.transport.ssl.certificate_authorities", serverCertPath.toString()) @@ -293,7 +293,7 @@ public void testReloadingPEMTrustConfig() throws Exception { final Runnable modifier = () -> { try { - atomicMoveIfPossible(updatedCert, serverCertPath); + atomicMoveIfPossible(updatedCertPath, serverCertPath); } catch (Exception e) { throw new RuntimeException("failed to modify file", e); } diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/SSLServiceTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/SSLServiceTests.java index 3f741f9bd80cd..45cb8f8d24075 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/SSLServiceTests.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/SSLServiceTests.java @@ -40,7 +40,6 @@ import javax.net.ssl.SSLSessionContext; import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; -import javax.net.ssl.X509ExtendedTrustManager; import javax.security.cert.X509Certificate; import java.nio.file.Path; import java.security.AccessController; @@ -64,7 +63,6 @@ import static org.hamcrest.Matchers.arrayContainingInAnyOrder; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.emptyArray; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.hasItem; import static org.hamcrest.Matchers.instanceOf; @@ -503,14 +501,6 @@ public void testSSLStrategy() { } } - public void testEmptyTrustManager() throws Exception { - Settings settings = Settings.EMPTY; - final SSLService sslService = new SSLService(settings, env); - X509ExtendedTrustManager trustManager = sslService.sslContextHolder(sslService.getSSLConfiguration("xpack.security.transport.ssl")) - .getEmptyTrustManager(); - assertThat(trustManager.getAcceptedIssuers(), emptyArray()); - } - public void testGetConfigurationByContextName() throws Exception { assumeFalse("Can't run in a FIPS JVM, JKS keystores can't be used", inFipsJvm()); final SSLContext sslContext = SSLContext.getInstance("TLSv1.2"); diff --git a/x-pack/plugin/security/build.gradle b/x-pack/plugin/security/build.gradle index a496748f80b29..517f45ba97840 100644 --- a/x-pack/plugin/security/build.gradle +++ b/x-pack/plugin/security/build.gradle @@ -22,38 +22,38 @@ dependencies { testCompile project(path: xpackModule('core'), configuration: 'testArtifacts') - compile 'com.unboundid:unboundid-ldapsdk:4.0.8' - compileOnly 'org.bouncycastle:bcprov-jdk15on:1.59' - compileOnly 'org.bouncycastle:bcpkix-jdk15on:1.59' + compile 'com.unboundid:unboundid-ldapsdk:4.0.8' - // the following are all SAML dependencies - might as well download the whole internet - compile "org.opensaml:opensaml-core:3.3.0" - compile "org.opensaml:opensaml-saml-api:3.3.0" - compile "org.opensaml:opensaml-saml-impl:3.3.0" - compile "org.opensaml:opensaml-messaging-api:3.3.0" - compile "org.opensaml:opensaml-messaging-impl:3.3.0" - compile "org.opensaml:opensaml-security-api:3.3.0" - compile "org.opensaml:opensaml-security-impl:3.3.0" - compile "org.opensaml:opensaml-profile-api:3.3.0" - compile "org.opensaml:opensaml-profile-impl:3.3.0" - compile "org.opensaml:opensaml-xmlsec-api:3.3.0" - compile "org.opensaml:opensaml-xmlsec-impl:3.3.0" - compile "org.opensaml:opensaml-soap-api:3.3.0" - compile "org.opensaml:opensaml-soap-impl:3.3.0" - compile "org.opensaml:opensaml-storage-api:3.3.0" - compile "org.opensaml:opensaml-storage-impl:3.3.0" - compile "net.shibboleth.utilities:java-support:7.3.0" - compile "org.apache.santuario:xmlsec:2.0.8" - compile "io.dropwizard.metrics:metrics-core:3.2.2" - compile "org.cryptacular:cryptacular:1.2.0" - compile "org.slf4j:slf4j-api:${versions.slf4j}" - compile "org.apache.logging.log4j:log4j-slf4j-impl:${versions.log4j}" - compile "org.apache.httpcomponents:httpclient:${versions.httpclient}" - compile "org.apache.httpcomponents:httpcore:${versions.httpcore}" - compile "org.apache.httpcomponents:httpasyncclient:${versions.httpasyncclient}" - compile "org.apache.httpcomponents:httpcore-nio:${versions.httpcore}" - compile "org.apache.httpcomponents:httpclient-cache:${versions.httpclient}" - compile 'com.google.guava:guava:19.0' + // the following are all SAML dependencies - might as well download the whole internet + compile "org.opensaml:opensaml-core:3.3.0" + compile "org.opensaml:opensaml-saml-api:3.3.0" + compile "org.opensaml:opensaml-saml-impl:3.3.0" + compile "org.opensaml:opensaml-messaging-api:3.3.0" + compile "org.opensaml:opensaml-messaging-impl:3.3.0" + compile "org.opensaml:opensaml-security-api:3.3.0" + compile "org.opensaml:opensaml-security-impl:3.3.0" + compile "org.opensaml:opensaml-profile-api:3.3.0" + compile "org.opensaml:opensaml-profile-impl:3.3.0" + compile "org.opensaml:opensaml-xmlsec-api:3.3.0" + compile "org.opensaml:opensaml-xmlsec-impl:3.3.0" + compile "org.opensaml:opensaml-soap-api:3.3.0" + compile "org.opensaml:opensaml-soap-impl:3.3.0" + compile "org.opensaml:opensaml-storage-api:3.3.0" + compile "org.opensaml:opensaml-storage-impl:3.3.0" + compile "net.shibboleth.utilities:java-support:7.3.0" + compile "org.apache.santuario:xmlsec:2.0.8" + compile "io.dropwizard.metrics:metrics-core:3.2.2" + compile ("org.cryptacular:cryptacular:1.2.0") { + exclude group: 'org.bouncycastle' + } + compile "org.slf4j:slf4j-api:${versions.slf4j}" + compile "org.apache.logging.log4j:log4j-slf4j-impl:${versions.log4j}" + compile "org.apache.httpcomponents:httpclient:${versions.httpclient}" + compile "org.apache.httpcomponents:httpcore:${versions.httpcore}" + compile "org.apache.httpcomponents:httpasyncclient:${versions.httpasyncclient}" + compile "org.apache.httpcomponents:httpcore-nio:${versions.httpcore}" + compile "org.apache.httpcomponents:httpclient-cache:${versions.httpclient}" + compile 'com.google.guava:guava:19.0' // Dependencies for oidc compile "com.nimbusds:oauth2-oidc-sdk:6.16.5" @@ -176,108 +176,269 @@ forbiddenApisMain { // classes are missing, e.g. com.ibm.icu.lang.UCharacter thirdPartyAudit { - ignoreMissingClasses( - // SAML dependencies - // [missing classes] Some cli utilities that we don't use depend on these missing JCommander classes - 'com.beust.jcommander.JCommander', - 'com.beust.jcommander.converters.BaseConverter', - // [missing classes] Shibboleth + OpenSAML have servlet support that we don't use - 'javax.servlet.AsyncContext', - 'javax.servlet.DispatcherType', - 'javax.servlet.Filter', - 'javax.servlet.FilterChain', - 'javax.servlet.FilterConfig', - 'javax.servlet.RequestDispatcher', - 'javax.servlet.ServletContext', - 'javax.servlet.ServletException', - 'javax.servlet.ServletInputStream', - 'javax.servlet.ServletOutputStream', - 'javax.servlet.ServletRequest', - 'javax.servlet.ServletResponse', - 'javax.servlet.http.Cookie', - 'javax.servlet.http.HttpServletRequest', - 'javax.servlet.http.HttpServletResponse', - 'javax.servlet.http.HttpServletResponseWrapper', - 'javax.servlet.http.HttpSession', - 'javax.servlet.http.Part', - // [missing classes] Shibboleth + OpenSAML have velocity support that we don't use - 'org.apache.velocity.VelocityContext', - 'org.apache.velocity.app.VelocityEngine', - 'org.apache.velocity.context.Context', - 'org.apache.velocity.exception.VelocityException', - 'org.apache.velocity.runtime.RuntimeServices', - 'org.apache.velocity.runtime.log.LogChute', - 'org.apache.velocity.runtime.resource.loader.StringResourceLoader', - 'org.apache.velocity.runtime.resource.util.StringResourceRepository', - // [missing classes] OpenSAML depends on Apache XML security which depends on Xalan, but only for functionality that OpenSAML doesn't use - 'org.apache.xml.dtm.DTM', - 'org.apache.xml.utils.PrefixResolver', - 'org.apache.xml.utils.PrefixResolverDefault', - 'org.apache.xpath.Expression', - 'org.apache.xpath.NodeSetDTM', - 'org.apache.xpath.XPath', - 'org.apache.xpath.XPathContext', - 'org.apache.xpath.compiler.FunctionTable', - 'org.apache.xpath.functions.Function', - 'org.apache.xpath.objects.XNodeSet', - 'org.apache.xpath.objects.XObject', - // [missing classes] OpenSAML storage has an optional LDAP storage impl - 'org.ldaptive.AttributeModification', - 'org.ldaptive.AttributeModificationType', - 'org.ldaptive.Connection', - 'org.ldaptive.DeleteOperation', - 'org.ldaptive.DeleteRequest', - 'org.ldaptive.LdapAttribute', - 'org.ldaptive.LdapEntry', - 'org.ldaptive.LdapException', - 'org.ldaptive.ModifyOperation', - 'org.ldaptive.ModifyRequest', - 'org.ldaptive.Response', - 'org.ldaptive.ResultCode', - 'org.ldaptive.SearchOperation', - 'org.ldaptive.SearchRequest', - 'org.ldaptive.SearchResult', - 'org.ldaptive.ext.MergeOperation', - 'org.ldaptive.ext.MergeRequest', - 'org.ldaptive.pool.ConnectionPool', - 'org.ldaptive.pool.PooledConnectionFactory', - // [missing classes] OpenSAML storage has an optional JSON-backed storage impl - 'javax.json.Json', - 'javax.json.JsonException', - 'javax.json.JsonNumber', - 'javax.json.JsonObject', - 'javax.json.JsonReader', - 'javax.json.JsonValue$ValueType', - 'javax.json.JsonValue', - 'javax.json.stream.JsonGenerator', - // [missing classes] OpenSAML storage has an optional JPA storage impl - 'javax.persistence.EntityManager', - 'javax.persistence.EntityManagerFactory', - 'javax.persistence.EntityTransaction', - 'javax.persistence.LockModeType', - 'javax.persistence.Query', - // [missing classes] OpenSAML storage and HttpClient cache have optional memcache support - 'net.spy.memcached.CASResponse', - 'net.spy.memcached.CASValue', - 'net.spy.memcached.MemcachedClient', - 'net.spy.memcached.MemcachedClientIF', - 'net.spy.memcached.CachedData', - 'net.spy.memcached.internal.OperationFuture', - 'net.spy.memcached.transcoders.Transcoder', - // [missing classes] Http Client cache has optional ehcache support - 'net.sf.ehcache.Ehcache', - 'net.sf.ehcache.Element', - // [missing classes] SLF4j includes an optional class that depends on an extension class (!) - 'org.slf4j.ext.EventData', - // Optional dependency of oauth2-oidc-sdk that we don't need since we do not support AES-SIV for JWE - 'org.cryptomator.siv.SivMode', - // Optional dependency of nimbus-jose-jwt for handling Ed25519 signatures and ECDH with X25519 (RFC 8037) - 'com.google.crypto.tink.subtle.Ed25519Sign', - 'com.google.crypto.tink.subtle.Ed25519Sign$KeyPair', - 'com.google.crypto.tink.subtle.Ed25519Verify', - 'com.google.crypto.tink.subtle.X25519' - - ) + ignoreMissingClasses ( + // SAML dependencies + // [missing classes] Some cli utilities that we don't use depend on these missing JCommander classes + 'com.beust.jcommander.JCommander', + 'com.beust.jcommander.converters.BaseConverter', + // [missing classes] Shibboleth + OpenSAML have servlet support that we don't use + 'javax.servlet.AsyncContext', + 'javax.servlet.DispatcherType', + 'javax.servlet.Filter', + 'javax.servlet.FilterChain', + 'javax.servlet.FilterConfig', + 'javax.servlet.RequestDispatcher', + 'javax.servlet.ServletContext', + 'javax.servlet.ServletException', + 'javax.servlet.ServletInputStream', + 'javax.servlet.ServletOutputStream', + 'javax.servlet.ServletRequest', + 'javax.servlet.ServletResponse', + 'javax.servlet.http.Cookie', + 'javax.servlet.http.HttpServletRequest', + 'javax.servlet.http.HttpServletResponse', + 'javax.servlet.http.HttpServletResponseWrapper', + 'javax.servlet.http.HttpSession', + 'javax.servlet.http.Part', + // [missing classes] Shibboleth + OpenSAML have velocity support that we don't use + 'org.apache.velocity.VelocityContext', + 'org.apache.velocity.app.VelocityEngine', + 'org.apache.velocity.context.Context', + 'org.apache.velocity.exception.VelocityException', + 'org.apache.velocity.runtime.RuntimeServices', + 'org.apache.velocity.runtime.log.LogChute', + 'org.apache.velocity.runtime.resource.loader.StringResourceLoader', + 'org.apache.velocity.runtime.resource.util.StringResourceRepository', + // [missing classes] OpenSAML depends on Apache XML security which depends on Xalan, but only for functionality that OpenSAML doesn't use + 'org.apache.xml.dtm.DTM', + 'org.apache.xml.utils.PrefixResolver', + 'org.apache.xml.utils.PrefixResolverDefault', + 'org.apache.xpath.Expression', + 'org.apache.xpath.NodeSetDTM', + 'org.apache.xpath.XPath', + 'org.apache.xpath.XPathContext', + 'org.apache.xpath.compiler.FunctionTable', + 'org.apache.xpath.functions.Function', + 'org.apache.xpath.objects.XNodeSet', + 'org.apache.xpath.objects.XObject', + // [missing classes] OpenSAML storage has an optional LDAP storage impl + 'org.ldaptive.AttributeModification', + 'org.ldaptive.AttributeModificationType', + 'org.ldaptive.Connection', + 'org.ldaptive.DeleteOperation', + 'org.ldaptive.DeleteRequest', + 'org.ldaptive.LdapAttribute', + 'org.ldaptive.LdapEntry', + 'org.ldaptive.LdapException', + 'org.ldaptive.ModifyOperation', + 'org.ldaptive.ModifyRequest', + 'org.ldaptive.Response', + 'org.ldaptive.ResultCode', + 'org.ldaptive.SearchOperation', + 'org.ldaptive.SearchRequest', + 'org.ldaptive.SearchResult', + 'org.ldaptive.ext.MergeOperation', + 'org.ldaptive.ext.MergeRequest', + 'org.ldaptive.pool.ConnectionPool', + 'org.ldaptive.pool.PooledConnectionFactory', + // [missing classes] OpenSAML storage has an optional JSON-backed storage impl + 'javax.json.Json', + 'javax.json.JsonException', + 'javax.json.JsonNumber', + 'javax.json.JsonObject', + 'javax.json.JsonReader', + 'javax.json.JsonValue$ValueType', + 'javax.json.JsonValue', + 'javax.json.stream.JsonGenerator', + // [missing classes] OpenSAML storage has an optional JPA storage impl + 'javax.persistence.EntityManager', + 'javax.persistence.EntityManagerFactory', + 'javax.persistence.EntityTransaction', + 'javax.persistence.LockModeType', + 'javax.persistence.Query', + // [missing classes] OpenSAML storage and HttpClient cache have optional memcache support + 'net.spy.memcached.CASResponse', + 'net.spy.memcached.CASValue', + 'net.spy.memcached.MemcachedClient', + 'net.spy.memcached.MemcachedClientIF', + 'net.spy.memcached.CachedData', + 'net.spy.memcached.internal.OperationFuture', + 'net.spy.memcached.transcoders.Transcoder', + // [missing classes] Http Client cache has optional ehcache support + 'net.sf.ehcache.Ehcache', + 'net.sf.ehcache.Element', + // [missing classes] SLF4j includes an optional class that depends on an extension class (!) + 'org.slf4j.ext.EventData', + // Optional dependency of oauth2-oidc-sdk that we don't need since we do not support AES-SIV for JWE + 'org.cryptomator.siv.SivMode', + // Optional dependency of nimbus-jose-jwt for handling Ed25519 signatures and ECDH with X25519 (RFC 8037) + 'com.google.crypto.tink.subtle.Ed25519Sign', + 'com.google.crypto.tink.subtle.Ed25519Sign$KeyPair', + 'com.google.crypto.tink.subtle.Ed25519Verify', + 'com.google.crypto.tink.subtle.X25519', + // Bouncycastle is an optional dependency for apache directory, cryptacular and opensaml packages. We + // acknowledge them here instead of adding bouncy castle as a compileOnly dependency + 'org.bouncycastle.asn1.ASN1Encodable', + 'org.bouncycastle.asn1.ASN1InputStream', + 'org.bouncycastle.asn1.ASN1Integer', + 'org.bouncycastle.asn1.ASN1ObjectIdentifier', + 'org.bouncycastle.asn1.ASN1OctetString', + 'org.bouncycastle.asn1.ASN1Primitive', + 'org.bouncycastle.asn1.ASN1Sequence', + 'org.bouncycastle.asn1.ASN1TaggedObject', + 'org.bouncycastle.asn1.DEROctetString', + 'org.bouncycastle.asn1.DERSequence', + 'org.bouncycastle.asn1.pkcs.EncryptedPrivateKeyInfo', + 'org.bouncycastle.asn1.pkcs.EncryptionScheme', + 'org.bouncycastle.asn1.pkcs.KeyDerivationFunc', + 'org.bouncycastle.asn1.pkcs.PBEParameter', + 'org.bouncycastle.asn1.pkcs.PBES2Parameters', + 'org.bouncycastle.asn1.pkcs.PBKDF2Params', + 'org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers', + 'org.bouncycastle.asn1.pkcs.PrivateKeyInfo', + 'org.bouncycastle.asn1.x500.AttributeTypeAndValue', + 'org.bouncycastle.asn1.x500.RDN', + 'org.bouncycastle.asn1.x500.X500Name', + 'org.bouncycastle.asn1.x509.AccessDescription', + 'org.bouncycastle.asn1.x509.AlgorithmIdentifier', + 'org.bouncycastle.asn1.x509.AuthorityKeyIdentifier', + 'org.bouncycastle.asn1.x509.BasicConstraints', + 'org.bouncycastle.asn1.x509.DistributionPoint', + 'org.bouncycastle.asn1.x509.Extension', + 'org.bouncycastle.asn1.x509.GeneralName', + 'org.bouncycastle.asn1.x509.GeneralNames', + 'org.bouncycastle.asn1.x509.GeneralNamesBuilder', + 'org.bouncycastle.asn1.x509.KeyPurposeId', + 'org.bouncycastle.asn1.x509.KeyUsage', + 'org.bouncycastle.asn1.x509.PolicyInformation', + 'org.bouncycastle.asn1.x509.SubjectKeyIdentifier', + 'org.bouncycastle.asn1.x509.SubjectPublicKeyInfo', + 'org.bouncycastle.asn1.x9.X9ECParameters', + 'org.bouncycastle.cert.X509v3CertificateBuilder', + 'org.bouncycastle.cert.jcajce.JcaX509CertificateConverter', + 'org.bouncycastle.cert.jcajce.JcaX509CertificateHolder', + 'org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils', + 'org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder', + 'org.bouncycastle.crypto.BlockCipher', + 'org.bouncycastle.crypto.BufferedBlockCipher', + 'org.bouncycastle.crypto.CipherParameters', + 'org.bouncycastle.crypto.Digest', + 'org.bouncycastle.crypto.InvalidCipherTextException', + 'org.bouncycastle.crypto.PBEParametersGenerator', + 'org.bouncycastle.crypto.StreamCipher', + 'org.bouncycastle.crypto.digests.GOST3411Digest', + 'org.bouncycastle.crypto.digests.MD2Digest', + 'org.bouncycastle.crypto.digests.MD4Digest', + 'org.bouncycastle.crypto.digests.MD5Digest', + 'org.bouncycastle.crypto.digests.RIPEMD128Digest', + 'org.bouncycastle.crypto.digests.RIPEMD160Digest', + 'org.bouncycastle.crypto.digests.RIPEMD256Digest', + 'org.bouncycastle.crypto.digests.RIPEMD320Digest', + 'org.bouncycastle.crypto.digests.SHA1Digest', + 'org.bouncycastle.crypto.digests.SHA224Digest', + 'org.bouncycastle.crypto.digests.SHA256Digest', + 'org.bouncycastle.crypto.digests.SHA384Digest', + 'org.bouncycastle.crypto.digests.SHA3Digest', + 'org.bouncycastle.crypto.digests.SHA512Digest', + 'org.bouncycastle.crypto.digests.TigerDigest', + 'org.bouncycastle.crypto.digests.WhirlpoolDigest', + 'org.bouncycastle.crypto.engines.AESEngine', + 'org.bouncycastle.crypto.engines.AESFastEngine', + 'org.bouncycastle.crypto.engines.BlowfishEngine', + 'org.bouncycastle.crypto.engines.CAST5Engine', + 'org.bouncycastle.crypto.engines.CAST6Engine', + 'org.bouncycastle.crypto.engines.CamelliaEngine', + 'org.bouncycastle.crypto.engines.DESEngine', + 'org.bouncycastle.crypto.engines.DESedeEngine', + 'org.bouncycastle.crypto.engines.GOST28147Engine', + 'org.bouncycastle.crypto.engines.Grain128Engine', + 'org.bouncycastle.crypto.engines.HC128Engine', + 'org.bouncycastle.crypto.engines.HC256Engine', + 'org.bouncycastle.crypto.engines.ISAACEngine', + 'org.bouncycastle.crypto.engines.NoekeonEngine', + 'org.bouncycastle.crypto.engines.RC2Engine', + 'org.bouncycastle.crypto.engines.RC4Engine', + 'org.bouncycastle.crypto.engines.RC532Engine', + 'org.bouncycastle.crypto.engines.RC564Engine', + 'org.bouncycastle.crypto.engines.RC6Engine', + 'org.bouncycastle.crypto.engines.SEEDEngine', + 'org.bouncycastle.crypto.engines.Salsa20Engine', + 'org.bouncycastle.crypto.engines.SerpentEngine', + 'org.bouncycastle.crypto.engines.SkipjackEngine', + 'org.bouncycastle.crypto.engines.TEAEngine', + 'org.bouncycastle.crypto.engines.TwofishEngine', + 'org.bouncycastle.crypto.engines.VMPCEngine', + 'org.bouncycastle.crypto.engines.XTEAEngine', + 'org.bouncycastle.crypto.generators.OpenSSLPBEParametersGenerator', + 'org.bouncycastle.crypto.generators.PKCS5S1ParametersGenerator', + 'org.bouncycastle.crypto.generators.PKCS5S2ParametersGenerator', + 'org.bouncycastle.crypto.io.CipherInputStream', + 'org.bouncycastle.crypto.io.CipherOutputStream', + 'org.bouncycastle.crypto.macs.HMac', + 'org.bouncycastle.crypto.modes.AEADBlockCipher', + 'org.bouncycastle.crypto.modes.CBCBlockCipher', + 'org.bouncycastle.crypto.modes.CCMBlockCipher', + 'org.bouncycastle.crypto.modes.CFBBlockCipher', + 'org.bouncycastle.crypto.modes.EAXBlockCipher', + 'org.bouncycastle.crypto.modes.GCMBlockCipher', + 'org.bouncycastle.crypto.modes.OCBBlockCipher', + 'org.bouncycastle.crypto.modes.OFBBlockCipher', + 'org.bouncycastle.crypto.paddings.BlockCipherPadding', + 'org.bouncycastle.crypto.paddings.ISO10126d2Padding', + 'org.bouncycastle.crypto.paddings.ISO7816d4Padding', + 'org.bouncycastle.crypto.paddings.PKCS7Padding', + 'org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher', + 'org.bouncycastle.crypto.paddings.TBCPadding', + 'org.bouncycastle.crypto.paddings.X923Padding', + 'org.bouncycastle.crypto.paddings.ZeroBytePadding', + 'org.bouncycastle.crypto.params.AEADParameters', + 'org.bouncycastle.crypto.params.AsymmetricKeyParameter', + 'org.bouncycastle.crypto.params.DSAKeyParameters', + 'org.bouncycastle.crypto.params.DSAParameters', + 'org.bouncycastle.crypto.params.DSAPrivateKeyParameters', + 'org.bouncycastle.crypto.params.DSAPublicKeyParameters', + 'org.bouncycastle.crypto.params.ECDomainParameters', + 'org.bouncycastle.crypto.params.ECKeyParameters', + 'org.bouncycastle.crypto.params.ECPrivateKeyParameters', + 'org.bouncycastle.crypto.params.ECPublicKeyParameters', + 'org.bouncycastle.crypto.params.KeyParameter', + 'org.bouncycastle.crypto.params.ParametersWithIV', + 'org.bouncycastle.crypto.params.RC2Parameters', + 'org.bouncycastle.crypto.params.RC5Parameters', + 'org.bouncycastle.crypto.params.RSAKeyParameters', + 'org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters', + 'org.bouncycastle.crypto.prng.EntropySource', + 'org.bouncycastle.crypto.prng.SP800SecureRandom', + 'org.bouncycastle.crypto.prng.SP800SecureRandomBuilder', + 'org.bouncycastle.crypto.prng.drbg.HashSP800DRBG', + 'org.bouncycastle.crypto.prng.drbg.SP80090DRBG', + 'org.bouncycastle.crypto.signers.DSASigner', + 'org.bouncycastle.crypto.signers.ECDSASigner', + 'org.bouncycastle.crypto.signers.RSADigestSigner', + 'org.bouncycastle.crypto.util.PrivateKeyFactory', + 'org.bouncycastle.crypto.util.PrivateKeyInfoFactory', + 'org.bouncycastle.crypto.util.PublicKeyFactory', + 'org.bouncycastle.crypto.util.SubjectPublicKeyInfoFactory', + 'org.bouncycastle.jcajce.provider.asymmetric.dsa.KeyPairGeneratorSpi', + 'org.bouncycastle.jcajce.provider.asymmetric.ec.KeyPairGeneratorSpi$EC', + 'org.bouncycastle.jcajce.provider.asymmetric.rsa.KeyPairGeneratorSpi', + 'org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util', + 'org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil', + 'org.bouncycastle.jce.provider.BouncyCastleProvider', + 'org.bouncycastle.jce.spec.ECNamedCurveGenParameterSpec', + 'org.bouncycastle.math.ec.ECFieldElement', + 'org.bouncycastle.math.ec.ECPoint', + 'org.bouncycastle.openssl.jcajce.JcaPEMWriter', + 'org.bouncycastle.operator.jcajce.JcaContentSignerBuilder', + 'org.bouncycastle.util.Arrays', + 'org.bouncycastle.util.Strings', + 'org.bouncycastle.util.io.Streams', + 'org.bouncycastle.x509.extension.X509ExtensionUtil', + 'org.bouncycastle.cert.X509CertificateHolder', + 'org.bouncycastle.openssl.PEMKeyPair', + 'org.bouncycastle.openssl.PEMParser', + 'org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter' + ) ignoreViolations( // Guava uses internal java api: sun.misc.Unsafe diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/LdapSessionFactoryTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/LdapSessionFactoryTests.java index 9867cc29fd3da..f7f38d41a2d66 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/LdapSessionFactoryTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/LdapSessionFactoryTests.java @@ -239,6 +239,9 @@ public void testGroupLookupBase() throws Exception { * (one failure, one success) depending on which file content is in place. */ public void testSslTrustIsReloaded() throws Exception { + assumeFalse("NPE thrown in BCFIPS JSSE - addressed in " + + "https://github.com/bcgit/bc-java/commit/5aed687e17a3cd63f34373cafe92699b90076fb6#diff-8e5d8089bc0d504d93194a1e484d3950R179", + inFipsJvm()); InMemoryDirectoryServer ldapServer = randomFrom(ldapServers); InetAddress listenAddress = ldapServer.getListenAddress("ldaps"); if (listenAddress == null) { diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/pki/PkiRealmTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/pki/PkiRealmTests.java index 132c22846cb6f..5b5d45b1d41fc 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/pki/PkiRealmTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/pki/PkiRealmTests.java @@ -236,6 +236,7 @@ public void testCustomUsernamePatternMismatchesAndNullToken() throws Exception { } public void testVerificationUsingATruststore() throws Exception { + assumeFalse("Can't run in a FIPS JVM, JKS keystores can't be used", inFipsJvm()); X509Certificate certificate = readCert(getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt")); UserRoleMapper roleMapper = buildRoleMapper(); @@ -294,6 +295,7 @@ public void testAuthenticationDelegationFailsWithoutTruststore() throws Exceptio } public void testAuthenticationDelegationSuccess() throws Exception { + assumeFalse("Can't run in a FIPS JVM, JKS keystores can't be used", inFipsJvm()); X509Certificate certificate = readCert(getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt")); Authentication mockAuthentication = mock(Authentication.class); User mockUser = mock(User.class); @@ -330,6 +332,7 @@ public void testAuthenticationDelegationSuccess() throws Exception { } public void testAuthenticationDelegationFailure() throws Exception { + assumeFalse("Can't run in a FIPS JVM, JKS keystores can't be used", inFipsJvm()); X509Certificate certificate = readCert(getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt")); X509AuthenticationToken delegatedToken = X509AuthenticationToken.delegated(new X509Certificate[] { certificate }, mock(Authentication.class)); @@ -353,6 +356,7 @@ public void testAuthenticationDelegationFailure() throws Exception { } public void testVerificationFailsUsingADifferentTruststore() throws Exception { + assumeFalse("Can't run in a FIPS JVM, JKS keystores can't be used", inFipsJvm()); X509Certificate certificate = readCert(getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt")); UserRoleMapper roleMapper = buildRoleMapper(); MockSecureSettings secureSettings = new MockSecureSettings(); @@ -377,6 +381,7 @@ public void testVerificationFailsUsingADifferentTruststore() throws Exception { } public void testTruststorePathWithoutPasswordThrowsException() throws Exception { + assumeFalse("Can't run in a FIPS JVM, JKS keystores can't be used", inFipsJvm()); Settings settings = Settings.builder() .put(globalSettings) .put("xpack.security.authc.realms.pki.mypki.truststore.path", @@ -391,6 +396,7 @@ public void testTruststorePathWithoutPasswordThrowsException() throws Exception } public void testTruststorePathWithLegacyPasswordDoesNotThrow() throws Exception { + assumeFalse("Can't run in a FIPS JVM, JKS keystores can't be used", inFipsJvm()); Settings settings = Settings.builder() .put(globalSettings) .put("xpack.security.authc.realms.pki.mypki.truststore.path", diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/AbstractSimpleSecurityTransportTestCase.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/AbstractSimpleSecurityTransportTestCase.java index 60fe6d15b9994..ffb470083e90e 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/AbstractSimpleSecurityTransportTestCase.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/AbstractSimpleSecurityTransportTestCase.java @@ -136,6 +136,8 @@ public void testTcpHandshake() { @SuppressForbidden(reason = "Need to open socket connection") public void testRenegotiation() throws Exception { + assumeFalse("BCTLS doesn't support renegotiation: https://github.com/bcgit/bc-java/issues/593#issuecomment-533518845", + inFipsJvm()); // force TLSv1.2 since renegotiation is not supported by 1.3 SSLService sslService = createSSLService(Settings.builder().put("xpack.security.transport.ssl.supported_protocols", "TLSv1.2").build()); diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/nio/SSLDriverTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/nio/SSLDriverTests.java index ab033caedc5ea..7a6a1fd859ac5 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/nio/SSLDriverTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/nio/SSLDriverTests.java @@ -38,6 +38,7 @@ public class SSLDriverTests extends ESTestCase { private final AtomicInteger openPages = new AtomicInteger(0); public void testPingPongAndClose() throws Exception { + assumeFalse("Fails in normalClose as receiveDriver.getOutboundBuffer().hasEncryptedBytesToFlush() is false", inFipsJvm()); SSLContext sslContext = getSSLContext(); SSLDriver clientDriver = getDriver(sslContext.createSSLEngine(), true); @@ -76,6 +77,8 @@ public void testDataStoredInOutboundBufferIsClosed() throws Exception { } public void testRenegotiate() throws Exception { + assumeFalse("BCTLS doesn't support renegotiation: https://github.com/bcgit/bc-java/issues/593#issuecomment-533518845", + inFipsJvm()); SSLContext sslContext = getSSLContext(); SSLEngine serverEngine = sslContext.createSSLEngine(); @@ -121,6 +124,7 @@ public void testRenegotiate() throws Exception { } public void testBigApplicationData() throws Exception { + assumeFalse("Fails in normalClose as receiveDriver.getOutboundBuffer().hasEncryptedBytesToFlush() is false", inFipsJvm()); SSLContext sslContext = getSSLContext(); SSLDriver clientDriver = getDriver(sslContext.createSSLEngine(), true); @@ -165,7 +169,9 @@ public void testHandshakeFailureBecauseProtocolMismatch() throws Exception { SSLException sslException = expectThrows(SSLException.class, () -> handshake(clientDriver, serverDriver)); String oldExpected = "Client requested protocol TLSv1.1 not enabled or not supported"; String jdk11Expected = "The client supported protocol versions [TLSv1.1] are not accepted by server preferences [TLS12]"; - boolean expectedMessage = oldExpected.equals(sslException.getMessage()) || jdk11Expected.equals(sslException.getMessage()); + String bctlsExpected = "org.bouncycastle.tls.TlsFatalAlert: protocol_version(70)"; + boolean expectedMessage = oldExpected.equals(sslException.getMessage()) || jdk11Expected.equals(sslException.getMessage()) + || bctlsExpected.equals(sslException.getMessage()); assertTrue("Unexpected exception message: " + sslException.getMessage(), expectedMessage); // Prior to JDK11 we still need to send a close alert @@ -199,7 +205,8 @@ public void testHandshakeFailureBecauseNoCiphers() throws Exception { } public void testCloseDuringHandshakeJDK11() throws Exception { - assumeTrue("this tests ssl engine for JDK11", JavaVersion.current().compareTo(JavaVersion.parse("11")) >= 0); + assumeTrue("this tests ssl engine for JDK11", + JavaVersion.current().compareTo(JavaVersion.parse("11")) >= 0 && inFipsJvm() == false); SSLContext sslContext = getSSLContext(); SSLDriver clientDriver = getDriver(sslContext.createSSLEngine(), true); SSLDriver serverDriver = getDriver(sslContext.createSSLEngine(), false); @@ -292,7 +299,7 @@ private SSLContext getSSLContext() throws Exception { (certPath)))); KeyManager km = CertParsingUtils.keyManager(CertParsingUtils.readCertificates(Collections.singletonList(getDataPath (certPath))), PemUtils.readPrivateKey(getDataPath(keyPath), "testclient"::toCharArray), "testclient".toCharArray()); - sslContext = SSLContext.getInstance(randomFrom("TLSv1.2", "TLSv1.3")); + sslContext = SSLContext.getInstance(inFipsJvm() ? "TLSv1.2" : randomFrom("TLSv1.2", "TLSv1.3")); sslContext.init(new KeyManager[] { km }, new TrustManager[] { tm }, new SecureRandom()); return sslContext; } diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/ssl/EllipticCurveSSLTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/ssl/EllipticCurveSSLTests.java index 04169c675953a..df701aacb26e2 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/ssl/EllipticCurveSSLTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/ssl/EllipticCurveSSLTests.java @@ -60,6 +60,7 @@ protected boolean transportSSLEnabled() { } public void testConnection() throws Exception { + assumeFalse("Fails on BCTLS with 'Closed engine without receiving the close alert message.'", inFipsJvm()); final Path keyPath = getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/prime256v1-key.pem"); final Path certPath = getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/prime256v1-cert.pem"); PrivateKey privateKey = PemUtils.readPrivateKey(keyPath, () -> null); diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLClientAuthTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLClientAuthTests.java index 819dd8d2ecc8c..216d0715f7b6f 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLClientAuthTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLClientAuthTests.java @@ -141,7 +141,7 @@ private SSLContext getSSLContext() { (certPath), getDataPath(nodeCertPath), getDataPath(nodeEcCertPath)))); KeyManager km = CertParsingUtils.keyManager(CertParsingUtils.readCertificates(Collections.singletonList(getDataPath (certPath))), PemUtils.readPrivateKey(getDataPath(keyPath), "testclient"::toCharArray), "testclient".toCharArray()); - SSLContext context = SSLContext.getInstance(randomFrom("TLSv1.3", "TLSv1.2")); + SSLContext context = SSLContext.getInstance(inFipsJvm() ? "TLSv1.2" : randomFrom("TLSv1.3", "TLSv1.2")); context.init(new KeyManager[] { km }, new TrustManager[] { tm }, new SecureRandom()); return context; } catch (Exception e) { diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLReloadIntegTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLReloadIntegTests.java index 25f3215a4841b..6354ddb5046c3 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLReloadIntegTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLReloadIntegTests.java @@ -91,6 +91,7 @@ protected boolean transportSSLEnabled() { } public void testThatSSLConfigurationReloadsOnModification() throws Exception { + assumeFalse("https://github.com/elastic/elasticsearch/issues/49094", inFipsJvm()); Path keyPath = createTempDir().resolve("testnode_updated.pem"); Path certPath = createTempDir().resolve("testnode_updated.crt"); Files.copy(getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_updated.pem"), keyPath);