Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pipeline modules #463

Draft
wants to merge 7 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Solutions/Pipelines/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
*-pkg.yaml
dist
deploy.sh
.DS_Store



25 changes: 25 additions & 0 deletions Solutions/Pipelines/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# CloudFormation CI/CD Pipelines

This project contains templates that can be used to create CI/CD pipelines.
The pipelines can be centrally managed and accessed by app teams via a web
application, or they can be owned and managed by autonomous teams. The
templates are composed of local modules, which can be used as building blocks
to create new types of pipelines.

In the centrally managed use case, templates are stored in an S3 bucket
controlled by the platform team. When an app team chooses a template to spin up
a pipeline, the pipeline is configured to self-mutate whenever there is a
change to the source in S3. Each pipeline has two sources, one for the pipeline
and one for the application itself. Application teams control the build
specification files for the CodeBuild jobs in pipeline actions.

The web application included in this project is a simple proof-of-concept that
could be used as a starting point for building a fully featured CI/CD portal.
Once a template is chosen from the administrative UI, access is granted to the
AWS console to view and interact with the stack and pipeline.

CloudFormation templates are divided up into two categories. Bootstrap
templates are used to install the correct roles into target deployment
accounts. Pipeline templates are used to create the pipelines in the central
account.

13 changes: 13 additions & 0 deletions Solutions/Pipelines/app/buildspec.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
version: 0.2
phases:
install:
commands:
- pwd
- ls
- echo "Install phase..."
build:
commands:
- pwd
- ls
- echo "Build phase..."

21 changes: 21 additions & 0 deletions Solutions/Pipelines/modules/bucket-policy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
Inputs:
PolicyBucketName:
Type: String
Resources:
Policy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref PolicyBucketName
PolicyDocument:
Statement:
- Action: s3:*
Condition:
Bool:
aws:SecureTransport: false
Effect: Deny
Principal:
AWS: '*'
Resource:
- !Sub "arn:${AWS::Partition}:s3:::${PolicyBucketName}"
- !Sub "arn:${AWS::Partition}:s3:::${PolicyBucketName}/*"
Version: "2012-10-17"
246 changes: 246 additions & 0 deletions Solutions/Pipelines/modules/bucket.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,246 @@
Description: This module creates an S3 bucket that will pass common compliance checks. It can create an associated log bucket and replica bucket, and encrypts the contents of the bucket.

Inputs:

Name:
Type: String
Description: This string will serve as a prefix for all resource names, which have the general form of Name-ResourceName-Region-Account.

CreateLogBucket:
Type: String
Description: If true, create a bucket for access logs
Default: false

CreateReplicaBucket:
Type: String
Description: If true, create a bucket for replicas
Default: false

EnableEventBridge:
Type: String
Description: Set this to true to enable notifications
Default: false

Conditions:

IsLoggingEnabled:
Fn::Equals:
- !Ref CreateLogBucket
- true

IsReplicationEnabled:
Fn::Equals:
- !Ref CreateReplicaBucket
- true

IsEventBridgeEnabled:
Fn::Equals:
- !Ref EnableEventBridge
- true

Constants:
S3Arn: "arn:${AWS::Partition}:s3:::"
BucketName: "${Name}-${AWS::Region}-${AWS::AccountId}"
LogBucketName: "${Name}-logs-${AWS::Region}-${AWS::AccountId}"
LogBucketArn: "${Const::S3Arn}${Const::LogBucketName}"
ReplicaBucketName: "${Name}-replicas-${AWS::Region}-${AWS::AccountId}"

Modules:

BucketAccess:
Source: bucket-policy.yaml
Properties:
PolicyBucketName: !Sub ${Const::BucketName}

LogBucketAccess:
Condition: IsLoggingEnabled
Source: bucket-policy.yaml
Properties:
PolicyBucketName: !Sub ${Const::LogBucketName}
Overrides:
Policy:
Properties:
PolicyDocument:
Statement:
- Action: s3:*
Condition:
Bool:
aws:SecureTransport: false
Effect: Deny
Principal:
AWS: '*'
Resource:
- !Sub ${Const::LogBucketArn}
- !Sub ${Const::LogBucketArn}/*
- Action: s3:PutObject
Condition:
ArnLike:
aws:SourceArn: !Sub ${Const::LogBucketArn}/*
StringEquals:
aws:SourceAccount: !Ref AWS::AccountId
Effect: Allow
Principal:
Service: logging.s3.amazonaws.com
Resource:
- !Sub ${Const::LogBucketArn}/*

ReplicaBucketAccess:
Condition: IsReplicationEnabled
Source: bucket-policy.yaml
Properties:
PolicyBucketName: !Sub ${Const::ReplicaBucketName}


Resources:

LogBucket:
Type: AWS::S3::Bucket
Condition: IsLoggingEnabled
Metadata:
Comment: This bucket records access logs for the main bucket
checkov:
skip:
- comment: This is the log bucket
id: CKV_AWS_18
guard:
SuppressedRules:
- S3_BUCKET_LOGGING_ENABLED
- S3_BUCKET_REPLICATION_ENABLED
Properties:
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
BucketName: !Sub ${Const::LogBucketName}
ObjectLockConfiguration:
ObjectLockEnabled: Enabled
Rule:
DefaultRetention:
Mode: COMPLIANCE
Years: 1
ObjectLockEnabled: true
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
VersioningConfiguration:
Status: Enabled

Bucket:
Type: AWS::S3::Bucket
Metadata:
guard:
SuppressedRules:
- S3_BUCKET_DEFAULT_LOCK_ENABLED
Properties:
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
BucketName: !Sub ${Const::BucketName}

NotificationConfiguration:
Fn::If:
- IsEventBridgeEnabled
- EventBridgeConfiguration:
EventBridgeEnabled: true
- !Ref AWS::NoValue
LoggingConfiguration:
Fn::If:
- IsLoggingEnabled
- DestinationBucketName: !Ref LogBucket
- !Ref AWS::NoValue
ObjectLockEnabled: false
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
ReplicationConfiguration:
Fn::If:
- IsReplicationEnabled
- Role: !GetAtt ReplicationRole.Arn
Rules:
- Destination:
Bucket: !GetAtt ReplicaBucket.Arn
Status: Enabled
- !Ref AWS::NoValue
VersioningConfiguration:
Status: Enabled


ReplicaBucket:
Condition: IsReplicationEnabled
Type: AWS::S3::Bucket
Metadata:
Comment: This bucket is used as a target for replicas from the main bucket
checkov:
skip:
- comment: This is the replica bucket
id: CKV_AWS_18
guard:
SuppressedRules:
- S3_BUCKET_DEFAULT_LOCK_ENABLED
- S3_BUCKET_REPLICATION_ENABLED
- S3_BUCKET_LOGGING_ENABLED
Properties:
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
BucketName: !Sub ${Constant:ReplicaBucketName}
ObjectLockEnabled: false
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
VersioningConfiguration:
Status: Enabled

ReplicationPolicy:
Condition: IsReplicationEnabled
Type: AWS::IAM::RolePolicy
Properties:
PolicyDocument:
Statement:
- Action:
- s3:GetReplicationConfiguration
- s3:ListBucket
Effect: Allow
Resource: !Sub arn:${AWS::Partition}:s3:::${Const::BucketName}
- Action:
- s3:GetObjectVersionForReplication
- s3:GetObjectVersionAcl
- s3:GetObjectVersionTagging
Effect: Allow
Resource: !Sub arn:${AWS::Partition}:s3:::${Const::BucketName}/*
- Action:
- s3:ReplicateObject
- s3:ReplicateDelete
- s3:ReplicationTags
Effect: Allow
Resource: !Sub arn:${AWS::Partition}:s3:::${Const::ReplicaBucketName}/*
Version: "2012-10-17"
PolicyName: bucket-replication-policy
RoleName: !Ref ReplicationRole

ReplicationRole:
Condition: IsReplicationEnabled
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Action:
- sts:AssumeRole
Effect: Allow
Principal:
Service:
- s3.amazonaws.com
Version: "2012-10-17"
Path: /

References:
BucketName: !Ref Bucket

70 changes: 70 additions & 0 deletions Solutions/Pipelines/modules/build-project.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
Inputs:

Name:
Type: String

ArtifactBucket:
Type: String

Resources:

Project:
Type: AWS::CodeBuild::Project
Properties:
Name: !Ref Name
Artifacts:
Type: CODEPIPELINE
Environment:
Image: aws/codebuild/amazonlinux2-x86_64-standard:5.0
ComputeType: BUILD_GENERAL1_LARGE
Type: LINUX_CONTAINER
ServiceRole: !GetAtt Role.Arn
Source:
Type: CODEPIPELINE
TimeoutInMinutes: 480

Role:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: codebuild.amazonaws.com
Version: '2012-10-17'

Policy:
Type: AWS::IAM::RolePolicy
Properties:
RoleName: !Ref Role
PolicyDocument:
Statement:
- Action:
- logs:*
Effect: Allow
Resource: !Sub arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/${Name}:*
- Action:
- codebuild:StartBuild
- codebuild:BatchGetBuilds
- codebuild:StopBuild
- codebuild:RetryBuild
- codebuild:StartBuildBatch
- codebuild:RetryBuildBatch
- codebuild:StopBuildBatch
Effect: Allow
Resource:
- !GetAtt Project.Arn
- Action:
- s3:Get*
- s3:List*
Effect: Allow
Resource:
- !Sub "arn:${AWS::Partition}:s3:::${ArtifactBucket}"
- !Sub "arn:${AWS::Partition}:s3:::${ArtifactBucket}/*"
Version: 2012-10-17
PolicyName: !Sub "${Name}-policy"

References:
ProjectName: !Ref Project

Loading