首页 > 解决方案 > 从担任的角色担任角色

问题描述

我有一个具有执行角色的 AWS Lambda 函数

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "sts:AssumeRole",
                "logs:CreateLogGroup"
            ],
            "Resource": [
                "arn:aws:logs:eu-west-1:<acc-no>:*",
                "arn:aws:iam::<acc-no>:role/myreportingrole"
            ]
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": "arn:aws:logs:eu-west-1:<acc-no>:log-group:/aws/lambda/<func-name>:*"
        }
    ]
}

执行角色有权将 STS AssumeRole 用于同一 AWS 账户中与其他 AWS 账户中的角色具有信任关系的角色 (myreportingrole)。

我想担任 myreportingrole,然后在另一个帐户中担任角色。

我有一些 Python 代码成功地假定了 myreportingrole 并允许我查询当前帐户中的服务。但是,当我尝试从另一个帐户担任角色时,我收到 accessdenied 错误

"errorMessage": "An error occurred (AccessDenied) when calling the AssumeRole operation: User: arn:aws:sts::<acc-no>:assumed-role/<exec-role>/<func-name> is not authorized to perform: sts:AssumeRole on resource: arn:aws:iam::<diff-acc-no>:role/roleX",

这是我的 Python 代码

import json
import boto3

def assume_local_role():
    sts_connection = boto3.client('sts')
    acct_b = sts_connection.assume_role(
        RoleArn="arn:aws:iam::<acc-no>:role/myreportingrole",
        RoleSessionName="lambdaTesting"
    )
    ACCESS_KEY = acct_b['Credentials']['AccessKeyId']
    SECRET_KEY = acct_b['Credentials']['SecretAccessKey']
    SESSION_TOKEN = acct_b['Credentials']['SessionToken']
    
    client = boto3.client(
        'ec2',
        aws_access_key_id=ACCESS_KEY,
        aws_secret_access_key=SECRET_KEY,
        aws_session_token=SESSION_TOKEN
    )
    return client

def assume_role():
    sts_connection = boto3.client('sts')
    acct_b = sts_connection.assume_role(
        RoleArn="arn:aws:iam::<diff-acc-no>:role/roleX",
        RoleSessionName="lambdaTesting"
    )
    ACCESS_KEY = acct_b['Credentials']['AccessKeyId']
    SECRET_KEY = acct_b['Credentials']['SecretAccessKey']
    SESSION_TOKEN = acct_b['Credentials']['SessionToken']
    
    client = boto3.client(
        'ec2',
        aws_access_key_id=ACCESS_KEY,
        aws_secret_access_key=SECRET_KEY,
        aws_session_token=SESSION_TOKEN
    )
    return client

def lambda_handler(event, context):
    # TODO implement
    client = assume_local_role() # Assumes myreportingrole
    client2 = assume_role() # Assumes roleX
    response = client2.describe_instances()
    print(response)
    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda!')
    }

该错误表明执行角色被用来承担RoleX,没有权限。

我无法弄清楚如何myreportingroleclient2. 通常在 EC2 上,我会使用~/.aws/config and credentials,但是,作为 Lambda,我不确定这是否可能。

我的理解是

`executionRole` assumes `myreportingrole`

credentials for `myreportingrole` then assumes `roleX`

但是,我得到的是

`executionRole` assumes `myreportingrole`

`executionRole` assumes `roleX` and fails.

有没有办法将凭据从clientto传递client2

标签: python-3.xamazon-web-servicesaws-lambdaamazon-iam

解决方案


您的问题是您在assume_local_role()和中调用相同的客户端工厂assume_role()。要使用本地角色担任远程角色,您需要使用第一个角色的凭据为第二个角色创建客户端。就像您在创建 EC2 客户端时所做的一样。

它看起来像这样(我只是输入这个,可能存在语法错误,我在每个函数调用之间放置了一个空行以使流程清晰):

def create_client_with_remote_role(local_role_name, remote_role_name, client_type):

    local_assume_client = boto3.client('sts')

    local_assume_result = local_assume_client.assume_role(
        RoleArn=local_role_name,
        RoleSessionName="lambdaTesting")

    remote_assume_client = boto3.client('sts',
        aws_access_key_id=local_assume_result['Credentials']['AccessKeyId']
        aws_secret_access_key=local_assume_result['Credentials']['SecretAccessKey']
        aws_session_token=local_assume_result['Credentials']['SessionToken'])

    remote_assume_result = remote_assume_client.assume_role(
        RoleArn=remote_role_name,
        RoleSessionName="lambdaTesting")

    return boto3.client(desired_client_type,
        aws_access_key_id=remote_assume_result['Credentials']['AccessKeyId']
        aws_secret_access_key=remote_assume_result['Credentials']['SecretAccessKey']
        aws_session_token=remote_assume_result['Credentials']['SessionToken'])

推荐阅读