From 9b141642badb68bd8e663a1f5f573a6c14561acf Mon Sep 17 00:00:00 2001 From: vsnyc Date: Mon, 21 Aug 2023 18:30:07 -0400 Subject: [PATCH] Addressed cfn-lint findings, added encryption for S3 buckets and SNS topics --- .../linux-ami-codepipeline.yaml | 3 +- patterns/LambdaZips/README.md | 10 ++++++ patterns/LambdaZips/example.yaml | 10 ++++++ .../LessSimpleNonWorking.yaml | 14 +++++++-- .../CircularDependency/LessSimpleWorking.yaml | 13 ++++++-- .../ami-factory.yaml | 1 + .../codebuild.yaml | 15 +++++++-- .../examples/bucket.yaml | 11 ++++++- .../templates/master.template.yaml | 31 ++++++++++++++----- templates/workload-yaml.template.yaml | 12 ++++++- 10 files changed, 103 insertions(+), 17 deletions(-) diff --git a/blog-assets/automate-ami-builds-aws-codepipeline-D35708869/linux-ami-codepipeline.yaml b/blog-assets/automate-ami-builds-aws-codepipeline-D35708869/linux-ami-codepipeline.yaml index c930c40..0acbc4f 100644 --- a/blog-assets/automate-ami-builds-aws-codepipeline-D35708869/linux-ami-codepipeline.yaml +++ b/blog-assets/automate-ami-builds-aws-codepipeline-D35708869/linux-ami-codepipeline.yaml @@ -75,6 +75,7 @@ Resources: CodePipelineSNSTopic: Type: AWS::SNS::Topic Properties: + KmsMasterKeyId: !Sub arn:${AWS::Partition}:kms:${AWS::Region}:${AWS::AccountId}:alias/aws/sns Subscription: - Endpoint: !Ref 'Email' Protocol: email @@ -159,7 +160,7 @@ Resources: - PolicyName: CloudFormationRole PolicyDocument: Version: '2012-10-17' - Statement: + Statement: - Effect: Allow Action: - ec2:ImportKeyPair diff --git a/patterns/LambdaZips/README.md b/patterns/LambdaZips/README.md index 705f8b1..a0acb00 100644 --- a/patterns/LambdaZips/README.md +++ b/patterns/LambdaZips/README.md @@ -13,6 +13,16 @@ Resources: # Create a bucket in the local region LambdaZipsBucket: Type: AWS::S3::Bucket + Properties: + BucketEncryption: + ServerSideEncryptionConfiguration: + - ServerSideEncryptionByDefault: + SSEAlgorithm: AES256 + PublicAccessBlockConfiguration: + BlockPublicAcls: true + BlockPublicPolicy: true + IgnorePublicAcls: true + RestrictPublicBuckets: true # Copy zip files from source bucket CopyZips: Type: Custom::CopyZips diff --git a/patterns/LambdaZips/example.yaml b/patterns/LambdaZips/example.yaml index b7088af..7a2a178 100644 --- a/patterns/LambdaZips/example.yaml +++ b/patterns/LambdaZips/example.yaml @@ -12,6 +12,16 @@ Parameters: Resources: LambdaZipsBucket: Type: AWS::S3::Bucket + Properties: + BucketEncryption: + ServerSideEncryptionConfiguration: + - ServerSideEncryptionByDefault: + SSEAlgorithm: AES256 + PublicAccessBlockConfiguration: + BlockPublicAcls: true + BlockPublicPolicy: true + IgnorePublicAcls: true + RestrictPublicBuckets: true CopyZips: Type: Custom::CopyZips Properties: diff --git a/patterns/blog/CircularDependency/LessSimpleNonWorking.yaml b/patterns/blog/CircularDependency/LessSimpleNonWorking.yaml index 5618e44..e0dcc62 100644 --- a/patterns/blog/CircularDependency/LessSimpleNonWorking.yaml +++ b/patterns/blog/CircularDependency/LessSimpleNonWorking.yaml @@ -2,7 +2,17 @@ AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Resources: Bucket: - Type: AWS::S3::Bucket + Type: AWS::S3::Bucket + Properties: + BucketEncryption: + ServerSideEncryptionConfiguration: + - ServerSideEncryptionByDefault: + SSEAlgorithm: AES256 + PublicAccessBlockConfiguration: + BlockPublicAcls: true + BlockPublicPolicy: true + IgnorePublicAcls: true + RestrictPublicBuckets: true Function: Type: AWS::Serverless::Function Properties: @@ -11,7 +21,7 @@ Resources: Handler: index.handler Policies: - Version: 2012-10-17 - Statement: + Statement: - Effect: Allow Action: s3:GetObject* Resource: !Sub "arn:aws:s3:::${Bucket}*" diff --git a/patterns/blog/CircularDependency/LessSimpleWorking.yaml b/patterns/blog/CircularDependency/LessSimpleWorking.yaml index 1813c90..b3a041f 100644 --- a/patterns/blog/CircularDependency/LessSimpleWorking.yaml +++ b/patterns/blog/CircularDependency/LessSimpleWorking.yaml @@ -2,9 +2,18 @@ AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Resources: Bucket: - Type: AWS::S3::Bucket + Type: AWS::S3::Bucket Properties: BucketName: !Sub "cderror-${AWS::AccountId}" + BucketEncryption: + ServerSideEncryptionConfiguration: + - ServerSideEncryptionByDefault: + SSEAlgorithm: AES256 + PublicAccessBlockConfiguration: + BlockPublicAcls: true + BlockPublicPolicy: true + IgnorePublicAcls: true + RestrictPublicBuckets: true Function: Type: AWS::Serverless::Function Properties: @@ -13,7 +22,7 @@ Resources: Handler: index.handler Policies: - Version: 2012-10-17 - Statement: + Statement: - Effect: Allow Action: s3:GetObject* Resource: !Sub "arn:aws:s3:::cderror-${AWS::AccountId}/*" diff --git a/samples/ami-factory-step-function/ami-factory.yaml b/samples/ami-factory-step-function/ami-factory.yaml index d496e9b..2d4fce8 100644 --- a/samples/ami-factory-step-function/ami-factory.yaml +++ b/samples/ami-factory-step-function/ami-factory.yaml @@ -18,6 +18,7 @@ Resources: SNSTopic: Type: AWS::SNS::Topic Properties: + KmsMasterKeyId: !Sub arn:${AWS::Partition}:kms:${AWS::Region}:${AWS::AccountId}:alias/aws/sns Subscription: - Endpoint: !Ref NotificationEmail Protocol: "email" diff --git a/samples/cloudformation-codebuild-container/codebuild.yaml b/samples/cloudformation-codebuild-container/codebuild.yaml index ba7d25f..b5aca24 100755 --- a/samples/cloudformation-codebuild-container/codebuild.yaml +++ b/samples/cloudformation-codebuild-container/codebuild.yaml @@ -120,6 +120,15 @@ Resources: LambdaZipsBucket: Type: AWS::S3::Bucket Properties: + BucketEncryption: + ServerSideEncryptionConfiguration: + - ServerSideEncryptionByDefault: + SSEAlgorithm: AES256 + PublicAccessBlockConfiguration: + BlockPublicAcls: true + BlockPublicPolicy: true + IgnorePublicAcls: true + RestrictPublicBuckets: true Tags: [] CopyZips: Type: AWS::CloudFormation::CustomResource @@ -200,7 +209,7 @@ Resources: - Name: IMAGE_REPO_NAME Value: !Ref ECRRepository - Name: IMAGE_TAG - Value: 'latest' + Value: 'latest' - Name: url_path Value: 'placeholder' - Name: url_query @@ -271,7 +280,7 @@ Resources: BuildProjectName: !Ref CodeBuildProject ECRRepository: !Ref ECRRepository # cfn_signal_url: is part of the event by default hence missing here - # cfn_stack_id: is part of the event by default + # cfn_stack_id: is part of the event by default # cfn_request_id: also part of the event # cfn_logical_resource_id: also part of the event # Lambda function passes the above into the build project when invoking StartBuild @@ -324,4 +333,4 @@ Resources: Action: - s3:GetObject - s3:PutObject - Resource: arn:aws:s3:::* + Resource: arn:aws:s3:::* diff --git a/samples/cloudformation-cross-account/examples/bucket.yaml b/samples/cloudformation-cross-account/examples/bucket.yaml index ad2291c..52c0104 100644 --- a/samples/cloudformation-cross-account/examples/bucket.yaml +++ b/samples/cloudformation-cross-account/examples/bucket.yaml @@ -1,11 +1,20 @@ AWSTemplateFormatVersion: "2010-09-09" Parameters: - Tag: + Tag: Type: String Resources: S3Bucket: Type: AWS::S3::Bucket Properties: + BucketEncryption: + ServerSideEncryptionConfiguration: + - ServerSideEncryptionByDefault: + SSEAlgorithm: AES256 + PublicAccessBlockConfiguration: + BlockPublicAcls: true + BlockPublicPolicy: true + IgnorePublicAcls: true + RestrictPublicBuckets: true Tags: - Key: cross-account Value: !Ref Tag diff --git a/samples/hugo-pipeline/templates/master.template.yaml b/samples/hugo-pipeline/templates/master.template.yaml index 12cd7a3..c9a5f61 100644 --- a/samples/hugo-pipeline/templates/master.template.yaml +++ b/samples/hugo-pipeline/templates/master.template.yaml @@ -6,6 +6,10 @@ Resources: ArtifactBucket: Type: 'AWS::S3::Bucket' Properties: + BucketEncryption: + ServerSideEncryptionConfiguration: + - ServerSideEncryptionByDefault: + SSEAlgorithm: AES256 AccessControl: Private LifecycleConfiguration: Rules: @@ -21,17 +25,21 @@ Resources: WebHostingBucket: Type: 'AWS::S3::Bucket' Properties: + BucketEncryption: + ServerSideEncryptionConfiguration: + - ServerSideEncryptionByDefault: + SSEAlgorithm: AES256 AccessControl: PublicRead BucketName: !Ref HostingBucketName WebsiteConfiguration: IndexDocument: index.html WebHostingBucketPolicy: Type: AWS::S3::BucketPolicy - Properties: + Properties: Bucket: !Ref WebHostingBucket PolicyDocument: Statement: - - + - Action: - "s3:GetObject" Effect: "Allow" @@ -43,6 +51,15 @@ Resources: - !Ref WebHostingBucket - "/*" Principal: "*" + - Action: s3:* + Effect: Deny + Principal: '*' + Resource: + - arn:aws:s3:::bucketname/* + - arn:aws:s3:::bucketname + Condition: + Bool: + aws:SecureTransport: false IAMRoleStack: Type: 'AWS::CloudFormation::Stack' DependsOn: @@ -62,10 +79,10 @@ Resources: https://${S3BucketName}.s3.amazonaws.com/${S3KeyPrefix}templates/pipeline.template.yaml Parameters: ArtifactBucket: !Ref ArtifactBucket - CodePipelineRoleArn: !GetAtt + CodePipelineRoleArn: !GetAtt - IAMRoleStack - Outputs.CodePipelineRoleArn - CodeBuildRoleArn: !GetAtt + CodeBuildRoleArn: !GetAtt - IAMRoleStack - Outputs.CodeBuildRoleArn CloudfrontDistId: '!Ref CloudfrontDistId' @@ -73,7 +90,7 @@ Resources: WebsiteBucket: !Ref WebHostingBucket RepoName: !Ref RepoName RepoBranch: 'master' - + Parameters: RepoName: Description: Enter the repository name to host hugo website content @@ -118,9 +135,9 @@ Outputs: Description: Name of S3 bucket to hold website content CodePipelineURL: Description: The URL of the created Pipeline - Value: !Sub + Value: !Sub - >- https://${AWS::Region}.console.aws.amazon.com/codepipeline/home?region=${AWS::Region}#/view/${CodePipelineName} - - CodePipelineName: !GetAtt + - CodePipelineName: !GetAtt - CodePipelineStack - Outputs.CodePipelineName diff --git a/templates/workload-yaml.template.yaml b/templates/workload-yaml.template.yaml index 4f28734..b80272e 100644 --- a/templates/workload-yaml.template.yaml +++ b/templates/workload-yaml.template.yaml @@ -230,6 +230,7 @@ Resources: NotificationTopic: Type: AWS::SNS::Topic Properties: + KmsMasterKeyId: !Sub arn:${AWS::Partition}:kms:${AWS::Region}:${AWS::AccountId}:alias/aws/sns Subscription: - Endpoint: Ref: OperatorEmail @@ -294,7 +295,7 @@ Resources: Resource: - !Sub - arn:${AWS::Partition}:s3:::${S3Bucket}/${QSS3KeyPrefix}* - - S3Bucket: !If + - S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName @@ -481,6 +482,15 @@ Resources: S3Bucket: Type: AWS::S3::Bucket Properties: + BucketEncryption: + ServerSideEncryptionConfiguration: + - ServerSideEncryptionByDefault: + SSEAlgorithm: AES256 + PublicAccessBlockConfiguration: + BlockPublicAcls: true + BlockPublicPolicy: true + IgnorePublicAcls: true + RestrictPublicBuckets: true BucketName: Ref: S3BucketName AccessControl: BucketOwnerFullControl