mirror of
https://github.com/elastic/elasticsearch.git
synced 2025-04-25 23:57:20 -04:00
This is a refactoring of the internal logic that's used to translate query-level into index-level field names for query APIs for security entities (i.e. users, API Keys, and soon, roles). The objective here is to have and reuse a single class to handle all the translations for different security query APIs.
783 lines
20 KiB
Text
783 lines
20 KiB
Text
[role="xpack"]
|
|
[[security-api-query-api-key]]
|
|
=== Query API key information API
|
|
|
|
++++
|
|
<titleabbrev>Query API key information</titleabbrev>
|
|
++++
|
|
|
|
////
|
|
[source,console]
|
|
----
|
|
POST /_security/user/king
|
|
{
|
|
"password" : "security-test-password",
|
|
"roles": []
|
|
}
|
|
POST /_security/user/june
|
|
{
|
|
"password" : "security-test-password",
|
|
"roles": []
|
|
}
|
|
POST /_security/api_key/grant
|
|
{
|
|
"grant_type": "password",
|
|
"username" : "king",
|
|
"password" : "security-test-password",
|
|
"api_key" : {
|
|
"name": "king-key-no-expire"
|
|
}
|
|
}
|
|
DELETE /_security/api_key
|
|
{
|
|
"name" : "king-key-no-expire"
|
|
}
|
|
POST /_security/api_key/grant
|
|
{
|
|
"grant_type": "password",
|
|
"username" : "king",
|
|
"password" : "security-test-password",
|
|
"api_key" : {
|
|
"name": "king-key-10",
|
|
"expiration": "10d"
|
|
}
|
|
}
|
|
POST /_security/api_key/grant
|
|
{
|
|
"grant_type": "password",
|
|
"username" : "king",
|
|
"password" : "security-test-password",
|
|
"api_key" : {
|
|
"name": "king-key-100",
|
|
"expiration": "100d"
|
|
}
|
|
}
|
|
POST /_security/api_key/grant
|
|
{
|
|
"grant_type": "password",
|
|
"username" : "june",
|
|
"password" : "security-test-password",
|
|
"api_key" : {
|
|
"name": "june-key-no-expire"
|
|
}
|
|
}
|
|
POST /_security/api_key/grant
|
|
{
|
|
"grant_type": "password",
|
|
"username" : "june",
|
|
"password" : "security-test-password",
|
|
"api_key" : {
|
|
"name": "june-key-10",
|
|
"expiration": "10d"
|
|
}
|
|
}
|
|
POST /_security/api_key/grant
|
|
{
|
|
"grant_type": "password",
|
|
"username" : "june",
|
|
"password" : "security-test-password",
|
|
"api_key" : {
|
|
"name": "june-key-100",
|
|
"expiration": "100d"
|
|
}
|
|
}
|
|
DELETE /_security/api_key
|
|
{
|
|
"name" : "june-key-100"
|
|
}
|
|
----
|
|
// TESTSETUP
|
|
|
|
[source,console]
|
|
--------------------------------------------------
|
|
DELETE /_security/user/king
|
|
DELETE /_security/user/june
|
|
DELETE /_security/api_key
|
|
{
|
|
"name" : "king-key-no-expire"
|
|
}
|
|
DELETE /_security/api_key
|
|
{
|
|
"name" : "king-key-10"
|
|
}
|
|
DELETE /_security/api_key
|
|
{
|
|
"name" : "king-key-100"
|
|
}
|
|
DELETE /_security/api_key
|
|
{
|
|
"name" : "june-key-no-expire"
|
|
}
|
|
DELETE /_security/api_key
|
|
{
|
|
"name" : "june-key-10"
|
|
}
|
|
--------------------------------------------------
|
|
// TEARDOWN
|
|
|
|
////
|
|
|
|
Retrieves information for API keys with <<query-dsl,Query DSL>>
|
|
in a <<paginate-search-results,paginated>> fashion.
|
|
|
|
[[security-api-query-api-key-request]]
|
|
==== {api-request-title}
|
|
|
|
`GET /_security/_query/api_key`
|
|
|
|
`POST /_security/_query/api_key`
|
|
|
|
[[security-api-query-api-key-prereqs]]
|
|
==== {api-prereq-title}
|
|
|
|
* To use this API, you must have at least the `manage_own_api_key` or the `read_security`
|
|
cluster privileges.
|
|
* If you have only the `manage_own_api_key` privilege, this API returns only
|
|
the API keys that you own. If you have the `read_security`, `manage_api_key` or greater
|
|
privileges (including `manage_security`), this API returns all API keys
|
|
regardless of ownership.
|
|
|
|
[[security-api-query-api-key-desc]]
|
|
==== {api-description-title}
|
|
|
|
Use this API to retrieve the API keys created with the
|
|
<<security-api-create-api-key,create API key API>> in a paginated manner.
|
|
You can optionally filter the results with a query.
|
|
|
|
[[security-api-query-api-key-query-params]]
|
|
==== {api-path-parms-title}
|
|
|
|
`with_limited_by`::
|
|
(Optional, Boolean) A boolean flag to return the snapshot of the owner user's role descriptors
|
|
associated with the API key. An API key's actual permission is the intersection of
|
|
its <<api-key-role-descriptors,assigned role descriptors>> and the owner user's role descriptors
|
|
(effectively limited by it). An API key cannot retrieve any API key's limited-by role descriptors
|
|
(including itself) unless it has `manage_api_key` or higher privileges.
|
|
|
|
`with_profile_uid`::
|
|
(Optional, boolean) Determines whether to also retrieve the <<user-profile,user profile>> `uid`, for the API key owner user.
|
|
If it exists, the profile uid is returned under the `profile_uid` response field for each API key.
|
|
Defaults to `false`.
|
|
|
|
`typed_keys`::
|
|
(Optional, Boolean) If `true`, aggregation names are prefixed by their respective types in the response.
|
|
Defaults to `false`.
|
|
|
|
[[security-api-query-api-key-request-body]]
|
|
==== {api-request-body-title}
|
|
|
|
You can specify the following parameters in the request body:
|
|
|
|
`query`::
|
|
(Optional, object) A <<query-dsl,query>> to filter which API keys to return.
|
|
If the query parameter is missing, it is equivalent to a `match_all` query.
|
|
The query supports a subset of query types, including
|
|
<<query-dsl-match-all-query,`match_all`>>, <<query-dsl-bool-query,`bool`>>,
|
|
<<query-dsl-term-query,`term`>>, <<query-dsl-terms-query,`terms`>>,
|
|
<<query-dsl-match-query,`match`>>, <<query-dsl-ids-query,`ids`>>,
|
|
<<query-dsl-prefix-query,`prefix`>>, <<query-dsl-wildcard-query,`wildcard`>>,
|
|
<<query-dsl-exists-query,`exists`>>, <<query-dsl-range-query,`range`>>,
|
|
and <<query-dsl-simple-query-string-query,`simple query string`>>.
|
|
+
|
|
You can query the following public values associated with an API key.
|
|
+
|
|
NOTE: The queryable string values associated with API keys are internally mapped as <<keyword,`keywords`>>.
|
|
Consequently, if no <<analysis-analyzers,`analyzer`>> parameter is specified for a
|
|
<<query-dsl-match-query,`match`>> query, then the provided match query string is interpreted as
|
|
a single keyword value. Such a <<query-dsl-match-query,`match`>> query is hence equivalent to a
|
|
<<query-dsl-term-query,`term`>> query.
|
|
+
|
|
.Valid values for `query`
|
|
[%collapsible%open]
|
|
====
|
|
`id`::
|
|
ID of the API key. Note `id` must be queried with the <<query-dsl-ids-query,`ids`>> query.
|
|
|
|
`type`::
|
|
API keys can be of type `rest`, if created via the <<security-api-create-api-key, Create API key>> or
|
|
the <<security-api-grant-api-key, Grant API key>> APIs, or of type `cross_cluster` if created via
|
|
the <<security-api-create-cross-cluster-api-key, Create Cross-Cluster API key>> API.
|
|
|
|
`name`::
|
|
Name of the API key.
|
|
|
|
`creation`::
|
|
Creation time of the API key in milliseconds.
|
|
|
|
`expiration`::
|
|
Expiration time of the API key in milliseconds. This is `null` if the key was not configured to expire.
|
|
|
|
`invalidated`::
|
|
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.
|
|
|
|
`realm`::
|
|
Realm name of the API key owner.
|
|
|
|
`metadata`::
|
|
Metadata field associated with the API key, such as `metadata.my_field`.
|
|
Metadata is internally indexed as a <<flattened,flattened>> field type.
|
|
This means that all fields act like `keyword` fields when querying and sorting.
|
|
It's not possible to refer to a subset of metadata fields using wildcard
|
|
patterns, e.g. `metadata.field*`, even for query types that support field
|
|
name patterns. Lastly, all the metadata fields can be searched together when
|
|
simply mentioning `metadata` (not followed by any dot and sub-field name).
|
|
|
|
NOTE: You cannot query the role descriptors of an API key.
|
|
====
|
|
|
|
`aggs` or `aggregations`::
|
|
(Optional, object) Any <<search-aggregations,aggregations>> to run over the corpus of returned API keys.
|
|
Aggregations and queries work together. Aggregations are computed only on the API keys that match the query.
|
|
This supports only a subset of aggregation types, namely: <<search-aggregations-bucket-terms-aggregation,terms>>,
|
|
<<search-aggregations-bucket-range-aggregation,range>>, <<search-aggregations-bucket-daterange-aggregation,date range>>,
|
|
<<search-aggregations-bucket-missing-aggregation,missing>>, <<search-aggregations-metrics-cardinality-aggregation,cardinality>>,
|
|
<<search-aggregations-metrics-valuecount-aggregation,value count>>, <<search-aggregations-bucket-composite-aggregation,composite>>,
|
|
<<search-aggregations-bucket-filter-aggregation,filter>>, and <<search-aggregations-bucket-filters-aggregation,filters>>.
|
|
Additionally, aggregations only run over the same subset of fields that `query` works with.
|
|
|
|
include::{es-ref-dir}/rest-api/common-parms.asciidoc[tag=from]
|
|
+
|
|
By default, you cannot page through more than 10,000 hits using the `from` and
|
|
`size` parameters. To page through more hits, use the
|
|
<<search-after,`search_after`>> parameter.
|
|
|
|
`size`::
|
|
(Optional, integer) The number of hits to return. Must not be negative and defaults to `10`.
|
|
The `size` parameter can be set to `0`, in which case no API key matches are returned,
|
|
only the aggregation results.
|
|
+
|
|
By default, you cannot page through more than 10,000 hits using the `from` and
|
|
`size` parameters. To page through more hits, use the
|
|
<<search-after,`search_after`>> parameter.
|
|
|
|
`sort`::
|
|
(Optional, object) <<sort-search-results,Sort definition>>. Other than `id`,
|
|
all public fields of an API key are eligible for sorting. In addition, sort can
|
|
also be applied to the `_doc` field to sort by index order.
|
|
|
|
`search_after`::
|
|
(Optional, array) <<search-after,Search after>> definition.
|
|
|
|
|
|
[[security-api-query-api-key-response-body]]
|
|
==== {api-response-body-title}
|
|
|
|
This API returns the following top level fields:
|
|
|
|
`total`::
|
|
The total number of API keys found.
|
|
|
|
`count`::
|
|
The number of API keys returned in the response.
|
|
|
|
`api_keys`::
|
|
A list of API key information.
|
|
|
|
[[security-api-query-api-key-example]]
|
|
==== {api-examples-title}
|
|
|
|
The following request lists all API keys, assuming you have the
|
|
`manage_api_key` privilege:
|
|
|
|
[source,console]
|
|
----
|
|
GET /_security/_query/api_key
|
|
----
|
|
|
|
A successful call returns a JSON structure that contains the information
|
|
retrieved from one or more API keys:
|
|
|
|
[source,js]
|
|
----
|
|
{
|
|
"total": 3,
|
|
"count": 3,
|
|
"api_keys": [ <1>
|
|
{
|
|
"id": "nkvrGXsB8w290t56q3Rg",
|
|
"name": "my-api-key-1",
|
|
"creation": 1628227480421,
|
|
"expiration": 1629091480421,
|
|
"invalidated": false,
|
|
"username": "elastic",
|
|
"realm": "reserved",
|
|
"realm_type": "reserved",
|
|
"metadata": {
|
|
"letter": "a"
|
|
},
|
|
"role_descriptors": { <2>
|
|
"role-a": {
|
|
"cluster": [
|
|
"monitor"
|
|
],
|
|
"indices": [
|
|
{
|
|
"names": [
|
|
"index-a"
|
|
],
|
|
"privileges": [
|
|
"read"
|
|
],
|
|
"allow_restricted_indices": false
|
|
}
|
|
],
|
|
"applications": [ ],
|
|
"run_as": [ ],
|
|
"metadata": { },
|
|
"transient_metadata": {
|
|
"enabled": true
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"id": "oEvrGXsB8w290t5683TI",
|
|
"name": "my-api-key-2",
|
|
"creation": 1628227498953,
|
|
"expiration": 1628313898953,
|
|
"invalidated": false,
|
|
"username": "elastic",
|
|
"realm": "reserved",
|
|
"metadata": {
|
|
"letter": "b"
|
|
},
|
|
"role_descriptors": { } <3>
|
|
}
|
|
]
|
|
}
|
|
----
|
|
// NOTCONSOLE
|
|
|
|
<1> The list of API keys that were retrieved for this request
|
|
<2> The role descriptors that are assigned to this API key when it was <<api-key-role-descriptors,created>>
|
|
or last <<security-api-update-api-key-api-key-role-descriptors,updated>>. Note the API key's
|
|
effective permissions are an intersection of its assigned privileges and the point-in-time snapshot of
|
|
the owner user's permissions.
|
|
<3> An empty role descriptors means the API key inherits the owner user's permissions.
|
|
|
|
If you create an API key with the following details:
|
|
|
|
[source,console]
|
|
----
|
|
POST /_security/api_key
|
|
{
|
|
"name": "application-key-1",
|
|
"metadata": { "application": "my-application"}
|
|
}
|
|
----
|
|
|
|
A successful call returns a JSON structure that provides
|
|
API key information. For example:
|
|
|
|
[source,console-result]
|
|
----
|
|
{
|
|
"id": "VuaCfGcBCdbkQm-e5aOx",
|
|
"name": "application-key-1",
|
|
"api_key": "ui2lp2axTNmsyakw9tvNnw",
|
|
"encoded": "VnVhQ2ZHY0JDZGJrUW0tZTVhT3g6dWkybHAyYXhUTm1zeWFrdzl0dk5udw=="
|
|
}
|
|
----
|
|
// TESTRESPONSE[s/VuaCfGcBCdbkQm-e5aOx/$body.id/]
|
|
// TESTRESPONSE[s/ui2lp2axTNmsyakw9tvNnw/$body.api_key/]
|
|
// TESTRESPONSE[s/VnVhQ2ZHY0JDZGJrUW0tZTVhT3g6dWkybHAyYXhUTm1zeWFrdzl0dk5udw==/$body.encoded/]
|
|
|
|
Use the information from the response to retrieve the API key by ID:
|
|
|
|
[source,console]
|
|
----
|
|
GET /_security/_query/api_key?with_limited_by=true
|
|
{
|
|
"query": {
|
|
"ids": {
|
|
"values": [
|
|
"VuaCfGcBCdbkQm-e5aOx"
|
|
]
|
|
}
|
|
}
|
|
}
|
|
----
|
|
// TEST[s/VuaCfGcBCdbkQm-e5aOx/$body.id/]
|
|
// TEST[continued]
|
|
|
|
A successful call returns a JSON structure for API key information including its limited-by role descriptors:
|
|
|
|
[source,js]
|
|
--------------------------------------------------
|
|
{
|
|
"api_keys": [
|
|
{
|
|
"id": "VuaCfGcBCdbkQm-e5aOx",
|
|
"name": "application-key-1",
|
|
"creation": 1548550550158,
|
|
"expiration": 1548551550158,
|
|
"invalidated": false,
|
|
"username": "myuser",
|
|
"realm": "native1",
|
|
"realm_type": "native",
|
|
"metadata": {
|
|
"application": "my-application"
|
|
},
|
|
"role_descriptors": { },
|
|
"limited_by": [ <1>
|
|
{
|
|
"role-power-user": {
|
|
"cluster": [
|
|
"monitor"
|
|
],
|
|
"indices": [
|
|
{
|
|
"names": [
|
|
"*"
|
|
],
|
|
"privileges": [
|
|
"read"
|
|
],
|
|
"allow_restricted_indices": false
|
|
}
|
|
],
|
|
"applications": [ ],
|
|
"run_as": [ ],
|
|
"metadata": { },
|
|
"transient_metadata": {
|
|
"enabled": true
|
|
}
|
|
}
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
--------------------------------------------------
|
|
// NOTCONSOLE
|
|
<1> The owner user's permissions associated with the API key.
|
|
It is a point-in-time snapshot captured at <<security-api-create-api-key,creation>> and
|
|
subsequent <<security-api-update-api-key,updates>>. An API key's
|
|
effective permissions are an intersection of its assigned privileges and
|
|
the owner user's permissions.
|
|
|
|
You can also retrieve the API key by name:
|
|
|
|
[source,console]
|
|
----
|
|
GET /_security/_query/api_key
|
|
{
|
|
"query": {
|
|
"term": {
|
|
"name": {
|
|
"value": "application-key-1"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
----
|
|
// TEST[continued]
|
|
|
|
Use a `bool` query to issue complex logical conditions and use
|
|
`from`, `size`, `sort` to help paginate the result:
|
|
|
|
[source,js]
|
|
----
|
|
GET /_security/_query/api_key
|
|
{
|
|
"query": {
|
|
"bool": {
|
|
"must": [
|
|
{
|
|
"prefix": {
|
|
"name": "app1-key-" <1>
|
|
}
|
|
},
|
|
{
|
|
"term": {
|
|
"invalidated": "false" <2>
|
|
}
|
|
}
|
|
],
|
|
"must_not": [
|
|
{
|
|
"term": {
|
|
"name": "app1-key-01" <3>
|
|
}
|
|
}
|
|
],
|
|
"filter": [
|
|
{
|
|
"wildcard": {
|
|
"username": "org-*-user" <4>
|
|
}
|
|
},
|
|
{
|
|
"term": {
|
|
"metadata.environment": "production" <5>
|
|
}
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"from": 20, <6>
|
|
"size": 10, <7>
|
|
"sort": [ <8>
|
|
{ "creation": { "order": "desc", "format": "date_time" } },
|
|
"name"
|
|
]
|
|
}
|
|
----
|
|
// NOTCONSOLE
|
|
|
|
<1> The API key name must begin with `app1-key-`
|
|
<2> The API key must still be valid
|
|
<3> The API key name must not be `app1-key-01`
|
|
<4> The API key must be owned by a username of the <<query-dsl-wildcard-query,wildcard>> pattern `org-*-user`
|
|
<5> The API key must have the metadata field `environment` that has the value of `production`
|
|
<6> The offset to begin the search result is the 20th (zero-based index) API key
|
|
<7> The page size of the response is 10 API keys
|
|
<8> The result is first sorted by `creation` date in descending order, then by name in ascending order
|
|
|
|
The response contains a list of matched API keys along with their sort values:
|
|
|
|
[source,js]
|
|
----
|
|
{
|
|
"total": 100,
|
|
"count": 10,
|
|
"api_keys": [
|
|
{
|
|
"id": "CLXgVnsBOGkf8IyjcXU7",
|
|
"name": "app1-key-79",
|
|
"creation": 1629250154811,
|
|
"invalidated": false,
|
|
"username": "org-admin-user",
|
|
"realm": "native1",
|
|
"metadata": {
|
|
"environment": "production"
|
|
},
|
|
"role_descriptors": { },
|
|
"_sort": [
|
|
"2021-08-18T01:29:14.811Z", <1>
|
|
"app1-key-79" <2>
|
|
]
|
|
},
|
|
{
|
|
"id": "BrXgVnsBOGkf8IyjbXVB",
|
|
"name": "app1-key-78",
|
|
"creation": 1629250153794,
|
|
"invalidated": false,
|
|
"username": "org-admin-user",
|
|
"realm": "native1",
|
|
"metadata": {
|
|
"environment": "production"
|
|
},
|
|
"role_descriptors": { },
|
|
"_sort": [
|
|
"2021-08-18T01:29:13.794Z",
|
|
"app1-key-78"
|
|
]
|
|
},
|
|
...
|
|
]
|
|
}
|
|
----
|
|
// NOTCONSOLE
|
|
|
|
<1> The first sort value is creation time, which is displayed in `date_time` <<mapping-date-format,format>> as defined in the request
|
|
<2> The second sort value is the API key name
|
|
|
|
[[security-api-query-api-key-with-aggs-example]]
|
|
==== Aggregations Example
|
|
|
|
For example, given 2 users "june" and "king", each owning 3 API keys:
|
|
|
|
* one that never expires (invalidated for user "king")
|
|
* one that expires in 10 days
|
|
* and one that expires in 100 day (invalidated for user "june")
|
|
|
|
the following request returns the names of valid (not expired and not invalidated) API keys
|
|
that expire soon (in 30 days time), grouped by owner username.
|
|
|
|
===== Request
|
|
|
|
[source,console]
|
|
----
|
|
POST /_security/_query/api_key
|
|
{
|
|
"size": 0,
|
|
"query": {
|
|
"bool": {
|
|
"must": {
|
|
"term": {
|
|
"invalidated": false <1>
|
|
}
|
|
},
|
|
"should": [ <2>
|
|
{
|
|
"range": { "expiration": { "gte": "now" } }
|
|
},
|
|
{
|
|
"bool": { "must_not": { "exists": { "field": "expiration" } } }
|
|
}
|
|
],
|
|
"minimum_should_match": 1
|
|
}
|
|
},
|
|
"aggs": {
|
|
"keys_by_username": {
|
|
"composite": {
|
|
"sources": [ { "usernames": { "terms": { "field": "username" } } } ] <3>
|
|
},
|
|
"aggs": {
|
|
"expires_soon": {
|
|
"filter": {
|
|
"range": { "expiration": { "lte": "now+30d/d" } } <4>
|
|
},
|
|
"aggs": {
|
|
"key_names": { "terms": { "field": "name" } }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
----
|
|
|
|
<1> Matching API keys must not be invalidated
|
|
<2> Matching API keys must be either not expired or not have an expiration date
|
|
<3> Aggregate all matching keys (i.e. all valid keys) by their owner username
|
|
<4> Further aggregate the per-username valid keys into a soon-to-expire bucket
|
|
|
|
===== Response
|
|
|
|
[source,console-result]
|
|
----
|
|
{
|
|
"total" : 4, <1>
|
|
"count" : 0,
|
|
"api_keys" : [ ],
|
|
"aggregations" : {
|
|
"keys_by_username" : {
|
|
"after_key" : {
|
|
"usernames" : "king"
|
|
},
|
|
"buckets" : [
|
|
{
|
|
"key" : {
|
|
"usernames" : "june"
|
|
},
|
|
"doc_count" : 2, <2>
|
|
"expires_soon" : {
|
|
"doc_count" : 1,
|
|
"key_names" : {
|
|
"doc_count_error_upper_bound" : 0,
|
|
"sum_other_doc_count" : 0,
|
|
"buckets" : [
|
|
{
|
|
"key" : "june-key-10",
|
|
"doc_count" : 1
|
|
}
|
|
]
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"key" : {
|
|
"usernames" : "king"
|
|
},
|
|
"doc_count" : 2,
|
|
"expires_soon" : {
|
|
"doc_count" : 1, <3>
|
|
"key_names" : {
|
|
"doc_count_error_upper_bound" : 0,
|
|
"sum_other_doc_count" : 0,
|
|
"buckets" : [ <4>
|
|
{
|
|
"key" : "king-key-10",
|
|
"doc_count" : 1
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
----
|
|
|
|
<1> Total number of valid API keys (2 for each user)
|
|
<2> Number of valid API keys for user "june"
|
|
<3> Number of valid API keys expiring soon for user "king"
|
|
<4> The names of soon-to-expire API keys for user "king"
|
|
|
|
To retrieve the invalidated (but not yet deleted) API keys,
|
|
grouped by owner username and API key name, issue the following request:
|
|
|
|
===== Request
|
|
|
|
[source,console]
|
|
----
|
|
POST /_security/_query/api_key
|
|
{
|
|
"size": 0,
|
|
"query": {
|
|
"bool": {
|
|
"filter": {
|
|
"term": {
|
|
"invalidated": true
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"aggs": {
|
|
"invalidated_keys": {
|
|
"composite": {
|
|
"sources": [
|
|
{ "username": { "terms": { "field": "username" } } },
|
|
{ "key_name": { "terms": { "field": "name" } } }
|
|
]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
----
|
|
|
|
===== Response
|
|
|
|
[source,console-result]
|
|
----
|
|
{
|
|
"total" : 2,
|
|
"count" : 0,
|
|
"api_keys" : [ ],
|
|
"aggregations" : {
|
|
"invalidated_keys" : {
|
|
"after_key" : {
|
|
"username" : "king",
|
|
"key_name" : "king-key-no-expire"
|
|
},
|
|
"buckets" : [
|
|
{
|
|
"key" : {
|
|
"username" : "june",
|
|
"key_name" : "june-key-100"
|
|
},
|
|
"doc_count" : 1
|
|
},
|
|
{
|
|
"key" : {
|
|
"username" : "king",
|
|
"key_name" : "king-key-no-expire"
|
|
},
|
|
"doc_count" : 1
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
----
|