简体   繁体   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

I have written a script to query a DynamoDB table using python SDK and Boto3.我编写了一个脚本来使用 python SDK 和 Boto3 查询 DynamoDB 表。 The AWS IAM role requires MFA, and using VSCode terminal (Version: 1.71.1 - Universal) I can successfully authenticate and run the following to get session_token for creating an authenticated Dynamo DB client: 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
    ) ...

However, when I run this same code in PyCharm (PyCharm 2022.2.2) or in the native Mac terminal (M1 2020, macOS Monterey v 12.5.1), I am getting an extra (additional) request for MFA from AWS (after inputting the MFA code to terminal input), and the authentication fails with this error:但是,当我在 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

I verified zsh shell for VSCode, PyCharm, and macOS terminal - but clearly there's some config difference between PyCharm/Mac native terminals and VSCode.我为 VSCode、PyCharm 和 macOS 终端验证了 zsh shell - 但显然 PyCharm/Mac 本机终端和 VSCode 之间存在一些配置差异。 I would like to run this in PyCharm. Ultimately I want to understand why this is occurring, and specifically what is causing an additional request for MFA token, when it should be read from the arguments to client.get_session_token .我想在 PyCharm 中运行它。最终我想了解为什么会发生这种情况,特别是什么导致了对 MFA 令牌的额外请求,当它应该从 arguments 读取到client.get_session_token

I was eventually able to authenticate successfully on Pycharm, VSCode, and native OSX terminal.我最终能够在 Pycharm、VSCode 和本机 OSX 终端上成功进行身份验证。 I believe the problem was that in both Pycharm or native OSX, Boto3 will default to assuming the most recently exported AWS profile in the current terminal window. This explains the unexpected extra request for MFA - the user values from my script were simply being ignored and the session credentials being used were incorrect.我认为问题在于,在 Pycharm 或本机 OSX 中,Boto3 将默认采用当前终端 window 中最近导出的 AWS 配置文件。这解释了对 MFA 的意外额外请求 - 我的脚本中的用户值只是被忽略并且使用的 session 凭证不正确。

So I solved this by always running the script from a new terminal window. I also updated Pycharm (2022.2.3).所以我通过始终从新终端 window 运行脚本来解决这个问题。我还更新了 Pycharm (2022.2.3)。 Here is the full method I am now using to authenticate:这是我现在用于身份验证的完整方法:

  1. Create new boto3 sts client.创建新的 boto3 sts客户端。
  2. get_session_token on this client, with user MFA code.此客户端上的get_session_token ,带有用户 MFA 代码。
  3. Create another new boto3 sts client, using credentials from the first client.使用来自第一个客户端的credentials创建另一个新的 boto3 sts客户端。
  4. assume_role with the second client, and user IAM role. assume_role与第二个客户端和用户 IAM 角色。
  5. Create new boto3 DynamoDB client, using credentials from second client.使用来自第二个客户端的凭据创建新的 boto3 DynamoDB客户端。

With this client, I was able to successfully make a DynamoDB query using the name of the table, as shown below:使用此客户端,我能够使用表名成功进行 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