使用 Python 的 aws 用户身份验证

User Authentication for aws using Python

我正在使用 Python(3.6) & Django(1.10) 开发一个项目,我在其中使用了 aws api,但我是 aws 的新手,不知道如何验证一个用户。

我的场景是: 我需要访问用户的 aws 资源,例如 projects listbuckets 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:

https://console.aws.amazon.com/iam/home?region=us-west-2#/roles$new?step=review&roleType=crossAccount&accountID=123412341234&policies=arn:aws:iam::aws:policy%2FAdministratorAccess&roleName=AdminAccessForServiceName

我不确定为什么其他人建议您不能这样做。这是完全正常且得到良好支持的——许多 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