cloudpackエバンジェリストの吉田真吾(@yoshidashingo)です。
AWSの各リソースへのアクセスは、デフォルトでは認証なしのアクセスができないため、たとえば1つのEC2を起動し、1つのS3バケットを作成し、EC2から中身を見ようとしてもcredentialが必要というエラーになります。
$ aws s3 ls bucket-policy-control-test
Unable to locate credentials. You can configure credentials by running "aws configure".
文言のとおり `aws configure` コマンドでS3の中身を参照可能なcredentialをインスタンス内に定義すればアクセス可能になりますが、たくさんのEC2を起動した後に `aws configure` コマンドを叩いて回るのは大変ですよね。
そこで`IAM Roles for EC2`を使うと便利です。
IAM Roleを作成する
1.IAM Management ConsoleのRolesで「Create New Role」を押下する
2.Role Nameを入力する
任意の文字列で構いませんが今回はS3にだけRoleでのアクセスが可能なものを作るためこんな名前にしました
3.Roleの使い方(適用先)に合わせて`Role Type`を選択する
今回はEC2に割り当てて使うRoleを作成するので、`Amazon EC2` を選択します
4.Permissionの設定でテンプレートから`Amazon S3 Full Access`を選択する
今回割り当てるPermissionとして、S3へのフルアクセスを選択します。
5.内容を確認してContinue
6.内容を確認してCreate
7.IAM Management Consoleに該当のRoleが作成されたことを確認する
8.EC2 Management ConsoleでEC2インスタンスを作成するときに該当のRoleを指定する
RoleのPermissionが有効か確認する
該当のEC2から、credentials設定なしでアクセスできることを確認する
Roleを指定しないと以下のような出力でしたが
$ aws s3 ls bucket-policy-control-test Unable to locate credentials. You can configure credentials by running "aws configure".
Roleを指定すると、RoleのPermission指定どおりS3へのアクセスができるようになっていることが分かります。
$ aws s3 ls bucket-policy-control-test 2014-08-02 09:36:17 45 test.txt
どこにcredentialがあるの?
EC2固有の、OSの外にあるメタデータ「インスタンスメタデータ」の中にあり、インスタンスからはこちらを参照して透過的に利用できるようになってます。
$ curl http://169.254.169.254/latest/meta-data/iam/security-credentials/s3access { "Code" : "Success", "LastUpdated" : "2014-08-03T06:43:14Z", "Type" : "AWS-HMAC", "AccessKeyId" : "xxxxxxxxxxxxxxxxxxx", "SecretAccessKey" : "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "Token" : "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "Expiration" : "2014-08-03T12:58:28Z" }
S3のBucket Policyでさらに細かくアクセス制御したい
さて、このRoleを適用して起動したEC2からはS3がフル権限で利用可能です。バケットによっては、IPアドレスでファイルのPutやGetを拒否したいことがあるかもしれません。
そんなときは、該当のバケット側に個別に `Bucket Policy` を設定することができます。
1.S3 Management Consoleで該当のBucket Policyを編集する
該当のバケットのProperties(虫眼鏡アイコンを押下するとアクセス可能)から`Edit bucket policy`を押下
2.Bucket Policy Editorで以下のように編集してSaveする
{ "Statement": [ { "Sid": "", "Effect": "Deny", "Principal": { "AWS": "*" }, "Action": "s3:*", "Resource": "arn:aws:s3:::bucketname/*", "Condition": { "IpAddress": { "aws:SourceIp": "0.0.0.0/0" }, "NotIpAddress": { "aws:SourceIp": "許可するIPaddress/32" } } } ] }
3.Roleを適用した、IPアドレス許可/不許可のインスタンスからアップロード/ダウンロードしてみる
- IPアドレスが許可されている
$ aws s3 cp filename s3://bucket-policy-control-test upload: ./filename to s3://bucket-policy-control-test/filename $ aws s3 cp s3://bucket-policy-control-test/filename . download: s3://bucket-policy-control-test/filename to ./filename
- IPアドレスが許可されていない
$ aws s3 cp filename s3://bucket-policy-control-test upload failed: ./filename to s3://bucket-policy-control-test/filename A client error (AccessDenied) occurred when calling the PutObject operation: Access Denied $ aws s3 cp s3://bucket-policy-control-test/filename . A client error (Forbidden) occurred when calling the HeadObject operation: Forbidden Completed 1 part(s) with ... file(s) remaining
こんな感じでアクセス許可/拒否設定ができます。