AWS SDK for JavaScriptでAmazon S3とDynamoDBをクライアントサイドJavaScriptのみで操作する
久保田です。
AWS SDK for JavaScriptのデベロッパープレビューがリリースされま した。AWSは今までウェブサービスのサーバサイドからしか扱えませんでしたが、このライブラリを用いることで、AWSのサービスをクライアントサイドのJavaScriptからでも操作できるようになります。つまり、IaaSとして利用できるAWSをサーバサイドのプログラム無しでBaaSのように扱うことができます。最も有名なBaaSの一つであるParse.comもバックエンドにはAWSを利用していることが知られていますが、今回登場したAWS SDK for JavaScriptを用いるとParse.comのようなBaaSと同じようなことがAWSでもできるのではないかと注目されているようです。
この記事では、AWSで提供されているファイルストレージのS3と分散キーバリューストアのDynamoDBを、AWS SDK for JavaScriptを使ってクライアントサイドJavaScriptから扱う例を紹介します。
Amazon S3をJavaScriptから扱う
ファイルストレージのS3をJavaScriptから扱う例を最初に紹介します。
Facebookアカウントで認証してS3にファイルをアップロードする例を紹介します。その次に、埋め込みのクレデンシャルを用いて認証無しでS3を操作する例を紹介します。
S3バケットを作成する
まずは、 JavaScriptで操作するためのS3バケットを作成します。
AWS Management Consoleにアクセスして、S3の管理画面に移動します。「Create Bucket」をクリックして、JavaScriptから操作するS3のバケットを作成します。
S3のバケットを作成したら、次にそのS3に対して他のドメインからAjaxでアクセスできるようにするために、CORS(Cross Origin Resource Sharering)を設定します。作成したBucketの詳細からPermissionsを選択して、「Add CORS Configulation」をクリックすると、CORSを設定ダイアログが表示されます。
ここに、以下の設定を貼り付けて保存してください。
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>PUT</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<AllowedMethod>DELETE</AllowedMethod>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
この設定では、どんなドメインからでもajaxでリクエストを投げられるようになります。認証は別にあるので、これでも一応問 題ありませんが気になる場合はAllowOrigin要素内に自分がアクセスするオリジンを指定するようにしてください。
Facebookアプリを作成する
ユーザをFacebookアカウントで認証するには、まずFacebookアプリの情報を設定しておく必要があります。
Facebook Developersのアプリ一覧にアクセスして、「新しいアプリを作成」をクリックします。Facebookアプリのデベロッパではない人はデベロッパとして登録しておいてください。
アプリを作成した後は、アプリを通じてウェブサイトでFacebook認証を行うための設定を追加します。「Facebookでログインが可能なウェブサイト」の欄に、AWS SDK for JavaScriptを使うサイトのドメインを設定します。
Facebook認証でS3を操作するためのパーミッションを追加する
次に、Facebookアカウントで認証したユーザがS3を扱えるための設定を追加します。IAMの管理画面にアクセスして、左のメニューのRolesをクリックします。
「Create New Role」をクリックすると、ロールを新規作成するためのダイアログが表示されます。ロールの種類を選択するダイアログが表示されるので、新しいロールを作成します。Select Role Typeでは、Role for Web Identity Provider Accessを選択します。次の画面では、認証に利用するIdentityProviderを選択します。「Facebook」を選択して、Application Idの欄では、先ほど作成したFacebookアプリのApp IDを入力します。
次に表示されるポリシーの選択では、Custom Policyを選択します。Policy Nameには適当な名前を入力して、Policy Documentには以下のポリシーを設定してください。(バケット名)には、先ほど作成したS3のバケット名を入れます。
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:PutObject",
"s3:PutObjectAcl"
],
"Resource": [
"arn:aws:s3:::(バケット名)/facebook-${graph.facebook.com:id}/*"
],
"Effect": "Allow"
}
]
}
このポリシーでは、バケット以下に作成し たfacebook-(ユーザのfacebookのID)ディレクトリ以下のフォルダにアップロードすることを許可するポリシーです。このポリシーを追加することで、facebookアカウントで認証したユーザが各々アップロードできるディレクトリを隔離できます。
作成したロールのARNも後で使うので確認して下さい。ロールを選択して詳細情報を見るとARNが書いてあります。
JavaScriptを記述する
Facebookアカウントで認証してS3へファイルをアップロードする例が以下になります。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Facebook認証でのS3アップロード</title>
<script type="text/javascript" src="https://sdk.amazonaws.com/js/aws-sdk-2.0.0-rc1.min.js"></script>
</head>
<body>
<h1>Facebook認証 でのS3アップロード</h1>
<input type="file" id="file-chooser" />
<button id="upload-button" style="display: none">Upload to S3</button>
<div id="results"></div>
<div id="fb-root"></div>
<script type="text/javascript">
// FacebookアプリのApp ID
var appId = 'xxxxxxxxxxxxxxxxxxxx';
// ロールのARN
var roleArn = 'arn:aws:iam::xxxxxxxxxxxx:role/HogeRole';
// S3のバケット名
var bucketName = '(バケット名)';
var fbUserId;
var bucket = new AWS.S3({params: {Bucket: bucketName}});
var button = document.getElementById('upload-button');
button.addEventListener('click', function() {
var fileChooser = document.getElementById('file-chooser');
var results = document.getElementById('results');
var file = fileChooser.files[0];
if (file) {
results.innerHTML = '';
var objKey = 'facebook-' + fbUserId + '/' + file.name;
var params = {Key: objKey, ContentType: file.type, Body: file, ACL: 'public-read'};
bucket.putObject(params, function (err, data) {
if (err) {
results.innerHTML = 'ERROR: ' + err;
} else {
alert('アップロードされました');
}
});
}
}, false);
/*
* Facebook認証処理
* https://developers.facebook.com/docs/javascript/gettingstarted/
*/
window.fbAsyncInit = function() {
FB.init({ appId: appId });
FB.login(function(response) {
bucket.config.credentials = new AWS.WebIdentityCredentials({
ProviderId: 'graph.facebook.com',
RoleArn: roleArn,
WebIdentityToken: response.authResponse.accessToken
});
fbUserId = response.authResponse.userID;
button.style.display = 'block';
});
};
// Facebook SDKを読み込む
(function(d, s, id){
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) {return;}
js = d.createElement(s); js.id = id;
js.src = "//connect.facebook.net/ja_JP/all.js";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
</script>
</body>
</html>
このHTMLをfacebookアプリで設定したドメインに設置してアクセスしてください。facebookの認証のためのダイアログが表示され、認証が済むとアップロードフォームが表示されます。このフォームでファイルをアップロードすると、S3のバケットにアップロードされます。アップロードしたファイルは、S3のダッシュボードで確認できます。
埋め込みのクレデンシャルで認証なしでS3を操作する
今度は、Facebookアカウントで認証するのではなく、予め発行したクレデンシャルをウェブページに埋め込んで認証なしでS3を扱う方法を紹介します。
この方法では、ウェブページにクレデンシャルを埋め込む形式のため、秘密にしなければいけないアクセスキーが容易に盗まれてしまいます。従って、一般に公開する用途には向いていません。限られた人だけが利用するバックエンド用のページ内などで使うことを想定してください。
まずIAMの管理画面にアクセスして、ウェブページに埋め込むクレデンシャルのための新しいユーザを作成します。左メニューのUsersをクリックして、Create New Usersをクリックしてください。
適当な名前を入力して、次に進むとユーザとそれに対応するアクセスキーが生成されます。Show User Security Credentialsをクリックして、Access Key IDとSecret Access Keyをメモしておいてください。このユーザの権現を利用したいときには、このアクセスキーが必要となります。
作成したユーザがS3を操作できるパーミッションを追加します。先ほど作成したユーザを選択してPermissions → Attach User PolicyをクリックしてCustom permissionをクリックします。ここでは、以下の様なポリシーを追加します。(バケット名)にはあなたのバケット名を入れてください。
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:*"
],
"Resource": [
"arn:aws:s3:::(バケット名)"
],
"Effect": "Allow"
}
]
}
IAMで作成したユーザのARNも後で利用するのでメモしておいてください。
S3の方にもパーミッションの設定があるのでこれも追加します。S3のバケットのPropertiesを開いて、PermissionsからEdit policyを選択すると、そのバケットのポリシ ーを編集するダイアログが開きます。ここに、先ほど追加したユーザがこのバケットの編集を許可するための設定を追加します。
{
"Version": "2008-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "(IAMで作成したユーザのARN)"
},
"Action": "s3:*",
"Resource": "arn:aws:s3:::(バケット名)/*"
}
]
}
このポリシーでは、指定したユーザに対して先ほど作成したバケットへのS3の全てのアクションを許可しています。
ようやく準備が整ったのでS3をJavaScriptから扱うコードを記述します。Facebook認証する箇所が無い代わりに、先ほど作成したユーザのクレデンシャルを埋め込んでいることに注意ください。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>埋め込みクレデンシャルでのS3アップロード</title>
<script type="text/javascript" src="https://sdk.amazonaws.com/js/aws-sdk-2.0.0-rc1.min.js"></script>
</head>
<body>
<h1>埋め込みクレデンシャルでのS3アップロード</h1>
<input type="file" id="file-chooser" />
<button id="upload-button">Upload to S3</button>
<div id="results"></div>
<script type="text/javascript">
// S3のバケット名
var bucketName = '(バケット名 )';
// ユーザ作成時のアクセスキーを設定
AWS.config.update({accessKeyId: '(アクセスキー)', secretAccessKey: '(シークレットアクセスキー)'});
var bucket = new AWS.S3({params: {Bucket: bucketName}});
var button = document.getElementById('upload-button');
button.addEventListener('click', function() {
var fileChooser = document.getElementById('file-chooser');
var results = document.getElementById('results');
var file = fileChooser.files[0];
if (file) {
results.innerHTML = '';
var objKey = file.name;
var params = {Key: objKey, ContentType: file.type, Body: