素のPHPでさくらのオブジェクトストレージをlistobject

前回AWS-SDKを使ったが、素のPHPだとどうなるか試した。

やったこと

  • Fiddlerでリクエストを確認
  • AWS 署名V2を調べた
  • 素のPHPでListObject

Fiddlerでリクエストを確認

FiddlerでCloudBerryのリクエストをとった。

GET /<<バケット>>?prefix=&max-keys=1000&delimiter=%2F HTTP/1.1
User-Agent: CloudBerryLab.Base.HttpUtil.Client 4.3.0 (
http://www.cloudberrylab.com/)
x-amz-date: Fri, 20 Nov 2015 12:21:06 GMT
Authorization: AWS <<アクセスキー>>:xxxxxxxxxxxxxxxxxxxxxxxxxxx=
Host: b.sakurastorage.jp
Connection: Keep-Alive

アクセスキーの右ブロックは

  • 同じリクエストでも毎回変わることから時間が関係してるっぽい
  • 最後が「=(イコール)」で終わるのでBASE64っぽい

ってことが分かった。

AWS 署名V2を調べた

アクセスキーの右ブロックの文字列は「AWS 署名バージョン 2」と呼ぶようだ。 さくらのオブジェクトストレージは、AWSSDKv2は成功するがv3は失敗するので、 v2をつかうといいようだ。

V2署名文字列生成は↓が分かり易かったです。

付録 B: リクエストの認証(AWS 署名バージョン 2) https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/dev/auth-request-sig-v2.html

PHPAmazon S3REST API を使用 #1 http://www.applelife100.com/2012/06/23/using-rest-api-of-amazon-s3-in-php-1/

素のPHPでListObject

こんな感じになりました。

<?php
$config = [
  'bucket' => '<<バケット>>',
  'accessKey' => '<<アクセスキー>>',
  'secretAccessKey' => '<<シークレットアクセスキー>>',
  'endpoint' => 'b.sakurastorage.jp',
];
$resource = "/{$config['bucket']}";

$req = makeRequest($config, $resource);
$res = file_get_contents($req['url'], false, $req['context']);
echo $res;

function makeRequest($config, $resource)
{
  $datetime = new DateTime('now', new DateTimeZone('UTC'));
  $date = $datetime->format(DateTime::RFC1123);
  $signature = v2signature($config, "GET", '', '', $datetime, '',
$resource);
  return [
    'context' => stream_context_create([
      "http" => [
        'method' => 'GET',
        'header' => implode("\r\n", [
          "Authorization: AWS {$config['accessKey']}:{$signature}",
          "Date: {$date}",
        ]),
      ],
    ]),
    'url' => "https://{$config['endpoint']}{$resource}",
  ];
}

function v2signature($config, $httpVerb, $contentMd5, $contentType,
$datetime, $canonicalizedAmzHeaders, $resource)
{
  $stringToSign =
    $httpVerb ."\n"
    . $contentMd5 ."\n"
    . $contentType ."\n"
    . $datetime->format(DateTime::RFC1123) ."\n"
    . $canonicalizedAmzHeaders
    . $resource;
  return base64_encode(hash_hmac('sha1', $stringToSign,
$config['secretAccessKey'], true));
}

参考

www.applelife100.com

docs.aws.amazon.com