Browse Source

Add support for invalidation timestamp in QueryApiKey (#102590)

This is a follow up PR from
https://github.com/elastic/elasticsearch/pull/102472. This adds the
ability to use `invalidation` timestamp as a valid [query
value](https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-query-api-key.html#security-api-query-api-key-request-body)
in the QueryApiKey API.
Johannes Fredén 1 year ago
parent
commit
6aad7f4e9f

+ 1 - 1
docs/reference/rest-api/security/get-api-keys.asciidoc

@@ -175,7 +175,7 @@ A successful call returns a JSON structure that contains the information of the
 <4> Creation time for the API key in milliseconds
 <5> Optional expiration time for the API key in milliseconds
 <6> Invalidation status for the API key. If the key has been invalidated, it has
-a value of `true`. Otherwise, it is `false`.
+a value of `true` and an additional field with the `invalidation` time in milliseconds. Otherwise, it is `false`.
 <7> Principal for which this API key was created
 <8> Realm name of the principal for which this API key was created
 <9> Metadata of the API key

+ 3 - 0
docs/reference/rest-api/security/query-api-key.asciidoc

@@ -77,6 +77,9 @@ Expiration time of the API key in milliseconds.
 Indicates whether the API key is invalidated. If `true`, the key is invalidated.
 Defaults to `false`.
 
+`invalidation`::
+Invalidation time of the API key in milliseconds. This field is only set for invalidated API keys.
+
 `username`::
 Username of the API key owner.
 

+ 13 - 1
x-pack/plugin/security/qa/security-basic/src/javaRestTest/java/org/elasticsearch/xpack/security/QueryApiKeyIT.java

@@ -129,7 +129,7 @@ public class QueryApiKeyIT extends SecurityInBasicRestTestCase {
             { "query": { "prefix": {"api_key_hash": "{PBKDF2}10000$"} } }""");
 
         // Search for fields that are not allowed in Query DSL but used internally by the service itself
-        final String fieldName = randomFrom("doc_type", "api_key_invalidated");
+        final String fieldName = randomFrom("doc_type", "api_key_invalidated", "invalidation_time");
         assertQueryError(API_KEY_ADMIN_AUTH_HEADER, 400, Strings.format("""
             { "query": { "term": {"%s": "%s"} } }""", fieldName, randomAlphaOfLengthBetween(3, 8)));
 
@@ -164,6 +164,7 @@ public class QueryApiKeyIT extends SecurityInBasicRestTestCase {
         final String queryString = randomFrom("""
             {"query": { "term": {"name": "temporary-key-1"} } }""", Strings.format("""
             {"query":{"bool":{"must":[{"term":{"name":{"value":"temporary-key-1"}}},\
+            {"range": {"invalidation": {"lte": "now"}}},
             {"term":{"invalidated":{"value":"%s"}}}]}}}
             """, randomBoolean()));
 
@@ -387,6 +388,12 @@ public class QueryApiKeyIT extends SecurityInBasicRestTestCase {
         // Create an invalidated API key
         createAndInvalidateApiKey("test-exists-4", authHeader);
 
+        // Get the invalidated API key
+        assertQuery(authHeader, """
+            {"query": {"exists": {"field": "invalidation" }}}""", apiKeys -> {
+            assertThat(apiKeys.stream().map(k -> (String) k.get("name")).toList(), containsInAnyOrder("test-exists-4"));
+        });
+
         // Ensure the short-lived key is expired
         final long elapsed = Instant.now().toEpochMilli() - startTime;
         if (elapsed < 10) {
@@ -403,6 +410,11 @@ public class QueryApiKeyIT extends SecurityInBasicRestTestCase {
                       "invalidated": false
                     }
                   },
+                  "must_not": {
+                    "exists": {
+                      "field": "invalidation"
+                    }
+                  },
                   "should": [
                     {
                       "range": {

+ 1 - 0
x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/support/ApiKeyBoolQueryBuilder.java

@@ -37,6 +37,7 @@ public class ApiKeyBoolQueryBuilder extends BoolQueryBuilder {
         "doc_type",
         "name",
         "api_key_invalidated",
+        "invalidation_time",
         "creation_time",
         "expiration_time"
     );

+ 1 - 0
x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/support/ApiKeyFieldNameTranslators.java

@@ -24,6 +24,7 @@ public class ApiKeyFieldNameTranslators {
             new ExactFieldNameTranslator(s -> "creation_time", "creation"),
             new ExactFieldNameTranslator(s -> "expiration_time", "expiration"),
             new ExactFieldNameTranslator(s -> "api_key_invalidated", "invalidated"),
+            new ExactFieldNameTranslator(s -> "invalidation_time", "invalidation"),
             new PrefixFieldNameTranslator(s -> "metadata_flattened" + s.substring(8), "metadata.")
         );
     }