簡體   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