修复botocore.exceptions.nocredentialserror:无法找到凭据[已解决]
#aws #python #boto3 #identity

如果在运行Python脚本或应用程序时看到此错误,则偶然发现了Boto3无法找到对特定AWS服务签署API呼叫所需的有效AWS凭据时出现的最常见错误之一。

有很多堆叠的问题:

此错误特定于Python;如果您正在寻找无法找到凭据的解决方案,那么我们已经写了一个blog post

在调用API之前,您需要创建特定于要使用的服务的客户端。

实例化服务客户端的最传统方法是使用Boto3 SDK提供的以下抽象之一:

  • boto3。客户端('s3');
  • boto3。资源('s3')。

不管抽象的类型如何,除非已经实例化了,否则将创建新的默认boto3.session.session。如果您想知道boto3.session.session对象是什么,我建议指其文档:

会话存储配置状态,并允许您创建服务客户端和资源。

一个简单的例子

要重现错误,让我使用一个示例脚本来调用Amazon S3 API,该Amazon S3 API返回请求的已验证发件人拥有的所有存储桶的列表。

import boto3

s3_client = boto3.client("s3")

list_buckets_response = s3_client.list_buckets()["Buckets"]
bucket_names = ", ".join(list(map(lambda bucket: bucket["Name"], list_buckets_response)))

print(bucket_names)

正如我先前所说,执行boto3.client("s3")指令并创建新的默认会话对象;此会话对象也包含AWS凭据信息。您可以轻松推断出,如果Boto3无法找到凭据,则会抛出 botocore.exceptions.nocredentialserror 错误。在这种情况下,执行上一个脚本将产生类似于以下内容的输出:

boto3在哪里寻找凭据?

boto3通过可能位置列表搜索AWS凭据,直到找到有效的位置为止。

documentation

中所述
  • boto3对客户初始化期间作为参数传递的凭据更高优先级。

  • 如果未提供凭据这种方式,它将在环境变量和共享配置文件中寻找它们(即〜/.aws/recertentials和〜/.aws/config Files)。

  • 如果它仍然无法获得有效的凭据,它试图通过配置IAM角色的Amazon EC2实例上的实例元数据服务获得它们。

再次, botocore.exceptions.nocredentialserror 如果boto3无法在任何列出的位置找到有效的AWS凭据。

让我们找到解决方案!

为了解决该问题,我将生成一组与特定IAM用户相关的临时凭据。为IAM用户生成临时凭证涉及调用STS旋转式API。我让Leapp自动为我生成它们。

设置后,BOTO3应该能够从〜/.aws/凭据文件中获得有效的AWS凭据。让我们尝试再次运行Python脚本。

正如预期的那样,boto3在〜/.aws/recertentials 文件中找到了一组有效的临时凭据。它使用这些凭据签署Amazon S3 API请求,并获取请求的身份验证发送者拥有的存储库列表。

boto3会话:锦上添花

长期运行的脚本呢?如果脚本试图访问Amazon S3列表存储桶API,但是BOTO3加载的第一组凭据已过期?好吧,它将无法转发请求。

问题在于,仅使用boto3.client或boto3.Resource模块级函数,第一组凭据包裹在默认 boto3.session.session.sessess.sessess对象中,不会刷新。

要保持凭证始终与凭证提供商链位置之一中的凭据保持一致,您可以直接实例化boto3.session.session.session对象,并从中获取新的Amazon S3客户端。


import boto3

while True:
  input("type a key to list the available Amazon S3 buckets")

  s3_client = boto3.session.Session().client("s3")

  try:
    buckets = s3_client.list_buckets()["Buckets"]
    bucket_names = ", ".join(list(map(lambda bucket: bucket["Name"], buckets)))
    print(bucket_names)
  except Exception as e:
    print(e)

为了模拟一个长期运行的脚本,我介绍了一个WILE循环,该循环首先要求用户键入一个键以运行n-th-th-Teperation。这样,我们可以通过在触发n-th Tiperation之前启动/停止LEAPP会话来控制凭据可用。

在这一点上,让我们通过离开Leapp会话停止来运行脚本;它返回以下输出。

您可以看到,它无法找到凭据,因为在触发第一次迭代时,任何凭据提供商链中都无法使用凭据。

现在,让我们开始Leapp会话。

此时,〜/.aws/凭据文件中关联的一组新的临时凭据。

通过触发第二次迭代,我们从脚本中获得了以下输出:

在第二次迭代期间,boto3能够从位于〜/.aws/凭据文件中的一组有效的AWS凭据来实例化新的会话对象。因此,它可以签名并转发到Amazon S3存储端端点,以获取身份验证的发送者拥有的存储桶列表。

我可以微调以前的脚本以维护会话对象的单个实例并重新确定它,只有在签署请求的凭据过期的情况下才能重新确定。

所以,我的建议是使用boto3.session.session对象作为实例化,是一种刷新凭证的优雅方式。

那就是,伙计们!

我希望您能找到理解和求解botocore.exceptions.nocredentialserror所需的所有信息!

作为外卖,请考虑重构现有代码以采用boto3.session.session对象,除非您已经使用了它。它可能是改变游戏规则的人,尤其是在长期运行的脚本中。

本文是该博客的IAM how to fix系列的一部分。

请访问subscribing to our newsletter的IAM专业知识!

在评论中分享您对此博客文章的想法和反馈,或通过我的Twitter profile与我联系。

如果您喜欢Leapp的体验,请给我们星星!