繁体   English   中英

Boto3 AWS MFA 身份验证在 Mac Native 和 PyCharm 终端上运行时失败,但在 VSCode 终端上运行

[英]Boto3 AWS MFA authentication fails when run on Mac Native and PyCharm terminals, but works on VSCode terminal

我编写了一个脚本来使用 python SDK 和 Boto3 查询 DynamoDB 表。 AWS IAM 角色需要 MFA,并且使用 VSCode 终端(版本:1.71.1 - 通用)我可以成功地进行身份验证并运行以下命令以获取用于创建经过身份验证的 Dynamo DB 客户端的 session_token:

def create_authenticated_dynamo_dict() -> dict:
    user_serial_number = input('Enter ARN serial number, e.g. arn:aws:iam::123456789012:mfa/user: ')
    user_role = 'arn:aws:iam::XXXXXXXXXXXXXXX:role/{role_name}'
    mfa = input('Enter the user device MFA code: ')
    client = boto3.client('sts')
    mfa_sts_client = client.get_session_token(
        DurationSeconds=900,
        SerialNumber=user_serial_number,
        TokenCode=mfa
    ) ...

但是,当我在 PyCharm (PyCharm 2022.2.2) 或本机 Mac 终端(M1 2020,macOS Monterey v 12.5.1)中运行相同的代码时,我收到来自 AWS 的额外(附加)MFA 请求(输入后) MFA 代码到终端输入),并且身份验证失败并出现以下错误:

botocore.exceptions.ClientError: An error occurred (AccessDenied) when
calling the GetSessionToken operation: Cannot call GetSessionToken
with session credentials

我为 VSCode、PyCharm 和 macOS 终端验证了 zsh shell - 但显然 PyCharm/Mac 本机终端和 VSCode 之间存在一些配置差异。 我想在 PyCharm 中运行它。最终我想了解为什么会发生这种情况,特别是什么导致了对 MFA 令牌的额外请求,当它应该从 arguments 读取到client.get_session_token

我最终能够在 Pycharm、VSCode 和本机 OSX 终端上成功进行身份验证。 我认为问题在于,在 Pycharm 或本机 OSX 中,Boto3 将默认采用当前终端 window 中最近导出的 AWS 配置文件。这解释了对 MFA 的意外额外请求 - 我的脚本中的用户值只是被忽略并且使用的 session 凭证不正确。

所以我通过始终从新终端 window 运行脚本来解决这个问题。我还更新了 Pycharm (2022.2.3)。 这是我现在用于身份验证的完整方法:

  1. 创建新的 boto3 sts客户端。
  2. 此客户端上的get_session_token ,带有用户 MFA 代码。
  3. 使用来自第一个客户端的credentials创建另一个新的 boto3 sts客户端。
  4. assume_role与第二个客户端和用户 IAM 角色。
  5. 使用来自第二个客户端的凭据创建新的 boto3 DynamoDB客户端。

使用此客户端,我能够使用表名成功进行 DynamoDB 查询,如下所示:

user_serial_number = input('Enter ARN serial number, e.g. arn:aws:iam::123456789012:mfa/user: ')
role = input('Enter AWS Role: e.g. arn:aws:iam::XXXXXXXXXXXXXXXX:role/{name of aws role from credentials file}: ')
mfa = input('Enter the MFA code: ')

mfa_sts_client = boto3.client('sts')

# Credentials are good for 1 hour
mfa_credentials = mfa_sts_client.get_session_token(
    DurationSeconds=3600,
    SerialNumber=user_serial_number,
    TokenCode=mfa
)['Credentials']

# Create a new client with credentials from the MFA enabled session we created above:
assumed_role_sts_client = boto3.client(
    'sts',
    aws_access_key_id=mfa_credentials['AccessKeyId'],
    aws_secret_access_key=mfa_credentials['SecretAccessKey'],
    aws_session_token=mfa_credentials['SessionToken']
)

# assume role with the authenticated client
assumed_role_res = assumed_role_sts_client.assume_role(
    RoleArn=role,
    RoleSessionName='{session name can be anything}'
)

# get temporary credentials from the assumed role
tmp_creds = assumed_role_res['Credentials']

# create authenticated DynamoDB client with the temporary credentials
dynamo_client = boto3.client(
    'dynamodb',
    region_name='{aws region of table, e.g. 'us-east-1'}',
    aws_access_key_id=tmp_creds['AccessKeyId'],
    aws_secret_access_key=tmp_creds['SecretAccessKey'],
    aws_session_token=tmp_creds['SessionToken']
)

response = dynamo_client.describe_table(
    TableName='{name_of_table}'
)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM