17

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

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

4

4 回答 4

17

Amazon 最近宣布了一项新功能,您可以在其中为您的 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 向实例提供凭证,因此在实例上运行的任何用户或进程都可以看到它们。

于 2012-07-06T20:46:21.303 回答
15

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

与 IAM 角色一起,新的AWS 命令​​行客户端使获取这些资产变得轻而易举。它将自动从环境中提取通过 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 复制整个目录内容并上传等。有关更多详细信息和选项,请参阅参考资料

于 2013-10-02T15:33:54.333 回答
5

具有 IAM 角色的实例具有自动轮换的临时安全凭证。它们可以通过 http at 获得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 为您查找并使用该角色的临时凭证,这使得它非常易于使用。

于 2012-12-20T14:45:19.423 回答
5

要安全地将私有 S3 资产下载到新的 EC2 实例上,您应该使用EC2 的IAM 角色向您的 EC2 实例授予必要的 S3 权限,然后调用aws s3 cp您实例的UserData cloudinit 脚本来下载资产。

要从 CloudFormation 模板为 EC2 设置 IAM 角色,请使用AWS::IAM::InstanceProfile资源,引用具有AWS::IAM::Role对 的AssumeRolePolicyDocument委派访问权限的资源ec2.amazonaws.com,以及旨在授予最低权限的策略(在这种情况下,'s3:GetObject'仅允许下载特定的 S3 资产)。

这是一个完整的示例模板,它使用 cloudinit 将 S3 资产下载到新的 EC2 实例上,并将其内容作为堆栈输出返回:

启动堆栈

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
于 2017-01-05T23:37:05.110 回答