CodePipeline Session Policy Error on S3 ListBucket During Deploy

0

I am creating an AWS CodePipeline via a CloudFormation template with three steps

  1. Checkout source from GitHub
  2. Build using CodeBuild
  3. Deploy

However, the pipeline fails on the Deploy step with the following message:

User: arn:aws:sts::AccountID:assumed-role/drive-tracker-cicd-prod-CodePipelineRole-QnWs78DD8pmv/1730118657170 is not authorized to perform: s3:ListBucket on resource: "arn:aws:s3:::drive-tracker-prod-artifacts" because no session policy allows the s3:ListBucket action (Service: Amazon S3; Status Code: 403; Error Code: AccessDenied; Request ID: Z7135KF3QJY8W53J; S3 Extended Request ID: N+tgLvQdEVUmRhbMJBh+vPIP7X1W+sIVBwzZg8sEjqRgR3ZxHuxi2+QOjpBkkdLyb+hxBkZGQjU=; Proxy: null)

I verified via IAM PolicySimulator that both CodePipelineRole and CodeDeployRole are able to perform s3:ListBucket operation on the artifact storage bucket. Furthermore, I read that the error may be related to the role's inability to access KMS key which was used to encrypt the bucket si I added KMS permissions to both roles. Lastly, I verified that CodePipelineRole is able to assume CodeDeployRole. However, the error remained the same after each of these changes.

The pipeline definition:

AWSTemplateFormatVersion: '2010-09-09'

Description: 'DriveTracker CI/CD pipeline'

Parameters:
  CodeStarArn:
    Type: String
  Branch:
    Type: String
  DeployStackName:
    Type: String

Resources:
  PipelineArtifactBucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Sub "${DeployStackName}-artifacts"

  DriveTrackerPipeline:
    Type: AWS::CodePipeline::Pipeline
    Properties:
      Name: drive-tracker-pipeline
      ArtifactStore:
        Type: S3
        Location: !Ref PipelineArtifactBucket
      RoleArn: !GetAtt CodePipelineRole.Arn
      Stages:
        - Name: Source
          Actions:
            - Name: CheckoutGithubSource
              ActionTypeId:
                Category: Source
                Owner: AWS
                Provider: CodeStarSourceConnection
                Version: '1'
              Configuration:
                ConnectionArn: !Ref CodeStarArn
                FullRepositoryId: "martinbalucha/DriveTracker"
                BranchName: !Ref Branch
              RunOrder: 1
              OutputArtifacts:
                - Name: SourceOutput

        - Name: Build
          Actions:
            - Name: BuildSolution
              ActionTypeId:
                Category: Build
                Owner: AWS
                Provider: CodeBuild
                Version: '1'
              InputArtifacts:
                - Name: SourceOutput
              OutputArtifacts:
                - Name: BuildOutput
              Configuration:
                ProjectName: !Ref DriveTrackerBuild

        - Name: Deploy
          Actions:
            - Name: !Join [ "-", [ "Deploy", !Ref DeployStackName ] ]
              ActionTypeId:
                Category: Deploy
                Owner: AWS
                Provider: CloudFormation
                Version: '1'
              Configuration:
                ActionMode: CREATE_UPDATE
                Capabilities: CAPABILITY_IAM
                OutputFileName: DeployResult
                StackName: !Ref DeployStackName
                TemplatePath: BuildOutput::deploy/application.yml
                RoleArn: !GetAtt CodeDeployRole.Arn
              InputArtifacts:
                - Name: BuildOutput
              RunOrder: 1

  CodePipelineRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: codepipeline.amazonaws.com
            Action: sts:AssumeRole
      Policies:
        - PolicyName: CodePipelineAccess
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - iam:PassRole
                Resource: "*"
              - Effect: Allow
                Action:
                  - s3:PutObject
                  - s3:GetObject
                  - s3:GetBucket
                  - s3:ListBucket
                Resource: 
                  - !Join
                    - ''
                    - - 'arn:aws:s3:::'
                      - !Ref PipelineArtifactBucket
                  - !Join
                    - ''
                    - - 'arn:aws:s3:::'
                      - !Ref PipelineArtifactBucket
                      - /*
              - Effect: Allow
                Action: 'codestar-connections:UseConnection'
                Resource: !Ref CodeStarArn
              - Effect: Allow
                Action:
                  - codebuild:StartBuild
                  - codebuild:BatchGetBuilds                  
                Resource: !GetAtt DriveTrackerBuild.Arn
              - Effect: Allow
                Action:
                  - cloudformation:CreateStack
                  - cloudformation:DeleteStack
                  - cloudformation:DescribeStacks
                  - cloudformation:UpdateStack
                  - cloudformation:CreateChangeSet
                  - cloudformation:DeleteChangeSet
                  - cloudformation:DescribeChangeSet
                  - cloudformation:ExecuteChangeSet
                  - cloudformation:SetStackPolicy
                  - cloudformation:ValidateTemplate
                  - sts:AssumeRole
                Resource: '*'
              - Effect: Allow
                Action:
                  - kms:*
                Resource: '*'

  DriveTrackerBuild:
    Type: AWS::CodeBuild::Project
    Properties:
      Name: !Sub "${DeployStackName}-Build"
      Source:
        Type: CODEPIPELINE
        BuildSpec: "buildspec.yml"
      Artifacts:
        Type: CODEPIPELINE
      Environment:
        ComputeType: BUILD_GENERAL1_SMALL
        Image: "aws/codebuild/standard:6.0"
        Type: LINUX_CONTAINER
      ServiceRole: !GetAtt CodeBuildServiceRole.Arn
      TimeoutInMinutes: 30
      QueuedTimeoutInMinutes: 60

  CodeBuildServiceRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - codebuild.amazonaws.com
                - codepipeline.amazonaws.com
            Action: sts:AssumeRole
      Policies:
        - PolicyName: CodeBuildPolicy
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action:
                  - s3:PutObject
                  - s3:GetObject*
                  - s3:GetBucket*
                  - s3:ListBucket
                Resource: 
                  - !Join
                    - ''
                    - - 'arn:aws:s3:::'
                      - !Ref PipelineArtifactBucket
                  - !Join
                    - ''
                    - - 'arn:aws:s3:::'
                      - !Ref PipelineArtifactBucket
                      - /*
                Resource: '*'
              - Effect: Allow
                Action:
                  - codepipeline:PutJobSuccessResult
                  - codepipeline:PutJobFailureResult
                Resource: "*"
              - Effect: Allow
                Action:
                  - logs:CreateLogStream
                  - logs:CreateLogGroup
                  - logs:PutLogEvents
                Resource: "*"
  
  CodeDeployRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              AWS: 
                - !GetAtt CodePipelineRole.Arn
              Service: 
                - cloudformation.amazonaws.com
                - codepipeline.amazonaws.com
            Action: sts:AssumeRole
      Policies:
        - PolicyName: CodeDeployRole
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action:
                  - s3:PutObject
                  - s3:GetObject*
                  - s3:GetBucket*
                  - s3:List*
                Resource: 
                  - !Join
                    - ''
                    - - 'arn:aws:s3:::'
                      - !Ref PipelineArtifactBucket
                  - !Join
                    - ''
                    - - 'arn:aws:s3:::'
                      - !Ref PipelineArtifactBucket
                      - /*
              - Effect: Allow
                Action:
                  - cloudformation:CreateStack
                  - cloudformation:DeleteStack
                  - cloudformation:DescribeStacks
                  - cloudformation:UpdateStack
                  - cloudformation:CreateChangeSet
                  - cloudformation:DeleteChangeSet
                  - cloudformation:DescribeChangeSet
                  - cloudformation:ExecuteChangeSet
                  - cloudformation:SetStackPolicy
                  - cloudformation:ValidateTemplate
                  - iam:PassRole
                Resource: '*'
              - Effect: Allow
                Action:
                  - kms:*
                Resource: '*'

Could anyone help me with this? What is the cause of this issue and how can I solve it?

1 Answer
0

The issue you're experiencing is likely related to the session policy that's applied when CodePipeline assumes the CodeDeployRole during the Deploy stage. Even though you've verified that both CodePipelineRole and CodeDeployRole have the necessary permissions, the session policy that's created when assuming the role might be restricting access.

To resolve this issue, try the following steps:

  1. Ensure that the CodePipelineRole has explicit permission to assume the CodeDeployRole. Add the following statement to the CodePipelineRole's policy:
{
  "Effect": "Allow",
  "Action": "sts:AssumeRole",
  "Resource": "<ARN of CodeDeployRole>"
}
  1. In your CodeDeployRole, make sure the trust relationship (AssumeRolePolicyDocument) explicitly allows CodePipeline to assume this role. You have this in your template, but double-check that it's correct.

  2. In the CodeDeployRole policy, ensure that the S3 permissions are explicitly granted for the artifact bucket. Your current policy uses a wildcard (*) for the Resource, which might be too broad. Instead, specify the exact ARN of your artifact bucket:

{
  "Effect": "Allow",
  "Action": [
    "s3:GetObject*",
    "s3:GetBucket*",
    "s3:List*"
  ],
  "Resource": [
    "arn:aws:s3:::${PipelineArtifactBucket}",
    "arn:aws:s3:::${PipelineArtifactBucket}/*"
  ]
}
  1. If you're using KMS encryption on your S3 bucket, make sure both roles have the necessary KMS permissions to decrypt objects in the bucket.

  2. In your pipeline configuration, make sure you're using the correct role ARN for the CloudFormation deploy action. Verify that the RoleArn in the Deploy action configuration is correctly referencing the CodeDeployRole:

RoleArn: !GetAtt CodeDeployRole.Arn
  1. If the issue persists, you may need to review the CloudTrail logs to see the exact API calls being made and identify where the permission is being denied.

Remember, when troubleshooting IAM issues, it's always best to start with the principle of least privilege and gradually add permissions as needed, rather than using overly broad permissions.
Sources
Troubleshooting CodePipeline - AWS CodePipeline
CI/CD Pipeline – AWS CodePipeline Features – AWS
Tutorial: Create a pipeline that uses variables from AWS CloudFormation deployment actions - AWS CodePipeline

profile picture
answered 10 days ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions