使用 Python 的 aws 用户身份验证
User Authentication for aws using Python
我正在使用 Python(3.6) & Django(1.10) 开发一个项目,我在其中使用了 aws api,但我是 aws 的新手,不知道如何验证一个用户。
我的场景是:
我需要访问用户的 aws 资源,例如 projects list、buckets list 等,为此,我需要对用户进行身份验证 向特定 API.
发出请求时
我如何在 python 中做到这一点?
我是 aws.So 的新手,请不要介意我的问题。
Update:
这是我尝试过的:
来自 views.py:
def boto3_with_role(role_arn, session_prefix, external_id, **kwargs):
"""
Create a partially applied session to assume a role with an external id.
A unique session_name will be generated by {session_prefix}_{time}
`session` can be passed, otherwise the default sesion will be used
see: http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-api.html
"""
sts = boto3.client('sts')
res = sts.assume_role(
RoleArn=role_arn,
RoleSessionName='{}_{}'.format(session_prefix, int(time.time())),
ExternalId=external_id,
)
creds = res['Credentials']
return partial(boto3.session.Session,
aws_access_key_id=creds['AccessKeyId'],
aws_secret_access_key=creds['SecretAccessKey'],
aws_session_token=creds['SessionToken']
)
class AwsAuthentication(LoginRequiredMixin, CreateView):
def post(self, request, *args, **kwargs):
AwsSession = boto3_with_role('ARN_LINK_FROM_CUSTOMER', 'MyPrefix',
'EXTERNAL_ID_FROM_CUSTOMER')
my_session = AwsSession()
client = my_session.resource('s3')
for bucket in client.buckets.all():
print(bucket.name)
return HttpResponse('Your Bucket is: {}'.format(bucket.name))
Now, it returns: botocore.exceptions.ClientError: An error occurred (InvalidClientTokenId) when calling the AssumeRole operation: The security token included in the request is invalid.
请帮帮我!
提前致谢!
目前不存在让用户登录其 AWS 账户以允许您的应用程序访问其 AWS 资源的功能。要考虑的一种可能的解决方法是为用户提供直接 link 以创建具有允许特定 AWS 帐户的特定托管策略的 IAM 角色。然后,您可以将其包含在您的注册流程中,并在您需要访问用户帐户中的资源时担任该角色。
示例link:
我不确定为什么其他人建议您不能这样做。这是完全正常且得到良好支持的——许多 AWS 账户用户允许第三方代表用户在用户的 AWS 账户中进行操作。例如,任何第三方监控服务或成本分析服务。
[坏方法] 第一种方法是简单地向用户询问 IAM 凭据(访问密钥和秘密密钥)。您的应用程序可以使用它们来访问用户的 AWS 账户。这很简单,但不要这样做。
[好方法]更好的方法是通过跨账户访问。您有一个 AWS 账户,您的用户也有一个 AWS 账户。您指示用户使用适当的 IAM 策略(您的应用程序需要的最小权限集)在他的帐户中创建一个 IAM 角色,并指示用户如何允许您的帐户在用户的帐户中担任此角色 - 执行此操作您宣传所需的 IAM 策略和您的 AWS 帐号。然后用户可以创建一个 IAM 策略,使用该策略创建一个角色,然后在您的账户之间建立信任关系,以便您可以承担 IAM 角色并在他的账户中进行操作。有关更多信息,请参阅 here and here。
请注意,您从 sts.AssumeRole 调用获得的凭据会在一段时间后过期(默认情况下为 15 分钟,但您可以在执行 AssumeRole 调用时将其设置得更长,直到您当前的会话最大值 API 会话持续时间,默认情况下 -- 1 小时),除非您刷新它们。
如果您需要自动刷新凭据,我在这里分享我在研究 boto 代码几个小时并尝试解决 boto 对文件系统和配置文件的依赖性后编写的代码。
这里我只是使用了内置的 boto 机制来缓存和定期刷新假定的凭据,而无需触及任何文件:
from datetime import datetime
import boto3
from botocore.credentials import (
AssumeRoleProvider,
AssumeRoleCredentialFetcher,
DeferredRefreshableCredentials,
CredentialResolver
)
from dateutil.tz import tzlocal
class CustomAssumeRoleProvider(AssumeRoleProvider):
"""
Overrides default AssumeRoleProvider to not use profiles from filesystem.
"""
def __init__(self,
source_session: boto3.Session,
assume_role_arn: str,
expiry_window_seconds: int):
super().__init__(
load_config=lambda: source_session._session.full_config,
client_creator=source_session._session.create_client,
cache={},
profile_name='not-used'
)
self.expiry_window_seconds = expiry_window_seconds
self.source_session = source_session
self.assume_role_arn = assume_role_arn
assert assume_role_arn, "assume_role_arn is required"
def load(self):
fetcher = AssumeRoleCredentialFetcher(
client_creator=self.source_session._session.create_client,
source_credentials=self.source_session.get_credentials(),
role_arn=self.assume_role_arn,
expiry_window_seconds=self.expiry_window_seconds,
cache=self.cache,
)
return DeferredRefreshableCredentials(
method=self.METHOD,
refresh_using=fetcher.fetch_credentials,
time_fetcher=lambda: datetime.now(tzlocal())
)
def get_assume_role_session(
source_session: boto3.Session,
assume_role_arn: str,
expiry_window_seconds=15 * 60
) -> boto3.Session:
"""
Creates a new boto3 session that will operate as of another user.
Source session must have permission to call sts:AssumeRole on the provided ARN,
and that ARN role must have been trusted to be assumed from this account (where source_session is from).
See https://docs.aws.amazon.com/IAM/latest/UserGuide/tutorial_cross-account-with-roles.html
Uses internal session._session to hack it together, as I haven't found another way.
"""
# must have .load() method to be used in CredentialsResolver.
provider = CustomAssumeRoleProvider(
source_session=source_session,
assume_role_arn=assume_role_arn,
expiry_window_seconds=expiry_window_seconds
)
# must have .load_credentials() method to be used in register_component()
resolver = CredentialResolver([provider])
new_session = boto3.Session()
new_session._session.register_component('credential_provider', resolver)
return new_session
我正在使用 Python(3.6) & Django(1.10) 开发一个项目,我在其中使用了 aws api,但我是 aws 的新手,不知道如何验证一个用户。
我的场景是: 我需要访问用户的 aws 资源,例如 projects list、buckets list 等,为此,我需要对用户进行身份验证 向特定 API.
发出请求时我如何在 python 中做到这一点? 我是 aws.So 的新手,请不要介意我的问题。
Update:
这是我尝试过的: 来自 views.py:
def boto3_with_role(role_arn, session_prefix, external_id, **kwargs):
"""
Create a partially applied session to assume a role with an external id.
A unique session_name will be generated by {session_prefix}_{time}
`session` can be passed, otherwise the default sesion will be used
see: http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-api.html
"""
sts = boto3.client('sts')
res = sts.assume_role(
RoleArn=role_arn,
RoleSessionName='{}_{}'.format(session_prefix, int(time.time())),
ExternalId=external_id,
)
creds = res['Credentials']
return partial(boto3.session.Session,
aws_access_key_id=creds['AccessKeyId'],
aws_secret_access_key=creds['SecretAccessKey'],
aws_session_token=creds['SessionToken']
)
class AwsAuthentication(LoginRequiredMixin, CreateView):
def post(self, request, *args, **kwargs):
AwsSession = boto3_with_role('ARN_LINK_FROM_CUSTOMER', 'MyPrefix',
'EXTERNAL_ID_FROM_CUSTOMER')
my_session = AwsSession()
client = my_session.resource('s3')
for bucket in client.buckets.all():
print(bucket.name)
return HttpResponse('Your Bucket is: {}'.format(bucket.name))
Now, it returns: botocore.exceptions.ClientError: An error occurred (InvalidClientTokenId) when calling the AssumeRole operation: The security token included in the request is invalid.
请帮帮我!
提前致谢!
目前不存在让用户登录其 AWS 账户以允许您的应用程序访问其 AWS 资源的功能。要考虑的一种可能的解决方法是为用户提供直接 link 以创建具有允许特定 AWS 帐户的特定托管策略的 IAM 角色。然后,您可以将其包含在您的注册流程中,并在您需要访问用户帐户中的资源时担任该角色。
示例link:
我不确定为什么其他人建议您不能这样做。这是完全正常且得到良好支持的——许多 AWS 账户用户允许第三方代表用户在用户的 AWS 账户中进行操作。例如,任何第三方监控服务或成本分析服务。
[坏方法] 第一种方法是简单地向用户询问 IAM 凭据(访问密钥和秘密密钥)。您的应用程序可以使用它们来访问用户的 AWS 账户。这很简单,但不要这样做。
[好方法]更好的方法是通过跨账户访问。您有一个 AWS 账户,您的用户也有一个 AWS 账户。您指示用户使用适当的 IAM 策略(您的应用程序需要的最小权限集)在他的帐户中创建一个 IAM 角色,并指示用户如何允许您的帐户在用户的帐户中担任此角色 - 执行此操作您宣传所需的 IAM 策略和您的 AWS 帐号。然后用户可以创建一个 IAM 策略,使用该策略创建一个角色,然后在您的账户之间建立信任关系,以便您可以承担 IAM 角色并在他的账户中进行操作。有关更多信息,请参阅 here and here。
请注意,您从 sts.AssumeRole 调用获得的凭据会在一段时间后过期(默认情况下为 15 分钟,但您可以在执行 AssumeRole 调用时将其设置得更长,直到您当前的会话最大值 API 会话持续时间,默认情况下 -- 1 小时),除非您刷新它们。
如果您需要自动刷新凭据,我在这里分享我在研究 boto 代码几个小时并尝试解决 boto 对文件系统和配置文件的依赖性后编写的代码。
这里我只是使用了内置的 boto 机制来缓存和定期刷新假定的凭据,而无需触及任何文件:
from datetime import datetime
import boto3
from botocore.credentials import (
AssumeRoleProvider,
AssumeRoleCredentialFetcher,
DeferredRefreshableCredentials,
CredentialResolver
)
from dateutil.tz import tzlocal
class CustomAssumeRoleProvider(AssumeRoleProvider):
"""
Overrides default AssumeRoleProvider to not use profiles from filesystem.
"""
def __init__(self,
source_session: boto3.Session,
assume_role_arn: str,
expiry_window_seconds: int):
super().__init__(
load_config=lambda: source_session._session.full_config,
client_creator=source_session._session.create_client,
cache={},
profile_name='not-used'
)
self.expiry_window_seconds = expiry_window_seconds
self.source_session = source_session
self.assume_role_arn = assume_role_arn
assert assume_role_arn, "assume_role_arn is required"
def load(self):
fetcher = AssumeRoleCredentialFetcher(
client_creator=self.source_session._session.create_client,
source_credentials=self.source_session.get_credentials(),
role_arn=self.assume_role_arn,
expiry_window_seconds=self.expiry_window_seconds,
cache=self.cache,
)
return DeferredRefreshableCredentials(
method=self.METHOD,
refresh_using=fetcher.fetch_credentials,
time_fetcher=lambda: datetime.now(tzlocal())
)
def get_assume_role_session(
source_session: boto3.Session,
assume_role_arn: str,
expiry_window_seconds=15 * 60
) -> boto3.Session:
"""
Creates a new boto3 session that will operate as of another user.
Source session must have permission to call sts:AssumeRole on the provided ARN,
and that ARN role must have been trusted to be assumed from this account (where source_session is from).
See https://docs.aws.amazon.com/IAM/latest/UserGuide/tutorial_cross-account-with-roles.html
Uses internal session._session to hack it together, as I haven't found another way.
"""
# must have .load() method to be used in CredentialsResolver.
provider = CustomAssumeRoleProvider(
source_session=source_session,
assume_role_arn=assume_role_arn,
expiry_window_seconds=expiry_window_seconds
)
# must have .load_credentials() method to be used in register_component()
resolver = CredentialResolver([provider])
new_session = boto3.Session()
new_session._session.register_component('credential_provider', resolver)
return new_session