浏览代码

Test modifications for FIPS 140 mode (#51832)

- Enable SunJGSS provider for Kerberos tests
- Handle the fact that in the decrypt method in KeyStoreWrapper might
not throw immediately when the GCM cipher is from BouncyCastle FIPS
and we end up with a DataInputStream that has reached it's end.
- Disable tests, jarHell, testingConventions for ingest attachment
plugin. We don't support this plugin (and document this) in FIPS
mode.
- Don't attempt to install ingest-attachment in smoke-test-plugins
Ioannis Kakavas 5 年之前
父节点
当前提交
12b24bfa57

+ 1 - 0
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=

+ 12 - 1
distribution/tools/keystore-cli/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 {

+ 12 - 1
distribution/tools/keystore-cli/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"));
+        }
 
     }
 

+ 12 - 1
distribution/tools/keystore-cli/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"));
+        }
     }
 }

+ 12 - 1
distribution/tools/keystore-cli/src/test/java/org/elasticsearch/common/settings/KeyStoreWrapperTests.java

@@ -59,6 +59,7 @@ import java.util.List;
 import java.util.Locale;
 import java.util.Set;
 
+import static org.hamcrest.Matchers.anyOf;
 import static org.hamcrest.Matchers.containsString;
 import static org.hamcrest.Matchers.equalTo;
 import static org.hamcrest.Matchers.instanceOf;
@@ -114,7 +115,17 @@ public class KeyStoreWrapperTests extends ESTestCase {
             SecurityException.class,
             () -> loadedkeystore.decrypt(new char[] { 'i', 'n', 'v', 'a', 'l', 'i', 'd' })
         );
-        assertThat(exception.getMessage(), containsString("Provided keystore password was incorrect"));
+        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 {

+ 12 - 1
distribution/tools/keystore-cli/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 {

+ 13 - 1
distribution/tools/keystore-cli/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 {

+ 5 - 2
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;
 }

+ 6 - 3
qa/os/src/test/java/org/elasticsearch/packaging/test/KeystoreManagementTests.java

@@ -34,6 +34,7 @@ import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.StandardOpenOption;
+import java.util.Arrays;
 import java.util.Map;
 
 import static org.elasticsearch.packaging.util.Archives.ARCHIVE_OWNER;
@@ -56,6 +57,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;
@@ -63,6 +65,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";
 
@@ -172,7 +175,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 */
@@ -208,7 +211,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)));
     }
 
     /**
@@ -277,7 +280,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");
         }

+ 15 - 5
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,12 +50,15 @@ 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;
 import static org.elasticsearch.packaging.util.Docker.removeContainer;
 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;
 
@@ -310,23 +315,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<String> expectedMessages, Packages.JournaldWrapper journaldWrapper) {
+        @SuppressWarnings("unchecked")
+        Matcher<String>[] 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
             assertTrue("log file exists", Files.exists(installation.logs.resolve("elasticsearch.log")));
             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) {
 
@@ -337,12 +347,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));
         }
     }
 

+ 5 - 0
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