2.

AWS「The request must contain the parameter

編集
この記事の要点
  • 典型ケース: AWS PA-API (Product Advertising API) や旧 SigV2 API でリクエストに Signature パラメータが付いていない
  • 原因: 自前で URL クエリ署名する実装が壊れている / 古い API バージョンを叩いている / SDK が古い
  • PA-API は 5.0 で SigV4 必須: 古い PA-API 4.0 / SOAP は 2020 年に廃止。今は POST + SigV4 ヘッダ署名
  • 対処: 公式 SDK (AWS SDK / paapi5-php-sdk 等) を利用し、AccessKey / SecretKey / Partner Tag / Region (us-east-1 等) を正しく設定
  • SigV4 のフロー: CanonicalRequest → StringToSign → HMAC-SHA256(SigningKey) → Authorization ヘッダ

このエラーが出る状況

AWS の API 呼び出しで以下のレスポンスが返ってくるケース:


  
    MissingParameter
    The request must contain the parameter Signature.
  

代表的なシチュエーション:

  • Amazon Product Advertising API (PA-API) を自前 URL 署名で叩いている
  • 古い AWS SigV2 (Query String 認証) API を叩いている
  • SDK ではなく file_get_contentscurl で手書きしている
  • 古いライブラリ(PA-API 4.0 系)を使っている

原因の本質

AWS は API リクエストが正しい呼び出し元から来たことを署名 (Signature) で検証します。SigV2(旧)と SigV4(現行)の 2 系統があり、どちらにせよ署名情報をリクエストに含める必要があります。このエラーは:

  1. SigV2: クエリ文字列に Signature=... パラメータが付いていない
  2. SigV4: Authorization ヘッダ(または X-Amz-Signature クエリ)が欠落

のどちらかを意味します。

対処1: 公式 SDK を使う

最も確実なのが公式 SDK の利用です。自分で署名計算をしないで済みます。

PA-API 5.0 (Amazon アソシエイト)

composer require amzn/paapi5-php-sdk
use Amazon\ProductAdvertisingAPI\v1\com\amazon\paapi5\v1\api\DefaultApi;
use Amazon\ProductAdvertisingAPI\v1\com\amazon\paapi5\v1\SearchItemsRequest;
use Amazon\ProductAdvertisingAPI\v1\com\amazon\paapi5\v1\PartnerType;
use Amazon\ProductAdvertisingAPI\v1\Configuration;

$config = new Configuration();
$config->setAccessKey(getenv('PAAPI_ACCESS_KEY'));
$config->setSecretKey(getenv('PAAPI_SECRET_KEY'));
$config->setHost('webservices.amazon.co.jp');
$config->setRegion('us-west-2');

$api = new DefaultApi(new GuzzleHttp\Client(), $config);

$req = new SearchItemsRequest();
$req->setPartnerTag(getenv('PAAPI_PARTNER_TAG'));
$req->setPartnerType(PartnerType::ASSOCIATES);
$req->setKeywords('プログラミング');
$req->setSearchIndex('Books');

$res = $api->searchItems($req);

一般 AWS API (S3 / DynamoDB 等)

$s3 = new Aws\S3\S3Client([
    'version' => 'latest',
    'region'  => 'ap-northeast-1',
    'credentials' => [
        'key'    => getenv('AWS_ACCESS_KEY_ID'),
        'secret' => getenv('AWS_SECRET_ACCESS_KEY'),
    ],
]);
$s3->putObject([
    'Bucket' => 'my-bucket',
    'Key'    => 'hello.txt',
    'Body'   => 'Hello world',
]);

SigV4 署名の仕組み(自前で計算する場合)

SDK が使えない事情がある場合は SigV4 を自前で計算します。手順:

  1. CanonicalRequest を作る
  2. StringToSign を作る
  3. SigningKey を派生
  4. HMAC-SHA256 で署名
  5. Authorization ヘッダを組み立て
function sigv4(
    string $method, string $host, string $path, array $query,
    string $payload, string $region, string $service,
    string $accessKey, string $secretKey
): array {
    $amzDate   = gmdate('Ymd\THis\Z');
    $dateStamp = gmdate('Ymd');

    // 1. CanonicalRequest
    ksort($query);
    $canonicalQuery = http_build_query($query, '', '&', PHP_QUERY_RFC3986);
    $payloadHash    = hash('sha256', $payload);
    $headers = [
        'host'         => $host,
        'x-amz-date'   => $amzDate,
        'x-amz-content-sha256' => $payloadHash,
    ];
    ksort($headers);
    $canonicalHeaders = '';
    $signedHeaders    = '';
    foreach ($headers as $k => $v) {
        $canonicalHeaders .= "$k:$v\n";
        $signedHeaders    .= ($signedHeaders ? ';' : '') . $k;
    }
    $canonicalRequest =
        "$method\n$path\n$canonicalQuery\n$canonicalHeaders\n$signedHeaders\n$payloadHash";

    // 2. StringToSign
    $credentialScope = "$dateStamp/$region/$service/aws4_request";
    $stringToSign    = "AWS4-HMAC-SHA256\n$amzDate\n$credentialScope\n" .
                       hash('sha256', $canonicalRequest);

    // 3. SigningKey
    $kDate    = hash_hmac('sha256', $dateStamp,  'AWS4' . $secretKey, true);
    $kRegion  = hash_hmac('sha256', $region,     $kDate,   true);
    $kService = hash_hmac('sha256', $service,    $kRegion, true);
    $kSigning = hash_hmac('sha256', 'aws4_request', $kService, true);

    // 4. Signature
    $signature = hash_hmac('sha256', $stringToSign, $kSigning);

    // 5. Authorization ヘッダ
    $authHeader =
        "AWS4-HMAC-SHA256 Credential=$accessKey/$credentialScope, " .
        "SignedHeaders=$signedHeaders, Signature=$signature";

    return array_merge($headers, ['Authorization' => $authHeader]);
}

よくあるミス

ミス症状対処
クエリパラメータの URL エンコードが不正確SignatureDoesNotMatchRFC3986 エンコード(+ ではなく %20
システム時計がずれているRequestTimeTooSkewedNTP 同期、5 分以内に
古い API 版を叩いているMissingParameter SignatureSigV4 / PA-API 5.0 へ移行
Content-Type と payload hash の不一致SignatureDoesNotMatchpayload を生のまま hash
パーソナルタグ未設定 (PA-API)InvalidPartnerTagアソシエイトコンソールでタグ取得

デバッグ手順

# 1. AWS CLI で同じリクエストを実行して成功するか確認
aws s3 ls --debug

# --debug 出力に「CanonicalRequest」「StringToSign」が出るので
# 自前実装と比較する

# 2. 時刻ずれを確認
date -u
# サーバー時刻と 5 分以上ずれていないか

# 3. SDK ロギング有効化(PHP)
$client = new Aws\S3\S3Client([
    ...,
    'debug' => true,
]);

FAQ

Q: PA-API 4.0 のコードがある
A: 2020 年 3 月に廃止済。PA-API 5.0 (SigV4) への完全書き換えが必要。エンドポイントも webservices.amazon.co.jp のパス /paapi5/searchitems に変わっています。

Q: SigV2 で良いケースは?
A: ほぼ無い。SQS の一部や旧 SES など。新規開発は必ず SigV4。

Q: Signature の有効期限
A: AWS は通常 15 分以内のリクエストしか受け付けません。Presigned URL は最大 7 日 (S3) など API ごとに異なります。

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. Error 400 : Bad Request Parameter Operation is missing
  2. MissingParameter. The request must contain the parameter Signature.
  3. RequestThrottled. AWS Access Key ID: ... . You are submitting requests too quickly
  4. SignatureDoesNotMatch. The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.
  5. failed to open stream: HTTP request failed! HTTP/1.1 503 Service Unavailable