AWS SDK for JavaScript をブラウザから使ってみた

こんにちは、sparkgeneです。

前からAWSのJavaScript SDKを使ってEC2のインスタンスをビジュアル表示するものを作りたくて色々とチャレンジしているのですが、ブラウザだけで完結(htmlファイル1つで)させることが中々出来ず、試しては挫折を繰り返してます。。。

一番の問題は、EC2のインスタンスの情報を取るためにEC2用のエンドポイントを叩くのですが、CORSの問題があってブラウザから直接情報を取ることが出来ない点です。

それ以外に、htmlにAPIを叩くためのシークレットキーなどをどう管理するかが気になるところですが、AWSではその対策として外部の認証プロバイダを使った方法も提供しています。
今回はその外部の認証プロバイダを使った設定方法について解説します。

元ネタとしては、こちらのGetting Startedを参考にしています。

Facebook Applicationを作成

今回のサンプルでは、認証プロバイダにFacebookを使うのでFacebookのApplication IDが必要になってきます。

こちらからアプリを追加してIDを取得してください。

IAMロールを作成

AWSマネージメントコンソールにログインしてIAMサービスを選択し、左側のメニューで"Roles"を選択してします。

Set Role Name

スクリーンショット-2014-10-15-10.28.24

ロール名を入力してNext Stepをクリック。

Select Role Type

スクリーンショット-2014-10-15-10.29.21

"Role for Identity Provider Access"を選択し、今回はFacebookを使うので"Grant access to web identity providers"のSelectをクリック。

 

スクリーンショット-2014-10-15-10.31.18

Identity ProviderでFacebookを選択し、Application Idを入力する。Next Stepをクリック。

Verify Role Trust

スクリーンショット-2014-10-15-10.33.351

Trust Pollcy DocmentはGeneratorで以下のように生成されるので問題がなければこのままで。Next Stepをクリック。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Principal": {
        "Federated": "graph.facebook.com"
      },
      "Condition": {
        "StringEquals": {
          "graph.facebook.com:app_id": "入力したFacebook Application Id"
        }
      }
    }
  ]
}
[/codescript]
<h3>Set Permissions</h3>
<a href="http://s3-ap-northeast-1.amazonaws.com/techblog.bucket/wp-content/uploads/2014/11/59d06d890d0c1838bc97d950879c315c.png" rel="shadowbox&#91;images&#93;" ><img src="http://s3-ap-northeast-1.amazonaws.com/techblog.bucket/wp-content/uploads/2014/11/59d06d890d0c1838bc97d950879c315c.png" alt="スクリーンショット-2014-10-15-10.35.02" width="819" height="245" class="aligncenter size-full wp-image-3061" /></a>
パーミッションを指定します。
今回はPolicy Generatorで指定するので、選んで<kbd>Select</kbd>をクリック。
<h3>Edit Permissions</h3>
<ul>
    <li>Effect: Allow</li>
    <li>AWS Service: "Amazon S3"を選択</li>
    <li>Actions: "PutObject"、"PutObjectAcl"にチェックを付ける</li>
    <li>Amazon Resource Name (ARN): S3の場合は以下のフォーマットで設定します。
<ul>
    <li>arn:aws:S3:::<バケット名>/<オブジェクト名></li>
    <li>今回の場合は、バケット内をすべて対象にするので、オブジェクト名のところはアスタリスクで。"arn:aws:s3:::for-browser/*"</li>
</ul>
</li>
</ul>
ここまで入力したら<kbd>Add Statement</kbd>をクリック。
続けてもう一つ追加します。
<ul>
    <li>Effect: Allow</li>
    <li>AWS Service: "Amazon S3"を選択</li>
    <li>Actions: "ListBucket"にチェックを付ける</li>
    <li>Amazon Resource Name (ARN): arn:aws:s3:::for-browser</li>
</ul>
&nbsp;
「Add Statement」をクリックすると、以下のように追加されます。
<a href="http://s3-ap-northeast-1.amazonaws.com/techblog.bucket/wp-content/uploads/2014/11/a48c92fbd38220d0927be6153c2802aa.png" rel="shadowbox&#91;images&#93;" ><img src="http://s3-ap-northeast-1.amazonaws.com/techblog.bucket/wp-content/uploads/2014/11/a48c92fbd38220d0927be6153c2802aa.png" alt="スクリーンショット-2014-10-22-11.36.08" width="703" height="466" class="aligncenter size-full wp-image-3071" /></a>
問題がなければ<kbd>Next Step</kbd>をクリック。
<h3>Set Permissions</h3>
<a href="http://s3-ap-northeast-1.amazonaws.com/techblog.bucket/wp-content/uploads/2014/11/7f5847206ac41c3fe3a4b46c5808584d.png" rel="shadowbox&#91;images&#93;" ><img src="http://s3-ap-northeast-1.amazonaws.com/techblog.bucket/wp-content/uploads/2014/11/7f5847206ac41c3fe3a4b46c5808584d.png" alt="スクリーンショット-2014-10-22-11.47.07" width="690" height="513" class="aligncenter size-full wp-image-3075" /></a>
&nbsp;
Set Permissionsで生成されたパーミッションを確認をして、<kbd>Next Step</kbd>をクリック。
&nbsp;

{
   "Version": "2012-10-17",
   "Statement": [
      {
         "Action": [
            "s3:PutObject",
            "s3:PutObjectAcl"
         ],
         "Resource": [
            "arn:aws:s3:::for-browser/*"
         ],
         "Effect": "Allow"
      },
      {
         "Action": [
            "s3:ListBucket"
         ],
         "Resource": [
            "arn:aws:s3:::for-browser"
         ],
         "Effect": "Allow"
      }
   ]
}
[/codescript]
<h3>Review</h3>
<a href="http://s3-ap-northeast-1.amazonaws.com/techblog.bucket/wp-content/uploads/2014/11/642d5035c87913d373785ddb68160882.png" rel="shadowbox&#91;images&#93;" ><img src="http://s3-ap-northeast-1.amazonaws.com/techblog.bucket/wp-content/uploads/2014/11/642d5035c87913d373785ddb68160882.png" alt="スクリーンショット-2014-10-15-10.50.09" width="561" height="211" class="aligncenter size-full wp-image-3066" /></a>
最終的に設定される内容を確認して、<kbd>Create Role</kbd>をクリック。
以上でJavaScriptのサンプルを実行するための以下の情報が揃いました。
<ul>
    <li>Facebook Application Id</li>
    <li>IAM Role</li>
</ul>
<h2>S3 バケットのCORS設定</h2>
バケットのドメインとJavaScriptが実行されるドメインが違うため、対象のバケットのCORSを正しく設定する必要があります。
マネージメントコンソールからS3を選んで、対象のバケットを選択します。
<a href="http://s3-ap-northeast-1.amazonaws.com/techblog.bucket/wp-content/uploads/2014/11/8a8a762509762fa4dcb907333d9656c2.png" rel="shadowbox&#91;images&#93;" ><img src="http://s3-ap-northeast-1.amazonaws.com/techblog.bucket/wp-content/uploads/2014/11/8a8a762509762fa4dcb907333d9656c2.png" alt="スクリーンショット-2014-10-22-10.08.56" width="876" height="478" class="aligncenter size-full wp-image-3067" /></a>
<kbd>Add CORS configuration</kbd>をクリックするとダイアログが開きますので、以下のように許可するドメインとアクションを指定します。
<a href="http://s3-ap-northeast-1.amazonaws.com/techblog.bucket/wp-content/uploads/2014/11/46288d8018146b8587ae8cc9023bfbca.png" rel="shadowbox&#91;images&#93;" ><img src="http://s3-ap-northeast-1.amazonaws.com/techblog.bucket/wp-content/uploads/2014/11/46288d8018146b8587ae8cc9023bfbca.png" alt="スクリーンショット-2014-10-22-10.09.51" width="722" height="408" class="aligncenter size-full wp-image-3068" /></a>
今回はローカルホスト上で動かすため、許可するドメインはlocalhost:8081を指定しています。

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01">
   <CORSRule>
      <AllowedOrigin>http://localhost:8081</AllowedOrigin>
      <AllowedMethod>GET</AllowedMethod>
      <AllowedMethod>PUT</AllowedMethod>
      <AllowedMethod>POST</AllowedMethod>
      <AllowedMethod>DELETE</AllowedMethod>
      <AllowedHeader>*</AllowedHeader>
   </CORSRule>
</CORSConfiguration>

入力したらSaveをクリックして保存してからダイアログを閉じます。

HTMLファイルの作成

AWSのサンプルを元にHTMLを作成します。

AWSのサンプルだとリージョンの指定が無いため、そのまま使うとデフォルトの"us-west-2"が対象となり、エラーが出てしまいます。デフォルトリージョン以外で試す場合は、以下のように指定しましょう。

AWS.config.region = 'ap-northeast-1';
[/codescript]

サンプルはGithubに上げてありますので、自分の環境に合わせて以下のソースのIDを書き換えてください。

var appId = '$$$ Facebook Application Id $$$';
var roleArn = 'arn:aws:iam::1234567890:role/for-browser';
var bucketName = 'for-browser';
[/codescript]

サンプルでは、ページ表示時にFacebookの認証が行われ、許可をすることで発行されるトークンを使って、バケットに対して操作する認証情報を付与しています。

FB.login(function (response) {
bucket.config.credentials = new AWS.WebIdentityCredentials({
ProviderId: 'graph.facebook.com',
RoleArn: roleArn,
WebIdentityToken: response.authResponse.accessToken
});
[/codescript]

実際にブラウザでサンプルを表示すると、Facebookに認証ダイアログが表示された後に以下の様な画面が表示されます。

スクリーンショット-2014-10-22-10.56.43

「ファイルを選択」でアップロードしたいファイルを選択して、アップロードしたあとにList bucketをクリックするとバケットに登録されているオブジェクトの一覧が表示されます。

スクリーンショット-2014-10-22-11.54.08

最後に

ソースを見ると分かるのですが、こっそりvue.jsを使っています。

社内でJSフレームワーク暗黒武術会なる、謎のイベントが立ち上がったので、調査のために使ってみました。

もっと調査が進んだらブログネタとして書こうと思います。