Skip to content

Commit fc012fb

Browse files
authored
Fix and unmute FIPS tests (#119618) (#119783)
Fixes and un-mutes tests associated with FIPS. Most of the fixes are due to differing expected exceptions or log messages when using BouncyCastle as the JCE/JSSE provider. Only test code is changed with this commit. fixes: #49094
1 parent 4eabb4c commit fc012fb

File tree

8 files changed

+85
-53
lines changed

8 files changed

+85
-53
lines changed

client/rest/src/test/java/org/elasticsearch/client/RestClientBuilderIntegTests.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,18 +89,22 @@ public static void stopHttpServers() throws IOException {
8989
}
9090

9191
public void testBuilderUsesDefaultSSLContext() throws Exception {
92-
assumeFalse("https://github.com/elastic/elasticsearch/issues/49094", inFipsJvm());
9392
final SSLContext defaultSSLContext = SSLContext.getDefault();
9493
try {
9594
try (RestClient client = buildRestClient()) {
9695
try {
9796
client.performRequest(new Request("GET", "/"));
9897
fail("connection should have been rejected due to SSL handshake");
9998
} catch (Exception e) {
100-
assertThat(e, instanceOf(SSLHandshakeException.class));
99+
if (inFipsJvm()) {
100+
// Bouncy Castle throw a different exception
101+
assertThat(e, instanceOf(IOException.class));
102+
assertThat(e.getCause(), instanceOf(javax.net.ssl.SSLException.class));
103+
} else {
104+
assertThat(e, instanceOf(SSLHandshakeException.class));
105+
}
101106
}
102107
}
103-
104108
SSLContext.setDefault(getSslContext());
105109
try (RestClient client = buildRestClient()) {
106110
Response response = client.performRequest(new Request("GET", "/"));
@@ -112,7 +116,6 @@ public void testBuilderUsesDefaultSSLContext() throws Exception {
112116
}
113117

114118
public void testBuilderSetsThreadName() throws Exception {
115-
assumeFalse("https://github.com/elastic/elasticsearch/issues/49094", inFipsJvm());
116119
final SSLContext defaultSSLContext = SSLContext.getDefault();
117120
try {
118121
SSLContext.setDefault(getSslContext());

modules/reindex/src/test/java/org/elasticsearch/reindex/ReindexRestClientSslTests.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,14 +113,20 @@ private static SSLContext buildServerSslContext() throws Exception {
113113
}
114114

115115
public void testClientFailsWithUntrustedCertificate() throws IOException {
116-
assumeFalse("https://github.com/elastic/elasticsearch/issues/49094", inFipsJvm());
117116
final List<Thread> threads = new ArrayList<>();
118117
final Settings.Builder builder = Settings.builder().put("path.home", createTempDir());
119118
final Settings settings = builder.build();
120119
final Environment environment = TestEnvironment.newEnvironment(settings);
121120
final ReindexSslConfig ssl = new ReindexSslConfig(settings, environment, mock(ResourceWatcherService.class));
122121
try (RestClient client = Reindexer.buildRestClient(getRemoteInfo(), ssl, 1L, threads)) {
123-
expectThrows(SSLHandshakeException.class, () -> client.performRequest(new Request("GET", "/")));
122+
if (inFipsJvm()) {
123+
// Bouncy Castle throws a different exception
124+
IOException exception = expectThrows(IOException.class, () -> client.performRequest(new Request("GET", "/")));
125+
assertThat(exception.getCause(), Matchers.instanceOf(javax.net.ssl.SSLException.class));
126+
} else {
127+
expectThrows(SSLHandshakeException.class, () -> client.performRequest(new Request("GET", "/")));
128+
129+
}
124130
}
125131
}
126132

x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/SSLConfigurationReloaderTests.java

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,6 @@ public void testReloadingKeyStore() throws Exception {
170170
* Tests the reloading of SSLContext when a PEM key and certificate are used.
171171
*/
172172
public void testPEMKeyConfigReloading() throws Exception {
173-
assumeFalse("https://github.com/elastic/elasticsearch/issues/49094", inFipsJvm());
174173
Path tempDir = createTempDir();
175174
Path keyPath = tempDir.resolve("testnode.pem");
176175
Path certPath = tempDir.resolve("testnode.crt");
@@ -221,11 +220,19 @@ public void testPEMKeyConfigReloading() throws Exception {
221220
try (MockWebServer server = new MockWebServer(updatedContext, false)) {
222221
server.enqueue(new MockResponse().setResponseCode(200).setBody("body"));
223222
server.start();
224-
SSLHandshakeException sslException = expectThrows(
225-
SSLHandshakeException.class,
226-
() -> privilegedConnect(() -> client.execute(new HttpGet("https://localhost:" + server.getPort())).close())
227-
);
228-
assertThat(sslException.getCause().getMessage(), containsString("PKIX path validation failed"));
223+
if (inFipsJvm()) {
224+
Exception sslException = expectThrows(
225+
IOException.class,
226+
() -> privilegedConnect(() -> client.execute(new HttpGet("https://localhost:" + server.getPort())).close())
227+
);
228+
assertThat(sslException.getCause().getMessage(), containsString("Unable to construct a valid chain"));
229+
} else {
230+
SSLHandshakeException sslException = expectThrows(
231+
SSLHandshakeException.class,
232+
() -> privilegedConnect(() -> client.execute(new HttpGet("https://localhost:" + server.getPort())).close())
233+
);
234+
assertThat(sslException.getCause().getMessage(), containsString("PKIX path validation failed"));
235+
}
229236
} catch (Exception e) {
230237
throw new RuntimeException("Exception starting or connecting to the mock server", e);
231238
}
@@ -290,7 +297,6 @@ public void testReloadingTrustStore() throws Exception {
290297
* Test the reloading of SSLContext whose trust config is backed by PEM certificate files.
291298
*/
292299
public void testReloadingPEMTrustConfig() throws Exception {
293-
assumeFalse("https://github.com/elastic/elasticsearch/issues/49094", inFipsJvm());
294300
Path tempDir = createTempDir();
295301
Path serverCertPath = tempDir.resolve("testnode.crt");
296302
Path serverKeyPath = tempDir.resolve("testnode.pem");
@@ -324,11 +330,19 @@ public void testReloadingPEMTrustConfig() throws Exception {
324330
// Client doesn't trust the Server certificate anymore so SSLHandshake should fail
325331
final Consumer<SSLContext> trustMaterialPostChecks = (updatedContext) -> {
326332
try (CloseableHttpClient client = createHttpClient(updatedContext)) {
327-
SSLHandshakeException sslException = expectThrows(
328-
SSLHandshakeException.class,
329-
() -> privilegedConnect(() -> client.execute(new HttpGet("https://localhost:" + server.getPort())).close())
330-
);
331-
assertThat(sslException.getCause().getMessage(), containsString("PKIX path validation failed"));
333+
if (inFipsJvm()) {
334+
Exception sslException = expectThrows(
335+
IOException.class,
336+
() -> privilegedConnect(() -> client.execute(new HttpGet("https://localhost:" + server.getPort())).close())
337+
);
338+
assertThat(sslException.getCause().getMessage(), containsString("Unable to construct a valid chain"));
339+
} else {
340+
SSLHandshakeException sslException = expectThrows(
341+
SSLHandshakeException.class,
342+
() -> privilegedConnect(() -> client.execute(new HttpGet("https://localhost:" + server.getPort())).close())
343+
);
344+
assertThat(sslException.getCause().getMessage(), containsString("PKIX path validation failed"));
345+
}
332346
} catch (Exception e) {
333347
throw new RuntimeException("Error closing CloseableHttpClient", e);
334348
}

x-pack/plugin/security/src/internalClusterTest/java/org/elasticsearch/xpack/ssl/SSLReloadIntegTests.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@ protected boolean transportSSLEnabled() {
9393
}
9494

9595
public void testThatSSLConfigurationReloadsOnModification() throws Exception {
96-
assumeFalse("https://github.com/elastic/elasticsearch/issues/49094", inFipsJvm());
9796
Path keyPath = createTempDir().resolve("testnode_updated.pem");
9897
Path certPath = createTempDir().resolve("testnode_updated.crt");
9998
Files.copy(getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_updated.pem"), keyPath);
@@ -127,6 +126,9 @@ public void testThatSSLConfigurationReloadsOnModification() throws Exception {
127126
fail("handshake should not have been successful!");
128127
} catch (SSLException | SocketException expected) {
129128
logger.trace("expected exception", expected);
129+
} catch (IOException e) {
130+
// BouncyCastle throws a different exception
131+
assertThat(e.getClass().getName(), is("org.bouncycastle.tls.TlsFatalAlertReceived"));
130132
}
131133
// Copy testnode_updated.crt to the placeholder updateable.crt so that the nodes will start trusting it now
132134
try {

x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLErrorMessageCertificateVerificationTests.java

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@
3939
import java.util.regex.Pattern;
4040

4141
import javax.net.ssl.HostnameVerifier;
42-
import javax.net.ssl.SSLHandshakeException;
4342
import javax.net.ssl.SSLParameters;
4443
import javax.net.ssl.SSLSocket;
4544
import javax.net.ssl.SSLSocketFactory;
@@ -104,7 +103,6 @@ public void testMessageForRestClientHostnameVerificationFailure() throws IOExcep
104103
}
105104

106105
public void testDiagnosticTrustManagerForHostnameVerificationFailure() throws Exception {
107-
assumeFalse("https://github.com/elastic/elasticsearch/issues/49094", inFipsJvm());
108106
final Settings settings = getPemSSLSettings(
109107
HTTP_SERVER_SSL,
110108
"not-this-host.crt",
@@ -133,7 +131,7 @@ public void testDiagnosticTrustManagerForHostnameVerificationFailure() throws Ex
133131
DiagnosticTrustManager.class.getName(),
134132
Level.WARN,
135133
"failed to establish trust with server at \\["
136-
+ Pattern.quote(webServer.getHostName())
134+
+ (inFipsJvm() ? "<unknown host>" : Pattern.quote(webServer.getHostName()))
137135
+ "\\];"
138136
+ " the server provided a certificate with subject name \\[CN=not-this-host\\],"
139137
+ " fingerprint \\[[0-9a-f]{40}\\], no keyUsage and no extendedKeyUsage;"
@@ -154,13 +152,12 @@ public void testDiagnosticTrustManagerForHostnameVerificationFailure() throws Ex
154152
enableHttpsHostnameChecking(clientSocket);
155153
connect(clientSocket, webServer);
156154
assertThat(clientSocket.isConnected(), is(true));
157-
final SSLHandshakeException handshakeException = expectThrows(
158-
SSLHandshakeException.class,
159-
() -> clientSocket.getInputStream().read()
160-
);
161-
assertThat(handshakeException, throwableWithMessage(containsStringIgnoringCase("subject alternative names")));
162-
assertThat(handshakeException, throwableWithMessage(containsString(webServer.getHostName())));
163-
155+
final Exception handshakeException = expectThrows(Exception.class, () -> clientSocket.getInputStream().read());
156+
// Bouncy Castle throws a different exception message
157+
if (inFipsJvm() == false) {
158+
assertThat(handshakeException, throwableWithMessage(containsStringIgnoringCase("subject alternative names")));
159+
assertThat(handshakeException, throwableWithMessage(containsString(webServer.getHostName())));
160+
}
164161
// Logging message failures are tricky to debug because you just get a "didn't find match" assertion failure.
165162
// You should be able to check the log output for the text that was logged and compare to the regex above.
166163
mockLog.assertAllExpectationsMatched();

x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/actions/email/EmailSslTests.java

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import java.util.HashSet;
3939
import java.util.List;
4040
import java.util.Set;
41+
import java.util.stream.Collectors;
4142

4243
import javax.mail.MessagingException;
4344
import javax.mail.internet.MimeMessage;
@@ -74,7 +75,6 @@ public void stopSmtpServer() {
7475
}
7576

7677
public void testFailureSendingMessageToSmtpServerWithUntrustedCertificateAuthority() throws Exception {
77-
assumeFalse("https://github.com/elastic/elasticsearch/issues/49094", inFipsJvm());
7878
final Settings.Builder settings = Settings.builder();
7979
final MockSecureSettings secureSettings = new MockSecureSettings();
8080
final ExecutableEmailAction emailAction = buildEmailAction(settings, secureSettings);
@@ -84,7 +84,14 @@ public void testFailureSendingMessageToSmtpServerWithUntrustedCertificateAuthori
8484
() -> emailAction.execute("my_action_id", ctx, Payload.EMPTY)
8585
);
8686
final List<Throwable> allCauses = getAllCauses(exception);
87-
assertThat(allCauses, Matchers.hasItem(Matchers.instanceOf(SSLException.class)));
87+
if (inFipsJvm()) {
88+
assertThat(
89+
allCauses.stream().map(c -> c.getClass().getCanonicalName()).collect(Collectors.toSet()),
90+
Matchers.hasItem("org.bouncycastle.tls.TlsFatalAlert")
91+
);
92+
} else {
93+
assertThat(allCauses, Matchers.hasItem(Matchers.instanceOf(SSLException.class)));
94+
}
8895
}
8996

9097
public void testCanSendMessageToSmtpServerUsingTrustStore() throws Exception {
@@ -149,7 +156,6 @@ public void testCanSendMessageToSmtpServerUsingSmtpSslTrust() throws Exception {
149156
* over the account level "smtp.ssl.trust" setting) but smtp.ssl.trust was ignored for a period of time (see #52153)
150157
* so this is the least breaking way to resolve that.
151158
*/
152-
@AwaitsFix(bugUrl = "https://github.com/elastic/elasticsearch/issues/49094")
153159
public void testNotificationSslSettingsOverrideSmtpSslTrust() throws Exception {
154160
List<MimeMessage> messages = new ArrayList<>();
155161
server.addListener(messages::add);
@@ -165,9 +171,16 @@ public void testNotificationSslSettingsOverrideSmtpSslTrust() throws Exception {
165171
MessagingException.class,
166172
() -> emailAction.execute("my_action_id", ctx, Payload.EMPTY)
167173
);
168-
169174
final List<Throwable> allCauses = getAllCauses(exception);
170-
assertThat(allCauses, Matchers.hasItem(Matchers.instanceOf(SSLException.class)));
175+
if (inFipsJvm()) {
176+
assertThat(
177+
allCauses.stream().map(c -> c.getClass().getCanonicalName()).collect(Collectors.toSet()),
178+
Matchers.hasItem("org.bouncycastle.tls.TlsFatalAlert")
179+
);
180+
} else {
181+
assertThat(allCauses, Matchers.hasItem(Matchers.instanceOf(SSLException.class)));
182+
}
183+
171184
} finally {
172185
server.clearListeners();
173186
}

x-pack/qa/smoke-test-plugins-ssl/build.gradle

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,14 @@ project(':plugins').getChildProjects().each { pluginName, pluginProject ->
4949
testClusters.matching { it.name == "yamlRestTest" }.configureEach {
5050
testDistribution = 'DEFAULT'
5151
setting 'xpack.monitoring.collection.interval', '1s'
52+
setting 'xpack.monitoring.collection.enabled', 'false' //will enable in test
53+
setting 'xpack.monitoring.exporters._http.enabled', 'false'//will enable in test
54+
setting 'xpack.monitoring.exporters._http.type', "http"
55+
setting 'xpack.monitoring.exporters._http.host', "https://example.com" //will be replaced in test
56+
setting 'xpack.monitoring.exporters._http.auth.username', 'monitoring_agent'
57+
setting 'xpack.monitoring.exporters._http.ssl.verification_mode', 'full'
58+
setting 'xpack.monitoring.exporters._http.ssl.certificate_authorities', 'testnode.crt'
59+
keystore 'xpack.monitoring.exporters._http.auth.secure_password', 'x-pack-test-password'
5260

5361
setting 'xpack.license.self_generated.type', 'trial'
5462
setting 'xpack.security.enabled', 'true'

x-pack/qa/smoke-test-plugins-ssl/src/yamlRestTest/java/org/elasticsearch/smoketest/SmokeTestMonitoringWithSecurityIT.java

Lines changed: 8 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
import org.elasticsearch.client.Response;
1212
import org.elasticsearch.client.RestClient;
1313
import org.elasticsearch.common.Strings;
14-
import org.elasticsearch.common.settings.MockSecureSettings;
1514
import org.elasticsearch.common.settings.SecureString;
1615
import org.elasticsearch.common.settings.Settings;
1716
import org.elasticsearch.common.util.concurrent.ThreadContext;
@@ -53,26 +52,25 @@ public class SmokeTestMonitoringWithSecurityIT extends ESRestTestCase {
5352

5453
private static final String USER = "test_user";
5554
private static final SecureString PASS = new SecureString("x-pack-test-password".toCharArray());
56-
private static final String KEYSTORE_PASS = "testnode";
5755
private static final String MONITORING_PATTERN = ".monitoring-*";
5856

59-
static Path keyStore;
57+
static Path trustStore;
6058

6159
@BeforeClass
6260
public static void getKeyStore() {
6361
try {
64-
keyStore = PathUtils.get(SmokeTestMonitoringWithSecurityIT.class.getResource("/testnode.jks").toURI());
62+
trustStore = PathUtils.get(SmokeTestMonitoringWithSecurityIT.class.getResource("/testnode.crt").toURI());
6563
} catch (URISyntaxException e) {
66-
throw new ElasticsearchException("exception while reading the store", e);
64+
throw new ElasticsearchException("exception while reading the truststore", e);
6765
}
68-
if (Files.exists(keyStore) == false) {
69-
throw new IllegalStateException("Keystore file [" + keyStore + "] does not exist.");
66+
if (Files.exists(trustStore) == false) {
67+
throw new IllegalStateException("Truststore file [" + trustStore + "] does not exist.");
7068
}
7169
}
7270

7371
@AfterClass
7472
public static void clearKeyStore() {
75-
keyStore = null;
73+
trustStore = null;
7674
}
7775

7876
@Override
@@ -85,24 +83,17 @@ protected Settings restClientSettings() {
8583
String token = basicAuthHeaderValue(USER, PASS);
8684
return Settings.builder()
8785
.put(ThreadContext.PREFIX + ".Authorization", token)
88-
.put(ESRestTestCase.TRUSTSTORE_PATH, keyStore)
89-
.put(ESRestTestCase.TRUSTSTORE_PASSWORD, KEYSTORE_PASS)
86+
.put(ESRestTestCase.CERTIFICATE_AUTHORITIES, trustStore)
9087
.build();
9188
}
9289

9390
@Before
9491
public void enableExporter() throws Exception {
95-
MockSecureSettings secureSettings = new MockSecureSettings();
96-
secureSettings.setString("xpack.monitoring.exporters._http.auth.secure_password", "x-pack-test-password");
9792
Settings exporterSettings = Settings.builder()
9893
.put("xpack.monitoring.collection.enabled", true)
9994
.put("xpack.monitoring.exporters._http.enabled", true)
10095
.put("xpack.monitoring.exporters._http.type", "http")
10196
.put("xpack.monitoring.exporters._http.host", "https://" + randomNodeHttpAddress())
102-
.put("xpack.monitoring.exporters._http.auth.username", "monitoring_agent")
103-
.put("xpack.monitoring.exporters._http.ssl.verification_mode", "full")
104-
.put("xpack.monitoring.exporters._http.ssl.certificate_authorities", "testnode.crt")
105-
.setSecureSettings(secureSettings)
10697
.build();
10798
updateClusterSettingsIgnoringWarnings(client(), exporterSettings);
10899
}
@@ -140,7 +131,6 @@ private boolean getMonitoringUsageExportersDefined() throws Exception {
140131
return exporters != null && exporters.isEmpty() == false;
141132
}
142133

143-
@AwaitsFix(bugUrl = "https://github.com/elastic/elasticsearch/issues/49094")
144134
public void testHTTPExporterWithSSL() throws Exception {
145135
// Ensures that the exporter is actually on
146136
assertBusy(() -> assertThat("[_http] exporter is not defined", getMonitoringUsageExportersDefined(), is(true)));
@@ -193,12 +183,11 @@ public void testHTTPExporterWithSSL() throws Exception {
193183
});
194184
}
195185

196-
@AwaitsFix(bugUrl = "https://github.com/elastic/elasticsearch/issues/49094")
197186
public void testSettingsFilter() throws IOException {
198187
final Request request = new Request("GET", "/_cluster/settings");
199188
final Response response = client().performRequest(request);
200189
final ObjectPath path = ObjectPath.createFromResponse(response);
201-
final Map<String, Object> settings = path.evaluate("transient.xpack.monitoring.exporters._http");
190+
final Map<String, Object> settings = path.evaluate("persistent.xpack.monitoring.exporters._http");
202191
assertThat(settings, hasKey("type"));
203192
assertThat(settings, not(hasKey("auth")));
204193
assertThat(settings, not(hasKey("ssl")));

0 commit comments

Comments
 (0)