«前の日記(2011-08-02 (Tue)) 最新 次の日記(2011-08-09 (Tue))» 編集

雑記帳


2011-08-04 (Thu) [長年日記]

[AWS][Ruby] AWS SDK for RubyでS3の期間限定のURLを生成する

先日参加したZmandaクラウドバックアップセミナーでの玉川憲さんの発表で、S3で期間限定のURLを生成することができるということを知った。これはAWS Manegement Consoleでは簡単に実現できないのでRubyでやってみた。

require 'aws-sdk'

AWS.config(YAML.load(File.read('config.yml')))
o = AWS::S3.new.buckets['your-bucket-name'].objects['object-name']
puts o.url_for(:read, :expires => 60*60*24*31)

これで、下記のようなURLが生成された。このURLは、一ヶ月間だけ有効のものになる。

https://rubysdktest-20110803.s3.amazonaws.com/logo.gif?AWSAccessKeyId=AKIAIFCOKTCTDSDMPX2A&Expires=1315125436&Signature=zEmS9f4%2Fm%2BFLgxEsVA9ppfQDhks%3D

期限が切れたあとにアクセスすると、次のようなXMLが返ってきて、期限が切れてエラーであることを示している。Expiresの値で、いつ期限が切れたのかがわかるようになっている。

<Error>
 <Code>AccessDenied</Code>
 <Message>Request has expired</Message>
 <RequestId>AC51F171E7F19E2C</RequestId>
 <Expires>2011-08-04T02:38:45Z</Expires>
 <HostId>13wxo/zprw3XJmIMeK2HEMAbJZx3C+Men58H1jwAGaSgrXm0v7TTdmoCR3ItaLB0</HostId>
 <ServerTime>2011-08-04T02:44:59Z</ServerTime>
</Error>

ところで、URLに"Expires=..."という文字列が含まれていたので、この値を変更すれば期限が切れた後でもアクセスできるのでは…、と思ってやってみたが、さすがにダメだった。今度は別のエラーになった。

<Error>
 <Code>SignatureDoesNotMatch</Code>
 <Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message>
 <StringToSignBytes>47 45 54 0a 0a 0a 31 33 31 32 34 32 39 38 32 30 0a 2f 72 75 62 79 73 64 6b 74 65 73 74 2d 32 30 31 31 30 38 30 33 2f 6c 6f 67 6f 2e 67 69 66</StringToSignBytes>
 <RequestId>8F681D480FCEC291</RequestId>
 <HostId>rm5EVi56+MRrDquW45CO3A98Fbnmxqmx7O39ssMbLNE2bBLe41g1fHTghXRmiPOa</HostId>
 <SignatureProvided>MAhvZtzwPBwPvNhsyVCVhNjYa74=</SignatureProvided>
 <StringToSign>GET 1312429820 /rubysdktest-20110803/logo.gif</StringToSign>
 <AWSAccessKeyId>AKIAIFCOKTCTDSDMPX2A</AWSAccessKeyId>
</Error>

署名が合わないエラーになったらしい。QueryStringが署名されたもので、改竄ができないようになっている様子。いやーすばらしい。

ちなみに、ACLの設定で誰でも参照できるように設定されていると、通常のURLでアクセスすれば問題なくアクセスできてしまうので要注意。