[Amazon CloudWatch Synthetics] Canary実行のログに’Unable to fetch S3 bucket location: Access Denied.’というエラーが記録されていたので調べてみた

2021.09.23

こんにちは、CX事業本部 IoT事業部の若槻です。

今回は、Amazon CloudWatch SyntheticsのCanary実行のログにUnable to fetch S3 bucket location: Access Denied.というエラーが記録されていたので調べてみました。

Canaryの実行ログでエラーが発生している

前回の下記エントリでCanaryをAWS CDKで実装しました。

マネジメントコンソールのCanaryの画面では、そのCanaryの最新の実行結果の詳細情報を確認することができます。(下記の囲んだ部分)

そのうち[Logs]タブではCanaryのスクリプト(Lambda)の実行ログを確認することができます。

この実行ログの中で1行だけERRORとなっている出力がありました。

ERROR: Unable to fetch S3 bucket location: Access Denied. Fallback to S3 client in current region: ap-northeast-1.

ちなみに該当のログのCanaryの実行自体は成功(Passed)となっています。

調べてみる

エラー出力の前後のログを合わせて見てみると、スクリーンショットの画像データをログ保管先のS3バケットにアップロードしようとしてエラーとなっているように見受けられます。ただしエラーの直後はINFO: Files successfully uploaded to S3というアップロードが成功したようなログとなっています。

INFO: Uploading files to S3 ["/tmp/01-dev.classmethod.jp-loaded.png"]
INFO: Getting S3 location for uploading files
INFO: S3 destination for uploading artifacts determined: {"s3Bucket":"awscdkappstack-websitecanaryartifactsbucketec81f5-XXXXXXXXXXXX","s3Key":"canary/ap-northeast-1/website-canary/2021/09/23/14/11-31-188"}
ERROR: Unable to fetch S3 bucket location: Access Denied. Fallback to S3 client in current region: ap-northeast-1.
INFO: Files successfully uploaded to S3

該当のS3バケットおよびキーの中を見てみると、画像データはアップロードされていました。

画像データをダウンロードして開いてみるとちゃんと監視対象のスクリーンショットが取得できています。

ここでもう一度該当のエラーを見直してみます。最初Unable to fetch S3 bucket location: Access Denied.とあり権限の問題でバケットのロケーションの取得(fetch)ができないようなメッセージとなっています。

ERROR: Unable to fetch S3 bucket location: Access Denied. Fallback to S3 client in current region: ap-northeast-1.

また同行で続けてFallback to S3 client in current region: ap-northeast-1.とも出力されています。ロケーション取得の試行の問題がFallback(解決?)したためか、最終的なアップロード結果は次行のログFiles successfully uploaded to S3の通り成功となっています。

切り分け

コンソールから作成したCanaryの場合

前述のCanaryはAWS CDKで作成したものでした。切り分けのためにコンソールから作成したCanaryの場合についても確認してみます。

コンソールから作成したCanaryの、スクリーンショットをアップロードした直後のログを見てみると、エラーは発生していませんでした。

S3 Bucket location determined: ap-northeast-1とあり、再試行することなく東京リージョンに画像データのアップロードが行われているようです。

INFO: S3 destination for uploading artifacts determined: {"s3Bucket":"cw-syn-results-XXXXXXXXXXXX-ap-northeast-1","s3Key":"canary/ap-northeast-1/test-03d-7b18e7ffff04/2021/09/23/15/07-35-305"}
INFO: S3 Bucket location determined: ap-northeast-1
INFO: Files successfully uploaded to S3

このCanaryのIAMロールを確認してみます。

ロールにポリシーがアタッチされています。

ポリシーの内容はこんな感じ。Canaryのスクリプトを実行するLambdaが使用する権限ですね。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:GetObject"
            ],
            "Resource": [
                "arn:aws:s3:::cw-syn-results-XXXXXXXXXXXX-ap-northeast-1/canary/ap-northeast-1/test-03d-7b18e7ffff04/*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetBucketLocation"
            ],
            "Resource": [
                "arn:aws:s3:::cw-syn-results-XXXXXXXXXXXX-ap-northeast-1"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogStream",
                "logs:PutLogEvents",
                "logs:CreateLogGroup"
            ],
            "Resource": [
                "arn:aws:logs:ap-northeast-1:XXXXXXXXXXXX:log-group:/aws/lambda/cwsyn-test-*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:ListAllMyBuckets",
                "xray:PutTraceSegments"
            ],
            "Resource": [
                "*"
            ]
        },
        {
            "Effect": "Allow",
            "Resource": "*",
            "Action": "cloudwatch:PutMetricData",
            "Condition": {
                "StringEquals": {
                    "cloudwatch:namespace": "CloudWatchSynthetics"
                }
            }
        }
    ]
}

AWS CDKで作成したCanaryの場合

一方で最初のCDKで作成したCanaryのIAMロールの場合。CDKでは特にロール用のリソースは作成していないが、自動作成はされていそう。

しかしリンクから飛んだ先でNo Entity Foundとなりました。あるはずのIAMロールがありません。

と思いきやロール一覧から探したらありました。どういうことや…

ロールにアタッチされたポリシーを見てみます。

ポリシーの内容です。コンソールで作成した場合との差分を探してみるとs3:GetObjectのアクションが許可されていませんね。これがエラーの原因のようです。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": "s3:ListAllMyBuckets",
            "Resource": "*",
            "Effect": "Allow"
        },
        {
            "Action": [
                "s3:PutObject",
                "s3:GetBucketLocation"
            ],
            "Resource": "arn:aws:s3:::awscdkappstack-websitecanaryartifactsbucketec81f5-xxxxxxxx/*",
            "Effect": "Allow"
        },
        {
            "Condition": {
                "StringEquals": {
                    "cloudwatch:namespace": "CloudWatchSynthetics"
                }
            },
            "Action": "cloudwatch:PutMetricData",
            "Resource": "*",
            "Effect": "Allow"
        },
        {
            "Action": [
                "logs:CreateLogStream",
                "logs:CreateLogGroup",
                "logs:PutLogEvents"
            ],
            "Resource": "arn:aws:logs:::*",
            "Effect": "Allow"
        }
    ]
}

このポリシーの差分とエラー時のログのメッセージから推測するに、スクリーンショットの画像データをS3バケットにアップロードする過程の中でバケットを取得してチェックする処理があるが権限不足でエラーとなった、しかしそのチェックが成功することは必須ではないため握りつぶされ、次に本来の目的であるアップロードが行われたがこちらは権限不足は無かったため問題なく成功した、という感じでしょうか。

なんかCloudFormationによるCanaryデプロイ時の処理のバグっぽいですね。

結論

  • 発生条件:AWS CDK(多分CloudFormation)でデプロイした場合
  • 原因:(おそらく)CloudFormationによるCanaryデプロイ時の処理のバグ
  • 影響:ログにエラーが出力されて気持ち悪いというだけ。Canary実行やログ保管の動作には特に影響なさそう。
  • 対処の必要性:静観で良さそう

というわけで静観することにしました。

以上