プログラマでありたい

おっさんになっても、プログラマでありつづけたい

AWS SDK for RubyでS3へのアクセス認証付きURLを生成する


 Amazon S3のアクセスコントロール(Access Control)には、次の5タイプがあります。

  1. IAMのポリシーを使った制御(Using IAM Policies)
  2. バケットポリシーを使った制御(Using Bucket Policies)
  3. ACLを使った制御(Using ACLs)
  4. ACLとバケットポリシーを併用した制御(Using ACLs and Bucket Policies Together)
  5. 認証付きクエリーを使った制御(Using Query String Authentication)


 用途に応じて上記の方法を使い分けるのですが、この中で面白いのが認証付きクエリーを使った制御です。要は、一時的に使用権を与えたURLを発行するという方法です。有効期限等を設定出来るので、期間限定のURL等を発行出来ます。キャンペーンで使用するといった方法や、アプリケーションから安全にアクセスさせるなど色々な用途があると思います。
 AWS SDK for Rubyを使って簡単に実現出来るので、サンプルのプログラムを書いてみました。

require 'aws-sdk'

AWS.config({
  :access_key_id => 'your_access_key_id',
  :secret_access_key => 'your_secret_access_key',
})

s3 = AWS::S3.new
obj = s3.buckets['yourbucketname'].objects['file_name']
puts obj.url_for(:read, :expires => 60) #seconds

これを実行すると、次のようなURLが発行されます。

https://yourbucketname.s3.amazonaws.com/file_name?AWSAccessKeyId=your_access_key_id&Expires=1348903870&Signature=we8vmLn%2BMB4nDx8bl7rz4nN0qcU%3D

 この例では、60秒間だけ有効なURLを発行されています。期限内でアクセスすると無事ダウンロード出来ますが、時間が過ぎると下記のようなエラーが出ます。Signatureがついているので、ExpiresやAccessKeyIDを勝手に変更しても無効になります。


有効期限が切れた場合のエラー


AccessDenied
Request has expired
964B6939794DBCEC
2012-09-29T07:18:01Z

1sFYnUfBAzVXwpgU1xMZa2C+02wLSp4CZLTFdp+wfzoOJcqiyj8r3zwQ3J41rnR2

2012-09-29T07:26:02Z


パラメータを改変した場合のエラー例


SignatureDoesNotMatch
The request signature we calculated does not match the signature you provided. Check your key and signing method.
47 45 54 0a 0a 0a 31 33 34 38 39 30 35 37 35 32 0a 2f 64 6f 63 6c 69 73 74 2d 74 6f 6b 79 6f 2d 72 65 67 69 6f 6e 2f 41 57 53 5f 53 69 6d 70 6c 65 5f 49 63 6f 6e 73 5f 70 70 74 2e 70 70 74 78
4B4BC82317D4BDC7
FPI7UtPOi6TRbQrDaWUEy2qme3UrqjpsV0zYMm8TNkfj3i0Qvs5JGswZAR78KFWE
imgbX/858pTQvsNmR8lbbOA8LDE=
GET 1348905752 /yourbucketname/file_name
your_access_key_id


 例えばS3と連携するiPhone/iPadアプリを作ろうとする場合、方法としてはiOSとS3を直接やりとりするという方法があります。その為のSDKも提供されています。一方で、そうするとアクセスコントロールをS3の方ですべてコントロールする必要があります。IAMを使えば可能ですが、現状の所まだ面倒くさいと思います。
 そんな時に、既存のサーバ側のアクセス・コントロールの資産を活用して、S3=>サーバ・アプリ=>iOSアプリという3層構造にしておけば楽な場合もあります。その際に、サーバ側でユーザごとの権限を確認した上で、認証付きURLを発行しiOSとS3の間でファイルのやり取りをするというのは有効な方法なのではと思います。
 活用方法は色々あるので、ぜひ一度ご検討あれ!


参照:
Access Control - Amazon Simple Storage Service
Signing and Authenticating REST Requests - Amazon Simple Storage Service
cloudpackブログ - AWS SDK for RubyでS3の期間限定のURLを生成する
Module: AWS — AWS SDK for Ruby