AWS Advent Calendar 2012の9日目です。
IAM roles for EC2 instances(以下IAM roles)ってご存知でしょうか?
AWSを利用して開発していると、どうしてもAccessKeyId/SecretAccessKeyの扱いに困りますよね?
IAM rolesを利用すると、このようにプログラムやコンフィグファイルに埋め込んでいたものが、
1
2
3
4
5
| require_once 'AWSSDKforPHP/sdk.class.php';
$s3 = new AmazonS3(array(
'key' => 'xxxxxx',
'secret' => 'xxxxxx',
));
|
書かなくて良くなります^^
1
2
3
4
| require_once 'AWSSDKforPHP/sdk.class.php';
$s3 = new AmazonS3(array(
'default_cache_config' => '/tmp'
));
|
今回は、普段良く利用しているS3 Pre-signed URL生成/Direct Object UploadがIAM rolesでもちゃんと動くか検証しないとなーと前から思っていましたので、この機会にやってみることにしました。
前提条件
以下の環境で動作確認を行いました。
- Amazon Linux AMI 2012.09
- PHP 5.3.18
- php-amazon-sdk-1.5.17
IAM rolesの作成
詳細は、クラスメソッド開発ブログさんのIAM roles for EC2 instancesって何?を参照されると良いと思います。今回S3を利用する上でポイントとなる部分を説明します。
特定のバケット以下のみアクセス権を与えたいので、Edit Permissionsで、下記のように設定しました。
特定のバケットのみ操作を許可したい場合でも、ListAllMyBuckets
はすべて許可しておく必要があります。get_bucket_list()
が失敗しますので。また、特定のバケット以下のみ許可する場合に、arn:aws:s3:::[bucket]
とarn:aws:s3:::[bucket]/*
を両方書かないと、うまく動かなかったです^^;
生成されたjsonはこちらになります。
EC2インスタンスの起動
ここもポイントだけ。Launch Instance
時はClassic Wizard
を選ばないと、IAM Role
を選べなかったです。
セットアップ
最低限、必要なものだけインストールしました。
1
| sudo yum -y install php httpd php-amazon-sdk
|
S3 Pre-signed URL生成
ここからが本題です。
サンプルコードはこちらです。とってもシンプルですね。
実行すると、このように1分のみ有効なURLが生成されます。
プログラム埋め込み時は固定だったAWSAccessKeyId
も、定期的に変更されます^^
1
2
| php get_object_url.php
https://test-twingob.s3.amazonaws.com/test.txt?AWSAccessKeyId=ASIAJQ4QZDDBS22LYMGA&Expires=1355056156&Signature=Zq9j1K6eG9zDjzA7uUrgIRr2i10%3D&x-amz-security-token=AQoDYXdzEC0agALr%2BzwOiErKaI1Jd1kg7Ejc1zx5TpExGmaYG2VliSjiOX%2BHZ09j9397tnGlcKthKixDTUDf49tHssOxAuyLAK5vM5jjz%2BA6CM4jZUz43%2FN4BbMWI%2FnyN2Bdf96xGrkOp1puOqoXt0hk134%2BqUEySXtSFIds8S%2B4Ijn0Oa7hlaVykkhfcx6YErTOfS6mc6U3DjkxZB9P9ia6c%2FlGEFexUzNVYi1hvgxTshBHA8bi%2FMXqhLNeY5XoDJ13S4Ym8BxD0N2P0thlEMF80xb9WcRyhuFWn4xumUSbdWYAcvXbrKR9mwbeY0qeRRUzBBAwSM%2BJM4rH8X5tLQQs4OCC7bCVx0EJIJvpkYYF
|
Direct Object Upload
CDPのDirect Object Uploadパターンになります。PHPで簡単に実現する方法ないかなーと思って探していたら、S3BrowserUploadを見つけました!自分でpolicyやsignature生成しなくても良いので、とっても便利!でも落とし穴が^^;
IAM rolesでAPIを利用するときに必要なx-amz-security-token
を自動で付与してくれないんですよね。付与しない状態で動かすと、
とエラーが出力されて、アップロードに失敗します。かなりググって悩みました。
サンプルコードはこちらです。x-amz-security-token
が解決できれば、すごくシンプルに書くことができました。
実行すると、このようなHTMLが生成されます。このフォームも表示後1分のみ有効です。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| curl http://localhost/post_object.php
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
</head>
<body>
<form action="http://test-twingob.s3.amazonaws.com/"
method="POST"
enctype="multipart/form-data">
<input type="hidden" name="AWSAccessKeyId" value="ASIAJQ4QZDDBS22LYMGA">
<input type="hidden" name="success_action_status" value="201">
<input type="hidden" name="acl" value="private">
<input type="hidden" name="Content-Disposition" value="attachment; filename=00000001.txt">
<input type="hidden" name="Content-Type" value="text/">
<input type="hidden" name="key" value="00000001.txt">
<input type="hidden" name="success_action_redirect" value="http://twingo-b.github.com/?id=00000001">
<input type="hidden" name="x-amz-security-token" value="AQoDYXdzEC0agALr+zwOiErKaI1Jd1kg7Ejc1zx5TpExGmaYG2VliSjiOX+HZ09j9397tnGlcKthKixDTUDf49tHssOxAuyLAK5vM5jjz+A6CM4jZUz43/N4BbMWI/nyN2Bdf96xGrkOp1puOqoXt0hk134+qUEySXtSFIds8S+4Ijn0Oa7hlaVykkhfcx6YErTOfS6mc6U3DjkxZB9P9ia6c/lGEFexUzNVYi1hvgxTshBHA8bi/MXqhLNeY5XoDJ13S4Ym8BxD0N2P0thlEMF80xb9WcRyhuFWn4xumUSbdWYAcvXbrKR9mwbeY0qeRRUzBBAwSM+JM4rH8X5tLQQs4OCC7bCVx0EJIJvpkYYF">
<input type="hidden" name="policy" value="eyJjb25kaXRpb25zIjpbeyJidWNrZXQiOiJ0ZXN0LXR3aW5nb2IifSx7InN1Y2Nlc3NfYWN0aW9uX3N0YXR1cyI6IjIwMSJ9LHsiYWNsIjoicHJpdmF0ZSJ9LHsiQ29udGVudC1EaXNwb3NpdGlvbiI6ImF0dGFjaG1lbnQ7IGZpbGVuYW1lPTAwMDAwMDAxLnR4dCJ9LFsic3RhcnRzLXdpdGgiLCIkQ29udGVudC1UeXBlIiwidGV4dFwvIl0seyJrZXkiOiIwMDAwMDAwMS50eHQifSx7InN1Y2Nlc3NfYWN0aW9uX3JlZGlyZWN0IjoiaHR0cDpcL1wvdHdpbmdvLWIuZ2l0aHViLmNvbVwvP2lkPTAwMDAwMDAxIn0seyJ4LWFtei1zZWN1cml0eS10b2tlbiI6IkFRb0RZWGR6RUMwYWdBTHIrendPaUVyS2FJMUpkMWtnN0VqYzF6eDVUcEV4R21hWUcyVmxpU2ppT1grSFowOWo5Mzk3dG5HbGNLdGhLaXhEVFVEZjQ5dEhzc094QXV5TEFLNXZNNWpqeitBNkNNNGpaVXo0M1wvTjRCYk1XSVwvbnlOMkJkZjk2eEdya09wMXB1T3FvWHQwaGsxMzQrcVVFeVNYdFNGSWRzOFMrNElqbjBPYTdobGFWeWtraGZjeDZZRXJUT2ZTNm1jNlUzRGpreFpCOVA5aWE2Y1wvbEdFRmV4VXpOVllpMWh2Z3hUc2hCSEE4YmlcL01YcWhMTmVZNVhvREoxM1M0WW04QnhEME4yUDB0aGxFTUY4MHhiOVdjUnlodUZXbjR4dW1VU2JkV1lBY3ZYYnJLUjltd2JlWTBxZVJSVXpCQkF3U00rSk00ckg4WDV0TFFRczRPQ0M3YkNWeDBFSklKdnBrWVlGIn1dLCJleHBpcmF0aW9uIjoiMjAxMi0xMi0wOVQxMjo1Njo1OVoifQ==">
<input type="hidden" name="signature" value="xjyu5PRSm0mZLg5s6yvbH4FUY9I=">
<input type="file" name="file">
<input type="submit" name="upload" value="Upload">
</form>
</body>
</html>
|
さいごに
ちゃんと動いてよかった^^。動かなくてS3BrowserUpload
のgithubのソースコード見てたら、authorがラスベガスのre:Inventでお会いしたJeremyさんでした。ちょっとほっこりした^^