You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Boto3 createAccessKey生成的凭证调用API失败问题排查

问题描述

我要写一个Python程序,流程是:用用户A的凭证调用部分API → 为用户B创建访问密钥 → 用新生成的密钥调用GetCallerIdentity API。但直接用createAccessKey返回的密钥时,一直收到错误:

Traceback (most recent call last):
  File "mock.py", line 142, in <module>
    main()
  File "mock.py", line 130, in main
    print(client1.get_caller_identity())
  File "/home/joe/.local/lib/python3.8/site-packages/botocore/client.py", line 535, in _api_call
    return self._make_api_call(operation_name, kwargs)
  File "/home/joe/.local/lib/python3.8/site-packages/botocore/client.py", line 980, in _make_api_call
    raise error_class(parsed_response, operation_name)
botocore.exceptions.ClientError: An error occurred (InvalidClientTokenId) when calling the GetCallerIdentity operation: The security token included in the request is invalid.

但如果手动把createAccessKey生成的密钥硬编码到程序里(取消下面代码注释并填入密钥),程序就能正常运行:

# NOTE: manually put in the key id and access key created by the createAccessKey call above
#cred_new = credential('', '', None)

完整程序代码:

import boto3
import time

class credential:
    aws_access_key_id = ''
    aws_secret_access_key = ''
    aws_session_token = ''

    def __init__(self, aws_access_key_id, aws_secret_access_key, aws_session_token=None) -> None:
        self.aws_access_key_id = aws_access_key_id
        self.aws_secret_access_key = aws_secret_access_key
        self.aws_session_token = aws_session_token


def initialize_each_service(cred, service_name):
    client = boto3.client(
        service_name = service_name, 
        aws_access_key_id=cred.aws_access_key_id, 
        aws_secret_access_key=cred.aws_secret_access_key,
        aws_session_token=cred.aws_session_token
    )
    return client


def initialize_clients(client_map, cred):
    # TODO: read keys from a file
    # Initialize the AWS STS (Security Token Service) client
    service_list = ['sts', 'iam', 'guardduty']
    for service_name in service_list:
        client_map[service_name] = initialize_each_service(cred, service_name)
    return client_map


def get_caller_identity(client_map):
    response = client_map['sts'].get_caller_identity()
    # Get the caller identity

    # Extract and print the caller identity information
    account_id = response['Account']
    arn = response['Arn']

    print(f"AWS Account ID: {account_id}")
    print(f"Caller ARN: {arn}")


def create_access_key(client_map, target_user_name):
    # Create an access key for the IAM user
    response = client_map['iam'].create_access_key(UserName=target_user_name)
    print(response)
    # Extract and print the access key information
    access_key_id = response['AccessKey']['AccessKeyId']
    secret_access_key = response['AccessKey']['SecretAccessKey']
    cred = credential(access_key_id, secret_access_key)

    print(f"Access Key ID: {access_key_id}")
    print(f"Secret Access Key: {secret_access_key}")
    return cred


def main():
    client_map = dict()
    client_map_new = dict()
    # Replace 'your_aws_access_key' and 'your_aws_secret_key' with your AWS IAM user's access key and secret key.
    aws_access_key_id = '<key_id>'
    aws_secret_access_key = '<access_key>'
    cred = credential(aws_access_key_id, aws_secret_access_key)
    print(f'aws_access_key_id = ', cred.aws_access_key_id)
    print(f'aws_secret_access_key = ', cred.aws_secret_access_key)
    print(f'aws_session_token = ', cred.aws_session_token)

    client_map = initialize_clients(client_map, cred)
    get_caller_identity(client_map)

    target_user_name = 'devOps'
    cred_new = create_access_key(client_map, target_user_name)
    # NOTE: manually put in the key id and access key created by the createAccessKey call above
    #cred_new = credential('', '', None)
    print(f'aws_access_key_id = ', cred_new.aws_access_key_id)
    print(f'aws_secret_access_key = ', cred_new.aws_secret_access_key)
    print(f'aws_session_token = ', cred_new.aws_session_token)

    time.sleep(5)

    client1 = boto3.client(
            service_name = 'sts', 
            aws_access_key_id=cred_new.aws_access_key_id, 
            aws_secret_access_key=cred_new.aws_secret_access_key,
            aws_session_token=cred.aws_session_token
        )        
    print(client1.get_caller_identity())
    
if __name__ == "__main__":
    main()

问题原因

你通过create_access_key生成的是IAM用户的长期访问密钥,这类密钥不需要会话令牌(aws_session_token)。但创建client1时,你错误传入了用户A的cred.aws_session_token,导致请求携带了不属于用户B的无效令牌,触发InvalidClientTokenId错误。

手动硬编码时,你显式传入None作为会话令牌,boto3不会在请求中添加令牌参数,所以请求合法。


修复方案

修改创建client1的代码,要么去掉aws_session_token参数,要么传入cred_new.aws_session_token(它本身就是None):

方案1:移除多余参数

client1 = boto3.client(
        service_name='sts', 
        aws_access_key_id=cred_new.aws_access_key_id, 
        aws_secret_access_key=cred_new.aws_secret_access_key
    )

方案2:复用已有函数(更规范)

直接用你写的initialize_each_service函数创建客户端,避免手动拼接参数出错:

client1 = initialize_each_service(cred_new, 'sts')

额外提示

  • 不需要time.sleep(5),IAM访问密钥创建后立即生效,等待毫无必要。

内容的提问来源于stack exchange,提问作者drdot

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 09:44:59