【问题标题】:Boto3 AWS MFA authentication fails when run on Mac Native and PyCharm terminals, but works on VSCode terminalBoto3 AWS MFA 身份验证在 Mac Native 和 PyCharm 终端上运行时失败,但在 VSCode 终端上运行
【发布时间】:2022-12-11 14:01:38
【问题描述】:
我已经编写了一个脚本来使用 python SDK 和 Boto3 查询 DynamoDB 表。 AWS IAM 角色需要 MFA,并且使用 VSCode 终端(版本:1.71.1 - 通用)我可以成功地进行身份验证并运行以下命令以获取 session_token 以创建经过身份验证的 Dynamo DB 客户端:
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 令牌的额外请求,而应该从 client.get_session_token 的参数中读取它。
【问题讨论】:
标签:
amazon-web-services
visual-studio-code
pycharm
boto3
zsh
【解决方案1】:
我最终能够使用以下步骤在 Pycharm、VSCode 和本机 OSX 终端上成功进行身份验证:
- 创建新的 boto3
sts 客户端。
-
get_session_token 在此客户端上,带有用户 MFA 代码。
- 创建另一个新的 boto3
sts 客户端,使用来自第一个客户端的 credentials。
-
assume_role 与第二个客户端和用户 IAM 角色。
- 使用第二个客户端的凭据创建新的 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}'
)