AWSTemplateFormatVersion: '2010-09-09' Parameters: BucketName: Type: String Description: "The name for the S3 bucket to be used for public website hosting (must be globally unique)" Default: "naputo-blog-public" Resources: WebsiteBucket: Type: AWS::S3::Bucket Properties: BucketName: !Ref BucketName PublicAccessBlockConfiguration: BlockPublicAcls: true BlockPublicPolicy: true IgnorePublicAcls: true RestrictPublicBuckets: true WebsiteBucketPolicy: Type: AWS::S3::BucketPolicy Properties: Bucket: !Ref WebsiteBucket PolicyDocument: Version: '2012-10-17' Statement: - Sid: AllowCodePipelineUpdates Effect: Allow Principal: AWS: !GetAtt CodePipelineRole.Arn Action: - s3:PutObject - s3:DeleteObject Resource: !Sub "arn:aws:s3:::${WebsiteBucket}/*" - Sid: AllowCloudFrontOACGetObject Effect: Allow Principal: Service: cloudfront.amazonaws.com Action: - s3:GetObject Resource: !Sub "arn:aws:s3:::${WebsiteBucket}/*" Condition: StringEquals: AWS:SourceArn: Fn::Sub: - arn:aws:cloudfront::${AWS::AccountId}:distribution/${MyCloudFrontDistribution} - MyCloudFrontDistribution: Fn::ImportValue: BlogCloudFrontDistribution-ID CodeBuildServiceRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: - codebuild.amazonaws.com Action: - sts:AssumeRole Policies: - PolicyName: CodeBuildPolicy PolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Action: - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents Resource: "*" - Effect: Allow Action: - s3:GetObject - s3:PutObject - s3:ListBucket Resource: - !Sub "arn:aws:s3:::codebuild-${AWS::Region}-${AWS::AccountId}-input-bucket" - !Sub "arn:aws:s3:::codebuild-${AWS::Region}-${AWS::AccountId}-input-bucket/*" - "arn:aws:s3:::naputo-blog-source" - "arn:aws:s3:::naputo-blog-source/*" MyBlogCodeBuildProject: Type: AWS::CodeBuild::Project Properties: ServiceRole: !GetAtt CodeBuildServiceRole.Arn Artifacts: Type: CODEPIPELINE Environment: ComputeType: BUILD_LAMBDA_1GB Image: aws/codebuild/amazonlinux-x86_64-lambda-standard:nodejs22 Type: LINUX_LAMBDA_CONTAINER Source: Type: CODEPIPELINE CodePipelineRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: - codepipeline.amazonaws.com Action: - sts:AssumeRole Policies: - PolicyName: CodePipelinePolicy PolicyDocument: Version: '2012-10-17' Statement: # Permissions for accessing the artifacts bucket - Effect: Allow Action: - s3:GetBucketAcl - s3:GetObjectTagging - s3:GetObjectVersionTagging - s3:GetObject - s3:GetObjectVersion - s3:PutObject - s3:ListBucket - s3:GetBucketLocation - s3:GetBucketVersioning Resource: - !Sub "arn:aws:s3:::codebuild-${AWS::Region}-${AWS::AccountId}-input-bucket" - !Sub "arn:aws:s3:::codebuild-${AWS::Region}-${AWS::AccountId}-input-bucket/*" - "arn:aws:s3:::naputo-blog-source" - "arn:aws:s3:::naputo-blog-source/*" # Permissions for CloudFormation actions - Effect: Allow Action: - cloudformation:CreateStack - cloudformation:DeleteStack - cloudformation:UpdateStack - cloudformation:DescribeStacks - cloudformation:DescribeStackEvents - cloudformation:ValidateTemplate Resource: "*" # Permissions for CodeBuild (if used) - Effect: Allow Action: - codebuild:StartBuild - codebuild:BatchGetBuilds Resource: - !Sub "arn:aws:codebuild:${AWS::Region}:${AWS::AccountId}:build/*" - !Sub "arn:aws:codebuild:${AWS::Region}:${AWS::AccountId}:project/*" # Permissions for manual approval actions in CodePipeline - Effect: Allow Action: - codepipeline:StartPipelineExecution - codepipeline:PutApprovalResult Resource: !Sub "arn:aws:codepipeline:${AWS::Region}:${AWS::AccountId}:*" MyBlogPipeline: Type: AWS::CodePipeline::Pipeline Properties: PipelineType: V2 ArtifactStore: Type: S3 Location: !Sub "codebuild-${AWS::Region}-${AWS::AccountId}-input-bucket" RoleArn: !GetAtt CodePipelineRole.Arn Tags: - Key: Project Value: Git-server Stages: - Name: Source Actions: - Name: S3Source ActionTypeId: Category: Source Owner: AWS Provider: S3 Version: "1" OutputArtifacts: - Name: SourceArtifact Configuration: S3Bucket: naputo-blog-source S3ObjectKey: source.zip PollForSourceChanges: false RunOrder: 1 - Name: Build Actions: - Name: CodeBuild ActionTypeId: Category: Build Owner: AWS Provider: CodeBuild Version: "1" Configuration: ProjectName: !Ref MyBlogCodeBuildProject OutputArtifacts: - Name: BuildArtifact InputArtifacts: - Name: SourceArtifact RunOrder: 1 - Name: Approval Actions: - Name: ManualApproval ActionTypeId: Category: Approval Owner: AWS Provider: Manual Version: "1" RunOrder: 1 Configuration: CustomData: "Please review the build artifact and approve the deployment." - Name: Deploy Actions: - Name: S3Deploy ActionTypeId: Category: Deploy Owner: AWS Provider: S3 Version: "1" InputArtifacts: - Name: BuildArtifact Configuration: BucketName: !Ref WebsiteBucket Extract: 'true' RunOrder: 1 S3SourceChangeRule: Type: AWS::Events::Rule Properties: Description: Trigger CodePipeline on S3 source update EventPattern: source: - aws.s3 detail-type: - Object Created detail: bucket: name: - naputo-blog-source object: key: - source.zip Targets: - Arn: !Sub arn:aws:codepipeline:${AWS::Region}:${AWS::AccountId}:${MyBlogPipeline} RoleArn: !GetAtt EventBridgeInvokePipelineRole.Arn Id: CodePipelineTarget EventBridgeInvokePipelineRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: events.amazonaws.com Action: sts:AssumeRole Policies: - PolicyName: AllowStartPipeline PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - codepipeline:StartPipelineExecution Resource: !Sub arn:aws:codepipeline:${AWS::Region}:${AWS::AccountId}:${MyBlogPipeline}