Back to notes

Your S3 bucket and CloudFront distribution are ready, but the bucket is empty. You need a way to get built files into it. CodePipeline automates the cycle: pull source from GitHub, build with CodeBuild, deploy to S3. This post sets up the foundation, and the next three posts cover each stage.

Artifact Bucket

The pipeline needs somewhere to store intermediate artifacts between stages. A separate AWS::S3::Bucket handles this.

  PipelineArtifactBucket:
    Type: 'AWS::S3::Bucket'
    Properties:
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true
      BucketEncryption:
        ServerSideEncryptionConfiguration:
          - ServerSideEncryptionByDefault:
              SSEAlgorithm: AES256
      LifecycleConfiguration:
        Rules:
          - Id: CleanupOldArtifacts
            Status: Enabled
            ExpirationInDays: 7
            NoncurrentVersionExpiration:
              NoncurrentDays: 3
            AbortIncompleteMultipartUpload:
              DaysAfterInitiation: 1

This is not your site bucket. The site bucket holds your final deployed files. The artifact bucket holds zipped source code and build output as they move between pipeline stages. PublicAccessBlockConfiguration keeps artifacts private. BucketEncryption sets SSE-S3 explicitly, same as the site bucket. There is no VersioningConfiguration here because pipeline artifacts are disposable. The pipeline writes new artifacts on every run, so there is no rollback value in keeping old versions.

ExpirationInDays: 7 deletes current artifacts after 7 days. Unlike the site bucket where you only expire noncurrent versions, artifact files themselves are temporary. NoncurrentVersionExpiration with NoncurrentDays: 3 catches any noncurrent versions if versioning is ever enabled at the bucket level. AbortIncompleteMultipartUpload with DaysAfterInitiation: 1 cleans up failed multipart uploads after 1 day. Without it, partial uploads from interrupted builds sit in the bucket forever and you pay for the storage.

Artifact Bucket Policy

The artifact bucket needs a bucket policy that enforces TLS. Without it, requests over plain HTTP would be allowed. An AWS::S3::BucketPolicy with a DenyInsecureTransport statement blocks any request where aws:SecureTransport is false.

  ArtifactBucketPolicy:
    Type: 'AWS::S3::BucketPolicy'
    Properties:
      Bucket: !Ref PipelineArtifactBucket
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Sid: DenyInsecureTransport
            Effect: Deny
            Principal: '*'
            Action: 's3:*'
            Resource:
              - !GetAtt PipelineArtifactBucket.Arn
              - !Sub '${PipelineArtifactBucket.Arn}/*'
            Condition:
              Bool:
                'aws:SecureTransport': 'false'

This is the same pattern used in the site bucket policy from post 7. The Resource array covers both the bucket itself and all objects inside it, so bucket-level and object-level API calls are both required to use TLS.

Updating the Role

Your Git Sync role from post 4 needs permissions to create all the pipeline resources. Add these statements to the inline policy in your role stack.

              - Effect: Allow
                Action:
                  - 'codepipeline:CreatePipeline'
                  - 'codepipeline:UpdatePipeline'
                  - 'codepipeline:DeletePipeline'
                  - 'codepipeline:GetPipeline'
                  - 'codepipeline:GetPipelineState'
                  - 'codepipeline:TagResource'
                Resource: '*'
              - Effect: Allow
                Action:
                  - 'codebuild:CreateProject'
                  - 'codebuild:UpdateProject'
                  - 'codebuild:DeleteProject'
                  - 'codebuild:BatchGetProjects'
                Resource: '*'
              - Effect: Allow
                Action:
                  - 'iam:CreateRole'
                  - 'iam:GetRole'
                  - 'iam:DeleteRole'
                  - 'iam:PutRolePolicy'
                  - 'iam:GetRolePolicy'
                  - 'iam:DeleteRolePolicy'
                  - 'iam:PassRole'
                  - 'iam:TagRole'
                Resource: '*'
              - Effect: Allow
                Action:
                  - 'codestar-connections:PassConnection'
                Resource: '*'
              - Effect: Allow
                Action:
                  - 'logs:CreateLogGroup'
                  - 'logs:DeleteLogGroup'
                  - 'logs:PutRetentionPolicy'
                Resource: '*'
  • CodePipeline actions cover the full lifecycle of pipelines.
  • CodeBuild actions let CloudFormation manage build projects.
  • IAM actions let CloudFormation create and manage the service roles defined above. iam:PassRole is critical because the template assigns roles to CodePipeline and CodeBuild. Without PassRole, CloudFormation can create the roles but cannot attach them to the pipeline or build project.
  • codestar-connections:PassConnection lets CloudFormation pass the connection ARN to the pipeline’s Source stage.
  • CloudWatch Logs actions let CloudFormation manage the log groups that CodeBuild creates.