我有一个AWS Lambda函数,它执行需要从S3读取C++代码。
当我在同一个 Lambda 函数中使用 Python 从 S3 读取时,它工作正常。当C++尝试读取同一文档时,出现以下错误:
获取对象错误:无效令牌无法解析
提供的令牌格式不正确或无效。
由于 Python 代码能够访问文档,我认为我的 IAM 权限在 Lambda 和 S3 之间设置正确。我已确认访问密钥、私有密钥和会话令牌环境变量可用于C++代码。我不确定为什么它从C++而不是从 Python 收到此错误。有什么想法吗?
作为参考,这是我的 Python 代码,它工作正常:
s3 = boto3.resource('s3')
obj = s3.Object(bucket, key)
obj.get()['Body'].read()
以及相关的C++代码,它会产生错误:
Aws::SDKOptions options;
Aws::InitAPI(options);
Aws::S3::S3Client s3_client;
Aws::S3::Model::GetObjectRequest object_request;
object_request.WithBucket(bucket_name).WithKey(key_name);
auto get_object_outcome = s3_client.GetObject(object_request);
Aws::FStream jsonFile;
if (get_object_outcome.IsSuccess())
{
jsonFile.open(key_name.c_str(), std::ios::out | std::ios::binary);
jsonFile << get_object_outcome.GetResult().GetBody().rdbuf();
std::cout << "Done!" << std::endl;
}
else
{
std::cout << "GetObject error: " <<
get_object_outcome.GetError().GetExceptionName() << " " <<
get_object_outcome.GetError().GetMessage() << std::endl;
}
Aws::ShutdownAPI(options);
我也尝试将凭据直接传递到客户端,但仍然收到 InvalidToken 错误:
const char* access_key = std::getenv("AWS_ACCESS_KEY_ID");
const char* secret_key = std::getenv("AWS_SECRET_ACCESS_KEY");
const char* session_token = std::getenv("AWS_SESSION_TOKEN");
Aws::Auth::AWSCredentials creds(access_key, secret_key, session_token);
Aws::S3::S3Client s3_client(creds);
我能够解决这个问题。问题在于使用 AWS GovCloud 和 C++ 开发工具包的组合,如 https://github.com/aws/aws-sdk-cpp/issues/365 中所述。
解决方案是手动设置S3Client
的region
和endpointOverride
,如下所示:
Aws::Client::ClientConfiguration config;
config.region = "us-gov-west-1";
config.endpointOverride = "s3-us-gov-west-1.amazonaws.com";
Aws::S3::S3Client s3_client(config);
希望这能为其他人节省一周的心痛。