diff --git a/x-pack/plugin/build.gradle b/x-pack/plugin/build.gradle index 41c8a8479a952..7acd20167747d 100644 --- a/x-pack/plugin/build.gradle +++ b/x-pack/plugin/build.gradle @@ -98,7 +98,6 @@ tasks.named("yamlRestTestV7CompatTransform").configure{ task -> task.skipTest("rollup/put_job/Test basic put_job", "rollup was an experimental feature, also see #41227") task.skipTest("rollup/start_job/Test start job twice", "rollup was an experimental feature, also see #41227") task.skipTest("ml/trained_model_cat_apis/Test cat trained models", "A type field was added to cat.ml_trained_models #73660, this is a backwards compatible change. Still this is a cat api, and we don't support them with rest api compatibility. (the test would be very hard to transform too)") - task.skipTest("api_key/10_basic/Test invalidate api keys with single id", "waiting for https://github.com/elastic/elasticsearch/pull/78664") task.replaceKeyInDo("license.delete", "xpack-license.delete") task.replaceKeyInDo("license.get", "xpack-license.get") diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/rest/action/apikey/RestInvalidateApiKeyAction.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/rest/action/apikey/RestInvalidateApiKeyAction.java index 7c11cba8f3349..9bdfa9540ccc7 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/rest/action/apikey/RestInvalidateApiKeyAction.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/rest/action/apikey/RestInvalidateApiKeyAction.java @@ -8,8 +8,10 @@ package org.elasticsearch.xpack.security.rest.action.apikey; import org.elasticsearch.client.node.NodeClient; -import org.elasticsearch.xcontent.ParseField; +import org.elasticsearch.common.Strings; import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.core.RestApiVersion; +import org.elasticsearch.xcontent.ParseField; import org.elasticsearch.xcontent.ConstructingObjectParser; import org.elasticsearch.xcontent.XContentBuilder; import org.elasticsearch.xcontent.XContentParser; @@ -42,11 +44,7 @@ public final class RestInvalidateApiKeyAction extends SecurityBaseRestHandler { }); static { - PARSER.declareString(ConstructingObjectParser.optionalConstructorArg(), new ParseField("realm_name")); - PARSER.declareString(ConstructingObjectParser.optionalConstructorArg(), new ParseField("username")); - PARSER.declareString(ConstructingObjectParser.optionalConstructorArg(), new ParseField("name")); - PARSER.declareBoolean(ConstructingObjectParser.optionalConstructorArg(), new ParseField("owner")); - PARSER.declareStringArray(ConstructingObjectParser.optionalConstructorArg(), new ParseField("ids")); + initObjectParser(PARSER, false); } public RestInvalidateApiKeyAction(Settings settings, XPackLicenseState licenseState) { @@ -61,7 +59,7 @@ public List routes() { @Override protected RestChannelConsumer innerPrepareRequest(RestRequest request, NodeClient client) throws IOException { try (XContentParser parser = request.contentParser()) { - final InvalidateApiKeyRequest invalidateApiKeyRequest = PARSER.parse(parser, null); + final InvalidateApiKeyRequest invalidateApiKeyRequest = getObjectParser(request).parse(parser, null); return channel -> client.execute(InvalidateApiKeyAction.INSTANCE, invalidateApiKeyRequest, new RestBuilderListener(channel) { @Override @@ -78,4 +76,43 @@ public RestResponse buildResponse(InvalidateApiKeyResponse invalidateResp, public String getName() { return "xpack_security_invalidate_api_key"; } + + private ConstructingObjectParser getObjectParser(RestRequest request) { + if (request.getRestApiVersion() == RestApiVersion.V_7) { + final ConstructingObjectParser objectParser = new ConstructingObjectParser<>( + "invalidate_api_key_v7", a -> { + final String id = (String) a[5]; + @SuppressWarnings("unchecked") + final List ids = (List) a[4]; + if (id != null && ids != null) { + throw new IllegalArgumentException("Must use either [id] or [ids], not both at the same time"); + } + final String[] idsArray; + if (Strings.hasText(id)) { + idsArray = new String[] { id }; + } else if (ids != null) { + idsArray = ids.toArray(String[]::new); + } else { + idsArray = null; + } + return new InvalidateApiKeyRequest((String) a[0], (String) a[1], (String) a[2], + (a[3] == null) ? false : (Boolean) a[3], idsArray); + }); + initObjectParser(objectParser, true); + return objectParser; + } else { + return PARSER; + } + } + + private static void initObjectParser(ConstructingObjectParser objectParser, boolean restCompatMode) { + objectParser.declareString(ConstructingObjectParser.optionalConstructorArg(), new ParseField("realm_name")); + objectParser.declareString(ConstructingObjectParser.optionalConstructorArg(), new ParseField("username")); + objectParser.declareString(ConstructingObjectParser.optionalConstructorArg(), new ParseField("name")); + objectParser.declareBoolean(ConstructingObjectParser.optionalConstructorArg(), new ParseField("owner")); + objectParser.declareStringArray(ConstructingObjectParser.optionalConstructorArg(), new ParseField("ids")); + if (restCompatMode) { + objectParser.declareString(ConstructingObjectParser.optionalConstructorArg(), new ParseField("id").withAllDeprecated("ids")); + } + } }