您如何在AWS API调用中使用“ NextToken”

时间:2018-08-29 00:57:15

标签: python amazon-web-services boto3 aws-organizations

我遇到了一个小问题,我真的很难理解它的工作原理。我有一个正在编写的工具,该工具基本上进行描述组织来收集我们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:调用ListAccounts操作时发生错误(InvalidInputException):您为nextToken指定了一个无效值。您必须从响应中获取该值,以响应上一次对API的调用。”

我真的对这意味着什么感到困惑。我看到了NextToken,并且可以在AWS文档中找到许多对它的引用,但是我不知道如何实际使用它。就像,我需要做什么?

6 个答案:

答案 0 :(得分:4)

不要直接使用boto3示例(它们不是实际示例)。这是这样的:

1)第一次调用list_accounts时,您将不用NextToken进行通话,因此简单地

getListAccounts = org_client.list_accounts()

2)这将返回一个大致像这样的JSON响应(这是保存在getListAccounts变量中的内容):

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

请注意,NextToken仅在您拥有的帐户数量超过一个list_accounts调用可以返回的情况下才返回,通常是100(boto3文档未说明默认情况下有多少个) )。如果一次调用返回了所有帐户,则响应中将没有NextToken

3)因此,当且仅当在第一次通话中未返回所有帐户时,您现在才想返回更多帐户,并且您必须使用NextToken才能做到这一点:

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

4)重复直到响应中不再返回NextToken(然后您检索了所有帐户)。

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

答案 1 :(得分:2)

您可以使用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)

答案 2 :(得分:1)

在我的示例中,我使用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))

答案 3 :(得分:1)

与其他答案相同,但是带有一个简单的var mylist = new List<string> { "A", "A", "B", "B", "B", "C", "C", "D" }; var result = mylist.GroupBy(x => x) .Select(x => x.OrderBy(x => x).Take(1)) .SelectMany(x => x) .ToList(); 循环的简短摘要。

while

答案 4 :(得分:1)

我尝试使用 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']))

答案 5 :(得分:0)

我知道这是一个不同的客户,但是对于仍然遇到问题的任何人,我花了一些时间来弄清楚:

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

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)