如何在通过SSO凭据连接时使用AWS Python SDK

dm7nw8vv  于 2024-01-05  发布在  Python
关注(0)|答案(6)|浏览(140)

我试图创建一个Python脚本来连接到我的AWS帐户并与之交互。我在这里阅读它https://boto3.amazonaws.com/v1/documentation/api/latest/guide/quickstart.html
我看到它从~/.aws/credentials(在Linux机器上)读取您的凭据。然而,我没有与IAM用户连接,而是与SSO用户连接。因此,我使用的配置文件连接数据位于~/.aws/sso/cache目录。
在该目录中,我看到两个json文件。其中一个具有以下键:

  • startUrl
  • 区域
  • accessToken
  • AmmoresAt

第二个具有以下键:

  • clientId
  • clientSecret
  • AmmoresAt

我在文档中没有看到任何关于如何告诉它使用我的SSO用户的地方。
因此,当我尝试运行我的脚本时,我会得到如下错误:

  1. botocore.exceptions.ClientError: An error occurred (AuthFailure) when calling the DescribeSecurityGroups operation: AWS was not able to validate the provided access credentials

字符串
即使我可以从命令提示符运行相同的命令。

eyh26e7m

eyh26e7m1#

这在boto3 1.14中得到了修复。
因此,如果您在~/.aws/config中有这样的配置文件:

  1. [profile sso_profile]
  2. sso_start_url = <sso-url>
  3. sso_region = <sso-region>
  4. sso_account_id = <account-id>
  5. sso_role_name = <role>
  6. region = <default region>
  7. output = <default output (json or text)>

字符串
然后用$ aws sso login --profile sso_profile登录
您可以创建一个会话:

  1. import boto3
  2. boto3.setup_default_session(profile_name='sso_profile')
  3. client = boto3.client('<whatever service you want>')

展开查看全部
vawmfj5a

vawmfj5a2#

已于2023.10.23发布最新的boto 3(hat tip commenter @Adam Smith,他的无形之手引导我们在boto 3的新版本中更新提取角色凭据):
下面是在boto3==1.28.69上测试的一个冗长而令人毛骨悚然的答案:
这是一个八步的过程,其中:
1.使用sso-oidc.register_client注册客户端
1.使用sso-oidc.start_device_authorization启动设备授权流
1.使用webbrowser.open将用户重定向到sso登录页
1.轮询sso-oidc.create_token,直到用户完成登录
1.使用sso.list_account_roles列出并向用户显示帐户角色
1.使用sso.get_role_credentials获取角色凭据
1.使用来自(6)的会话凭证创建新的boto 3会话
1.吃饼干
第8步是真正的关键,不应该被忽视,作为任何成功的授权流程的一部分。
在下面的示例中,account_id应该是您试图获取凭据的帐户的帐户ID。start_url应该是AWS为您生成的用于启动SSO流的URL(在AWS SSO管理控制台中,在设置下)。

  1. from time import time, sleep
  2. import webbrowser
  3. from boto3.session import Session
  4. # if your sso is setup in a different region, you will
  5. # want to include region_name=sso_region in the
  6. # session constructor below
  7. session = Session()
  8. account_id = '1234567890'
  9. start_url = 'https://d-0987654321.awsapps.com/start'
  10. region = 'us-east-1'
  11. sso_oidc = session.client('sso-oidc')
  12. client_creds = sso_oidc.register_client(
  13. clientName='myapp',
  14. clientType='public',
  15. )
  16. device_authorization = sso_oidc.start_device_authorization(
  17. clientId=client_creds['clientId'],
  18. clientSecret=client_creds['clientSecret'],
  19. startUrl=start_url,
  20. )
  21. url = device_authorization['verificationUriComplete']
  22. device_code = device_authorization['deviceCode']
  23. expires_in = device_authorization['expiresIn']
  24. interval = device_authorization['interval']
  25. webbrowser.open(url, autoraise=True)
  26. for n in range(1, expires_in // interval + 1):
  27. sleep(interval)
  28. try:
  29. token = sso_oidc.create_token(
  30. grantType='urn:ietf:params:oauth:grant-type:device_code',
  31. deviceCode=device_code,
  32. clientId=client_creds['clientId'],
  33. clientSecret=client_creds['clientSecret'],
  34. )
  35. break
  36. except sso_oidc.exceptions.AuthorizationPendingException:
  37. pass
  38. access_token = token['accessToken']
  39. sso = session.client('sso')
  40. account_roles = sso.list_account_roles(
  41. accessToken=access_token,
  42. accountId=account_id,
  43. )
  44. roles = account_roles['roleList']
  45. # simplifying here for illustrative purposes
  46. role = roles[0]
  47. # earlier versions of the sso api returned the
  48. # role credentials directly, but now they appear
  49. # to be in a subkey called `roleCredentials`
  50. role_creds = sso.get_role_credentials(
  51. roleName=role['roleName'],
  52. accountId=account_id,
  53. accessToken=access_token,
  54. )['roleCredentials']
  55. session = Session(
  56. region_name=region,
  57. aws_access_key_id=role_creds['accessKeyId'],
  58. aws_secret_access_key=role_creds['secretAccessKey'],
  59. aws_session_token=role_creds['sessionToken'],
  60. )

字符串

展开查看全部
hmmo2u0o

hmmo2u0o3#

您当前的.aws/sso/cache文件夹结构如下所示:

  1. $ ls
  2. botocore-client-XXXXXXXX.json cXXXXXXXXXXXXXXXXXXX.json

字符串
这两个json文件包含3个不同的有用参数。

  1. botocore-client-XXXXXXXX.json -> clientId and clientSecret
  2. cXXXXXXXXXXXXXXXXXXX.json -> accessToken


使用cXXXXXXXXXXXXXXXXX.json中的访问令牌,您可以调用get-role-credentials。此命令的输出可用于创建新会话。
你的Python文件应该看起来像这样:

  1. import json
  2. import os
  3. import boto3
  4. dir = os.path.expanduser('~/.aws/sso/cache')
  5. json_files = [pos_json for pos_json in os.listdir(dir) if pos_json.endswith('.json')]
  6. for json_file in json_files :
  7. path = dir + '/' + json_file
  8. with open(path) as file :
  9. data = json.load(file)
  10. if 'accessToken' in data:
  11. accessToken = data['accessToken']
  12. client = boto3.client('sso',region_name='us-east-1')
  13. response = client.get_role_credentials(
  14. roleName='string',
  15. accountId='string',
  16. accessToken=accessToken
  17. )
  18. 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')

展开查看全部
ibps3vxo

ibps3vxo4#

一个格式良好的基于boto3的脚本应该基于配置文件名透明地进行身份验证。不建议您自己处理缓存的文件或密钥或令牌,因为官方代码方法可能会在将来更改。要查看您的配置文件的状态,请运行aws configure list--examples:

  1. $ aws configure list --profile=sso
  2. Name Value Type Location
  3. ---- ----- ---- --------
  4. profile sso manual --profile
  5. The SSO session associated with this profile has expired or is otherwise invalid.
  6. To refresh this SSO session run aws sso login with the corresponding profile.
  7. $ aws configure list --profile=old
  8. Name Value Type Location
  9. ---- ----- ---- --------
  10. profile old manual --profile
  11. access_key ****************3DSx shared-credentials-file
  12. secret_key ****************sX64 shared-credentials-file
  13. region us-west-1 env ['AWS_REGION', 'AWS_DEFAULT_REGION']

字符串

展开查看全部
rsaldnfx

rsaldnfx5#

对我有效的方法如下:

  1. import boto 3
  2. session = boto3.Session(profile_name="sso_profile_name")
  3. session.resource("whatever")

字符串
使用boto3==1.20.18
如果您之前已为aws(即aws configure sso)配置了SSO,则此操作将有效。
有趣的是,如果我使用ipython,我不必经历这些,我只是事先调用aws sso login,然后调用boto3.Session()。我试图弄清楚我的方法是否有问题-我完全同意上面关于透明度的说法,尽管它是一个可行的解决方案,但我并不喜欢它。
编辑:有一些错误,下面是我如何修复它:
1.运行aws configure sso(如上所述);
1.安装aws-vault-它基本上取代了aws sso login --profile <profile-name>;
1.运行aws-vault exec <profile-name>创建一个子shell,并将AWS凭据导出到环境变量中。
这样,就可以交互地(例如iPython)或从脚本运行任何boto3命令,就像我的例子一样。

  1. import boto 3
  2. session = boto3.Session()
  3. session.resource("whatever")


Here,了解有关AWS存储库的更多详细信息。

展开查看全部
btxsgosb

btxsgosb6#

如果您以前在终端中执行过aws sso configure命令并按照提示操作,那么您的~/.aws/config文件中应该有以下内容。

  1. [profile <profile_name>]
  2. sso_session = <sso_session_name>
  3. sso_account_id = <account_id>
  4. sso_role_name = <role_name>
  5. region = <region>
  6. output = text
  7. [sso-session <sso_session_name>]
  8. sso_start_url = <sso_start_url>
  9. sso_region = <region>
  10. sso_registration_scopes = sso:account:access

字符串
在使用aws sso login --profile <profile_name>登录终端后,其中<profile_name>必须与上面~/.aws/config文件中的一个配置文件匹配,您需要将AWS_PROFILE环境变量设置为与上面相同的配置文件名称。如果您只想为当前终端设置环境变量,(在这里运行Python脚本),在终端中运行export AWS_PROFILE=<profile_name>。或者如果它是你经常使用的配置文件,将上面相同的export语句添加到类似~/.bashrc的文件中。

相关问题