使用Python的用户身份验证

时间:2017-12-09 06:28:51

标签: python django amazon-web-services boto aws-api-gateway

我正在使用Python(3.6)&amp ;; Django(1.10),其中我使用aws apis,但我不熟悉aws并且不知道如何验证用户。

我的方案是: 我需要访问用户的资源,例如项目列表存储桶列表等,为此,我需要验证用户向特定API发出请求。

我怎么能在python中做到这一点? 我是aws的新手。所以,请不要介意我的问题。

  

更新

这是我尝试过的: 来自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))
  

现在,它返回: botocore.exceptions.ClientError:调用AssumeRole操作时发生错误(InvalidClientTokenId):请求中包含的安全令牌无效。

请帮帮我!

提前致谢!

3 个答案:

答案 0 :(得分:2)

我不确定为什么其他人会建议你不能这样做。这是完全正常且得到良好支持的 - 许多AWS账户用户允许第三方代表用户在用户的AWS账户中运营。例如,任何第三方监控服务或成本分析服务。

[糟糕的方式]第一种方法是简单地向用户询问IAM凭证(访问密钥和密钥)。您的应用可以使用这些访问用户的AWS账户。这很简单,但不要这样做。

[好方法]更好的方法是通过跨账户访问。您拥有AWS账户,并且您的用户拥有AWS账户。您指示用户使用适当的IAM策略(您的应用程序需要的最小权限集)在其帐户中创建IAM角色,并指示用户如何允许您的帐户在用户的帐户中担任此角色 - 为此您宣传所需的IAM政策和您的AWS账号。然后,用户可以创建IAM策略,使用该策略创建角色,然后在您的帐户之间建立信任关系,以便您可以假设IAM角色并在其帐户中运行。有关更多信息,请参阅herehere

答案 1 :(得分:0)

目前不存在让用户登录其AWS账户以允许您的应用访问其AWS资源的功能。可能需要考虑的工作是为用户提供直接链接,以创建具有特定托管策略的IAM角色,从而允许特定的AWS账户。然后,您可以将其包含在注册流程中,并在需要访问用户帐户中的资源时承担该角色。

示例链接:

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

答案 2 :(得分:0)

请注意,您从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