CloudFormationを使用してTomcatWebサーバースタックを管理していますが、新しいアプリケーションバージョンの生のAMI管理を行うのにうんざりしています。シェフの方に移動したいのですが、今は時間がありません。代わりに、Webサーバーのインスタンス化における単純な問題を克服しようとしています。新しいマシンが起動したときに「現在の」WARをダウンロードするにはどうすればよいですか。
私の考えはプライベートS3バケットとcloudinitを利用することでしたが、IAM認証情報をどう処理するかについて少し困惑しています。それらをテンプレートのユーザーデータに入れることはできますが、特にそのファイルをバージョン管理しているので、そうするのは嫌です。私が考えることができる唯一の選択肢は、AMI自体で環境変数を使用することです。それらはプレーンテキストである必要がありますが...ええと、私のインスタンスに侵入できれば、ジップアップして私のWebサーバー全体をダウンロードできます。 IAMユーザーが他の目的で再利用されず、定期的にローテーションされる限り、問題を解決するための合理的な方法のように思われます。私は何かが足りませんか? cloudinitを使用してプライベートS3アセットを安全にダウンロードするにはどうすればよいですか?
Amazonは最近、EC2インスタンスに「IAMロール」を与えることができる新機能を発表しました。これにより、特定のインスタンスに特定のS3リソースを読み取る権限を与えることがかなり簡単になります。
新機能を発表した彼らのブログ投稿は次のとおりです。
EC2ドキュメントのセクションは次のとおりです。
IAMドキュメントのセクションは次のとおりです。
http://docs.amazonwebservices.com/IAM/latest/UserGuide/WorkingWithRoles.html
IAMロールは、HTTPを介してインスタンスが認証情報を利用できるようにするため、インスタンスで実行されているすべてのユーザーまたはプロセスが認証情報を表示できます。
この質問への回答を少し更新するには:
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からディレクトリの内容全体をコピーしてアップロードすることもできます。詳細とオプションについては、 参考資料 を参照してください。
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は、ロールの一時的な資格情報を見つけて使用します。これにより、非常に使いやすくなります。
プライベートS3アセットを新しいEC2インスタンスに安全にダウンロードするには、EC2の IAMロール を使用してEC2インスタンスに必要なS3アクセス許可を付与してから、 aws s3 cp
インスタンスの UserDatacloudinitスクリプト でアセットをダウンロードします。
CloudFormationテンプレートからEC2のIAMロールを設定するには、 AWS::IAM::InstanceProfile
リソースを使用し、 AWS::IAM::Role
リソースをAssumeRolePolicyDocument
ec2.amazonaws.com
へのアクセスを委任し、 最小特権 を付与するように設計されたポリシーを使用します(この場合、ダウンロードされる特定のS3アセットに対してのみ's3:GetObject'
を許可します)。
これは、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