【问题标题】:IAM policy/role setup for Start and Stop EC2 instances in a different AWS account在不同 AWS 账户中启动和停止 EC2 实例的 IAM 策略/角色设置
【发布时间】:2022-01-15 10:24:55
【问题描述】:

我想从另一个 AWS 账户(账户:BBB)启动和停止 AWS 账户(账户:AAA)中的 EC2 实例。具体来说,我在 Account BBB 中的 ECS 上设置了一个 API 来执行此操作。当我测试用于启动和停止同一帐户中的帐户的 API 时,它运行良好。但是,我无法让 IAM 角色跨多个帐户正常工作。

我的 API 使用 boto3 并使用 describe_instance_status 来识别实例状态,然后使用 start_instances 或 stop_instances 来启动/停止。只要 EC2 实例与托管 API 的 ECS 位于同一账户中,所有这些都可以正常工作。

跨多个帐户进行此操作。我执行了以下操作,但出现错误:

"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."

我的设置如下:

  1. 在托管 EC2 实例的账户 AAA 中,我创建了如下所示的策略。 BBB 代表托管运行 API 的 ECS 任务的帐户。
{
    "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. 创建了一个角色 (ec2-instance-mgmt-role),该角色使用上述策略并与 Account: BBB 建立信任关系。

  2. 在 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. 在帐户 BBB 中,我创建了一个附加了 (3) 中的策略的角色。此外,我为此角色创建了与 ecs-tasks 的信任关系。

我的 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. 将步骤 (4) 中创建的角色分配为 ECS 任务的任务角色,该任务定义了为启动和停止 EC2 实例而构建的 API 的容器。 ECS 实例在账户 BBB 中运行。

当我尝试调用此 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."

【问题讨论】:

    标签: amazon-web-services amazon-iam amazon-ecs


    【解决方案1】:

    最后,我能够解决这个问题。我错过的是我没有承担 boto3 代码中的角色。一旦添加它就可以了。下面的代码显示了被调用来承担角色的函数,下面的代码显示了在承担角色后描述 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)
    
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-06-01
      • 2017-10-01
      • 2019-08-03
      • 2017-09-21
      • 2015-03-13
      • 1970-01-01
      • 2021-04-25
      相关资源
      最近更新 更多