2013-11-02

AWSのJavaScriptSDKのDeveloperプレビュー試してみた。(S3編)

先日AWSがJavascriptSDKのDeveloperプレビューをローンチしました。

http://aws.typepad.com/aws_japan/2013/11/developer-preview-aws-sdk-for-javascript.html

 

ということで、S3との連携をやってみました。

 

基本的な流れは

  1. Web Federationの設定

2.AWS側の設定(CORS,IAM Role等)

  1. javascriptコーディング

って感じ。

 

1. AWS Web Identity Federation

AWS Web Identity Federation ってのは別のWebサービスを利用したID連携のことです。

OpenID的なもの?

詳しくはこちら↓

http://aws.amazon.com/jp/iam/

http://docs.aws.amazon.com/STS/latest/UsingSTS/CreatingWIF.html

 

JavaScriptでKeyとSecretをハードコーディングして指定してしまうやり方も出来るんだけど、

そうするとクレデンシャルが丸見えなので

Roleでアクセスコントロールをかなり厳しくしとかないとNG。

その点Web Identity FederationはOAuthみたいにクレデンシャルを一切外部に公開しないため

セキュアということで、今回はWeb Identity Federationを採用。

 

facebookあんまり好きじゃないので天下のAmazonさん(Login with Amazon)を利用。

認証アプリの作成方法は

  1. AmazonのDeveloperアカウントをとる

  2. アプリ登録

  3. アプリのAppIDとClientIDをメモ

でOK。

 

 2.AWS側の設定(CORS,IAM Role等)

S3を利用する場合はCORSをバケットに対して設定する。

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

Web Identity FederationのためのIAM(Role)を作成する。

IAM>Role>Create New Roleで

Role for Web Identity Provider Accessを選択してあとはウィザード形式で作成。

www.amazon.com:app_idはアプリ登録で取得したApp IDを入力。

 

ポリシーはこんな感じになる。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "s3:DeleteObject",
        "s3:GetObject",
        "s3:ListBucket",
        "s3:PutObject"
      ],
      "Sid": "Stmt1383361580000",
      "Resource": [
        "arn:aws:s3:::testbucket",
        "arn:aws:s3:::testbucket/*"
      ],
      "Effect": "Allow"
    }
  ]
}

詳細はここらへん参照。

 

作成後は対象Roleのarnをメモ。

 

3. javascriptコーディング

全ての準備が整ったらあとは書くだけ!

こんな感じです。

テキトー&8割型コピペなのでご容赦を。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf8"/>
    <script src="https://sdk.amazonaws.com/js/aws-sdk-2.0.0-rc1.min.js"></script>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
    <script>
        var s3BucketName = 'testbucket';
        var url_params = get_url_vars();

        //認証後も同じページに遷移するため、access_tokenがパラメータに含まれていれば設定
        var ACCESS_TOKEN = decodeURIComponent(url_params["access_token"]);

        AWS.config.credentials = new AWS.WebIdentityCredentials({
            RoleArn: 'input your role arn',
            ProviderId: 'www.amazon.com',
            WebIdentityToken: ACCESS_TOKEN
        });

        //S3のバケットに入っているオブジェクト一覧を取得&表示
        function listObjs() {
            var s3 = new AWS.S3({ params: {Bucket: s3BucketName} });
            s3.listObjects(function(error,data) {
                if (error === null) {
                    var html_keys = '';

                    jQuery.each(data.Contents, function(index, obj) {
                       html_keys += (index + ': ' + obj.Key + '<br />');
                    });
                    jQuery("#objKeys").html(html_keys);
                } else {
                    console.log(error);
                }
            });
        }

        //アップロード
        function uploadObj() {
            var s3 = new AWS.S3({ params: {Bucket: s3BucketName}});
            var file = $("#uploadFile")[0].files[0];
            s3.putObject({
                Key: file.name,
                ContentType: file.type,
                Body: file,
            }, function (err, data) {
                console.log(err, data);
            });
        }

        function get_url_vars() {
            var vars = new Object, params;
            var temp_params = window.location.search.substring(1).split('&');
            for(var i = 0; i <temp_params.length; i++) {
                params = temp_params[i].split('=');
                vars[params[0]] = params[1];
            }
            return vars;
        }

        $(function(){

            //AmazonでログインするためのClientID設定
            window.onAmazonLoginReady = function() {
                amazon.Login.setClientId('input your app client id');
            };
            //Amazonでログインする為のスクリプトの非同期読み込み
            (function(d) {
                var a = d.createElement('script'); a.type = 'text/javascript';
                a.async = true;
                a.id = 'amazon-login-sdk';
                a.src = 'https://api-cdn.amazon.com/sdk/login1.js?v=3';
                d.getElementById('amazon-root').appendChild(a);
            })(document);

            //ログイン
            $('#LoginWithAmazon').click(function() {
                options = { scope : 'profile' };
                amazon.Login.authorize(options, 'https://localhost/js/aws/test3.html');
                return false;
            });

            //ログアウト
            $('#Logout').click(function() {
                console.log("logout");
                amazon.Login.logout();
            });

            //S3へアップロード
            $("#uploadBtn").click(uploadObj);
        });
    </script>
</head>
<body>
    <div id="amazon-root"></div>
    <a href="#" id="LoginWithAmazon">
      <img border="0" alt="Login with Amazon"
        src="https://images-na.ssl-images-amazon.com/images/G/01/lwa/btnLWA_gold_156x32.png"
        width="156" height="32" />
    </a>
    <a id="Logout">Logout</a>
    <button onclick="listObjs()">S3 - List Objects</button>

    <div id="objKeys"></div>
    <form>
        <input type="file" id="uploadFile"/>
        <input type="button" value="アップロード" id="uploadBtn">
    </form>
</body>
</html>

 

Role ArnとアプリのClientIDをそれぞれ書き込めば動きます。

 

JavaScript単体で動くっていうことはS3のStatic Web Hostingにhtml&JS置いて

S3にオブジェクト置いたり、取得したりっていうS3だけで完結するアプリが書けるようになったってこと。

しかもS3だけじゃなくてDynamoDBとかSNSとかモバイル向けのサービスにもアクセス出来る。

 

やっぱり時代の流れはモバイルか!

このエントリーをはてなブックマークに追加