Boto3 STS AssumeRole与MFA工作示例

时间:2017-08-05 04:14:06

标签: python boto3

我在这里做错了什么?如果我使用的话,我可以通过aws cli以及boto来承担角色:

boto3.setup_default_session(profile_name="ROLE_TO_ASSUME")

我尝试做的事情:我的脚本需要运行多个AWS账户。每次我需要在不同的配置文件上运行脚本时,我已经厌倦了输入我的mfa角色。

我收到以下代码的错误消息:

 User: arn:aws:iam::<management account>:user/Ops/<my user> is not authorized to perform: sts:AssumeRole on resource

我们的AWS设置如下: 我是用户,是管理帐户组的一部分。该组具有在每个帐户上设置了ROLE_TO_ASSUME角色的信任关系。

这是我的蟒蛇:

import boto3

def main():
    boto3.setup_default_session(profile_name="default")
    ec2 = boto3.client('ec2')
    get_assumerole_credentials('arn:aws:iam::<REPLACE WITH ACCOUNTID>:role/ROLE_TO_ASSUME')

def get_assumerole_credentials(arn):
    sts_client = boto3.client('sts')
    # Use client object and pass the role ARN
    assumedRoleObject = sts_client.assume_role(RoleArn=arn,

RoleSessionName="AssumeRoleCredstashSession1")
    credentials = assumedRoleObject['Credentials']
    return dict(aws_access_key_id=credentials['AccessKeyId'],
            aws_secret_access_key=credentials['SecretAccessKey'],
            aws_session_token=credentials['SessionToken'])

if __name__ == "__main__":
    main()

这是我的〜/ .aws / config

[profile default]
region = us-west-2
output = json
aws_access_key_id=<censored>
aws_secret_access_key=<censored>

[profile ROLE_TO_ASSUME]
region = us-west-2
source_profile = default
role_arn = arn:aws:iam::<accountid>:role/ROLE_TO_ASSUME
mfa_serial = arn:aws:iam::<accountid>:mfa/<my_user>

根据第一回复编辑:
要明确的是,如果我指定了&#39;个人资料,我可以担任一个角色。参数如下例所示:

boto3.setup_default_session(profile_name='ROLE_TO_ASSUME')
ec2 = boto3.resource('ec2', region_name='us-west-1')

但是我需要在脚本中使用boto3的STS来获取角色,以获得临时证书。
当我使用boto3 STS假设角色连接方法时,我注意到没有MFA提示。

5 个答案:

答案 0 :(得分:2)

此处所有其他解决方案均不刷新假定的凭证。但是它们确实会过期(默认情况下为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 RamAssumeRoleProvider(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 = RamAssumeRoleProvider(
        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

答案 1 :(得分:1)

我认为以下内容适合您

boto3.setup_default_session(profile_name='ROLE_TO_ASSUME')
ec2 = boto3.resource('ec2', region_name='us-west-1')

因此,要获得STS临时凭证,请执行以下操作

boto3.setup_default_session(profile_name='ROLE_TO_ASSUME')
session = boto3.session.Session()
temp_credentials = session.get_credentials().get_frozen_credentials()

注意:如果第一个假设工作正常,这与MFA无关。

如果您正在寻找MFA的假定角色,请参阅假设MFA角色 http://boto3.readthedocs.io/en/latest/reference/services/sts.html#STS.Client.assume_role

答案 2 :(得分:1)

import boto3

# Prompt for MFA time-based one-time password (TOTP)
mfa_TOTP = raw_input("Enter the MFA code: ")

def role_arn_to_session(**args):
    """
    Usage :
        session = role_arn_to_session(
            RoleArn='arn:aws:iam::<ACCOUNT_NUMBER>:role/example-role',
            RoleSessionName=<'SESSION_NAME'>,
            SerialNumber='<ARN_OF_MFA_DEVICE',
            TokenCode=mfa_TOTP)
        client = session.client('ec2')
    """
    client = boto3.client('ec2')
    response = client.assume_role(**args)
    return boto3.Session(
        aws_access_key_id=response['Credentials']['AccessKeyId'],
        aws_secret_access_key=response['Credentials']['SecretAccessKey'],
        aws_session_token=response['Credentials']['SessionToken'])

答案 3 :(得分:0)

我认为如果我们需要承担角色-这就是我所做的,它会自动承担角色。步骤(Windows / Unix):

  1. 在Windows中的C:/ Users / Loginname /和Unix / home / username /
  2. 中创建目录.aws
  3. 在目录中,创建一个名为凭据的文件名(不带扩展名) 在凭据中,输入

    [default]
    aws_access_key_id=AKIAIOSFODNN7EXAMPLE
    aws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
    
  4. 在同一目录.aws中,创建一个名为config的文件名(不带扩展名)并输入以下信息

    [default]
    region=us-west-2
    role_arn=arn:aws:iam::
    source_profile=default
    
    
    import boto3
    client = boto3.client('s3')
    

    boto3会在这些默认位置查找凭据/配置文件,并在其中拾取所有访问/角色信息。

答案 4 :(得分:0)

import boto3
mfa=raw_input()
hours_required=2
device_id=<arn of mfa device>
sts_client=boto3.client('sts')
credentials=sts_client.get_session_token(DurationSeconds=hours_required*60*60,SerialNumber=device_id,TokenCode=mfa)
session=boto3.session.Session(
    aws_access_key_id=credentials['Credentials']['AccessKeyId'],
    aws_secret_access_key=credentials['Credentials']['SecretAccessKey'],
    aws_session_token=credentials['Credentials']['SessionToken']
)

现在您可以使用会话变量并使用它来创建sts客户端,并在该对象上调用承担角色。