Skip to content

Commit 43fbfb9

Browse files
committed
Fix ApiKeyBackwardsCompatibilityIT.testCertificateIdentityBackwardsCompatibility()
1 parent d8b64d2 commit 43fbfb9

File tree

2 files changed

+59
-7
lines changed

2 files changed

+59
-7
lines changed

x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/ApiKeyService.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -563,7 +563,14 @@ private void createApiKeyAndIndexIt(
563563
: "Invalid API key (name=[" + request.getName() + "], type=[" + request.getType() + "], length=[" + apiKey.length() + "])";
564564

565565
computeHashForApiKey(apiKey, listener.delegateFailure((l, apiKeyHashChars) -> {
566-
String certificateIdentity = getCertificateIdentityFromRequest(request);
566+
final String certificateIdentity;
567+
try {
568+
certificateIdentity = getCertificateIdentityFromRequest(request);
569+
} catch (ElasticsearchException e) {
570+
listener.onFailure(e);
571+
return;
572+
}
573+
567574
try (
568575
XContentBuilder builder = newDocument(
569576
apiKeyHashChars,

x-pack/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/ApiKeyBackwardsCompatibilityIT.java

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -218,8 +218,9 @@ public void testCertificateIdentityBackwardsCompatibility() throws Exception {
218218
}
219219
case MIXED -> {
220220
try {
221-
this.createClientsByVersion();
221+
this.createClientsByCertificateIdentityCapability();
222222

223+
// Test against old node - should get parsing error
223224
Exception oldNodeException = expectThrows(
224225
Exception.class,
225226
() -> createCrossClusterApiKeyWithCertIdentity(oldVersionClient, "CN=test-.*")
@@ -236,16 +237,12 @@ public void testCertificateIdentityBackwardsCompatibility() throws Exception {
236237
);
237238
assertThat(
238239
newNodeException.getMessage(),
239-
containsString(
240-
"API key creation failed. The cluster is in a mixed-version state and does not yet "
241-
+ "support the [certificate_identity] field. Please retry after the upgrade is complete."
242-
)
240+
containsString("cluster is in a mixed-version state and does not yet support the [certificate_identity] field")
243241
);
244242
} finally {
245243
this.closeClientsByVersion();
246244
}
247245
}
248-
249246
case UPGRADED -> {
250247
// Fully upgraded cluster should support certificate identity
251248
final Tuple<String, String> apiKey = createCrossClusterApiKeyWithCertIdentity("CN=test-.*");
@@ -484,6 +481,53 @@ private void assertQuery(RestClient restClient, String body, Consumer<List<Map<S
484481
apiKeysVerifier.accept(apiKeys);
485482
}
486483

484+
private boolean nodeSupportsCertificateIdentity(Map<String, Object> nodeDetails) {
485+
String nodeVersionString = (String) nodeDetails.get("version");
486+
Version nodeVersion = Version.fromString(nodeVersionString);
487+
// Certificate identity was introduced in 9.2.0
488+
return nodeVersion.onOrAfter(Version.V_9_2_0);
489+
}
490+
491+
@SuppressWarnings("unchecked")
492+
private Map<Boolean, RestClient> getRestClientByCertificateIdentityCapability() throws IOException {
493+
Response response = client().performRequest(new Request("GET", "_nodes"));
494+
assertOK(response);
495+
ObjectPath objectPath = ObjectPath.createFromResponse(response);
496+
Map<String, Object> nodesAsMap = objectPath.evaluate("nodes");
497+
Map<Boolean, List<HttpHost>> hostsByCapability = new HashMap<>();
498+
499+
for (Map.Entry<String, Object> entry : nodesAsMap.entrySet()) {
500+
Map<String, Object> nodeDetails = (Map<String, Object>) entry.getValue();
501+
var capabilitySupported = nodeSupportsCertificateIdentity(nodeDetails);
502+
Map<String, Object> httpInfo = (Map<String, Object>) nodeDetails.get("http");
503+
hostsByCapability.computeIfAbsent(capabilitySupported, k -> new ArrayList<>())
504+
.add(HttpHost.create((String) httpInfo.get("publish_address")));
505+
}
506+
507+
Map<Boolean, RestClient> clientsByCapability = new HashMap<>();
508+
for (var entry : hostsByCapability.entrySet()) {
509+
clientsByCapability.put(entry.getKey(), buildClient(restClientSettings(), entry.getValue().toArray(new HttpHost[0])));
510+
}
511+
return clientsByCapability;
512+
}
513+
514+
private void createClientsByCertificateIdentityCapability() throws IOException {
515+
var clientsByCapability = getRestClientByCertificateIdentityCapability();
516+
if (clientsByCapability.size() == 2) {
517+
for (Map.Entry<Boolean, RestClient> client : clientsByCapability.entrySet()) {
518+
if (client.getKey() == false) {
519+
oldVersionClient = client.getValue();
520+
} else {
521+
newVersionClient = client.getValue();
522+
}
523+
}
524+
assertThat(oldVersionClient, notNullValue());
525+
assertThat(newVersionClient, notNullValue());
526+
} else {
527+
fail("expected 2 versions during rolling upgrade but got: " + clientsByCapability.size());
528+
}
529+
}
530+
487531
private Tuple<String, String> createCrossClusterApiKeyWithCertIdentity(String certificateIdentity) throws IOException {
488532
return createCrossClusterApiKeyWithCertIdentity(client(), certificateIdentity);
489533
}
@@ -514,4 +558,5 @@ private Tuple<String, String> createCrossClusterApiKeyWithCertIdentity(RestClien
514558
assertThat(key, notNullValue());
515559
return Tuple.tuple(id, key);
516560
}
561+
517562
}

0 commit comments

Comments
 (0)