【问题标题】:Assume a Role from an Assumed Role从担任的角色担任角色
【发布时间】:2021-03-03 20:35:21
【问题描述】:

我有一个具有执行角色的 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 并允许我查询当前帐户中的服务。但是,当我尝试从另一个帐户担任角色时,我会收到拒绝访问错误

"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,它没有权限。

我不知道如何在client2 中使用myreportingrole。通常在 EC2 上,我会使用 ~/.aws/config and credentials,但是,作为 Lambda,我不确定这是否可行。

我的理解是这样的

`executionRole` assumes `myreportingrole`

credentials for `myreportingrole` then assumes `roleX`

然而,我得到的是

`executionRole` assumes `myreportingrole`

`executionRole` assumes `roleX` and fails.

有没有办法将凭据从client 传递到client2

【问题讨论】:

    标签: python-3.x amazon-web-services aws-lambda amazon-iam


    【解决方案1】:

    您的问题是您在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'])
    

    【讨论】:

    • 谢谢,这行得通。我的假设是某种形式的处理凭证的 AWS 魔法。看起来将凭据传递给 client2 会起作用。
    【解决方案2】:

    您需要在用于跨账户角色的 IAM 角色定义中添加“信任”语句。为了安全起见,您还应该添加一个带有外部 ID 的条件。以下类似:

    AssumeRolePolicyDocument:
      Version: "2012-10-17"
      Statement:
        Effect: Allow
        Principal:
          AWS: <source-aws-account-id>
        Condition:
          StringEquals:
            "sts:ExternalId": <some-unique-identifier>
        Action:
          - "sts:AssumeRole"
    

    【讨论】:

    • myreportingrole 与 roleX 有信任关系,允许执行角色承担 myreportingrole。同意 externalId,我在测试时保留了它
    猜你喜欢
    • 2020-11-08
    • 1970-01-01
    • 2020-09-16
    • 2018-09-10
    • 2021-03-09
    • 1970-01-01
    • 2022-07-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多