use*_*214 6 python boto amazon-web-services single-sign-on
我正在尝试创建一个 python 脚本来连接到我的 AWS 账户并与之交互。我在这里阅读了它https://boto3.amazonaws.com/v1/documentation/api/latest/guide/quickstart.html
我看到它从 ~/.aws/credentials (在 Linux 机器上)读取您的凭据。然而,我并没有与 IAM 用户连接,而是与 SSO 用户连接。因此,我使用的配置文件连接数据位于 ~/.aws/sso/cache 目录。
在该目录中,我看到两个 json 文件。一个有以下键:
第二个有以下键:
我在文档中没有看到关于如何告诉它使用我的 SSO 用户的任何地方。
因此,当我尝试运行我的脚本时,我收到错误,例如
botocore.exceptions.ClientError: An error occurred (AuthFailure) when calling the DescribeSecurityGroups operation: AWS was not able to validate the provided access credentials
Run Code Online (Sandbox Code Playgroud)
即使我可以从命令提示符运行相同的命令。
2ps*_*2ps 22
于 2023 年 10 月 23 日更新了最新的 boto3(帽子评论者@Adam Smith,他的无形之手引导我们更新在新版本的 boto3 中提取角色凭证):
所以这是在 上测试的又长又毛茸茸的答案boto3==1.28.69:
这是一个八步过程,其中:
sso-oidc.register_clientsso-oidc.start_device_authorizationwebbrowser.opensso-oidc.create_token直到用户完成登录sso.list_account_rolessso.get_role_credentials第 8 步确实很关键,作为任何成功授权流程的一部分,不应被忽视。
在下面的示例中,account_id应该是您尝试获取其凭据的帐户的帐户 ID。并且start_url应该是 aws 为您生成的用于启动 sso 流程的 url(在 AWS SSO 管理控制台的“设置”下)。
from time import time, sleep
import webbrowser
from boto3.session import Session
# if your sso is setup in a different region, you will
# want to include region_name=sso_region in the
# session constructor below
session = Session()
account_id = '1234567890'
start_url = 'https://d-0987654321.awsapps.com/start'
region = 'us-east-1'
sso_oidc = session.client('sso-oidc')
client_creds = sso_oidc.register_client(
clientName='myapp',
clientType='public',
)
device_authorization = sso_oidc.start_device_authorization(
clientId=client_creds['clientId'],
clientSecret=client_creds['clientSecret'],
startUrl=start_url,
)
url = device_authorization['verificationUriComplete']
device_code = device_authorization['deviceCode']
expires_in = device_authorization['expiresIn']
interval = device_authorization['interval']
webbrowser.open(url, autoraise=True)
for n in range(1, expires_in // interval + 1):
sleep(interval)
try:
token = sso_oidc.create_token(
grantType='urn:ietf:params:oauth:grant-type:device_code',
deviceCode=device_code,
clientId=client_creds['clientId'],
clientSecret=client_creds['clientSecret'],
)
break
except sso_oidc.exceptions.AuthorizationPendingException:
pass
access_token = token['accessToken']
sso = session.client('sso')
account_roles = sso.list_account_roles(
accessToken=access_token,
accountId=account_id,
)
roles = account_roles['roleList']
# simplifying here for illustrative purposes
role = roles[0]
# earlier versions of the sso api returned the
# role credentials directly, but now they appear
# to be in a subkey called `roleCredentials`
role_creds = sso.get_role_credentials(
roleName=role['roleName'],
accountId=account_id,
accessToken=access_token,
)['roleCredentials']
session = Session(
region_name=region,
aws_access_key_id=role_creds['accessKeyId'],
aws_secret_access_key=role_creds['secretAccessKey'],
aws_session_token=role_creds['sessionToken'],
)
Run Code Online (Sandbox Code Playgroud)
您当前的 .aws/sso/cache 文件夹结构如下所示:
$ ls
botocore-client-XXXXXXXX.json cXXXXXXXXXXXXXXXXXXX.json
Run Code Online (Sandbox Code Playgroud)
这 2 个 json 文件包含 3 个有用的不同参数。
botocore-client-XXXXXXXX.json -> clientId and clientSecret
cXXXXXXXXXXXXXXXXXXX.json -> accessToken
Run Code Online (Sandbox Code Playgroud)
使用 cXXXXXXXXXXXXXXXXXXXXX.json 中的访问令牌,您可以调用get-role-credentials。该命令的输出可用于创建新会话。
您的 Python 文件应该如下所示:
import json
import os
import boto3
dir = os.path.expanduser('~/.aws/sso/cache')
json_files = [pos_json for pos_json in os.listdir(dir) if pos_json.endswith('.json')]
for json_file in json_files :
path = dir + '/' + json_file
with open(path) as file :
data = json.load(file)
if 'accessToken' in data:
accessToken = data['accessToken']
client = boto3.client('sso',region_name='us-east-1')
response = client.get_role_credentials(
roleName='string',
accountId='string',
accessToken=accessToken
)
session = boto3.Session(aws_access_key_id=response['roleCredentials']['accessKeyId'], aws_secret_access_key=response['roleCredentials']['secretAccessKey'], aws_session_token=response['roleCredentials']['sessionToken'], region_name='us-east-1')
Run Code Online (Sandbox Code Playgroud)
这已在boto3 1.14中修复。
因此,鉴于您的个人资料中有这样的个人资料~/.aws/config:
[profile sso_profile]
sso_start_url = <sso-url>
sso_region = <sso-region>
sso_account_id = <account-id>
sso_role_name = <role>
region = <default region>
output = <default output (json or text)>
Run Code Online (Sandbox Code Playgroud)
然后登录
$ aws sso login --profile sso_profile
您将能够创建一个会话:
import boto3
boto3.setup_default_session(profile_name='sso_profile')
client = boto3.client('<whatever service you want>')
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4833 次 |
| 最近记录: |