查询 API 密钥信息 API

编辑

查询 DSL 方式,分页检索 API 密钥的信息。

请求

编辑

GET /_security/_query/api_key

POST /_security/_query/api_key

先决条件

编辑
  • 要使用此 API,您必须至少具有 manage_own_api_keyread_security 集群权限。
  • 如果您只有 manage_own_api_key 权限,则此 API 仅返回您拥有的 API 密钥。如果您具有 read_securitymanage_api_key 或更高的权限(包括 manage_security),则此 API 将返回所有 API 密钥,无论所有权如何。

描述

编辑

使用此 API 以分页方式检索使用 创建 API 密钥 API 创建的 API 密钥。您可以选择使用查询来过滤结果。

路径参数

编辑
with_limited_by
(可选,布尔值)一个布尔标志,用于返回与 API 密钥关联的所有者用户的角色描述符快照。API 密钥的实际权限是其已分配的角色描述符与所有者用户的角色描述符(有效地受其限制)的交集。除非 API 密钥具有 manage_api_key 或更高的权限,否则它无法检索任何 API 密钥的 limited-by 角色描述符(包括其自身)。
with_profile_uid
(可选,布尔值)确定是否也检索 API 密钥所有者用户的用户配置文件 uid。如果存在,则配置文件 uid 将在每个 API 密钥的 profile_uid 响应字段下返回。默认为 false
typed_keys
(可选,布尔值)如果为 true,则聚合名称在响应中会加上各自的类型前缀。默认为 false

请求正文

编辑

您可以在请求正文中指定以下参数

query

(可选,对象)用于筛选要返回的 API 密钥的查询。如果缺少 query 参数,则等效于 match_all 查询。该查询支持查询类型的子集,包括 match_allbooltermtermsmatchidsprefixwildcardexistsrangesimple query string

您可以查询与 API 密钥关联的以下公共值。

与 API 密钥关联的可查询字符串值在内部映射为 keywords。因此,如果未为 match 查询指定 analyzer 参数,则提供的 match 查询字符串将被解释为单个关键字值。因此,此类 match 查询等效于 term 查询。

query 的有效值
id
API 密钥的 ID。请注意,必须使用 ids 查询来查询 id
type
如果 API 密钥是通过 创建 API 密钥授予 API 密钥 API 创建的,则 API 密钥的类型可以为 rest;如果通过 创建跨集群 API 密钥 API 创建的,则类型可以为 cross_cluster
name
API 密钥的名称。
creation
API 密钥的创建时间(以毫秒为单位)。
expiration
API 密钥的过期时间(以毫秒为单位)。如果未配置密钥过期,则为 null
invalidated
指示 API 密钥是否已失效。如果为 true,则密钥失效。默认为 false
invalidation
API 密钥的失效时间(以毫秒为单位)。此字段仅针对失效的 API 密钥设置。
username
API 密钥所有者的用户名。
realm
API 密钥所有者的领域名称。
metadata
与 API 密钥关联的元数据字段,例如 metadata.my_field。元数据在内部以扁平化字段类型进行索引。这意味着在查询和排序时,所有字段的行为都类似于 keyword 字段。即使对于支持字段名称模式的查询类型,也无法使用通配符模式(例如 metadata.field*)来引用元数据字段的子集。最后,当仅提及 metadata(后跟任何点和子字段名称)时,可以一起搜索所有元数据字段。

您无法查询 API 密钥的角色描述符。

aggsaggregations
(可选,对象)在返回的 API 密钥主体上运行的任何聚合。聚合和查询协同工作。聚合仅在与查询匹配的 API 密钥上计算。这仅支持聚合类型的子集,即:词项范围日期范围缺失基数值计数复合过滤器过滤器。此外,聚合仅在 query 使用的相同字段子集上运行。
from

(可选,整数)起始文档偏移量。必须为非负数,默认为 0

默认情况下,您不能使用 fromsize 参数分页超过 10,000 个命中。要分页浏览更多命中,请使用search_after参数。

size

(可选,整数)要返回的命中数。不得为负数,默认为 10size 参数可以设置为 0,在这种情况下,将不返回 API 密钥匹配,而仅返回聚合结果。

默认情况下,您不能使用 fromsize 参数分页超过 10,000 个命中。要分页浏览更多命中,请使用search_after参数。

sort
(可选,对象)排序定义。除了 id 之外,API 密钥的所有公共字段都适合排序。此外,排序还可以应用于 _doc 字段以按索引顺序排序。
search_after
(可选,数组)Search after 定义。

响应正文

编辑

此 API 返回以下顶级字段

total
找到的 API 密钥总数。
count
响应中返回的 API 密钥数。
api_keys
API 密钥信息列表。

示例

编辑

以下请求列出所有 API 密钥,假设您具有 manage_api_key 权限

resp = client.security.query_api_keys()
print(resp)
const response = await client.security.queryApiKeys();
console.log(response);
GET /_security/_query/api_key

成功的调用会返回一个 JSON 结构,其中包含从一个或多个 API 密钥检索的信息

{
  "total": 3,
  "count": 3,
  "api_keys": [ 
    {
      "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": { 
        "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": { } 
    }
  ]
}

为此请求检索的 API 密钥列表

创建或上次更新时分配给此 API 密钥的角色描述符。请注意,API 密钥的有效权限是其已分配的权限与所有者用户的权限的瞬时快照的交集。

空的角色描述符表示 API 密钥继承所有者用户的权限。

如果您使用以下详细信息创建 API 密钥

resp = client.security.create_api_key(
    name="application-key-1",
    metadata={
        "application": "my-application"
    },
)
print(resp)
const response = await client.security.createApiKey({
  name: "application-key-1",
  metadata: {
    application: "my-application",
  },
});
console.log(response);
POST /_security/api_key
{
  "name": "application-key-1",
  "metadata": { "application": "my-application"}
}

成功的调用会返回一个 JSON 结构,其中提供了 API 密钥信息。例如

{
  "id": "VuaCfGcBCdbkQm-e5aOx",
  "name": "application-key-1",
  "api_key": "ui2lp2axTNmsyakw9tvNnw",
  "encoded": "VnVhQ2ZHY0JDZGJrUW0tZTVhT3g6dWkybHAyYXhUTm1zeWFrdzl0dk5udw=="
}

使用响应中的信息按 ID 检索 API 密钥

resp = client.security.query_api_keys(
    with_limited_by=True,
    query={
        "ids": {
            "values": [
                "VuaCfGcBCdbkQm-e5aOx"
            ]
        }
    },
)
print(resp)
const response = await client.security.queryApiKeys({
  with_limited_by: "true",
  query: {
    ids: {
      values: ["VuaCfGcBCdbkQm-e5aOx"],
    },
  },
});
console.log(response);
GET /_security/_query/api_key?with_limited_by=true
{
  "query": {
    "ids": {
      "values": [
        "VuaCfGcBCdbkQm-e5aOx"
      ]
    }
  }
}

成功的调用会返回 API 密钥信息的 JSON 结构,包括其 limited-by 角色描述符

{
  "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": [ 
        {
          "role-power-user": {
            "cluster": [
              "monitor"
            ],
            "indices": [
              {
                "names": [
                  "*"
                ],
                "privileges": [
                  "read"
                ],
                "allow_restricted_indices": false
              }
            ],
            "applications": [ ],
            "run_as": [ ],
            "metadata": { },
            "transient_metadata": {
              "enabled": true
            }
          }
        }
      ]
    }
  ]
}

与 API 密钥关联的所有者用户的权限。它是创建和后续更新时捕获的瞬时快照。API 密钥的有效权限是其已分配的权限与所有者用户的权限的交集。

您还可以按名称检索 API 密钥

resp = client.security.query_api_keys(
    query={
        "term": {
            "name": {
                "value": "application-key-1"
            }
        }
    },
)
print(resp)
const response = await client.security.queryApiKeys({
  query: {
    term: {
      name: {
        value: "application-key-1",
      },
    },
  },
});
console.log(response);
GET /_security/_query/api_key
{
  "query": {
    "term": {
      "name": {
        "value": "application-key-1"
      }
    }
  }
}

使用 bool 查询发出复杂的逻辑条件,并使用 fromsizesort 来帮助对结果进行分页

GET /_security/_query/api_key
{
  "query": {
    "bool": {
      "must": [
        {
          "prefix": {
            "name": "app1-key-" 
          }
        },
        {
          "term": {
            "invalidated": "false" 
          }
        }
      ],
      "must_not": [
        {
          "term": {
            "name": "app1-key-01" 
          }
        }
      ],
      "filter": [
        {
          "wildcard": {
            "username": "org-*-user" 
          }
        },
        {
          "term": {
            "metadata.environment": "production" 
          }
        }
      ]
    }
  },
  "from": 20, 
  "size": 10, 
  "sort": [ 
    { "creation": { "order": "desc", "format": "date_time" } },
    "name"
  ]
}

API 密钥名称必须以 app1-key- 开头

API 密钥必须仍然有效

API 密钥名称不能是 app1-key-01

API 密钥的所有者用户名必须符合 通配符 模式 org-*-user

API 密钥必须具有元数据字段 environment,其值为 production

搜索结果的起始偏移量是第 20 个(从零开始的索引)API 密钥

响应的页面大小为 10 个 API 密钥

结果首先按 creation 日期降序排序,然后按名称升序排序

响应包含匹配的 API 密钥列表及其排序值

{
  "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",  
        "app1-key-79"  
      ]
    },
    {
      "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"
      ]
    },
    ...
  ]
}

第一个排序值是创建时间,以请求中定义的 date_time 格式 显示

第二个排序值是 API 密钥名称

聚合示例

编辑

例如,假设有 2 个用户 "june" 和 "king",每个用户拥有 3 个 API 密钥

  • 一个永不过期(对用户 "king" 无效)
  • 一个在 10 天后过期
  • 一个在 100 天后过期(对用户 "june" 无效)

以下请求返回将在不久后(30 天内)过期的有效(未过期且未失效)API 密钥的名称,并按所有者用户名分组。

请求

编辑
resp = client.security.query_api_keys(
    size=0,
    query={
        "bool": {
            "must": {
                "term": {
                    "invalidated": False
                }
            },
            "should": [
                {
                    "range": {
                        "expiration": {
                            "gte": "now"
                        }
                    }
                },
                {
                    "bool": {
                        "must_not": {
                            "exists": {
                                "field": "expiration"
                            }
                        }
                    }
                }
            ],
            "minimum_should_match": 1
        }
    },
    aggs={
        "keys_by_username": {
            "composite": {
                "sources": [
                    {
                        "usernames": {
                            "terms": {
                                "field": "username"
                            }
                        }
                    }
                ]
            },
            "aggs": {
                "expires_soon": {
                    "filter": {
                        "range": {
                            "expiration": {
                                "lte": "now+30d/d"
                            }
                        }
                    },
                    "aggs": {
                        "key_names": {
                            "terms": {
                                "field": "name"
                            }
                        }
                    }
                }
            }
        }
    },
)
print(resp)
const response = await client.security.queryApiKeys({
  size: 0,
  query: {
    bool: {
      must: {
        term: {
          invalidated: false,
        },
      },
      should: [
        {
          range: {
            expiration: {
              gte: "now",
            },
          },
        },
        {
          bool: {
            must_not: {
              exists: {
                field: "expiration",
              },
            },
          },
        },
      ],
      minimum_should_match: 1,
    },
  },
  aggs: {
    keys_by_username: {
      composite: {
        sources: [
          {
            usernames: {
              terms: {
                field: "username",
              },
            },
          },
        ],
      },
      aggs: {
        expires_soon: {
          filter: {
            range: {
              expiration: {
                lte: "now+30d/d",
              },
            },
          },
          aggs: {
            key_names: {
              terms: {
                field: "name",
              },
            },
          },
        },
      },
    },
  },
});
console.log(response);
POST /_security/_query/api_key
{
  "size": 0,
  "query": {
    "bool": {
      "must": {
        "term": {
          "invalidated": false  
        }
      },
      "should": [  
        {
          "range": { "expiration": { "gte": "now" } }
        },
        {
          "bool": { "must_not": { "exists": { "field": "expiration" } } }
        }
      ],
      "minimum_should_match": 1
    }
  },
  "aggs": {
    "keys_by_username": {
      "composite": {
        "sources": [ { "usernames": { "terms": { "field": "username" } } } ]  
      },
      "aggs": {
        "expires_soon": {
          "filter": {
            "range": { "expiration": { "lte": "now+30d/d" } }  
          },
          "aggs": {
            "key_names": { "terms": { "field": "name" } }
          }
        }
      }
    }
  }
}

匹配的 API 密钥必须未失效

匹配的 API 密钥必须未过期或没有过期日期

按所有者用户名聚合所有匹配的密钥(即所有有效密钥)

进一步将每个用户名的有效密钥聚合到即将过期的存储桶中

响应

编辑
{
  "total" : 4,  
  "count" : 0,
  "api_keys" : [ ],
  "aggregations" : {
    "keys_by_username" : {
      "after_key" : {
        "usernames" : "king"
      },
      "buckets" : [
        {
          "key" : {
            "usernames" : "june"
          },
          "doc_count" : 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,  
            "key_names" : {
              "doc_count_error_upper_bound" : 0,
              "sum_other_doc_count" : 0,
              "buckets" : [  
                {
                  "key" : "king-key-10",
                  "doc_count" : 1
                }
              ]
            }
          }
        }
      ]
    }
  }
}

有效 API 密钥的总数(每个用户 2 个)

用户 "june" 的有效 API 密钥数量

用户 "king" 即将过期的有效 API 密钥数量

用户 "king" 即将过期的 API 密钥名称

要检索按所有者用户名和 API 密钥名称分组的失效(但尚未删除)的 API 密钥,请发出以下请求

请求

编辑
resp = client.security.query_api_keys(
    size=0,
    query={
        "bool": {
            "filter": {
                "term": {
                    "invalidated": True
                }
            }
        }
    },
    aggs={
        "invalidated_keys": {
            "composite": {
                "sources": [
                    {
                        "username": {
                            "terms": {
                                "field": "username"
                            }
                        }
                    },
                    {
                        "key_name": {
                            "terms": {
                                "field": "name"
                            }
                        }
                    }
                ]
            }
        }
    },
)
print(resp)
const response = await client.security.queryApiKeys({
  size: 0,
  query: {
    bool: {
      filter: {
        term: {
          invalidated: true,
        },
      },
    },
  },
  aggs: {
    invalidated_keys: {
      composite: {
        sources: [
          {
            username: {
              terms: {
                field: "username",
              },
            },
          },
          {
            key_name: {
              terms: {
                field: "name",
              },
            },
          },
        ],
      },
    },
  },
});
console.log(response);
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" } } }
        ]
      }
    }
  }
}

响应

编辑
{
  "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
        }
      ]
    }
  }
}