まめ畑

ゆるゆると書いていきます

mod_access_tokenを入れてみた

今日livedoor ラボ「EDGE」 開発日誌 : 「mod_access_token」の配布開始と「EDGE src」公開のお知らせ - livedoor Blog(ブログ)で、mod_access_tokenが公開されました。
mod_access_tokenとは、Apacheモジュールで、特定のコンテンツの公開期間設定をするものです。
早速、Ubuntu8.04にインストールしてみました。
さくっといくと思ったら、いかなかった。


とりあえず、modaccesstoken - Secure downloading module for Apache2 - Google Project HostingからDLして解凍します。

wget http://modaccesstoken.googlecode.com/files/mod_access_token-0.10.tar.gz
tar zxvf mod_access_token-0.10.tar.gz


そして、ビルドします。

cd mod_access_token/
sudo chmod +x configure
sudo ./configure 

で「sudo make」となるはずですが、以下のエラー

no -c   mod_access_token.c 
make: no: Command not found
make: *** [all] Error 127

noって何か調べてもよくわからなかったのでMakefileを覗くと
「APXS=no」となってる。
まぁ、Apacheモジュールのインストール関係なので、ここを
「APXS=apxs2」
に変更しました。

その後

sudo make
sudo make install

を実行。
少々エラーが出ますが、問題なくインストールされていました。
(少し気持ち悪いですが)


後は設定ファイルを書きます。

cd /etc/apache2/mods-available
sudo vim access_token.load

中身は

LoadModule access_token_module /usr/lib/apache2/modules/mod_access_token.so

これを保存。

その後

sudo vim access_token.conf

中身は(例:Tokenはサンプルのやつ)

<Location /hoge>
    AccessTokenCheck On
    AccessTokenSecret 15cfb576a8bdc1551219fdeb3117ed85
    AccessTokenAccessKey 7864ffcb01fb5cde1f1c2f37b619fbcd
</Location>

Locationは対象コンテンツを配置するディレクトリです。

後は、

sudo a2enmod access_token
sudo /etc/init.d/apache2 force-reload

で適用します。


後は、ディレクトリにコンテンツを配置して

http://example.com/hoge/piyo.png?AccessKey=&Expires=&Signature=

といった感じでアクセスします。
コンテンツは何でも構いません。


Signatureは

PlainText = + + +
Signature = Base64(HMAC_SHA1(PlainText, Secret))

で生成します。

Signatureの例

GET/hoge/piyo.png12341853987864ffcb01fb5cde1f1c2f37b619fbcd
をHMAC-SHA1でハッシュにします。KeyはAccessTokenSecretを使用します。
この結果を、Base64でエンコードします。


ここで、EXPIRESはUnixエポックからの秒数で期限を表したものです。

Rubyであれば

irb(main):001:0> require 'time'
=> true
irb(main):002:0> (Time.new+300).to_i
=> 1234185624

こんな感じで現在からの時間を確認できます。
例では300秒(5分)後を指定しています。


これで、指定時間以降はアクセスすると403が返ってくるようになります。
ログに成功のメッセージ、エラーログに認証失敗のログが記録されます。
エラーログには送信されたSignatureと所望のSignatureが両方表示されます。

所望のSignature:送信されて来たSignature

の順です。


ここまでは良かったのですが、Signatureを生成するスクリプトを作ろうと思ったのですが、Rubyで上手くいかない・・・。
一応、Perlの物は標準でegディレクトリ内に添付されています。
CPANでDigest::HMAC_SHA1を入れてください。


Rubyで生成される物と違うのはなぜだ・・・。
一応、こんな感じのコード
修正しました。

require 'openssl'
require 'base64'

h = OpenSSL::HMAC::digest(OpenSSL::Digest::SHA1.new, "15cfb576a8bdc1551219fdeb3117ed85", 'GET/hoge/piyo.png12341853987864ffcb01fb5cde1f1c2f37b619fbcd')
sign = Base64.encode64(h.to_s).chomp.sub(/=*$/, '')

明らかに、実行結果が違うんだよなぁ。
何か勘違いしているのかな。


ruby-hmacを入れてみたけど同じ結果。
使い方の問題か?
一応、そのコード。

sudo gem install ruby-hmac

で入れれる物。

require 'hmac-sha1'
require 'base64'

h = HMAC::SHA1.new("15cfb576a8bdc1551219fdeb3117ed85")
h.update("GET/hoge/piyo.png12341853987864ffcb01fb5cde1f1c2f37b619fbcd")
sign = Base64.b64encode(h.to_s)

to_sとかhexdigestだから悪いんだろうか。
Perlだとこのタイミングでb64digestしてるし。


ここは確認しないと。

追記(2009/2/12)

Big Sky :: mod_access_tokenで制御されたリソースにrubyからアクセス
で指摘していただきました。
hexdigestではなく、digestを使うとの事でした。
また、b64encodeではなくencode64を使ったほうがいいとの事です。

ありがとうございました。