跨区域Lambda调用Sagemaker签名异常及获取aws-requests-auth规范字符串方法
问题1:如何打印aws-requests-auth发送的Canonical String?
要捕获aws-requests-auth生成的Canonical String,最直接的方式是自定义一个继承自AWSRequestsAuth的类,重写它的调用方法来打印生成的Canonical请求。这样既能保留原有的签名逻辑,又能精准输出你需要的内容:
from aws_requests_auth.boto_utils import BotoAWSRequestsAuth class DebugAuth(BotoAWSRequestsAuth): def __call__(self, request): # 生成Canonical请求并打印 canonical_request = self._get_canonical_request(request) print("Generated Canonical String:\n", canonical_request) # 执行原有的签名流程 return super().__call__(request) # 使用自定义的DebugAuth替代原类 auth = DebugAuth( aws_host='runtime.sagemaker.us-east-1.amazonaws.com', aws_region='us-east-1', aws_service='sagemaker' ) # 后续发送请求时就会自动打印Canonical String response = requests.post(your_sagemaker_url, json=payload, auth=auth)
如果你不想修改代码,也可以尝试开启debug级别的日志,不过这种方式会输出大量无关日志,需要自行过滤:
import logging logging.basicConfig(level=logging.DEBUG)
问题2:跨区域调用Sagemaker出现签名不匹配错误
这个错误几乎都是因为签名时的区域、服务名或主机头配置与目标资源不匹配导致的,结合你给出的预期Canonical String,你可以按以下步骤排查:
确认Auth对象的核心参数
必须确保AWSRequestsAuth的参数完全匹配目标Sagemaker实例所在的区域:auth = BotoAWSRequestsAuth( aws_host='runtime.sagemaker.us-east-1.amazonaws.com', # 和预期Canonical String中的host一致 aws_region='us-east-1', # 目标Sagemaker的区域,不是Lambda运行的区域 aws_service='sagemaker' # 注意是`sagemaker`,不是`runtime.sagemaker` )很多人跨区域调用时会错误地使用Lambda所在区域的
aws_region,这会直接导致签名计算错误。对比实际生成的Canonical String
用问题1中的方法打印实际生成的Canonical String,和你给出的预期值对比:- 检查
host是否完全一致(必须是runtime.sagemaker.us-east-1.amazonaws.com) - 确认HTTP方法是
POST,路径是/endpoints/foo-endpoint/invocations - 核对
x-amz-开头的请求头(比如x-amz-date、x-amz-region)是否符合目标区域要求
- 检查
验证请求URL的正确性
确保你发送请求的URL是目标区域的Sagemaker endpoint:https://runtime.sagemaker.us-east-1.amazonaws.com/endpoints/foo-endpoint/invocations
如果以上配置都正确,签名应该就能匹配了。如果还是有问题,检查你的AWS凭证是否有权限跨区域调用Sagemaker(不过权限错误通常会返回不同的提示,签名不匹配还是优先看配置)。
内容的提问来源于stack exchange,提问作者Martin Thoma
相关产品推荐
相关产品推荐

