Boto3:动态获取凭据?

54

我正在努力找出如何从我的代码中动态获取aws_access_key_id和aws_secret_access_key。

在boto2中,我可以通过以下方式执行:boto.config.get_value('Credentials', 'aws_secret_access_key') 但是在boto3中似乎找不到类似的方法。如果我查看boto3.Session()._session._credentials,我能够找到密钥,但那似乎是一个“大杀器”,我宁愿不走这条路。


你能解释一下为什么你需要在代码中直接访问凭据吗? - Mark B
1
我需要这个是因为我要从S3复制数据到Redshift,所以我需要 aws_access_key_idaws_secret_access_key。我宁愿不编写代码来进入配置/凭证文件并在Boto已经执行此操作时找到它们。 - Mo.
是的,将这些密钥传递给Redshift以访问S3非常麻烦。我希望他们能够允许我们为Redshift分配IAM角色,以避免这种需要。我担心您的解决方案在使用IAM实例配置文件的EC2实例或Lambda函数中无法正常工作。 - Mark B
@Mo。我同意MarkB的观点。这不是一种可移植的解决方案。请检查我的解决方案并看看它是否有效。 - helloV
把密钥放在凭证配置文件中,给它一个新的配置文件名称,而不是[default]怎么样?然后使用profile_name=指向显式的配置文件密钥? - mootmoot
顺便提一下,您不再需要为Redshift COPY命令执行此操作。现在,Redshift可以使用IAM角色:https://aws.amazon.com/releasenotes/8869404215180370 这是更好的解决方案。 - Mark B
4个回答

80

通常最佳实践是只使用临时凭证。您可以使用STS.get_session_token获取临时凭证。

编辑:自此PR起,您可以通过以下方式访问当前会话凭证:

import boto3

session = boto3.Session()
credentials = session.get_credentials()

# Credentials are refreshable, so accessing your access key / secret key
# separately can lead to a race condition. Use this to get an actual matched
# set.
credentials = credentials.get_frozen_credentials()
access_key = credentials.access_key
secret_key = credentials.secret_key

redshift = session.client('redshift')
...

我仍然建议使用临时凭据,范围仅限于redshift所需的内容。


7
嗨@Jordon Phillips,如果我们使用get_frozen_credentials(),令牌会再次过期吗?还是它会继续工作而无需刷新令牌? - Manish Kakati
这似乎也适用于获取临时凭证(从OIDC的K8S服务帐户派生,并具有IAM角色关联)。 - CoatedMoose

24

使用 botocore

>>> import botocore.session
>>> session = botocore.session.get_session()

>>> session.get_credentials().access_key
'AKIAABCDEF6RWSGI234Q'

>>> session.get_credentials().secret_key
'abcdefghijkl+123456789+qbcd'

>>> session.get_config_variable('region')
'us-east-1'

这些是IAM的编程访问密钥吗?没有ARN,它们是如何生成的,请您解释一下。 - sudhir tataraju
@sudhirtataraju Boto可以通过多种方式获取密钥。该代码展示了如何像Boto一样检索密钥。例如,当您提供凭据且Boto出现访问错误时,您可能希望确认您传递的凭据是否与Boto使用的相同。请参见:https://boto3.amazonaws.com/v1/documentation/api/latest/guide/configuration.html - helloV

10

我可以建议使用boto3访问键是错误的:

import boto3
session = boto3.Session(profile_name="my-profile")

dynamodb = session.resource(
    "dynamodb",
    region_name=session.region_name,
    # aws_access_key_id=session.get_credentials().access_key,
    # aws_secret_access_key=session.get_credentials().secret_key,
)

注意,我注释掉了访问密钥的部分,因为1:

从此会话创建的任何客户端都将使用来自 ~/.aws/credentials [my-profile]部分的凭证。


1
很好,这正是我所需要的。谢谢。 - Jeshizaemon
有一些用例,如果要在boto3之外使用密钥将会很有用。一个例子是,如果您想将凭据传递给某个进程,但由于某种原因(比如旧的SDK),该进程无法访问凭据本身。 - Rory Browne

0
import boto3
from botocore import session

def get_credentials():
   credentials = boto3.client(
       'sts',
       region_name="us-east-1", 
       aws_access_key_id='123', 
       aws_secret_access_key='123',
   ).assume_role(
       RoleArn="arn:aws-cn:iam::123",  # Your RoleArn
       RoleSessionName='boto3_client')

   return credentials


def db_conn():
    credentials = get_credentials()

    db = boto3.resource(
        'dynamodb',
        region_name="us-east-1",
        aws_access_key_id=credentials['Credentials']['AccessKeyId'],
        aws_secret_access_key=credentials['Credentials']['SecretAccessKey'],
        aws_session_token=credentials['Credentials']['SessionToken'],
    )
   
    # table = db.Table(your_table_name)

    # response = table.query(
    # IndexName='age',
    # KeyConditionExpression=Key('age').eq(11)
    # )


if __name__ == "__main__": 
   db_conn()




你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心中找到有关如何编写良好答案的更多信息。 - Community

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接