web-dev-qa-db-ja.com

cloudinitを使用してプライベートS3アセットを新しいEC2インスタンスに(安全に)ダウンロードするにはどうすればよいですか?

CloudFormationを使用してTomcatWebサーバースタックを管理していますが、新しいアプリケーションバージョンの生のAMI管理を行うのにうんざりしています。シェフの方に移動したいのですが、今は時間がありません。代わりに、Webサーバーのインスタンス化における単純な問題を克服しようとしています。新しいマシンが起動したときに「現在の」WARをダウンロードするにはどうすればよいですか。

私の考えはプライベートS3バケットとcloudinitを利用することでしたが、IAM認証情報をどう処理するかについて少し困惑しています。それらをテンプレートのユーザーデータに入れることはできますが、特にそのファイルをバージョン管理しているので、そうするのは嫌です。私が考えることができる唯一の選択肢は、AMI自体で環境変数を使用することです。それらはプレーンテキストである必要がありますが...ええと、私のインスタンスに侵入できれば、ジップアップして私のWebサーバー全体をダウンロードできます。 IAMユーザーが他の目的で再利用されず、定期的にローテーションされる限り、問題を解決するための合理的な方法のように思われます。私は何かが足りませんか? cloudinitを使用してプライベートS3アセットを安全にダウンロードするにはどうすればよいですか?

16
Christopher

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を介してインスタンスが認証情報を利用できるようにするため、インスタンスで実行されているすべてのユーザーまたはプロセスが認証情報を表示できます。

16
Eric Hammond

この質問への回答を少し更新するには:

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からディレクトリの内容全体をコピーしてアップロードすることもできます。詳細とオプションについては、 参考資料 を参照してください。

15
James van Dyke

IAMロールを持つインスタンスには、自動的にローテーションされる一時的なセキュリティ認証情報があります。これらはhttpのhttp://169.254.169.254/latest/meta-data/iam/security-credentials/RoleNameから入手できます。ここで、RoleNameはあなたが自分の役割と呼んだものです。そのため、インスタンスから簡単に取得できますが、定期的に期限切れになります。

それらを使用するのは少し難しいです。 CloudFormationは、一時的な認証情報を直接使用することはできません。 Amazon LinuxAMIには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は、ロールの一時的な資格情報を見つけて使用します。これにより、非常に使いやすくなります。

5
Charles Engelke

プライベートS3アセットを新しいEC2インスタンスに安全にダウンロードするには、EC2の IAMロール を使用してEC2インスタンスに必要なS3アクセス許可を付与してから、 aws s3 cp インスタンスの UserDatacloudinitスクリプト でアセットをダウンロードします。

CloudFormationテンプレートからEC2のIAMロールを設定するには、 AWS::IAM::InstanceProfile リソースを使用し、 AWS::IAM::Role リソースをAssumeRolePolicyDocumentec2.amazonaws.comへのアクセスを委任し、 最小特権 を付与するように設計されたポリシーを使用します(この場合、ダウンロードされる特定のS3アセットに対してのみ's3:GetObject'を許可します)。

これは、cloudinitを使用してS3アセットを新しいEC2インスタンスにダウンロードし、そのコンテンツを スタック出力 として返す完全なサンプルテンプレートです。

Launch Stack

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
3
wjordan