Enable tests in FIPS 140 in JDK 11 (#49485)

This change changes the way to run our test suites in 
JVMs configured in FIPS 140 approved mode. It does so by:

- Configuring any given runtime Java in FIPS mode with the bundled
policy and security properties files, setting the system
properties java.security.properties and java.security.policy
with the == operator that overrides the default JVM properties
and policy.

- When runtime java is 11 and higher, using BouncyCastle FIPS 
Cryptographic provider and BCJSSE in FIPS mode. These are 
used as testRuntime dependencies for unit
tests and internal clusters, and copied (relevant jars)
explicitly to the lib directory for testclusters used in REST tests

- When runtime java is 8, using BouncyCastle FIPS 
Cryptographic provider and SunJSSE in FIPS mode. 

Running the tests in FIPS 140 approved mode doesn't require an
additional configuration either in CI workers or locally and is
controlled by specifying -Dtests.fips.enabled=true
This commit is contained in:
Ioannis Kakavas 2020-01-27 11:14:52 +02:00 committed by GitHub
parent dd3e2f1e18
commit ee202a642f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
44 changed files with 750 additions and 253 deletions

View File

@ -7,7 +7,6 @@
ES_RUNTIME_JAVA:
- java8
- java8fips
- java11
- openjdk13
- openjdk14

View File

@ -172,6 +172,9 @@ if (project != rootProject) {
forbiddenApisTest.enabled = false
jarHell.enabled = false
thirdPartyAudit.enabled = false
if (Boolean.parseBoolean(System.getProperty("tests.fips.enabled"))){
test.enabled = false
}
configurations {
distribution
@ -204,6 +207,7 @@ if (project != rootProject) {
exclude '**/*.p12'
// the file that actually defines nocommit
exclude '**/ForbiddenPatternsTask.java'
exclude '**/*.bcfks'
}
testingConventions {

View File

@ -18,7 +18,6 @@
*/
package org.elasticsearch.gradle
import com.github.jengelman.gradle.plugins.shadow.ShadowPlugin
import com.github.jengelman.gradle.plugins.shadow.ShadowBasePlugin
import com.github.jengelman.gradle.plugins.shadow.ShadowExtension
import com.github.jengelman.gradle.plugins.shadow.ShadowJavaPlugin
@ -34,9 +33,9 @@ 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.gradle.api.Action
import org.elasticsearch.gradle.testclusters.TestDistribution
import org.elasticsearch.gradle.tool.Boilerplate
import org.gradle.api.Action
import org.gradle.api.GradleException
import org.gradle.api.InvalidUserDataException
import org.gradle.api.JavaVersion
@ -141,34 +140,71 @@ class BuildPlugin implements Plugin<Project> {
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<ElasticsearchCluster> testClusters = project.extensions.findByName(TestClustersPlugin.EXTENSION_NAME) as NamedDomainObjectContainer<ElasticsearchCluster>
if (testClusters != null) {
testClusters.all { ElasticsearchCluster cluster ->
cluster.setTestDistribution(TestDistribution.DEFAULT)
cluster.systemProperty 'javax.net.ssl.trustStorePassword', 'password'
cluster.systemProperty 'javax.net.ssl.keyStorePassword', 'password'
// Can't use our DiagnosticTrustManager with SunJSSE in FIPS mode
cluster.setting 'xpack.security.ssl.diagnose.trust', 'false'
static void configureFips140(Project project) {
// Common config when running with a FIPS-140 runtime JVM
if (inFipsJvm()) {
// 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")
}
ExportElasticsearchBuildResourcesTask buildResources = project.tasks.getByName('buildResources') as ExportElasticsearchBuildResourcesTask
File securityProperties = buildResources.copy("fips_java.security")
File security8Properties = buildResources.copy("fips_java8.security")
File securityPolicy = buildResources.copy("fips_java.policy")
File security8Policy = buildResources.copy("fips_java8.policy")
File bcfksKeystore = buildResources.copy("cacerts.bcfks")
GlobalInfoExtension globalInfo = project.rootProject.extensions.getByType(GlobalInfoExtension)
project.pluginManager.withPlugin("elasticsearch.testclusters") {
NamedDomainObjectContainer<ElasticsearchCluster> testClusters = project.extensions.findByName(TestClustersPlugin.EXTENSION_NAME) as NamedDomainObjectContainer<ElasticsearchCluster>
if (testClusters != null) {
testClusters.all { ElasticsearchCluster cluster ->
cluster.setTestDistribution(TestDistribution.DEFAULT)
for (File dep : project.getConfigurations().getByName("extraJars").getFiles()) {
cluster.extraJarFile(dep)
}
globalInfo.ready {
if (BuildParams.runtimeJavaVersion > JavaVersion.VERSION_1_8) {
cluster.extraConfigFile("fips_java.security", securityProperties)
cluster.extraConfigFile("fips_java.policy", securityPolicy)
} else {
cluster.extraConfigFile("fips_java.security", security8Properties)
cluster.extraConfigFile("fips_java.policy", security8Policy)
}
}
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')
// Can't use our DiagnosticTrustManager with SunJSSE in FIPS mode
cluster.setting 'xpack.security.ssl.diagnose.trust', 'false'
}
}
}
project.tasks.withType(Test).configureEach { Test task ->
task.dependsOn(buildResources)
globalInfo.ready {
// 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
if (BuildParams.runtimeJavaVersion > JavaVersion.VERSION_1_8) {
task.systemProperty('java.security.properties', String.format(Locale.ROOT, "=%s", securityProperties.toString()))
task.systemProperty('java.security.policy', String.format(Locale.ROOT, "=%s", securityPolicy.toString()))
} else {
task.systemProperty('java.security.properties', String.format(Locale.ROOT, "=%s", security8Properties.toString()))
task.systemProperty('java.security.policy', String.format(Locale.ROOT, "=%s", security8Policy.toString()))
}
}
task.systemProperty('javax.net.ssl.trustStorePassword', 'password')
task.systemProperty('javax.net.ssl.keyStorePassword', 'password')
task.systemProperty('javax.net.ssl.trustStoreType', 'BCFKS')
task.systemProperty('javax.net.ssl.trustStore', bcfksKeystore.toString())
}
}
}
@ -659,12 +695,6 @@ class BuildPlugin implements Plugin<Project> {
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}")
}
if (BuildParams.runtimeJavaVersion >= JavaVersion.VERSION_1_9) {
test.jvmArgs '--illegal-access=warn'
}
@ -675,7 +705,10 @@ class BuildPlugin implements Plugin<Project> {
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)
@ -821,4 +854,8 @@ class BuildPlugin implements Plugin<Project> {
})
}
}
private static inFipsJvm(){
return Boolean.parseBoolean(System.getProperty("tests.fips.enabled"));
}
}

View File

@ -42,14 +42,12 @@ public class GenerateGlobalBuildInfoTask extends DefaultTask {
private final RegularFileProperty outputFile;
private final RegularFileProperty compilerVersionFile;
private final RegularFileProperty runtimeVersionFile;
private final RegularFileProperty fipsJvmFile;
@Inject
public GenerateGlobalBuildInfoTask(ObjectFactory objectFactory) {
this.outputFile = objectFactory.fileProperty();
this.compilerVersionFile = objectFactory.fileProperty();
this.runtimeVersionFile = objectFactory.fileProperty();
this.fipsJvmFile = objectFactory.fileProperty();
}
@Input
@ -114,11 +112,6 @@ public class GenerateGlobalBuildInfoTask extends DefaultTask {
return runtimeVersionFile;
}
@OutputFile
public RegularFileProperty getFipsJvmFile() {
return fipsJvmFile;
}
@TaskAction
public void generate() {
String javaVendorVersion = System.getProperty("java.vendor.version", System.getProperty("java.vendor"));
@ -137,7 +130,6 @@ public class GenerateGlobalBuildInfoTask extends DefaultTask {
String runtimeJavaVersionDetails = gradleJavaVersionDetails;
JavaVersion runtimeJavaVersionEnum = JavaVersion.current();
File gradleJavaHome = Jvm.current().getJavaHome();
boolean inFipsJvm = false;
try {
if (Files.isSameFile(compilerJavaHome.toPath(), gradleJavaHome.toPath()) == false) {
@ -153,10 +145,6 @@ public class GenerateGlobalBuildInfoTask extends DefaultTask {
if (runtimeJavaHome.exists()) {
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));
} else {
throw new RuntimeException("Runtime Java home path of '" + compilerJavaHome + "' does not exist");
}
@ -242,7 +230,6 @@ public class GenerateGlobalBuildInfoTask extends DefaultTask {
writeToFile(compilerVersionFile.getAsFile().get(), compilerJavaVersionEnum.name());
writeToFile(runtimeVersionFile.getAsFile().get(), runtimeJavaVersionEnum.name());
writeToFile(fipsJvmFile.getAsFile().get(), Boolean.toString(inFipsJvm));
}
private void writeToFile(File file, String content) {

View File

@ -76,14 +76,12 @@ public class GlobalBuildInfoPlugin implements Plugin<Project> {
task.getOutputFile().set(new File(project.getBuildDir(), "global-build-info"));
task.getCompilerVersionFile().set(new File(project.getBuildDir(), "java-compiler-version"));
task.getRuntimeVersionFile().set(new File(project.getBuildDir(), "java-runtime-version"));
task.getFipsJvmFile().set(new File(project.getBuildDir(), "in-fips-jvm"));
});
PrintGlobalBuildInfoTask printTask = project.getTasks().create("printGlobalBuildInfo", PrintGlobalBuildInfoTask.class, task -> {
task.getBuildInfoFile().set(generateTask.getOutputFile());
task.getCompilerVersionFile().set(generateTask.getCompilerVersionFile());
task.getRuntimeVersionFile().set(generateTask.getRuntimeVersionFile());
task.getFipsJvmFile().set(generateTask.getFipsJvmFile());
task.setGlobalInfoListeners(extension.listeners);
});
@ -103,6 +101,7 @@ public class GlobalBuildInfoPlugin implements Plugin<Project> {
params.setIsCi(System.getenv("JENKINS_URL") != null);
params.setIsInternal(GlobalBuildInfoPlugin.class.getResource("/buildSrc.marker") != null);
params.setDefaultParallel(findDefaultParallel(project));
params.setInFipsJvm(isInFipsJvm());
});
project.allprojects(
@ -160,6 +159,10 @@ public class GlobalBuildInfoPlugin implements Plugin<Project> {
return "JAVA" + version + "_HOME";
}
private static boolean isInFipsJvm() {
return Boolean.parseBoolean(System.getProperty("tests.fips.enabled"));
}
private static String getResourceContents(String resourcePath) {
try (
BufferedReader reader = new BufferedReader(new InputStreamReader(GlobalBuildInfoPlugin.class.getResourceAsStream(resourcePath)))

View File

@ -16,7 +16,6 @@ public class PrintGlobalBuildInfoTask extends DefaultTask {
private final RegularFileProperty buildInfoFile;
private final RegularFileProperty compilerVersionFile;
private final RegularFileProperty runtimeVersionFile;
private final RegularFileProperty fipsJvmFile;
private List<Runnable> globalInfoListeners = new ArrayList<>();
@Inject
@ -24,7 +23,6 @@ public class PrintGlobalBuildInfoTask extends DefaultTask {
this.buildInfoFile = objectFactory.fileProperty();
this.compilerVersionFile = objectFactory.fileProperty();
this.runtimeVersionFile = objectFactory.fileProperty();
this.fipsJvmFile = objectFactory.fileProperty();
}
@InputFile
@ -42,11 +40,6 @@ public class PrintGlobalBuildInfoTask extends DefaultTask {
return runtimeVersionFile;
}
@InputFile
public RegularFileProperty getFipsJvmFile() {
return fipsJvmFile;
}
public void setGlobalInfoListeners(List<Runnable> globalInfoListeners) {
this.globalInfoListeners = globalInfoListeners;
}
@ -57,6 +50,7 @@ public class PrintGlobalBuildInfoTask extends DefaultTask {
getLogger().quiet("Elasticsearch Build Hamster says Hello!");
getLogger().quiet(getFileText(getBuildInfoFile()).asString());
getLogger().quiet(" Random Testing Seed : " + BuildParams.getTestSeed());
getLogger().quiet(" In FIPS 140 mode : " + BuildParams.isInFipsJvm());
getLogger().quiet("=======================================");
setGlobalProperties();
@ -76,7 +70,6 @@ public class PrintGlobalBuildInfoTask extends DefaultTask {
BuildParams.init(params -> {
params.setCompilerJavaVersion(JavaVersion.valueOf(getFileText(getCompilerVersionFile()).asString()));
params.setRuntimeJavaVersion(JavaVersion.valueOf(getFileText(getRuntimeVersionFile()).asString()));
params.setInFipsJvm(Boolean.parseBoolean(getFileText(getFipsJvmFile()).asString()));
});
}
}

View File

@ -366,6 +366,11 @@ public class ElasticsearchCluster implements TestClusterConfiguration, Named {
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<String, String> userSpec) {
nodes.all(node -> node.user(userSpec));

View File

@ -129,6 +129,7 @@ public class ElasticsearchNode implements TestClusterConfiguration {
private final LazyPropertyMap<String, CharSequence> environment = new LazyPropertyMap<>("Environment", this);
private final LazyPropertyList<CharSequence> jvmArgs = new LazyPropertyList<>("JVM arguments", this);
private final LazyPropertyMap<String, File> extraConfigFiles = new LazyPropertyMap<>("Extra config files", this, FileEntry::new);
private final LazyPropertyList<File> extraJarFiles = new LazyPropertyList<>("Extra jar files", this);
private final List<Map<String, String>> credentials = new ArrayList<>();
final LinkedHashMap<String, String> defaultConfig = new LinkedHashMap<>();
@ -420,6 +421,11 @@ public class ElasticsearchNode implements TestClusterConfiguration {
} catch (IOException e) {
throw new UncheckedIOException("Failed to create working directory for " + this, e);
}
copyExtraJars();
copyExtraConfigFiles();
createConfiguration();
final List<String> pluginsToInstall = new ArrayList<>();
@ -465,8 +471,6 @@ public class ElasticsearchNode implements TestClusterConfiguration {
installModules();
copyExtraConfigFiles();
if (isSettingTrue("xpack.security.enabled")) {
if (credentials.isEmpty()) {
user(Collections.emptyMap());
@ -551,6 +555,25 @@ public class ElasticsearchNode implements TestClusterConfiguration {
});
}
/**
* 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");
@ -593,6 +616,14 @@ public class ElasticsearchNode implements TestClusterConfiguration {
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<String, String> userSpec) {
Set<String> keys = new HashSet<>(userSpec.keySet());
@ -654,6 +685,10 @@ public class ElasticsearchNode implements TestClusterConfiguration {
+ systemProperties.entrySet()
.stream()
.map(entry -> "-D" + entry.getKey() + "=" + entry.getValue())
// ES_PATH_CONF is also set as an environment variable and for a reference to ${ES_PATH_CONF}
// to work ES_JAVA_OPTS, we need to make sure that ES_PATH_CONF before ES_JAVA_OPTS. Instead,
// we replace the reference with the actual value in other environment variables
.map(p -> p.replace("${ES_PATH_CONF}", configFile.getParent().toString()))
.collect(Collectors.joining(" "));
}
String jvmArgsString = "";

View File

@ -93,6 +93,8 @@ public interface TestClusterConfiguration {
void extraConfigFile(String destination, File from, PropertyNormalization normalization);
void extraJarFile(File from);
void user(Map<String, String> userSpec);
String getHttpSocketURI();

Binary file not shown.

View File

@ -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";
};

View File

@ -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;!*

View File

@ -0,0 +1,16 @@
grant codeBase "file:${java.home}/lib/ext/localedata.jar" {
// Allow resource bundles to be loaded for non root locales. See
// https://github.com/elastic/elasticsearch/issues/39981
permission java.lang.RuntimePermission "accessClassInPackage.sun.util.*";
};
grant {
permission org.bouncycastle.crypto.CryptoServicesPermission "exportPrivateKey";
permission org.bouncycastle.crypto.CryptoServicesPermission "exportSecretKey";
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";
};

View File

@ -0,0 +1,133 @@
# List of providers and their preference orders (see above):
security.provider.1=org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider
security.provider.2=com.sun.net.ssl.internal.ssl.Provider BCFIPS
security.provider.3=sun.security.provider.Sun
security.provider.4=sun.security.jgss.SunProvider
securerandom.source=file:/dev/urandom
securerandom.strongAlgorithms=NativePRNGBlocking:SUN
login.configuration.provider=sun.security.provider.ConfigFile
policy.provider=sun.security.provider.PolicyFile
policy.url.1=file:${java.home}/lib/security/java.policy
policy.url.2=file:${user.home}/.java.policy
policy.expandProperties=true
policy.allowSystemProperty=true
policy.ignoreIdentityScope=false
keystore.type=bcfks
keystore.type.compat=true
package.access=sun.,\
org.GNOME.Accessibility.,\
com.sun.xml.internal.,\
com.sun.imageio.,\
com.sun.istack.internal.,\
com.sun.jmx.,\
com.sun.media.sound.,\
com.sun.naming.internal.,\
com.sun.proxy.,\
com.sun.corba.se.,\
com.sun.org.apache.bcel.internal.,\
com.sun.org.apache.regexp.internal.,\
com.sun.org.apache.xerces.internal.,\
com.sun.org.apache.xpath.internal.,\
com.sun.org.apache.xalan.internal.extensions.,\
com.sun.org.apache.xalan.internal.lib.,\
com.sun.org.apache.xalan.internal.res.,\
com.sun.org.apache.xalan.internal.templates.,\
com.sun.org.apache.xalan.internal.utils.,\
com.sun.org.apache.xalan.internal.xslt.,\
com.sun.org.apache.xalan.internal.xsltc.cmdline.,\
com.sun.org.apache.xalan.internal.xsltc.compiler.,\
com.sun.org.apache.xalan.internal.xsltc.trax.,\
com.sun.org.apache.xalan.internal.xsltc.util.,\
com.sun.org.apache.xml.internal.res.,\
com.sun.org.apache.xml.internal.resolver.helpers.,\
com.sun.org.apache.xml.internal.resolver.readers.,\
com.sun.org.apache.xml.internal.security.,\
com.sun.org.apache.xml.internal.serializer.utils.,\
com.sun.org.apache.xml.internal.utils.,\
com.sun.org.glassfish.,\
com.oracle.xmlns.internal.,\
com.oracle.webservices.internal.,\
oracle.jrockit.jfr.,\
org.jcp.xml.dsig.internal.,\
jdk.internal.,\
jdk.nashorn.internal.,\
jdk.nashorn.tools.,\
jdk.xml.internal.,\
com.sun.activation.registries.
package.definition=sun.,\
com.sun.xml.internal.,\
com.sun.imageio.,\
com.sun.istack.internal.,\
com.sun.jmx.,\
com.sun.media.sound.,\
com.sun.naming.internal.,\
com.sun.proxy.,\
com.sun.corba.se.,\
com.sun.org.apache.bcel.internal.,\
com.sun.org.apache.regexp.internal.,\
com.sun.org.apache.xerces.internal.,\
com.sun.org.apache.xpath.internal.,\
com.sun.org.apache.xalan.internal.extensions.,\
com.sun.org.apache.xalan.internal.lib.,\
com.sun.org.apache.xalan.internal.res.,\
com.sun.org.apache.xalan.internal.templates.,\
com.sun.org.apache.xalan.internal.utils.,\
com.sun.org.apache.xalan.internal.xslt.,\
com.sun.org.apache.xalan.internal.xsltc.cmdline.,\
com.sun.org.apache.xalan.internal.xsltc.compiler.,\
com.sun.org.apache.xalan.internal.xsltc.trax.,\
com.sun.org.apache.xalan.internal.xsltc.util.,\
com.sun.org.apache.xml.internal.res.,\
com.sun.org.apache.xml.internal.resolver.helpers.,\
com.sun.org.apache.xml.internal.resolver.readers.,\
com.sun.org.apache.xml.internal.security.,\
com.sun.org.apache.xml.internal.serializer.utils.,\
com.sun.org.apache.xml.internal.utils.,\
com.sun.org.glassfish.,\
com.oracle.xmlns.internal.,\
com.oracle.webservices.internal.,\
oracle.jrockit.jfr.,\
org.jcp.xml.dsig.internal.,\
jdk.internal.,\
jdk.nashorn.internal.,\
jdk.nashorn.tools.,\
jdk.xml.internal.,\
com.sun.activation.registries.
ssl.KeyManagerFactory.algorithm=SunX509
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
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.lang.Enum;java.security.KeyRep;\
java.security.KeyRep$Type;javax.crypto.spec.SecretKeySpec;!*

View File

@ -81,6 +81,7 @@ public class RestClientBuilderIntegTests extends RestClientTestCase {
}
public void testBuilderUsesDefaultSSLContext() throws Exception {
assumeFalse("https://github.com/elastic/elasticsearch/issues/49094", inFipsJvm());
final SSLContext defaultSSLContext = SSLContext.getDefault();
try {
try (RestClient client = buildRestClient()) {
@ -109,7 +110,8 @@ public class RestClientBuilderIntegTests extends RestClientTestCase {
private static SSLContext getSslContext() throws Exception {
SSLContext sslContext = SSLContext.getInstance(getProtocol());
try (InputStream certFile = RestClientBuilderIntegTests.class.getResourceAsStream("/test.crt")) {
try (InputStream certFile = RestClientBuilderIntegTests.class.getResourceAsStream("/test.crt");
InputStream keyStoreFile = RestClientBuilderIntegTests.class.getResourceAsStream("/test_truststore.jks")) {
// Build a keystore of default type programmatically since we can't use JKS keystores to
// init a KeyManagerFactory in FIPS 140 JVMs.
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
@ -122,8 +124,10 @@ public class RestClientBuilderIntegTests extends RestClientTestCase {
new Certificate[]{certFactory.generateCertificate(certFile)});
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(keyStore, "password".toCharArray());
KeyStore trustStore = KeyStore.getInstance("JKS");
trustStore.load(keyStoreFile, "password".toCharArray());
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(keyStore);
tmf.init(trustStore);
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
}
return sslContext;

Binary file not shown.

View File

@ -108,4 +108,8 @@ public abstract class RestClientTestCase extends RandomizedTest {
}
values.add(value);
}
public static boolean inFipsJvm() {
return Boolean.parseBoolean(System.getProperty("tests.fips.enabled"));
}
}

View File

@ -32,6 +32,7 @@ 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;
@ -85,10 +86,12 @@ final class JvmOptionsParser {
Arrays.stream(environmentJvmOptions.split("\\s+")).filter(s -> s.trim().isEmpty() == false).collect(Collectors.toList())
);
}
final List<String> substitutedJvmOptions = substitutePlaceholders(
jvmOptions,
Collections.singletonMap("ES_TMPDIR", System.getenv("ES_TMPDIR"))
);
final Map<String, String> 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<String> substitutedJvmOptions = substitutePlaceholders(jvmOptions, Collections.unmodifiableMap(substitutions));
final List<String> ergonomicJvmOptions = JvmErgonomics.choose(substitutedJvmOptions);
final List<String> systemJvmOptions = SystemJvmOptions.systemJvmOptions();
final List<String> finalJvmOptions = new ArrayList<>(

View File

@ -74,6 +74,10 @@ project.rootProject.subprojects.findAll { it.parent.path == ':plugins' }.each {
if (subproj.path.startsWith(':plugins:repository-')) {
return
}
// Do not install ingest-attachment in a FIPS 140 JVM as this is not supported
if (subproj.path.startsWith(':plugins:ingest-attachment') && Boolean.parseBoolean(System.getProperty("tests.fips.enabled"))) {
return
}
// FIXME
subproj.afterEvaluate { // need to wait until the project has been configured
testClusters.integTest {
@ -92,6 +96,12 @@ buildRestTests.docs = fileTree(projectDir) {
exclude 'README.asciidoc'
// Broken code snippet tests
exclude 'reference/graph/explore.asciidoc'
if (Boolean.parseBoolean(System.getProperty("tests.fips.enabled"))) {
// We don't install/support this plugin in FIPS 140
exclude 'plugins/ingest-attachment.asciidoc'
// We can't conditionally control output, this would be missing the ingest-attachment plugin
exclude 'reference/cat/plugins.asciidoc'
}
}
listSnippets.docs = buildRestTests.docs

View File

@ -56,7 +56,7 @@ public class SslConfiguration {
SSLContext.getInstance("TLSv1.3");
protocolAlgorithmMap.put("TLSv1.3", "TLSv1.3");
} catch (NoSuchAlgorithmException e) {
// ignore since we support JVMs that do not support TLSv1.3
// ignore since we support JVMs (and BC JSSE in FIPS mode) that do not support TLSv1.3
}
protocolAlgorithmMap.put("TLSv1.2", "TLSv1.2");
protocolAlgorithmMap.put("TLSv1.1", "TLSv1.1");

View File

@ -117,6 +117,7 @@ public class ReindexRestClientSslTests extends ESTestCase {
}
public void testClientFailsWithUntrustedCertificate() throws IOException {
assumeFalse("https://github.com/elastic/elasticsearch/issues/49094", inFipsJvm());
final List<Thread> threads = new ArrayList<>();
final Settings settings = Settings.builder()
.put("path.home", createTempDir())

View File

@ -113,6 +113,7 @@ thirdPartyAudit {
'org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder',
'org.bouncycastle.jce.provider.BouncyCastleProvider',
'org.bouncycastle.operator.jcajce.JcaContentSignerBuilder',
'org.bouncycastle.asn1.x500.X500Name',
// from io.netty.handler.ssl.JettyNpnSslEngine (netty)
'org.eclipse.jetty.npn.NextProtoNego$ClientProvider',
@ -169,7 +170,6 @@ thirdPartyAudit {
'org.eclipse.jetty.alpn.ALPN$ServerProvider',
'org.eclipse.jetty.alpn.ALPN',
'org.conscrypt.AllocatedBuffer',
'org.conscrypt.BufferAllocator',
'org.conscrypt.Conscrypt',
@ -197,12 +197,10 @@ thirdPartyAudit {
)
}
rootProject.globalInfo.ready {
if (BuildParams.inFipsJvm == false) {
// BouncyCastleFIPS provides this class, so the exclusion is invalid when running CI in
// a FIPS JVM with BouncyCastleFIPS Provider
thirdPartyAudit.ignoreMissingClasses(
'org.bouncycastle.asn1.x500.X500Name'
)
}
if (BuildParams.inFipsJvm == false) {
// BouncyCastleFIPS provides this class, so the exclusion is invalid when running CI in
// a FIPS JVM with BouncyCastleFIPS Provider
thirdPartyAudit.ignoreMissingClasses(
'org.bouncycastle.asn1.x500.X500Name'
)
}

View File

@ -89,7 +89,7 @@ thirdPartyAudit {
}
thirdPartyAudit.onlyIf {
// FIPS JVM includes manny classes from bouncycastle which count as jar hell for the third party audit,
// FIPS JVM includes many classes from bouncycastle which count as jar hell for the third party audit,
// rather than provide a long list of exclusions, disable the check on FIPS.
BuildParams.inFipsJvm == false
}

View File

@ -65,6 +65,7 @@ thirdPartyAudit {
'org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder',
'org.bouncycastle.jce.provider.BouncyCastleProvider',
'org.bouncycastle.operator.jcajce.JcaContentSignerBuilder',
'org.bouncycastle.asn1.x500.X500Name',
// from io.netty.handler.ssl.JettyNpnSslEngine (netty)
'org.eclipse.jetty.npn.NextProtoNego$ClientProvider',
@ -155,12 +156,12 @@ thirdPartyAudit {
'io.netty.handler.ssl.util.OpenJdkSelfSignedCertGenerator'
)
}
rootProject.globalInfo.ready {
if (BuildParams.inFipsJvm == false) {
// BouncyCastleFIPS provides this class, so the exclusion is invalid when running CI in
// a FIPS JVM with BouncyCastleFIPS Provider
thirdPartyAudit.ignoreMissingClasses(
'org.bouncycastle.asn1.x500.X500Name'
)
}
if (BuildParams.inFipsJvm == false) {
// BouncyCastleFIPS provides this class, so the exclusion is invalid when running CI in
// a FIPS JVM with BouncyCastleFIPS Provider
thirdPartyAudit.ignoreMissingClasses(
'org.bouncycastle.asn1.x500.X500Name'
)
}

View File

@ -158,7 +158,6 @@ import java.net.InetSocketAddress;
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;
@ -2253,6 +2252,6 @@ public abstract class ESIntegTestCase extends ESTestCase {
}
public static boolean inFipsJvm() {
return Security.getProviders()[0].getName().toLowerCase(Locale.ROOT).contains("fips");
return Boolean.parseBoolean(System.getProperty(FIPS_SYSPROP));
}
}

View File

@ -119,7 +119,6 @@ import org.junit.rules.RuleChain;
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;
@ -193,6 +192,8 @@ public abstract class ESTestCase extends LuceneTestCase {
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();
@ -1366,7 +1367,7 @@ public abstract class ESTestCase extends LuceneTestCase {
}
public static boolean inFipsJvm() {
return Security.getProviders()[0].getName().toLowerCase(Locale.ROOT).contains("fips");
return Boolean.parseBoolean(System.getProperty(FIPS_SYSPROP));
}
/**

View File

@ -174,8 +174,7 @@ public class ReproduceInfoPrinter extends RunListener {
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;
}

View File

@ -10,6 +10,7 @@ import org.elasticsearch.common.Nullable;
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.io.IOException;
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

View File

@ -29,7 +29,6 @@ import org.elasticsearch.xpack.core.ssl.cert.CertificateInfo;
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.SSLException;
@ -39,7 +38,6 @@ import javax.net.ssl.SSLSession;
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 javax.security.auth.x500.X500Principal;
@ -48,7 +46,6 @@ import java.net.InetAddress;
import java.net.Socket;
import java.security.GeneralSecurityException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
@ -698,10 +695,8 @@ public class SSLService {
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);
loadedTrustManager = wrapWithDiagnostics(loadedTrustManager, sslConfiguration);
SSLContext loadedSslContext = SSLContext.getInstance(sslContextAlgorithm(sslConfiguration.supportedProtocols()));
@ -709,27 +704,11 @@ public class SSLService {
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);
}

View File

@ -5,6 +5,7 @@
*/
package org.elasticsearch.xpack.core.ssl;
import org.elasticsearch.bootstrap.JavaVersion;
import org.elasticsearch.test.ESTestCase;
import org.hamcrest.Description;
import org.hamcrest.TypeSafeMatcher;
@ -33,6 +34,8 @@ import java.util.Objects;
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 +135,9 @@ public class RestrictedTrustManagerTests extends ESTestCase {
if (cert.endsWith("/ca")) {
assertTrusted(trustManager, cert);
} else {
assertNotValid(trustManager, cert, "PKIX path building failed.*");
assertNotValid(trustManager, cert, inFipsJvm() && JavaVersion.current().compareTo(JavaVersion.parse("8")) > 0 ?
"unable to process certificates: Unable to find certificate chain.":
"PKIX path building failed.*");
}
}
}

View File

@ -154,15 +154,16 @@ public class SSLConfigurationReloaderTests extends ESTestCase {
* 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()
@ -267,15 +268,14 @@ public class SSLConfigurationReloaderTests extends ESTestCase {
* 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())
@ -294,7 +294,7 @@ public class SSLConfigurationReloaderTests extends ESTestCase {
final Runnable modifier = () -> {
try {
atomicMoveIfPossible(updatedCert, serverCertPath);
atomicMoveIfPossible(updatedCertPath, serverCertPath);
} catch (Exception e) {
throw new RuntimeException("failed to modify file", e);
}

View File

@ -65,7 +65,6 @@ import static org.elasticsearch.test.TestMatchers.throwableWithMessage;
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;
@ -504,14 +503,6 @@ public class SSLServiceTests extends ESTestCase {
}
}
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");
@ -587,11 +578,12 @@ public class SSLServiceTests extends ESTestCase {
final SSLService sslService = new SSLService(settings, env);
final List<CertificateInfo> certificates = new ArrayList<>(sslService.getLoadedCertificates());
assertThat(certificates, iterableWithSize(10));
assertThat(certificates, iterableWithSize(13));
Collections.sort(certificates,
Comparator.comparing((CertificateInfo c) -> c.alias() == null ? "" : c.alias()).thenComparing(CertificateInfo::path));
final Iterator<CertificateInfo> iterator = certificates.iterator();
CertificateInfo cert = iterator.next();
assertThat(cert.alias(), nullValue());
assertThat(cert.path(), equalTo(pemPath.toString()));
@ -655,6 +647,15 @@ public class SSLServiceTests extends ESTestCase {
assertThat(cert.expiry(), equalTo(ZonedDateTime.parse("2045-10-02T09:43:18.000Z")));
assertThat(cert.hasPrivateKey(), equalTo(true));
cert = iterator.next();
assertThat(cert.alias(), equalTo("testnode_dsa"));
assertThat(cert.path(), equalTo(p12Path.toString()));
assertThat(cert.format(), equalTo("PKCS12"));
assertThat(cert.serialNumber(), equalTo("223c736a"));
assertThat(cert.subjectDn(), equalTo("CN=Elasticsearch Test Node"));
assertThat(cert.expiry(), equalTo(ZonedDateTime.parse("2045-10-02T09:43:18.000Z")));
assertThat(cert.hasPrivateKey(), equalTo(true));
cert = iterator.next();
assertThat(cert.alias(), equalTo("testnode_ec"));
assertThat(cert.path(), equalTo(jksPath.toString()));
@ -664,6 +665,15 @@ public class SSLServiceTests extends ESTestCase {
assertThat(cert.expiry(), equalTo(ZonedDateTime.parse("2045-10-02T09:36:10.000Z")));
assertThat(cert.hasPrivateKey(), equalTo(true));
cert = iterator.next();
assertThat(cert.alias(), equalTo("testnode_ec"));
assertThat(cert.path(), equalTo(p12Path.toString()));
assertThat(cert.format(), equalTo("PKCS12"));
assertThat(cert.serialNumber(), equalTo("7268203b"));
assertThat(cert.subjectDn(), equalTo("CN=Elasticsearch Test Node"));
assertThat(cert.expiry(), equalTo(ZonedDateTime.parse("2045-10-02T09:36:10.000Z")));
assertThat(cert.hasPrivateKey(), equalTo(true));
cert = iterator.next();
assertThat(cert.alias(), equalTo("testnode_rsa"));
assertThat(cert.path(), equalTo(jksPath.toString()));
@ -679,9 +689,18 @@ public class SSLServiceTests extends ESTestCase {
assertThat(cert.format(), equalTo("PKCS12"));
assertThat(cert.serialNumber(), equalTo("b8b96c37e332cccb"));
assertThat(cert.subjectDn(), equalTo("CN=Elasticsearch Test Node, OU=elasticsearch, O=org"));
assertThat(cert.expiry(), equalTo(ZonedDateTime.parse("2019-09-22T18:52:57Z")));
assertThat(cert.expiry(), equalTo(ZonedDateTime.parse("2019-09-22T18:52:57.000Z")));
assertThat(cert.hasPrivateKey(), equalTo(true));
cert = iterator.next();
assertThat(cert.alias(), equalTo("trusted_testnode_ec"));
assertThat(cert.path(), equalTo(jksPath.toString()));
assertThat(cert.format(), equalTo("jks"));
assertThat(cert.serialNumber(), equalTo("7268203b"));
assertThat(cert.subjectDn(), equalTo("CN=Elasticsearch Test Node"));
assertThat(cert.expiry(), equalTo(ZonedDateTime.parse("2045-10-02T09:36:10.000Z")));
assertThat(cert.hasPrivateKey(), equalTo(false));
assertFalse(iterator.hasNext());
}

View File

@ -24,9 +24,7 @@ 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.4.5"
@ -47,7 +45,9 @@ dependencies {
compile "net.shibboleth.utilities:java-support:7.5.1"
compile "org.apache.santuario:xmlsec:2.1.4"
compile "io.dropwizard.metrics:metrics-core:3.2.2"
compile "org.cryptacular:cryptacular:1.2.3"
compile ("org.cryptacular:cryptacular:1.2.3") {
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}"
@ -178,107 +178,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.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.BCrypt',
'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

View File

@ -24,18 +24,16 @@ forbiddenPatterns {
exclude '**/*.jks'
}
rootProject.globalInfo.ready {
if (BuildParams.inFipsJvm) {
test.enabled = false
testingConventions.enabled = false
// Forbiden APIs non-portable checks fail because bouncy castle classes being used from the FIPS JDK since those are
// not part of the Java specification - all of this is as designed, so we have to relax this check for FIPS.
tasks.withType(CheckForbiddenApis) {
bundledSignatures -= "jdk-non-portable"
}
// FIPS JVM includes many classes from bouncycastle which count as jar hell for the third party audit,
// rather than provide a long list of exclusions, disable the check on FIPS.
thirdPartyAudit.enabled = false
if (BuildParams.inFipsJvm) {
test.enabled = false
testingConventions.enabled = false
// Forbiden APIs non-portable checks fail because bouncy castle classes being used from the FIPS JDK since those are
// not part of the Java specification - all of this is as designed, so we have to relax this check for FIPS.
tasks.withType(CheckForbiddenApis) {
bundledSignatures -= "jdk-non-portable"
}
// FIPS JVM includes many classes from bouncycastle which count as jar hell for the third party audit,
// rather than provide a long list of exclusions, disable the check on FIPS.
thirdPartyAudit.enabled = false
}

View File

@ -239,6 +239,9 @@ public class LdapSessionFactoryTests extends LdapTestCase {
* (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) {

View File

@ -236,6 +236,7 @@ public class PkiRealmTests extends ESTestCase {
}
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 class PkiRealmTests extends ESTestCase {
}
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 class PkiRealmTests extends ESTestCase {
}
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 class PkiRealmTests extends ESTestCase {
}
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 class PkiRealmTests extends ESTestCase {
}
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 class PkiRealmTests extends ESTestCase {
}
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",

View File

@ -136,6 +136,8 @@ public abstract class AbstractSimpleSecurityTransportTestCase extends AbstractSi
@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());

View File

@ -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 class SSLDriverTests extends ESTestCase {
}
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 class SSLDriverTests extends ESTestCase {
}
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 class SSLDriverTests extends ESTestCase {
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 class SSLDriverTests extends ESTestCase {
}
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);
@ -288,7 +295,7 @@ public class SSLDriverTests extends ESTestCase {
(certPath))));
KeyManager km = CertParsingUtils.keyManager(CertParsingUtils.readCertificates(Collections.singletonList(getDataPath
(certPath))), PemUtils.readPrivateKey(getDataPath(keyPath), "testclient"::toCharArray), "testclient".toCharArray());
if (JavaVersion.current().compareTo(JavaVersion.parse("11")) >= 0) {
if (JavaVersion.current().compareTo(JavaVersion.parse("11")) >= 0 && inFipsJvm() == false) {
sslContext = SSLContext.getInstance(randomFrom("TLSv1.2", "TLSv1.3"));
} else {
sslContext = SSLContext.getInstance(randomFrom("TLSv1.2"));

View File

@ -75,6 +75,7 @@ public class EllipticCurveSSLTests extends SecurityIntegTestCase {
}
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);

View File

@ -184,7 +184,7 @@ public class SSLClientAuthTests extends SecurityIntegTestCase {
(certPath))), PemUtils.readPrivateKey(getDataPath(keyPath), "testclient"::toCharArray), "testclient".toCharArray());
final SSLContext context;
if (XPackSettings.DEFAULT_SUPPORTED_PROTOCOLS.contains("TLSv1.3")) {
if (XPackSettings.DEFAULT_SUPPORTED_PROTOCOLS.contains("TLSv1.3") && inFipsJvm() == false) {
context = SSLContext.getInstance(randomBoolean() ? "TLSv1.3" : "TLSv1.2");
} else {
context = SSLContext.getInstance("TLSv1.2");

View File

@ -91,6 +91,7 @@ public class SSLReloadIntegTests extends SecurityIntegTestCase {
}
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);