雑記帳
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でアクセスすれば問題なくアクセスできてしまうので要注意。