如何(安全地)使用cloudinit将私有S3资产下载到新的EC2实例上?

时间:2012-07-06 15:59:04

标签: amazon-s3 amazon-web-services amazon-cloudformation cloud-init

我正在使用CloudFormation来管理Tomcat网络服务器堆栈,但我厌倦了为新的应用程序版本进行原始AMI管理。我想向厨师方向走,但现在没有时间。相反,我试图在网络服务器实例化中克服一个简单的问题:当新机器启动时,如何下载“当前”WAR?

我的想法是利用私有S3存储桶和cloudinit,但我对IAM凭据的处理方式感到有点困惑。我可以将它们放在模板的用户数据中,但我不愿意这样做,特别是因为我是控制该文件的版本。我能想到的唯一选择是在AMI本身中使用环境变量。它们必须是纯文本,但是......呃,如果你可以打破我的实例,你可以压缩并下载我的整个网络服务器。只要IAM用户不被重复用于任何其他用户并且定期轮换,这似乎是解决问题的合理方法。我错过了什么吗?如何使用cloudinit安全地下载私有S3资产?

4 个答案:

答案 0 :(得分:16)

亚马逊最近宣布了一项新功能,您可以在其中为您的EC2实例提供“IAM角色”。这使得允许特定实例具有读取特定S3资源的权限非常容易。

这是他们宣布新功能的博文:

http://aws.typepad.com/aws/2012/06/iam-roles-for-ec2-instances-simplified-secure-access-to-aws-service-apis-from-ec2.html

以下是EC2文档中的部分:

http://docs.amazonwebservices.com/AWSEC2/latest/UserGuide/UsingIAM.html#UsingIAMrolesWithAmazonEC2Instances

以下是IAM文档中的部分:

http://docs.amazonwebservices.com/IAM/latest/UserGuide/WorkingWithRoles.html

IAM角色通过HTTP使实例可以使用凭据,因此在实例上运行的任何用户或进程都可以看到它们。

答案 1 :(得分:15)

稍微更新一下这个问题的答案:

与IAM角色一起,新的AWS command-line client使得获取这些资产变得微不足道。它将自动从环境中提取通过IAM提供的AWS凭证,并处理这些凭据的刷新。

以下是在用户数据脚本中从安全S3存储桶中获取单个资产的示例:

# Install the AWS command-line tools
pip install awscli

# Fetch the asset
aws s3 cp --region us-east-1 s3://my-private-bucket/a-folder/an-asset.zip /some/destination

这很简单。您还可以从S3复制整个目录内容并上传等。有关详细信息和选项,请参阅the reference material

答案 2 :(得分:5)

具有IAM角色的实例具有自动轮换的临时安全凭证。它们可以通过http http://169.254.169.254/latest/meta-data/iam/security-credentials/RoleName获得,其中RoleName就是您所谓的角色。因此,它们很容易从您的实例中获取,但它们会定期过期。

使用它们有点困难。 CloudFormation无法直接使用临时凭证。 Amazon Linux AMI安装了Python boto,现在它足够聪明,可以自动为您查找和使用这些凭据。您可以在脚本中添加一个单行程序,用于从S3存储桶 b ,键 k 获取文件 f

python -c "import boto;boto.connect_s3().get_bucket('b').get_key('k').get_contents_to_filename('f')"

boto为您查找并使用该角色的临时凭证,这使其非常易于使用。

答案 3 :(得分:3)

要将私有S3资产安全地下载到新的EC2实例,您应该使用IAM Roles for EC2向您的EC2实例授予必要的S3权限,然后在您的实例中调用aws s3 cp { {3}} UserData下载资产。

要从CloudFormation模板为EC2设置IAM角色,请使用cloudinit script资源,引用具有AssumeRolePolicyDocument ec2.amazonaws.com 's3:GetObject'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 个权限的AWS::IAM::InstanceProfile资源,针对AWS::IAM::Role设计的政策(在这种情况下,仅允许bookID下载特定的S3资产。)

这是一个完整的示例模板,可以使用cloudinit将S3资产下载到新的EC2实例上,并将其内容作为grant least privilege返回:

Stack Output

BookComponent