diff --git a/buildSrc/src/main/resources/fips_java.security b/buildSrc/src/main/resources/fips_java.security index 6c59c35b456..62448c21551 100644 --- a/buildSrc/src/main/resources/fips_java.security +++ b/buildSrc/src/main/resources/fips_java.security @@ -1,6 +1,7 @@ security.provider.1=org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider security.provider.2=org.bouncycastle.jsse.provider.BouncyCastleJsseProvider fips:BCFIPS security.provider.3=SUN +security.provider.4=SunJGSS securerandom.source=file:/dev/urandom securerandom.strongAlgorithms=NativePRNGBlocking:SUN,DRBG:SUN securerandom.drbg.config= diff --git a/plugins/ingest-attachment/build.gradle b/plugins/ingest-attachment/build.gradle index f329c8f1a50..d5f0928fb7d 100644 --- a/plugins/ingest-attachment/build.gradle +++ b/plugins/ingest-attachment/build.gradle @@ -88,8 +88,11 @@ thirdPartyAudit { ignoreMissingClasses() } -jarHell.onlyIf { +if (BuildParams.inFipsJvm) { // 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 + jarHell.enabled = false + test.enabled = false + integTest.enabled = false; + testingConventions.enabled = false; } diff --git a/qa/os/src/test/java/org/elasticsearch/packaging/test/KeystoreManagementTests.java b/qa/os/src/test/java/org/elasticsearch/packaging/test/KeystoreManagementTests.java index c9e9231a566..a77f00fa9ba 100644 --- a/qa/os/src/test/java/org/elasticsearch/packaging/test/KeystoreManagementTests.java +++ b/qa/os/src/test/java/org/elasticsearch/packaging/test/KeystoreManagementTests.java @@ -35,6 +35,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; @@ -58,6 +59,7 @@ import static org.elasticsearch.packaging.util.Packages.verifyPackageInstallatio import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.Matchers.anyOf; import static org.hamcrest.Matchers.startsWith; import static org.junit.Assume.assumeThat; import static org.junit.Assume.assumeTrue; @@ -65,6 +67,7 @@ import static org.junit.Assume.assumeTrue; public class KeystoreManagementTests extends PackagingTestCase { public static final String ERROR_INCORRECT_PASSWORD = "Provided keystore password was incorrect"; + public static final String ERROR_CORRUPTED_KEYSTORE = "Keystore has been corrupted or tampered with"; public static final String ERROR_KEYSTORE_NOT_PASSWORD_PROTECTED = "ERROR: Keystore is not password-protected"; public static final String ERROR_KEYSTORE_NOT_FOUND = "ERROR: Elasticsearch keystore not found"; @@ -174,7 +177,7 @@ public class KeystoreManagementTests extends PackagingTestCase { assertPasswordProtectedKeystore(); Shell.Result result = startElasticsearchStandardInputPassword("wrong"); - assertElasticsearchFailure(result, ERROR_INCORRECT_PASSWORD, null); + assertElasticsearchFailure(result, Arrays.asList(ERROR_INCORRECT_PASSWORD, ERROR_CORRUPTED_KEYSTORE), null); } @Ignore /* Ignored for feature branch, awaits fix: https://github.com/elastic/elasticsearch/issues/49340 */ @@ -210,7 +213,7 @@ public class KeystoreManagementTests extends PackagingTestCase { Shell.Result result = startElasticsearchTtyPassword("wrong"); // error will be on stdout for "expect" - assertThat(result.stdout, containsString(ERROR_INCORRECT_PASSWORD)); + assertThat(result.stdout, anyOf(containsString(ERROR_INCORRECT_PASSWORD), containsString(ERROR_CORRUPTED_KEYSTORE))); } /** @@ -279,7 +282,7 @@ public class KeystoreManagementTests extends PackagingTestCase { Packages.JournaldWrapper journaldWrapper = new Packages.JournaldWrapper(sh); Shell.Result result = runElasticsearchStartCommand(); - assertElasticsearchFailure(result, ERROR_INCORRECT_PASSWORD, journaldWrapper); + assertElasticsearchFailure(result, Arrays.asList(ERROR_INCORRECT_PASSWORD, ERROR_CORRUPTED_KEYSTORE), journaldWrapper); } finally { sh.run("sudo systemctl unset-environment ES_KEYSTORE_PASSPHRASE_FILE"); } diff --git a/qa/os/src/test/java/org/elasticsearch/packaging/test/PackagingTestCase.java b/qa/os/src/test/java/org/elasticsearch/packaging/test/PackagingTestCase.java index 076b543124c..f433219e86d 100644 --- a/qa/os/src/test/java/org/elasticsearch/packaging/test/PackagingTestCase.java +++ b/qa/os/src/test/java/org/elasticsearch/packaging/test/PackagingTestCase.java @@ -34,6 +34,8 @@ import org.elasticsearch.packaging.util.Installation; import org.elasticsearch.packaging.util.Packages; import org.elasticsearch.packaging.util.Platforms; import org.elasticsearch.packaging.util.Shell; +import org.hamcrest.CoreMatchers; +import org.hamcrest.Matcher; import org.junit.After; import org.junit.AfterClass; import org.junit.Assert; @@ -48,6 +50,8 @@ import org.junit.runner.RunWith; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.Collections; +import java.util.List; import static org.elasticsearch.packaging.util.Cleanup.cleanEverything; import static org.elasticsearch.packaging.util.Docker.ensureImageIsLoaded; @@ -55,6 +59,7 @@ import static org.elasticsearch.packaging.util.Docker.removeContainer; import static org.elasticsearch.packaging.util.FileExistenceMatchers.fileExists; import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.anyOf; import static org.junit.Assume.assumeFalse; import static org.junit.Assume.assumeTrue; @@ -311,23 +316,28 @@ public abstract class PackagingTestCase extends Assert { return Archives.startElasticsearchWithTty(installation, sh, password); } - public void assertElasticsearchFailure(Shell.Result result, String expectedMessage, Packages.JournaldWrapper journaldWrapper) { + assertElasticsearchFailure(result, Collections.singletonList(expectedMessage), journaldWrapper); + } + public void assertElasticsearchFailure(Shell.Result result, List expectedMessages, Packages.JournaldWrapper journaldWrapper) { + @SuppressWarnings("unchecked") + Matcher[] stringMatchers = expectedMessages.stream().map(CoreMatchers::containsString).toArray(Matcher[]::new); if (Files.exists(installation.logs.resolve("elasticsearch.log"))) { // If log file exists, then we have bootstrapped our logging and the // error should be in the logs assertThat(installation.logs.resolve("elasticsearch.log"), fileExists()); String logfile = FileUtils.slurp(installation.logs.resolve("elasticsearch.log")); - assertThat(logfile, containsString(expectedMessage)); + + assertThat(logfile, anyOf(stringMatchers)); } else if (distribution().isPackage() && Platforms.isSystemd()) { // For systemd, retrieve the error from journalctl assertThat(result.stderr, containsString("Job for elasticsearch.service failed")); Shell.Result error = journaldWrapper.getLogs(); - assertThat(error.stdout, containsString(expectedMessage)); + assertThat(error.stdout, anyOf(stringMatchers)); } else if (Platforms.WINDOWS) { @@ -338,12 +348,12 @@ public abstract class PackagingTestCase extends Assert { sh.runIgnoreExitCode("Get-EventSubscriber | " + "where {($_.EventName -eq 'OutputDataReceived' -Or $_.EventName -eq 'ErrorDataReceived' |" + "Unregister-EventSubscriber -Force"); - assertThat(FileUtils.slurp(Archives.getPowershellErrorPath(installation)), containsString(expectedMessage)); + assertThat(FileUtils.slurp(Archives.getPowershellErrorPath(installation)), anyOf(stringMatchers)); } else { // Otherwise, error should be on shell stderr - assertThat(result.stderr, containsString(expectedMessage)); + assertThat(result.stderr, anyOf(stringMatchers)); } } diff --git a/qa/smoke-test-plugins/build.gradle b/qa/smoke-test-plugins/build.gradle index bdd5e74184e..f5b441f0763 100644 --- a/qa/smoke-test-plugins/build.gradle +++ b/qa/smoke-test-plugins/build.gradle @@ -18,6 +18,7 @@ */ import org.elasticsearch.gradle.MavenFilteringHack +import org.elasticsearch.gradle.info.BuildParams apply plugin: 'elasticsearch.testclusters' apply plugin: 'elasticsearch.standalone-rest-test' @@ -27,6 +28,10 @@ int pluginsCount = 0 testClusters.integTest { project(':plugins').getChildProjects().each { pluginName, pluginProject -> + if (BuildParams.inFipsJvm && pluginName == "ingest-attachment"){ + //Do not attempt to install ingest-attachment in FIPS 140 as it is not supported (it depends on non-FIPS BouncyCastle + return + } plugin file(pluginProject.tasks.bundlePlugin.archiveFile) tasks.integTest.dependsOn pluginProject.tasks.bundlePlugin pluginsCount += 1 diff --git a/server/src/test/java/org/elasticsearch/common/settings/AddFileKeyStoreCommandTests.java b/server/src/test/java/org/elasticsearch/common/settings/AddFileKeyStoreCommandTests.java index cd64fdc08d3..8d6a2d7e438 100644 --- a/server/src/test/java/org/elasticsearch/common/settings/AddFileKeyStoreCommandTests.java +++ b/server/src/test/java/org/elasticsearch/common/settings/AddFileKeyStoreCommandTests.java @@ -29,6 +29,7 @@ import org.elasticsearch.cli.ExitCodes; import org.elasticsearch.cli.UserException; import org.elasticsearch.env.Environment; +import static org.hamcrest.Matchers.anyOf; import static org.hamcrest.Matchers.containsString; public class AddFileKeyStoreCommandTests extends KeyStoreCommandTestCase { @@ -192,7 +193,17 @@ public class AddFileKeyStoreCommandTests extends KeyStoreCommandTestCase { terminal.addSecretInput("thewrongkeystorepassword"); UserException e = expectThrows(UserException.class, () -> execute("foo", file.toString())); assertEquals(e.getMessage(), ExitCodes.DATA_ERROR, e.exitCode); - assertThat(e.getMessage(), containsString("Provided keystore password was incorrect")); + if (inFipsJvm()) { + assertThat( + e.getMessage(), + anyOf( + containsString("Provided keystore password was incorrect"), + containsString("Keystore has been corrupted or tampered with") + ) + ); + } else { + assertThat(e.getMessage(), containsString("Provided keystore password was incorrect")); + } } public void testAddToUnprotectedKeystore() throws Exception { diff --git a/server/src/test/java/org/elasticsearch/common/settings/AddStringKeyStoreCommandTests.java b/server/src/test/java/org/elasticsearch/common/settings/AddStringKeyStoreCommandTests.java index 274dfb39eff..5ee0f98cc7c 100644 --- a/server/src/test/java/org/elasticsearch/common/settings/AddStringKeyStoreCommandTests.java +++ b/server/src/test/java/org/elasticsearch/common/settings/AddStringKeyStoreCommandTests.java @@ -30,6 +30,7 @@ import org.elasticsearch.cli.ExitCodes; import org.elasticsearch.cli.UserException; import org.elasticsearch.env.Environment; +import static org.hamcrest.Matchers.anyOf; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.hasToString; @@ -57,7 +58,17 @@ public class AddStringKeyStoreCommandTests extends KeyStoreCommandTestCase { terminal.addSecretInput("thewrongpassword"); UserException e = expectThrows(UserException.class, () -> execute("foo2")); assertEquals(e.getMessage(), ExitCodes.DATA_ERROR, e.exitCode); - assertThat(e.getMessage(), containsString("Provided keystore password was incorrect")); + if (inFipsJvm()) { + assertThat( + e.getMessage(), + anyOf( + containsString("Provided keystore password was incorrect"), + containsString("Keystore has been corrupted or tampered with") + ) + ); + } else { + assertThat(e.getMessage(), containsString("Provided keystore password was incorrect")); + } } diff --git a/server/src/test/java/org/elasticsearch/common/settings/ChangeKeyStorePasswordCommandTests.java b/server/src/test/java/org/elasticsearch/common/settings/ChangeKeyStorePasswordCommandTests.java index ca0b5fa3633..9d07d81bd97 100644 --- a/server/src/test/java/org/elasticsearch/common/settings/ChangeKeyStorePasswordCommandTests.java +++ b/server/src/test/java/org/elasticsearch/common/settings/ChangeKeyStorePasswordCommandTests.java @@ -26,6 +26,7 @@ import org.elasticsearch.env.Environment; import java.util.Map; +import static org.hamcrest.Matchers.anyOf; import static org.hamcrest.Matchers.containsString; public class ChangeKeyStorePasswordCommandTests extends KeyStoreCommandTestCase { @@ -90,6 +91,16 @@ public class ChangeKeyStorePasswordCommandTests extends KeyStoreCommandTestCase // We'll only be prompted once (for the old password) UserException e = expectThrows(UserException.class, this::execute); assertEquals(e.getMessage(), ExitCodes.DATA_ERROR, e.exitCode); - assertThat(e.getMessage(), containsString("Provided keystore password was incorrect")); + if (inFipsJvm()) { + assertThat( + e.getMessage(), + anyOf( + containsString("Provided keystore password was incorrect"), + containsString("Keystore has been corrupted or tampered with") + ) + ); + } else { + assertThat(e.getMessage(), containsString("Provided keystore password was incorrect")); + } } } diff --git a/server/src/test/java/org/elasticsearch/common/settings/KeyStoreWrapperTests.java b/server/src/test/java/org/elasticsearch/common/settings/KeyStoreWrapperTests.java index aa4dc566e69..43d97a1d61d 100644 --- a/server/src/test/java/org/elasticsearch/common/settings/KeyStoreWrapperTests.java +++ b/server/src/test/java/org/elasticsearch/common/settings/KeyStoreWrapperTests.java @@ -60,6 +60,7 @@ import java.util.HashSet; import java.util.List; import java.util.Locale; +import static org.hamcrest.Matchers.anyOf; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.instanceOf; @@ -111,9 +112,21 @@ public class KeyStoreWrapperTests extends ESTestCase { KeyStoreWrapper keystore = KeyStoreWrapper.create(); keystore.save(env.configFile(), new char[0]); final KeyStoreWrapper loadedkeystore = KeyStoreWrapper.load(env.configFile()); - final SecurityException exception = expectThrows(SecurityException.class, - () -> loadedkeystore.decrypt(new char[]{'i', 'n', 'v', 'a', 'l', 'i', 'd'})); - assertThat(exception.getMessage(), containsString("Provided keystore password was incorrect")); + final SecurityException exception = expectThrows( + SecurityException.class, + () -> loadedkeystore.decrypt(new char[] { 'i', 'n', 'v', 'a', 'l', 'i', 'd' }) + ); + if (inFipsJvm()) { + assertThat( + exception.getMessage(), + anyOf( + containsString("Provided keystore password was incorrect"), + containsString("Keystore has been corrupted or tampered with") + ) + ); + } else { + assertThat(exception.getMessage(), containsString("Provided keystore password was incorrect")); + } } public void testCannotReadStringFromClosedKeystore() throws Exception { diff --git a/server/src/test/java/org/elasticsearch/common/settings/ListKeyStoreCommandTests.java b/server/src/test/java/org/elasticsearch/common/settings/ListKeyStoreCommandTests.java index f79fd751465..5a1d3d2f350 100644 --- a/server/src/test/java/org/elasticsearch/common/settings/ListKeyStoreCommandTests.java +++ b/server/src/test/java/org/elasticsearch/common/settings/ListKeyStoreCommandTests.java @@ -26,6 +26,7 @@ import org.elasticsearch.cli.ExitCodes; import org.elasticsearch.cli.UserException; import org.elasticsearch.env.Environment; +import static org.hamcrest.Matchers.anyOf; import static org.hamcrest.Matchers.containsString; public class ListKeyStoreCommandTests extends KeyStoreCommandTestCase { @@ -76,7 +77,17 @@ public class ListKeyStoreCommandTests extends KeyStoreCommandTestCase { terminal.addSecretInput("thewrongkeystorepassword"); UserException e = expectThrows(UserException.class, this::execute); assertEquals(e.getMessage(), ExitCodes.DATA_ERROR, e.exitCode); - assertThat(e.getMessage(), containsString("Provided keystore password was incorrect")); + if (inFipsJvm()) { + assertThat( + e.getMessage(), + anyOf( + containsString("Provided keystore password was incorrect"), + containsString("Keystore has been corrupted or tampered with") + ) + ); + } else { + assertThat(e.getMessage(), containsString("Provided keystore password was incorrect")); + } } public void testListWithUnprotectedKeystore() throws Exception { diff --git a/server/src/test/java/org/elasticsearch/common/settings/RemoveSettingKeyStoreCommandTests.java b/server/src/test/java/org/elasticsearch/common/settings/RemoveSettingKeyStoreCommandTests.java index b4cc08c8465..5138206cf34 100644 --- a/server/src/test/java/org/elasticsearch/common/settings/RemoveSettingKeyStoreCommandTests.java +++ b/server/src/test/java/org/elasticsearch/common/settings/RemoveSettingKeyStoreCommandTests.java @@ -27,6 +27,7 @@ import org.elasticsearch.env.Environment; import java.util.Map; import java.util.Set; +import static org.hamcrest.Matchers.anyOf; import static org.hamcrest.Matchers.containsString; public class RemoveSettingKeyStoreCommandTests extends KeyStoreCommandTestCase { @@ -93,7 +94,18 @@ public class RemoveSettingKeyStoreCommandTests extends KeyStoreCommandTestCase { terminal.addSecretInput("thewrongpassword"); UserException e = expectThrows(UserException.class, () -> execute("foo")); assertEquals(e.getMessage(), ExitCodes.DATA_ERROR, e.exitCode); - assertThat(e.getMessage(), containsString("Provided keystore password was incorrect")); + if (inFipsJvm()) { + assertThat( + e.getMessage(), + anyOf( + containsString("Provided keystore password was incorrect"), + containsString("Keystore has been corrupted or tampered with") + ) + ); + } else { + assertThat(e.getMessage(), containsString("Provided keystore password was incorrect")); + } + } public void testRemoveFromUnprotectedKeystore() throws Exception {