How can I (securely) download a private S3 asset onto a new EC2 instance with cloudinit?

前端 未结 4 872
清歌不尽
清歌不尽 2020-12-08 11:26

I\'m using CloudFormation to manage a Tomcat webserver stack but am tired of doing raw AMI management for new application versions. I\'d like to move in the direction of Che

4条回答
  •  無奈伤痛
    2020-12-08 12:12

    To securely download a private S3 asset onto a new EC2 instance, you should use IAM Roles for EC2 to grant the necessary S3 permission to your EC2 instance, then call aws s3 cp in your instance's UserData cloudinit script to download the asset.

    To setup an IAM Role for EC2 from a CloudFormation template, use the AWS::IAM::InstanceProfile resource, referencing an AWS::IAM::Role resource with an AssumeRolePolicyDocument delegating access to ec2.amazonaws.com, with a Policy designed to grant least privilege (in this case, allowing 's3:GetObject' only for the specific S3 asset being downloaded).

    Here's a full example template that downloads an S3 asset onto a new EC2 instance using cloudinit, returning its contents as a Stack Output:

    Description: (securely) download a private S3 asset onto a new EC2 instance with cloudinit
    Parameters:
      S3Bucket:
        Description: S3 bucket name
        Type: String
      S3Key:
        Description: S3 object key
        Type: String
    Mappings:
      # amzn-ami-hvm-2016.09.1.20161221-x86_64-gp2
      RegionMap:
        us-east-1:
          "64": "ami-9be6f38c"
    Resources:
      EC2Role:
        Type: AWS::IAM::Role
        Properties:
          AssumeRolePolicyDocument:
            Version: 2012-10-17
            Statement:
            - Effect: Allow
              Principal: {Service: [ ec2.amazonaws.com ]}
              Action: ["sts:AssumeRole"]
          Path: /
          Policies:
          - PolicyName: EC2Policy
            PolicyDocument:
              Version: 2012-10-17
              Statement:
              - Effect: Allow
                Action: ['s3:GetObject']
                Resource: !Sub 'arn:aws:s3:::${S3Bucket}/${S3Key}'
      RootInstanceProfile:
        Type: AWS::IAM::InstanceProfile
        Properties:
          Path: /
          Roles: [ !Ref EC2Role ]
      WebServer:
        Type: AWS::EC2::Instance
        Properties:
          ImageId: !FindInMap [ RegionMap, !Ref "AWS::Region", 64 ]
          InstanceType: m3.medium
          IamInstanceProfile: !Ref RootInstanceProfile
          UserData:
            "Fn::Base64":
              !Sub |
                #!/bin/bash
                DATA=$(aws s3 cp s3://${S3Bucket}/${S3Key} -)
                /opt/aws/bin/cfn-signal \
                  -e $? \
                  -d "$DATA" \
                  '${Handle}'
      Handle:
        Type: AWS::CloudFormation::WaitConditionHandle
      Wait:
        Type: AWS::CloudFormation::WaitCondition
        Properties:
          Handle: !Ref Handle
          Timeout: 300
    Outputs:
      Result:
        Value: !GetAtt Wait.Data
    

提交回复
热议问题