S3 見習い兼 PHP と Ruby 初心者のかっぱ(@inokara)です。
はじめに
既にご存知の方もいらっしゃると思いますが、Amazon S3 の各バケットに保存されているコンテンツ(オブジェクト)に期限をつけてアクセスさせることが出来る機能(以下、「期限付き URL 生成機能」)があります。これは一時的に一部の方にだけファイルをダウンロードさせたい時等に非常に便利な機能だと思います。
この期限付きの URL 生成方法について AWS SDK for PHP と AWS SDK for Ruby の二種類を利用した手順を簡単にまとめてみたいと思います。
尚、上記のドキュメントでは Pre-Signed URL(事前署名付き URL)とありますが、本記事はタイトルを除いて、全編を通して期限付き URL と呼びたいと思います。
制限
いきなり制限で恐縮ですが、この期限付き URL 生成機能は SDK でのみ利用可能です。尚、今回利用する AWS SDK for PHP と AWS SDK for Ruby のドキュメントは下記の通りです。
必要に応じて見ましょう。
やってみよう
まずは AWS SDK for PHP を使って期限付き URL 生成機能を使ってみたいと思います。
準備
AWS SDK for PHP のインストール(Composer を使う方法)
こちら を参考にして Composer というツールを利用して AWS SDK for PHP をインストールします。尚、インストールした環境は下記の通りです。
- MacOS X 10.9 Marvericks
- PHP 5.4.24
まずは適当なディレクトリを作成しましょう。
mkdir -p ~/aws/
次に composer.json という Composer が利用するプロジェクトファイルを生成します。
cat << composer.json > EOT { "require": { "aws/aws-sdk-php": "2.*" } } EOT
次に Composer のインストールを行います。
curl -sS https://getcomposer.org/installer | php
この時点で Composer のインストールが終了です。Composer のインストールが終わったら AWS SDK for PHP のインストールです。
php composer.phar install
正常にインストールが終了した場合には以下のようなディレクトリ構成となっている(はず)です。
. ├── composer.json ├── composer.lock ├── composer.phar └── vendor 1 directory, 4 filesction_requests
上記のようになっていない場合には改めて手順や composer.json の中身等に間違いがないか確認しましょう。また、Composer を使わない AWS SDK for PHP のインストールについては以下のおまけをご確認ください。尚、インストールされる SDK のバージョンは 2.6.7 となります。これは composer.lock というファイルにて確認することが可能です。
"packages": [ { "name": "aws/aws-sdk-php", "version": "2.6.7", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git",
バケットにファイルを置く
バケットを作って適当なファイルを置きましょう。既に対象のオブジェクトがある場合にはこのステップはすっ飛ばしましょう。
バケットを作成
オブジェクトをアップロード
こちらのロゴ画像を利用させて頂きアップロードしました。
この時点で既にエンドポイント(リンク)が生成されているのが判りますが、このリンクにアクセスしても…
アクセス出来ませんね。
期限付きの URL を生成してみる
では、先ほどアップロードしたファイルにアクセス出来るように期限付きの URL を生成してみましょう。
いきなりソースコード
先ほど SDK をインストールしたディレクトリと同じディレクトリに test.php というファイルを作成し、こちらを参考にして以下のようなコードを書きました。
'AKxxxxxxxxxxxxxxxxxxxxxxxxx', 'secret' => 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' ); use AwsS3S3Client; $s3 = S3Client::factory($config); $url = $s3->getObjectUrl("kappa-test", "fluentd.png", "1 minutes"); print $url;
見て判る通り…
- key には AWS のアクセスキー
- secret には AWS のシークレットアクセスキー
をそれぞれ設定します。
次に getObjectUrl の引数に…
- バケット名(kappa-test)
- ファイル名(fluentd.png)
- 期限(時間)(1 minutes)
を指定します。
この test.php を以下のように実行します。
php test.php
実行すると…
上記のように長ったらしい URL が表示されますのでこの URL をコピーしてブラウザでアクセスしてみます。
おお、画像が表示されました。しばらくリロードを繰り返し続けると…
期限切れとなりアクセスが出来なくなりました。
2014-06-19T05:42:34Z
上記のように期限が切られていたことが判ります。
AWS SDK for Ruby でもやってみる
インストール
環境は以下のような環境でインストールします。
- MacOS X 10.9 Marvericks
- ruby 2.0.0p451
既に Ruby がインストールされていれば gem 一発です。
gem install aws-sdk --no-ri --no-rdoc -V
簡単ですね。
URL を生成する
こちらを参考にして以下のようなコードを書いてみました。
#!/usr/bin/env ruby require 'aws-sdk' AWS.config( :access_key_id => 'AKxxxxxxxxxxxxxxxxxxx', :secret_access_key => 'xxxxxxxxxxxxxxxxxxxxxxx', ) obj = AWS::S3.new.buckets['kappa-test'].objects['fluentd.png'] print obj.url_for(:read, :expires => 5*60)
アクセスキーやシークレットアクセスキーが必要になるのは PHP 版と同様です。処理の流れとしては…
- AWS::S3 クラスの bucket collection でバケットを object でファイル名を指定した上でオブジェクトを生成
- オブジェクトの url_for メソッドで URL を生成
- url_for メソッドで URL を生成する際に権限(:read)と期限(:expires)を引数として指定
このコードを test.rb というファイル名で作成して実行権限を与えてから以下のように実行します。
./test.rb
以下のように URL が生成されます。
生成された URL をブラウザで確認してみましょう。
ロゴが表示されました。しばらくリロード繰り返しているうちに…
アクセス出来なくなりました。
ちなみに Expires を修正すればなんとかなるんぢゃないかなと思った方、ご安心(お諦め)ください。Expires を巻き戻しても問題なくアクセス制限が掛かった状態でした。
まとめ
今回やったこと
- PHP と Ruby 版の AWS SDK を利用して S3 にアップロードしたファイルにに期限付きの URL を設定してみました
意外に…
- SDK さえ準備できれば簡単に期限付きの URL を生成することが出来ますね
おまけ
Amazon Linux で AWS SDK for PHP をインストールする
yum -y install php-amazon-sdk2
上記の場合には、バージョン 2.6.6 がインストールされます。また、
yum -y install php-amazon-sdk
の場合には、バージョン 1.6.2 がインストールされます。
おまけ(2)ファイルダウンロード中に期限が過ぎてしまった場合にどうなるの?
むむ確かに…
記事をアップした後に記事を読んで下さった方から…
大容量なデータで期限内にダウンロードできなかった場合でもセッションが生きていたら大丈夫なんですか?
という鋭い質問を頂きましたので試してみました。
実験くん
ざっくり手順
以下のような手順で実験を行いました。
- でっかいファイル(CentOS の iso ファイル)をアップロードしておく
- 期限を人間が操作出来るくらいのレベルで出来るかぎり短くして URL を発行する
- ファイルの転送を開始する
確認ポイント
- 期限が過ぎても最初のダウンロードは継続するのか?しないのか?
- 期限が切れた際の挙動
iso ファイルのアップ
結構デカイですね。
期限を 60 秒に設定
以下のようにスクリプトを修正してダウンロード期限を 60 秒間に設定します。
obj = AWS::S3.new.buckets['kappa-test'].objects['CentOS-6.5-x86_64-minimal.iso'] print obj.url_for(:read, :expires => 1*60)
スクリプトは AWS SDK for Ruby を利用します。
URL を発行
./test.rb
を実行して URL を発行します。
curl にてダウンロード開始
以下のようなダウンロードをあらかじめ用意しておいて…
#!/usr/bin/env bash cd ~/tmp/ echo "start : `date`" echo "" curl --limit-rate 10K -k -o test.iso "$1" echo "" echo "end : `date`"
以下のように実行すると…
download.sh https://kappa-test.s3.amazonaws.com/CentOS-6.5-x86_64-minimal.iso?AWSAccessKeyId=AKxxxxxxxxxxxxxxxxxxxxxxxx&Expires=1403227984&Signature=tgND5F1dc9NGQDMRWS3Y3Gk%2B5iM%3D
ダウンロードが開始されます…。
開始後 60 秒を経過したころに…
ブラウザから同じ URL を叩くと…
それれでも最初にダウンロードを開始したセッションは…
実験のまとめ
- ダウンロード中に期限が切れてもセッションは継続されてダウンロードは継続されます
- 期限切れの後の新しいセッションに関しては従来どおりオブジェクトへのアクセスは制限されます
元記事はこちら