您如何在 AWS API 调用中使用 "NextToken"

How do you use "NextToken" in AWS API calls

我 运行 遇到了一个小问题,我真的很难理解它是如何工作的。我有一个我正在编写的工具,它基本上执行一个描述组织来收集我们 AWS 组织中的所有帐户。根据文档 here,它表示它以 json 个帐户进行响应,在我的情况下,这将是成百上千个帐户。所以我写了一些非常简单的代码来将角色切换到我们的主帐户并拨打电话:

import boto3
import uuid
import pprint

iam_client = boto3.client('iam')
sts_client = boto3.client('sts')
org_client = boto3.client('organizations')


print("Starting in account: %s" % sts_client.get_caller_identity().get('Account'))

assumedRoleObject = sts_client.assume_role(
    RoleArn="arn:aws:iam::123456xxx:role/MsCrossAccountAccessRole",
    RoleSessionName="MasterPayer"
)

credentials = assumedRoleObject['Credentials']

org_client = boto3.client(
    'organizations',
    aws_access_key_id = credentials['AccessKeyId'],
    aws_secret_access_key = credentials['SecretAccessKey'],
    aws_session_token = credentials['SessionToken'],
)

getListAccounts = org_client.list_accounts(
    NextToken='string'
)

但是当我执行代码时,出现以下错误:

"botocore.errorfactory.InvalidInputException: An error occurred (InvalidInputException) when calling the ListAccounts operation: You specified an invalid value for nextToken. You must get the value from the response to a previous call to the API."

我真的不知道那是什么意思。我看到了 NextToken,我可以在 AWS 文档中找到很多对它的引用,但我不知道如何实际使用它。比如,我需要用它做什么?

不要从字面上理解 boto3 示例(它们不是实际示例)。这是它的工作原理:

1) 第一次调用 list_accounts 时不需要 NextToken,所以只需

getListAccounts = org_client.list_accounts()

2) 这将 return 一个 JSON 大致如下所示的响应(这是保存在您的 getListAccounts 变量中的内容):

{
    "Accounts": [<lots of accounts information>], 
    "NextToken": <some token>
}

请注意,NextToken 仅被 return 编辑,以防您的帐户多于一个 list_accounts 调用可以 return,通常是 100 (boto3 文档没有说明默认有多少)。如果所有帐户都在一次调用中 returned,则响应中没有 NextToken

3) 因此,当且仅当并非所有帐户都在第一次调用中被 return 编辑时,您现在想要 return 更多帐户,并且您将不得不使用 NextToken为了做到这一点:

getListAccountsMore = org_client.list_accounts(NextToken=getListAccounts['NextToken'])

4) 重复直到没有 NextToken 被 return 编辑在响应中(然后你检索了所有帐户)。

这就是 AWS SDK 在许多情况下处理分页的方式。您还将在其他服务客户端中看到 NextToken 的用法。

这里是我使用 NextToken 来检查 SecretManager 中是否存在秘密的示例。 还有一些印刷品对第一次可视化很有用

def check_if_secret_existv2(username):
    results_for_call=5
    response = client.list_secrets(MaxResults=results_for_call)
    i=0
    while True:
        i=i+1
        if 'NextToken' in response:
            response = client.list_secrets(MaxResults=results_for_call,NextToken=response['NextToken'])
        else:
            response = client.list_secrets(MaxResults=results_for_call)

        for secret in response['SecretList']:
            print(secret['Name'])
            if secret['Name'] == username:
                return True
        print('End cycle '+str(i))

        if 'NextToken' not in response:
            break
    return False

print(check_if_secret_existv2(myusername))

您可以使用 get_paginator api。 找到下面的示例,在我的用例中,我必须获取 SSM 参数存储的所有值,并想将其与字符串进行比较。

import boto3
import sys

LBURL = sys.argv[1].strip()
client = boto3.client('ssm')
p = client.get_paginator('describe_parameters')
paginator = p.paginate().build_full_result()
for page in paginator['Parameters']:
    response = client.get_parameter(Name=page['Name'])
    value = response['Parameter']['Value']
    if LBURL in value:
        print("Name is: " + page['Name'] + " and Value is: " + value)

我知道这是一个不同的客户端,但对于仍然有问题的任何人,我花了一些时间才弄明白:

此客户端还要求包含初始请求参数。这是代码:

import boto3

lex_client = boto3.client("lex-models")
response = lex_client.get_slot_types(
    nameContains='search_string',
    maxResults=50
)
slot_types = response['slotTypes']
while 'nextToken' in response.keys():
    response = lex_client.get_slot_types(nameContains='search_string', maxResults=50, nextToken=response['nextToken'])
    slot_types.extend(response['slotTypes'])
print('here are the slot types', slot_types)

与其他答案相同,但有一个带有简单 while 循环的简短片段。

response = client.list_accounts()
results = response["Accounts"]
while "NextToken" in response:
    response = client.list_accounts(NextToken=response["NextToken"])
    results.extend(response["Accounts"])

我尝试使用 boto3 在我的机密管理器中列出机密名称 python:

secrets = secret_client.list_secrets()
secrets_manager = (secrets['SecretList'])

for secret in secrets_manager: 
    print ("{0}".format(secret['Name']))

完整列表大约有 20 个,但输出的秘密名称只有 5 个。

将代码更新为以下,有效:

secrets = secret_client.list_secrets()
secrets_manager = (secrets['SecretList'])

while "NextToken" in secrets:
    secrets = secret_client.list_secrets(NextToken=secrets["NextToken"])
    secrets_manager.extend(secrets['SecretList'])

for secret in secrets_manager: 
    print ("{0}".format(secret['Name']))