SREチームの長田です。 CloudFrontでstaticなファイルを配信しようとした時に少々ハマったのでそのメモです。
TL;DR
CloudFront distributionのS3 Originは、Managed Policyの Managed-AllViewer
を使うと機能しない。
何をしたのか
statcなファイルを配信する要件があり、その対応としてCloudFront distributionのOriginにS3を設定しました。 CloudFrontのOrigin Access Identity(OAI)を作成し、S3 bucket policyにはこのOAIからのAPIリクエストのみを受け付けるよう設定しました。
いざ配信用URLにHTTPリクエストすると以下のようなエラーになってしまいました。
<Error> <Code>SignatureDoesNotMatch</Code> <Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message> <AWSAccessKeyId>AKIA***</AWSAccessKeyId> ... </Error>
何が起こっていたのか
Origin request policyとして、Managed Policyの Managed-AllViewer
を使用していました。
このPolicyはすべてのリクエストヘッダーをOriginに転送します。 Originに何らかのアプリケーションがあり、リクエストヘッダーを参照する場合はこのPolicyを使うことになるでしょう。
OriginにS3を設定した場合、S3バケットの特定にはhostヘッダーが使われます。
Managed-AllViewer
を使用すると CloudFrontからS3へAPIリクエストする際のhostヘッダーが、クライアントリクエストのhostヘッダーで上書きされてしまいます
結果、S3バケットが見つからず、上記のようなエラーが発生するというわけです。
ドキュメントにもちゃんと記載があります。
それ以外の場合、リクエストのバケットは Host ヘッダーの小文字の値、リクエストのキーはリクエスト URI になります。
host
ヘッダーの他にも、 authorization
ヘッダーなどS3が使用するヘッダーを上書きしてしまうと同様のエラーになってしまいます。
ハマりどころ
エラーメッセージとして表示される SignatureDoesNotMatch
で検索すると、
AWSCLIの不具合issueや、
これを見て、「CloudFrontが持っているアクセスキーに不備があるのか・・・?」とOrigin Access Identityを作り直したり、 別のCloudFront distributionを用意したりしたものの解決せず、というのを繰り返してしまったわけです。
ちなみに、調査のためOAIを使用せずS3 bucket policyに Principal:"*"
を設定した場合は以下のようなエラーになります。
404 Not Found - Code: NoSuchBcket - Message: The specified bucket dose not exist - BucketName: foo.exmaple.com ...
BucketName
の部分がクライアントからCloudFrontにリクエストした場合のドメイン名になっています。
これが解決のヒントになりました。
おわり
仕組みがわかっていれば簡単に解決できるところですが、 エラーメッセージに踊らされてだいぶ時間をかけてしまいました。 仕組みを知っているというのは大事ですね。
同じようなハマり方をしている人の助けになれば幸いです。