简体   繁体   English

在不同 AWS 账户中启动和停止 EC2 实例的 IAM 策略/角色设置

[英]IAM policy/role setup for Start and Stop EC2 instances in a different AWS account

I would like to start and stop EC2 instances in an AWS account (Account: AAA) from another AWS account (Account: BBB).我想从另一个 AWS 账户(账户:BBB)启动和停止 AWS 账户(账户:AAA)中的 EC2 实例。 Specifically, I am setting up an API to do this on ECS in Account BBB.具体来说,我正在设置 API 以在账户 BBB 中的 ECS 上执行此操作。 When I tested the API for starting and stopping the accounts in the same Account it worked fine.当我测试 API 以启动和停止同一帐户中的帐户时,它工作正常。 However, I am not able to get the IAM roles to work across multiples accounts right.但是,我无法让 IAM 角色正确地跨多个账户工作。

My API uses boto3 and uses describe_instance_status to identify the instance status and then uses start_instances or stop_instances to start/stop.我的 API 使用 boto3 并使用 describe_instance_status 识别实例状态,然后使用 start_instances 或 stop_instances 启动/停止。 All this works fine as long as the EC2 instances are in the same account as the ECS that hosts the API.只要 EC2 实例与托管 API 的 ECS 位于同一账户中,所有这些都可以正常工作。

To work this across multiple Accounts.跨多个帐户工作。 I did the following but I am getting the error:我做了以下,但我得到了错误:

"botocore.exceptions.ClientError: An error occurred (UnauthorizedOperation) when calling the DescribeInstanceStatus operation: You are not authorized to perform this operation.botocore.exceptions.ClientError: An error occurred (UnauthorizedOperation) when calling the DescribeInstanceStatus operation: You are not authorized to perform this operation."

My setup is as follows:我的设置如下:

  1. In the account AAA that hosts the EC2 instances I created a policy that looks like below.在托管 EC2 实例的账户 AAA 中,我创建了一个如下所示的策略。 BBB stands for the Account hosting the ECS task that runs the API. BBB 代表托管 ECS 任务的账户,该任务运行 API。
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "ec2:DescribeInstanceStatus",
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "ec2:StartInstances",
                "ec2:StopInstances"
            ],
            "Resource": "arn:aws:ec2:*:AAA:instance/*",
            "Condition": {
                "StringEqualsIgnoreCase": {
                    "ec2:ResourceTag/ManagedBy": "API"
                }
            }
        }
    ]
  1. Created a role (ec2-instance-mgmt-role) that uses the above policy with a trust relationship to Account: BBB.创建了一个角色 (ec2-instance-mgmt-role),该角色使用上述策略并与 Account: BBB 建立信任关系。

  2. In Account BBB, I created a policy (ec2-assume-managerole) that looks like below where AAA is the account name of the account that hosts the EC2 instances.在 Account BBB 中,我创建了一个策略 (ec2-assume-managerole),如下所示,其中 AAA 是托管 EC2 实例的帐户的帐户名称。

{
    "Version": "2012-10-17",
    "Statement": {
        "Effect": "Allow",
        "Action": "sts:AssumeRole",
        "Resource": "arn:aws:iam::AAA:role/ec2-instance-mgmt-role"
    }
} 
  1. In Account BBB, I created a role with the policy in (3) attached.在 Account BBB 中,我创建了一个附加了 (3) 中的策略的角色。 Additionally, I created the trust relationship to ecs-tasks for this role.此外,我为此角色创建了与 ecs-tasks 的信任关系。

Fragment of my boto3 code to start is below:我要开始的 boto3 代码片段如下:

ec2 = boto3.client('ec2', region_name=region_name)

resp = ec2.describe_instance_status(
        InstanceIds=[str(instance_id)],
        IncludeAllInstances=True)

print("Response = ",resp)

instance_status = resp['InstanceStatuses'][0]['InstanceState']['Code']

print("Instance status =", instance_status)

if instance_status == 80:
    ec2.start_instances(InstanceIds=[instance_id])
    print("Started instance with Instance_id",instance_id)
    return {'message': 'instance started'}
else:
     print("Instance not in a state to start")
     return {'message': 'instance not in a state to be started'}
  1. Assigned the role created in Step (4) as the Task Role of the ECS Task that defines the Container of the API that is built to start and stop EC2 instances.将步骤 (4) 中创建的角色分配为 ECS 任务的任务角色,该任务定义为启动和停止 EC2 实例而构建的 API 的容器。 The ECS instance is running in account BBB. ECS 实例在账户 BBB 中运行。

When I try to call this API I get the error described in the beginning which is pasted below as well.当我尝试调用此 API 时,我收到开头描述的错误,该错误也粘贴在下面。

"botocore.exceptions.ClientError: An error occurred (UnauthorizedOperation) when calling the DescribeInstanceStatus operation: You are not authorized to perform this operation.botocore.exceptions.ClientError: An error occurred (UnauthorizedOperation) when calling the DescribeInstanceStatus operation: You are not authorized to perform this operation."

Finally, I was able to solve this problem.最后,我能够解决这个问题。 What I had missed was I was not assuming the role in the boto3 code.我错过的是我没有承担 boto3 代码中的角色。 Once that was added it worked.一旦添加它就可以了。 Following code shows the function that is called to assume role and the code below that shows the usage to describe ec2 instance status after assuming the role.下面的代码显示了被调用来承担角色的 function,下面的代码显示了在承担角色后描述 ec2 实例状态的用法。

def assume_role(role_arn):
    sts_client = boto3.client('sts')

    letters = string.ascii_letters
    session_name = f"AssumeRoleSession{random.choice(letters)}"
    assumed_role_object=sts_client.assume_role(
        RoleArn=role_arn,
        RoleSessionName=session_name
    )

    credentials=assumed_role_object['Credentials']

    print(f"Credentials: {credentials}")

    ec2_resource=boto3.resource(
                                    'ec2',
                                    aws_access_key_id=credentials['AccessKeyId'],
                                    aws_secret_access_key=credentials['SecretAccessKey'],
                                    aws_session_token=credentials['SessionToken'],
                                )


    return ec2_resource


 ec2_resource = assume_role(assume_role_arn)
  
 ec2 = ec2_resource.meta.client

 resp = ec2.describe_instance_status(
            InstanceIds=[str(instance_id)],
            IncludeAllInstances=True)


声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM