CodePipelineのビルドフェーズでSorceArtifactの保存先へAccessDeniedにより失敗したときの原因と対応

2021.08.25

FargateへCI/CDの設定をCloudformationで作成したCodePipelineで行っていました。CodeCommitのフェーズでS3へアップロードされたSorceArtrifactを、CodeBuildのフェーズでS3から取得しようとするところでAccessDeniedとビルドログに表示されCodeBuildが失敗しました。そのエラーと対応内容を紹介します。

CodeBuildのビルドログより

AccessDenied: Access Denied status code: 403, request id: C7DTB8NZWBE6JGFP, host id: QswsuzoG0XAomr3+5mgVRbns/qYfBouTWzgG4JOF66uOCMV5mM5JXB5T9jpmiGKYK/BaQQrcPMA= for primary source and source version arn:aws:s3:::sample3-dev-webservice-artifact/sample3-dev-webservi/SourceArti/fPaPz8E

原因

  • CodeBuildのビルドプロジェクトに設定したサービスロールの権限に不備があった。
  • マネージメントコンソールからビルドプロジェクトを作成し、サービスロールの自動作成を選択した場合はほどよい権限を与えてくれていた。

状況と設定内容

パイプラインはビルドフェーズで失敗して終わっています。

CodeBuildの詳細を確認すると開始早々に失敗しています。

表示されているメッセージ内容からS3バケットに保存されているSorceArtifactの取得に失敗していることがわかります。AccessDeniedからIAMポリシーが疑わしいです。

メッセージ内容抜粋

CLIENT_ERROR: AccessDenied: Access Denied status code: 403 ... for primary source and source version arn:aws:s3:::...

CodePipelineのアーティファクト保存先S3バケットは以下の設定です。CodeBuildのビルドプロジェクトがこのS3バケットに対して権限があるのか確認します。

CodeBuildのビルドプロジェクトに設定しているサービスロールを確認します。サービスロールと、サービスロールにアタッチしているIAMポリシーは自作したものです。

自作したIAMポリシーの内容を確認します。

ResourceSourceArtifactが保存されるS3バケットを指定しています。改めて考えるとS3バケットの中までの権限がないですね。CloudformationでIAMポリシーを作成していたのですが、先に作成したS3バケット名をIAMポリシーに設定して満足していました。

S3部分の抜粋

        {
            "Action": [
                "s3:PutObject",
                "s3:GetObject",
                "s3:GetObjectVersion",
                "s3:GetBucketAcl",
                "s3:GetBucketLocation"
            ],
            "Resource": [
                "arn:aws:s3:::sample3-dev-webservice-artifact"
            ],
            "Effect": "Allow"
        },

修正

Resourcesの指定方法を[バケット名]*としました。

修正版S3部分の抜粋

        {
            "Action": [
                "s3:PutObject",
                "s3:GetObject",
                "s3:GetObjectVersion",
                "s3:GetBucketAcl",
                "s3:GetBucketLocation"
            ],
            "Resource": [
                "arn:aws:s3:::sample3-dev-webservice-artifact*"
            ],
            "Effect": "Allow"
        },

パイプライン再実行

ビルドフェーズ成功しました。

マネコンから作成した場合は?

マネージメントコンソールから手動でビルドプロジェクトを作成しようとすると、新規にサービスロール作成してくる選択があります。

そこで作成されたサービスロールのIAMポリシーは以下でした。codepipelineとリージョン名から始まるS3バケットに対して許可を与えています。

S3部分抜粋

        {
            "Action": [
                "s3:PutObject",
                "s3:GetObject",
                "s3:GetObjectVersion",
                "s3:GetBucketAcl",
                "s3:GetBucketLocation"
            ],
            "Resource": [
                "arn:aws:s3:::codepipeline-ap-northeast-1-*"
            ],
            "Effect": "Allow"
        },

アーティファクト保存先のS3バケットはマネジメントコンソールからはじめてパイプラインを作成するタイミングで、codepipeline-region-12345EXAMPLEの形式のS3バケットが作成されます。IAMポリシーのリソース名の指定方法にも納得がいきますね。

codepipeline-ap-norutheast-1-hogeのS3バケットが確かに指定されています。

対象のS3バケットを確認すると、手動で作成した過去のパイプライン名のフォルダが存在していました。

サービスロール自動生成の場合は意識しないけど、手動またはIaCツールからサービスロール、IAMポリシーを作成するときは意識してみてください。

おわりに

今回はCloudformationで作成していました。マネコンからパイプラインを作成すると意識しないCodePipelineのサービスロール、CodeBuildのサービスロールの権限設定を自分でやってみると関連しているリソースが見えてきて勉強になりました。