日報 #106 - S3でリクエストの署名と認証
乾燥しておるようです。
毎年この時期というのは、寒いし乾燥してるしインフルエンザも流行るしで、
病気リスクの高い時期なわけです。
その割に大事なイベントが多い時期でもあるわけです。
受験とか特に。
ちなみに僕は浪人時のセンター試験当日にインフルエンザになりました組です。
浪人・センター・インフルのSEO、狙っていきたいです。
さて、
本日は「これ豆な」的な話。
S3のファイルに期限付き認証を付ける話。
BASIC認証とかPHPとかが動かないS3ですので、
意外とアクセス制限をかけたファイル共有は面倒だったりします。
ですが、不可能というわけではありません。
S3へのリクエストに、「署名による認証」を付けることは可能です。
ドキュメントはこちらです。
http://docs.aws.amazon.com/ja_jp/AmazonS3/latest/dev/RESTAuthentication.html
まぁぶっちゃけこれをよくよく読んでね☆で終わりな話なのですが、
実際url生成のphpサンプルとかがあったほうがより便利だと思いますので、
今回僕がやった方法を紹介いたします。
目標はこんな感じ。
「S3にあるファイルを、一定期間だけ公開する認証付きURLを生成する。」
なんか複雑な言い回しにしているのは、
いわゆるファイル添付サービスみたいな「Webページにアクセスしてパスワードを入力してファイルゲット」というシステムではない、
という理由からです。
早い話がパスワードがついたURLを特定の相手に送信して、クリックさせ、DLさせる。
そのURLは時期がくれば自然と利用不可能になるし、そのURLを直接教えてもらう以外にアクセス方法は事実上存在しない、
みたいな共有方法です。
僕としてはメールでパスワードを送るのと大して変わりはないと思っていますので、
簡単なファイルならこれで共有してしまいます。
前置きが長くなったのでサクッとURLの生成方法を。
どういうシステムでS3のファイルに認証アクセスをするのかと申しますと、
まぁいわゆる「署名による認証」という感じです。
「目的のファイルへのリクエスト文」+「有効期限の情報」みたいなテキスト文を、
秘密の情報を用いてハッシュ化し、
実際のリクエスト文に署名として付与しながらアクセスする。
AWS側でもらったリクエスト文を使って改めて署名を作成してみて、
付与された署名と一致すれば認証成功、晴れてDLが始まる、といったシステムです。
なので問題はその「署名」の作り方です。
冒頭のドキュメントにぜーーんぶ署名の作り方がかいてありますが、
それを見ろってのも面倒な人向けにPHP組みました。
さっさと署名を作りたい方はお使いください。
<?php // AWS IAM INFO // IAM = hoge_iam $accessKey = "HOGEHOGEACCESSKEY"; $secretAccessKey = "HOGEHOGESecretAccessKey"; // S3 INFO $S3Host = "s3.amazonaws.com"; $bucketName = "EXT-DL"; $URLFormat = $S3Host."/".$bucketName."/%s?AWSAccessKeyId=%s&Expires=%s&Signature=%s"; // FILE NAME if (!isset($argv[1])) { echo "Need filename.\n"; exit; } $fileName = $argv[1]; // HTTP-Verb $httpVerb = 'GET' . "\n"; // Content-MD5 $contentMd5 = "\n"; // Content-Type $contentType = "\n"; // EXPIRE $datetime = new DateTime('+ 3days', new DateTimeZone('UTC')); $date = $datetime->format(DateTime::RFC1123); $expires = $datetime->format('U'); // CanonicalizedAmzHeaders $canonicalizedAmzHeaders = ''; // CanonicalizedResource $canonicalizedResource = "/".$bucketName."/".$fileName; // StringToSign $stringToSign = $httpVerb . $contentMd5 . $contentType . $expires . "\n" . $canonicalizedAmzHeaders . $canonicalizedResource; // Signature $hash = hash_hmac('sha1', $stringToSign, $secretAccessKey, true); $signature = urlencode(base64_encode($hash)); echo "\n===stringToSign===\n"; echo $stringToSign; echo "\n==================\n"; echo "\n=======URL=======\n"; echo sprintf($URLFormat, $fileName, $accessKey, $expires, $signature); echo "\n==================\n"; echo "\n=======EXPIRE=======\n"; echo $date; echo "\n==================\n"; ?>
と、こういう感じです。
これをsignature.phpとかに保存して、引数にファイル名を付与すればよいのです。
(EXPIREを変更したければ$datetimeのところを+ 7daysとかにしてちょ)
php signature.php hoge.txt
また、AWSのアクセスキーやシークレットアクセスキーが必要になるので、
IAMでDL専用のユーザを作成しておくとよいと思います。
それから、S3のDL対象ファイルですが、permissionのところで、Authenticated Usersにopen/Download権限を与えておきましょう。
さすればサクッとDLできるであろう…
今日は寒いし、乾燥ているから、以上でした。