twitter icon   twitter icon   rss icon

Linux.com Japan

Home Linux Jp チュートリアル 自分のサーバーからAmazonのS3ファイルを管理する

自分のサーバーからAmazonのS3ファイルを管理する

原文は 2015 年 5 月 21 日に掲載されました。 

 本チュートリアルでは、自分のサーバーサイドから Amazon の S3 を管理する方法について学びます。S3 (Simple Storage Serviceの略) は、Amazon の Web サービスの 1 つです。ファイルの格納機能が基本です。Amazon は、巨大な分散データ センターにファイルを格納します。ファイルは自動的にバックアップされ、コピーが作成されます。紛失する心配がなく、いつでも参照できます。ファイルを非公開にして自分だけがダウンロードできるようにするか、公開して誰でも参照できるようにもできます。

 ソフトウェア開発の観点から言えば、S3 はファイル格納機能を提供しますが、我々のサーバーの処理を邪魔することはありません。価格も非常に安価です (格納、転送、両者とも GB で円単位です)。そのため、自分のサーバーに対する要求も抑えることができます。Web サーバーで動くアプリケーションやモバイル アプリから S3 にアクセスするための API が公開されています。

  HTTP コールを用いた REST フル サービスを使って、S3 にアクセスします。サーバーからアクセスしてブラウザを用いない場合でも、そうします。ブラウザからもアクセスできますが、セキュリティの問題があります。AWS にアクセスするにはプライベート キーが必要です。ブラウザから AWS にアクセスして、プライベートキーを安全に使う方法はありません。他人があなたの S3 アカウントを許可なく使えてしまいます。その代わりに、プライベート キーを格納しているサーバーから AWS にアクセスするのです。そうすれば、ブラウザは AWS に直接アクセスするのではなく、サーバーにアクセスすることになります。

 サーバーでは、どんな言語を使えばよいでしょうか。最近の好みは node.js です。ここでもそれを使いますが、考え方は他言語でも同じです。

 新しい REST フル API を勉強する時は、まず、ダイレクト HTTP インタフェースを学びます。つづいて、SDK を使うかどうかを決めます。REST フル API は往々にして使いづらいものです。そのため、API 提供者は他言語用の SDK を提供しています。SDK は、API を使いやすくするためにクラスと関数群を提供しています。しかしながら、API のほうが使いやすい時もあり、その場合は SDK を使わないようにしています。もちろん、SDK が使いやすい時もあります。

 AWSは、比較的使いやすい API を提供しています。一部セキュリティを除いてですが。AWS API を使うためには、すべての HTTP コールに署名する必要があります。署名は、パラメーターの暗号化されたハッシュとプライベート キーからできています。これにより、Amazon は、呼び出し元は誰か、呼び出しアプリケーションは何か、を知ることができます。パラメーターに付け加えて、タイムスタンプも付加します。AWS は、タイムスタンプを調べて、15 分以上経過していればエラーを戻します。つまり有効期間切れということです。API 呼び出しを組み立てる時には、適切な時間内に呼び出す必要があります。

 暗号化ハッシュの追加は、特にヘルパー コードなしでは難しいビット変換です。そのため、Amazon を使う時には、HTTP コールではなく SDK を選びます。SDK には、呼び出しに署名するためのコードが含まれています。私は通常、HTTP コールを学び、それから必要な SDK を学ぶのですが、今回は SDK に直接行きました。

AWS SDK を使う 

始めましょう。node.js でアプリケーションを開発するためのディレクトリを作成します。AWS SDK を追加します。

npm install aws-sdk

SDK を使うためにはクレデンシャルが必要です。構成ファイルに別途保管してもよいし、直接コードに書き込んでも構いません。セキュリティの専門家はコード内に書き込むことに反対のようですが、今回はテストなので、良しとします。aws-sdk ドキュメント (訳注:日本語はこちら) には、別ファイルにクレデンシャルを格納する方法が記載されています。

 クレデンシャルを得るために、コンソールの右上の隅の名前をクリックします。ドロップダウンから "Security redentials" をクリックします。ここで、セキュリティ キーの管理や作成ができます。"Access Keys" セクションを広げて、"Access Key ID" と "Secret Access Key" を作成します。 好みのテキスト エディターで test1.js にコードを作成します。コード内で S3 バケットを作成します。S3 バケットの名称は、すべてのユーザーの中でユニークである必要があります。私は s3demo2015 としたので、皆さんはもう使えません。まず、使いたい名前を入れてみて、エラーが出たらやり直してください。コードは、以下のようになります。

var aws = require('aws-sdk');
aws.config.update({
  accessKeyId: 'abcdef',
  secretAccessKey: '123456',
  region:'us-west-2' 
});

 abcdef を皆さんの Access Key ID で、123456 を Secret Access Key で置き換えてください。

 require('aws-sdk') が戻すオブジェクトは、複数の AWS サービス用のコンストラクターとして動作する関数群を含みます。その 1 つが S3 用です。ファイルの最後に S3 コンストラクター呼び出し、オブジェクト格納の行を追加してください。

var s3 = new aws.S3();

 作成された S3 オブジェクトのメンバーを確認する行を追加してください。

console.log(s3);

 実行します。

node test1.js

 クレデンシャルとエンドポイントを含むメンバーが表示されます。これが、REST フル API です。エンドポイントとして参照される URL が含まれます。S3 バケットを処理するために、アプリケーション内で使用する URL です。。

 直接、これらを使わないので、次に進み、console.log の行を削除します。

バケット作成

バケット作成コードを追加します。エンドポイントを利用して、HTTP リクエストを作成します。SDK が提供するラッパー関数を利用します。

バケット作成関数は、createBucket です (この関数は aws.S3 コンストラクター用プロトタイプの一部なので、console.log の出力には含まれていません)。node.js は同期型なので、createBucket を呼ぶ時にはコールバック関数をパラメーターとして渡します。以下のコードを追加してください。バケット名の s3demo2015 を皆さんのバケット名に変更しないでください。これで、既存のバケットと同じ名前のものを作成する時に出るエラーを表示させることになります。

s3.createBucket({Bucket: 's3demo2015'}, function(err, resp) {
    if (err) {
        console.log(err);
    }
});

 実行してください。

node test1.js

エラーが表示されます。ここでは、オブジェクトをそのまま記載しています。実際のアプリケーションでは、エラー メッセージのみを表示させます。それには err.message を使います。完全なエラー オブジェクトがエラー用ログ ファイルに格納されます (ログを保管しますよね? )。

キーが間違っている場合は、キー誤りに関するメッセージが表示されます。

さあ、s3demo2015 を皆さんが作成したい名称に変更しましょう。応答を表示するようにコードを変更します。

s3.createBucket({Bucket: 's3demo2015'}, function(err, resp) {
    if (err) {
        console.log(err);
        return;
    }
    console.log(resp);
});

実行します。もし、バケットの名称が問題なければ、1 つのメンバーから構成される JavaScript が戻されます。

{ Location: 'http://s3demo2015.s3.amazonaws.com/' }

 このオブジェクトが含む URL は、作成したバケットを指します。後で使用するため、URL を格納します

バケット コードをコメントアウトする

バケット作成用のコールバック関数にコードを追加することもできます。しかし、練習という観点から、今回は行いません。実際のアプリケーションでは、バケット作成は少なく、作成済みのバケットを利用することが多いでしょう。そこで、バケット作成コードをコメント アウトし、後で見ることができるようにしておきます。

var aws = require('aws-sdk');
aws.config.update({
    accessKeyId: 'abcdef',
    secretAccessKey: '123456',
    region:'us-west-2' }
);
var s3 = new aws.S3();
/*s3.createBucket({Bucket: 's3demo2015'}, function(err, resp) {
    if (err) {
        console.log(err);
        return;
    }
    console.log(resp);
    for (name in resp) {
        console.log(name);
    }
});*/

バケットにコードを追加する

作成したバケットを利用するためのコードを追加します。S3 はそれほど複雑ではありません。基本的にストレージなので、ファイル格納、読み出し、削除とリストの手順を提供しています。バケットのリストと削除もできます。ファイルのアクセス権限 (他者がアクセス可能か) の設定を含むセキュリティも設定可能です。詳細は、ここにあります。

 ファイルをアップロードして、全員へ公開するコードを追加します。S3 では、ファイルもオブジェクトです。アップロード用の関数は putObject です。オプションについては、このページを見てください。オプションは、オブジェクトの値として与えられます。つまり、関数のパラメーターとして、オブジェクトを渡します。JavaScript 内のオブジェクトのメンバーの順番については問われません (JavaScriptは、オブジェクトの作成された時間順に管理していますが、それに依存するのは良くありません)。メンバーを任意に並べます。

ドキュメント中の最初の 2 つ: バケット名称とファイル名称が必須です。ファイル名称を Key として与えます。

{
  Bucket: 'bucketname',
  Key: 'filename'
}

ファイルを他者に公開したい場合は、セキュリティ情報を付加することができます。標準では、所有者のみが読めます。ファイルを他者に読み出し、書き込みさせることができます。通常は、他者が書き込めるようにはしません。今回は、読み込みできるようにします。このためのメンバーを ACL と呼びます。これは、Access Control List の略です。ACL は権限を示す文字列です。ドキュメント内に記載されています。今回のものは 'public-read' です。

S3 を理解するためには、putObject の全オプションを理解することをお勧めします。これにより、S3 で出来ることが良くわかるようになります。これに加えて、SDK のドキュメントではなく、S3 の全般的なドキュメントを読むことです。StorageClass というオプションを使いました。少数の人たちと大きいファイルを共有したいことがありますが、S3 のクラウド ストレージは必要ありません。節約するために、StorageClass を 'REDUCED_REDUNDANCY' として、ファイルを格納します。こうすると、ファイルは AWS のクラウドに分散して格納されないため、料金が節約できます。パラメーター オブジェクトを使って、これらを設定できます。

S3 へファイルをアップロードする

 それでは、S3 へファイルをアップロードします。HTML ファイルを格納します。これで、 アップロードしたファイルをブラウザで簡単に見ることができます。以下を追加します。

var html = '<html><body><h1>Welcome to S3</h1></body></html>';
s3.putObject( {Bucket:'s3demo2015', Key:'myfile.html', ACL:'public-read', Body: html}, function(err, resp) {
    if (err) {
        console.log(err);
        return;
    }
    console.log(resp);
});

新しいパラメーターがあります。テストした後に追加したパラメーターです。これについては後で説明します。

問題なく動けば、以下のような文字列が返されます。

{ ETag: '"a8c49e10d2a2bbe0c3e662ee7557e79e"' }

Etag は、ファイルが変更されたかどうかを示します。おもに Web ブラウザで使われます。ブラウザは、ファイルが変更されていなければキャッシュから表示します。変更されていればダウンロードします。

変更の有無を決定するために、Etag という長い文字列をダウンロードします。ブラウザは、まず、サーバーに Etag を要求します。サーバーは Etag を戻します。ブラウザがキャッシュに保持している Etag と異なれば、ファイルが変化したことがわかります。同じであれば変化していないので、ファイルをダウンロードする必要がありません。これで、スピード向上とバンド使用率の最小化を図ります。

アップロードされたファイルを読む

ファイルを読みます。AWS コンソールからバケットを見ます。上図には、先のコードを使ってアップロードしたファイルが見えます。他にもチュートリアル用に用意したファイルがあります。ファイルを直接見ます。バケットを作成したときに入手した URL が必要です。以前に、格納しておきました。URL とファイル名称を組み合わせます。ブラウザで、新しくタブを作成し、アドレス バーに入力します。以下の例の s3demo2015 を皆さんのバケット名称に置き換えてください。

https://s3demo2015.s3.amazonaws.com/myfile.html

(AWS コンソールでファイルをクリックし、Properties ボタンをクリックすることで、このURL を入手できます)。アップロードした HTML ファイルが以下のように見えます。

Amazon S3 にアップロードした HTML ファイルを表示した。

コンテント タイプを正しく指定する

最初に例題を作成したあとに、追加したパラメータの最後のものを説明します。最初の例題では、URL をポイントすると、HTML 表示の代わりに、ダウンロードされたのです。今までの経験から、何が起こったかわかりました。コンテント タイプを間違えたのです。コンテント タイプを指定することで、ブラウザはそのファイルの取り扱い方法がわかるのです。ドキュメントをチェックすると、ContentType というメンバーがありました。HTML のコンテントを意味する "text/html" を指定しました。

 コンテント タイプは、CSS や JavaScript ファイルをアップロードするときに重要です。もし誤ったタイプを指定すると、ブラウザはそれらを正しく処理できません。正しく指定するようにしてください。

 テキスト ファイル以外にバイナリもアップロードできます。REST フル API を直接呼び出す時は、ちょっと工夫が必要です。しかし Amazon が提供する SDK は良くできていて、バイナリ ファイルでも問題なくアップロードできます。node ファイル システム (fs) を使うと、バイナリ ファイルを読んだり、バイナリの配列を戻すことができます。putObject 関数にこの配列を渡すと、正しくアップロードできます。

 C++ を使って、数字の 1 を書くプログラムを作成しました。コンパイラーは、a.out というバイナリ ファイルを作成します。先のコードを変更して、ファイルを読んで、S3 にアップロードしました。そして、アップロードされたファイルを wget で読んで、元のファイルと比較しました。もちろん、実行することもできました。これにより、バイナリ ファイルとしてアップロードされ、途中でテキスト ファイルへの変換などが行われていないことが確認できました。

結論

S3 は、プログラム的に簡単に使うことができます。S3 の動作を理解し、バケットを通したファイルの管理、セキュリティの制御をきちっと学ぶことが大事です。言語に合わせた SDK をインストールし、バケットの作成、ファイルのアップロードを行ってみます。JavaScript は、非同期に設計 (AJAX のように、ネットワークを通した処理中にフリーズしないように) されています。他言語用には、また違う設計になっています。しかし、SDK はシンプルにできています。

S3 SDK を学べば、アプリケーションに S3 ストレージ機能を追加できます。そして、他の AWS サービスを利用できるようにもなります。AWS の他のサービスについても知りたい方は、コメントに書いてください。

Linux Foundationメンバーシップ

30人のカーネル開発者

人気コンテンツ

  1. Today's Linux 2018/01/10 2018年 1月 09日
  2. Today's Linux 2018/01/12 2018年 1月 11日
  3. Today's Linux 2018/01/15 2018年 1月 14日
  4. Today's Linux 2018/01/16 2018年 1月 15日
  5. Today's Linux 2018/01/17 2018年 1月 16日

Linux Foundationについて

Linux Foundation はLinux の普及,保護,標準化を進めるためにオープンソース コミュニティに資源とサービスを提供しています

 

The Linux Foundation Japan

サイトマップ

問い合わせ先

サイトに関するお問い合わせはこちらまで

Linux Foundation Japan

Linux Foundation

Linux Training

提案、要望

Linux.com JAPANでは広く皆様の提案、要望、投稿を受け付ける予定です。

乞うご期待!