S3の署名付きURLがSignatureDoesNotMatchになるとき、署名条件と送信内容を照合する

S3の署名付きURLでSignatureDoesNotMatchが返るとき、HTTP method・header・queryなど署名対象の差分を照合します。

AIものさし編集部

まず結論:URLを作り直す前に署名時と送信時を比べる

Amazon S3のpresigned URLでSignatureDoesNotMatchが返るときは、署名を作った側と実際に送ったrequestで、HTTP method、署名対象のheader、query stringなどが一致しているか確認します。URLを再発行するだけでは、送信側が別のmethodやheaderを付けていれば同じ失敗を繰り返します。AWSは、system clockのずれ、proxyによるheader/queryの変更、URL生成時と利用時のrequest parameterの不一致を代表的な確認項目として挙げています。

403というHTTP statusだけでSignatureDoesNotMatchとAccessDeniedを同じ原因にしないでください。S3 responseのerror codeを読み、SignatureDoesNotMatch、AccessDenied、ExpiredToken、RequestTimeTooSkewed等を分けます。AWSのpresigned URL公式FAQではSignatureDoesNotMatchについてmethod、headers、query string、clock、proxyを確認し、AccessDeniedでは生成principalのpermissionやbucket policyも調べるよう案内しています。

まず安全に残す情報

失敗したresponseから、XML error code/message、HTTP status、request ID、発生時刻を記録します。Presigned URLには一時的なアクセス権を与える署名やcredential関連parameterが含まれ、AWSはこれをbearer tokenとして保護するよう勧めています。URL全文、X-Amz-Signature、credential、秘密鍵をissue、chat、一般ログへ貼らないでください。共有する必要がある場合はURLを伏せ、method、対象bucket/keyの識別情報を安全に記録します。

表は横にスクロールできます

記録項目見る理由公開ログに残す内容
Error code / messageSignature mismatchかpermissionかを分けるcodeと機密を除いたmessage
HTTP methodGET/PUT等が署名時と同じかmethod名
Host / region対象endpointと署名regionが合うかhostname/region。ただしURL queryを伏せる
Signed headersclientが同じ値を送っているかheader名と安全な比較結果
Query string署名対象parameterが改変されていないかparameter名・差分だけ
発行時刻 / 実行時刻clock driftや期限を切り分けるtimestamp
Request IDAWS側サポート調査やログ相関に使うRequest ID

一時的にログを詳しくする場合でも、URLやfile内容をそのまま出しません。presigned URLを保管したログ自体が、期限内にファイルへアクセスできる情報になり得ます。

URL生成時のrequest条件を確認する

発行側の実装・設定から、どの操作に対するURLかを確認します。AWSはpresigned URLを作る際にbucket、object key、HTTP method、expiration等を指定すると説明しています。アップロードなら一般にPUT、ダウンロードならGETなど、利用時のmethodを発行時と同じにします。単にURL文字列だけを別clientへ渡し、methodやheaderを推測で設定しないでください。

次を発行側で記録し、送信側と比較します。

  1. 使用したS3 bucketとobject key。

  2. presigned URLが許可するHTTP method。

  3. signing時に指定したRegionとS3 endpoint。

  4. SignedHeadersに含まれるheader名と、その期待値。

  5. Content-Type、checksum、暗号化等、clientが追加するheader。

  6. expirationと、署名に使ったcredentialsの種類・有効期間。

  7. requestを経由するproxy、gateway、HTTP libraryの有無。

Regionを間違えた場合にAWS SDKやendpointが別のhostへredirectする構成では、署名されたhostと最終request先が異なることがあります。署名付きURLを不必要に再構成せず、clientが受け取ったURLをそのまま使っているか確認します。URLのpath、queryのencoding・順序・値、object keyのspaceや記号も比較対象です。Query stringは署名へ含まれ得るため、parameterを削る、追加する、URL decodeして再encodeする処理を挟まないようにします。

Client requestとの差分を取る

送信側で実際に送ったmethodとheaderを確認します。たとえば発行時にContent-Typeを署名対象として指定したのに、clientが異なるContent-Typeを送れば一致しません。一方、どのheaderが署名対象かはURLのX-Amz-SignedHeadersや生成コードで確認し、すべてのheaderが必ず署名に含まれると決めつけないでください。AWSの案内に従い、生成時と利用時のrequest parameterをひとつずつ照合します。

表は横にスクロールできます

比較対象URL発行側実際の送信側不一致時の対応
HTTP methodGET / PUT等の署名methodclientが送ったmethod発行methodと一致させる
Host / Region発行bucketのregion/endpoint実際の接続host正しいregionのendpointで発行する
SignedHeaders署名に含めたheader名同じheaderを送ったかheader名・値・正規化を確認
Content-Type発行時の指定有無と値clientの送信値署名時指定があれば同値を送る
Query発行時parameterclient/proxy後のquery余分なparameterや改変を除く
Path / object key発行したkey実request pathencodingとpath変更を照合
時刻・期限署名生成時刻、expirationclient clock、実行時刻NTP、credential期限、URL期限を確認

アップロードではSDKやHTTP clientが自動でContent-Type、checksum、transfer encodingなどを加えることがあります。これらが署名されたheaderに含まれているかを確認します。AWSが示す一般原則は「signed requestのmethod・headers・queryを生成時と利用時で一致させる」ことです。別のheaderが常に禁止という意味ではなく、実際の署名条件とS3のrequest要件に従います。

Clock、Credential、Proxyを分けて調べる

AWSはsystem clockが同期していない場合、署名時刻が不正となりSignatureDoesNotMatchを起こす可能性を案内しています。発行サーバーとclientの時計をNTP等で確認し、発行時刻・実行時刻をUTCで比較します。数分の差があれば常に同じ挙動になる、という独自の閾値は設定せず、S3 responseと署名条件で確認してください。

Presigned URLは生成時に指定した期限まで有効ですが、生成に使ったcredentialが先に失効すればURLもそれより早く無効になる場合があります。AWSは一時credentialを使うURLはcredentialの有効期間を超えて有効にならないと説明しています。期限切れなら通常はExpiredTokenやAccessDenied等別のerrorになる場合もあるため、error codeを見ずに署名不一致と同一視しないでください。

Corporate proxyやAPI gatewayを経由する場合、URL queryやheaderを変更していないか確認します。AWSは一部proxyがheader/query stringを変更し、signature mismatchを起こし得るため、proxyを介さない安全なテストを試すよう案内しています。通信経路を変えるときも、credentialが含まれるURLを安全に保ち、公開ネットワークや第三者へ不用意に送らないでください。

SignatureDoesNotMatchとAccessDeniedを分ける

SignatureDoesNotMatchは署名値の一致に関するエラーとして調べます。method、signed header、query、path、region、時間、proxyが候補です。AccessDeniedの場合は、署名されたrequestの主体に対象操作の権限があるか、bucket/access point policyが拒否していないかを確認します。AWSのFAQは、presigned URLを生成するIAM user/roleに対象操作のpermission(例:s3:GetObject)があること、およびbucket policyに明示的なdenyがないことを確認するよう案内しています。

表は横にスクロールできます

Error codeの例最初の調査先先に避けること
SignatureDoesNotMatchmethod、signed headers/query、region、clock、proxyIAM policyを広げるだけで直そうとする
AccessDenied発行principalのaction permission、bucket/access point policy署名内容の問題と決めつける
ExpiredToken発行元credential/sessionの有効期限URL expirationだけを延長する
RequestTimeTooSkewed等system clock、発行時刻、request時刻error responseを保存せずURLを何度も作る

同じ403でもpolicy変更が必要とは限りません。最小権限の範囲を維持し、具体的なerrorと対象操作に合わせて調査します。permissionを確認する作業はbucket ownerやAWS管理者と行い、診断目的でbucketをpublicにしたり、全actionを許可したりしないでください。

最小再現で再試験する

本番objectを使う前に、許可されたtest bucketや非機密objectで同じmethod・region・signed header構成を再現します。発行側とclient側の比較表を埋め、まず一つの差分だけ修正して再試験します。複数の条件を一度に変えると原因が分からなくなります。GETとPUT、Content-Type有無、proxy経由/非経由など、変更する条件を明示します。

再試験記録には、URLを伏せた状態で、error code、発行時と実行時のmethod、region、SignedHeaders、Content-Typeの一致有無、時刻、proxy有無、Request IDを記録します。成功しても、presigned URLの漏洩リスク、期限、対象object、許可された操作、再利用可否を確認します。AWSは期限まで同じpresigned URLを複数回利用できると説明しており、PUTの場合は指定keyに既存objectがあれば置き換わるため、アップロード再試行前には上書きの影響も確認してください。

確認チェックリスト

  • S3 XML responseのerror codeを確認した

  • URL全文・署名・credentialsを安全な場所へ保存した、またはログで伏せた

  • 発行したbucket、object key、Region、endpointを確認した

  • 発行methodと実際のHTTP methodが一致している

  • SignedHeadersのheader名と値を照合した

  • Content-Typeやchecksum等を実requestと比較した

  • Query stringとobject pathがproxy等で変わっていない

  • 発行側とclientの時計を確認した

  • Presigned URLのexpirationとcredential期限を確認した

  • Proxyやgatewayを介さない安全な最小テストを検討した

  • AccessDeniedならpermission/policyを別調査した

  • PUT再試行で既存objectを上書きしないか確認した

  • 公開bucket化や過剰なpermission付与をしていない

次に行うこと

responseのerror codeとRequest IDを控え、URLを共有せずに発行側のmethod、Region、SignedHeadersとclientの実requestを比較します。差分があれば一つずつ直し、最小限のtest objectで再試験します。条件が一致するのに失敗する場合は、clock、credential/session期限、bucket policy、proxy経路を確認し、必要に応じてAWSサポートへRequest IDを含む安全な診断情報を提供します。

実際のbucket、client library、発行コード、policyはこのガイドで確認していません。AWSの現行公式資料と環境のrequest logsで条件を照合し、原因を確認できるまで特定の修正を断定しないでください。

Sources