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

使用moto模拟AWS凭证测试S3操作时出现InvalidClientTokenId错误如何解决

问题原因

你代码的报错来自两个配置错误:

  • 测试方法上的@set_initial_no_auth_action_count(0)装饰器要求moto从第一个请求开始就必须校验凭证,但是你调用create_user_with_access_key_and_policy创建IAM用户时,内部的IAM客户端没有传入任何凭证,属于无认证请求,直接被拦截,触发InvalidClientTokenId报错。
  • 你的测试用例只加了@mock_s3装饰器,和create_user_with_access_key_and_policy上的@mock_iam属于两个隔离的mock上下文,IAM生成的凭证无法被S3的mock识别,就算创建用户的步骤通过了,后续S3操作也会校验失败。

解决方案

调整装饰器配置和set_initial_no_auth_action_count的调用时机即可:

  1. 测试方法同时添加@mock_iam和@mock_s3装饰器,保证两个服务的mock在同一个上下文内,IAM生成的凭证可以被S3识别。
  2. 移除测试方法上的@set_initial_no_auth_action_count(0)装饰器,改为在所有预置操作(创建IAM用户、创建S3桶)完成后再调用该方法,避免预置阶段的无认证请求被拦截。

修改后可运行代码

import os
import unittest
import boto3
import botocore
from moto import mock_s3, mock_iam
from botocore.client import ClientError
from moto.core import set_initial_no_auth_action_count

import json

def my_head_bucket(bucket, aws_access_key_id, aws_secret_access_key):
    """
    示例函数,实际场景下会包含更多S3操作,从其他模块导入,不需要添加moto相关装饰器
    """
    s3_client = boto3.client("s3", aws_access_key_id=aws_access_key_id, aws_secret_access_key=aws_secret_access_key)
    s3_client.head_bucket(Bucket=bucket)

def create_user_with_access_key_and_policy(user_name="test-user"):
    """
    创建带S3全权限的IAM用户,返回访问密钥
    """
    policy_document = {
        "Version": "2012-10-17",
        "Statement": [
            {"Effect": "Allow", "Action": "s3:*", "Resource": "*"}
        ],
    }
    
    # 创建IAM客户端和用户
    client = boto3.client("iam", region_name="us-east-1")
    client.create_user(UserName=user_name)

    # 创建并挂载权限策略
    policy_arn = client.create_policy(
        PolicyName="policy1", PolicyDocument=json.dumps(policy_document)
    )["Policy"]["Arn"]
    client.attach_user_policy(UserName=user_name, PolicyArn=policy_arn)
    
    # 返回访问密钥
    return client.create_access_key(UserName=user_name)["AccessKey"]

class TestMyTest(unittest.TestCase):
    @mock_iam
    @mock_s3
    def test_correct_credentials(self):
        """测试合法凭证可以正常执行操作"""
        # 预置资源:创建IAM用户、S3桶
        iam_keys = create_user_with_access_key_and_policy()

        s3 = boto3.client('s3', aws_access_key_id=iam_keys["AccessKeyId"],aws_secret_access_key=iam_keys["SecretAccessKey"])
        s3.create_bucket(Bucket='mock_bucket')
        
        # 预置完成,开启强制凭证校验
        set_initial_no_auth_action_count(0)
        
        # 执行测试逻辑,预期无报错
        my_head_bucket('mock_bucket', aws_access_key_id=iam_keys["AccessKeyId"],aws_secret_access_key=iam_keys["SecretAccessKey"])
        
    @mock_iam
    @mock_s3
    def test_incorrect_credentials(self):
        """测试非法密钥会抛出预期异常"""
        # 预置资源:创建IAM用户、S3桶
        iam_keys = create_user_with_access_key_and_policy()

        s3 = boto3.client('s3', aws_access_key_id=iam_keys["AccessKeyId"],aws_secret_access_key=iam_keys["SecretAccessKey"])
        s3.create_bucket(Bucket='mock_bucket')
        
        # 预置完成,开启强制凭证校验
        set_initial_no_auth_action_count(0)
        
        # 执行测试逻辑,预期抛出ClientError
        with self.assertRaises(ClientError):
            my_head_bucket('mock_bucket', aws_access_key_id=iam_keys["AccessKeyId"],aws_secret_access_key="invalid")

if __name__ == '__main__':
    unittest.main()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 19:24:03