From 0caf4186325af2a63075bb3b6eda1ba794ed9c54 Mon Sep 17 00:00:00 2001 From: fidelis-ogunsanmi Date: Mon, 1 Aug 2022 21:21:25 -0400 Subject: [PATCH] added changes --- 12-codepipeline/12-1-1.yaml | 246 +++++++++++++++++ 12-codepipeline/12-1-2.yaml | 396 +++++++++++++++++++++++++++ 12-codepipeline/app-code.yaml | 52 ++++ 12-codepipeline/application.yaml | 11 + 12-codepipeline/buildspec.yml | 30 +++ 12-codepipeline/exec.sh | 15 ++ 12-codepipeline/main/12-2.yaml | 444 +++++++++++++++++++++++++++++++ 12-codepipeline/mynotes.md | 339 +++++++++++++++++++++++ 8 files changed, 1533 insertions(+) create mode 100644 12-codepipeline/12-1-1.yaml create mode 100644 12-codepipeline/12-1-2.yaml create mode 100644 12-codepipeline/app-code.yaml create mode 100644 12-codepipeline/application.yaml create mode 100644 12-codepipeline/buildspec.yml create mode 100755 12-codepipeline/exec.sh create mode 100644 12-codepipeline/main/12-2.yaml create mode 100644 12-codepipeline/mynotes.md diff --git a/12-codepipeline/12-1-1.yaml b/12-codepipeline/12-1-1.yaml new file mode 100644 index 00000000..08b7df19 --- /dev/null +++ b/12-codepipeline/12-1-1.yaml @@ -0,0 +1,246 @@ +AWSTemplateFormatVersion: '2010-09-09' +Description: github-codepipeline + +Parameters: + + GitHubOwner: + Type: String + Default: fidelisogunsanmi + AllowedPattern: "[A-Za-z0-9-]+" + + GitHubRepo: + Type: String + Default: stelligent-u + AllowedPattern: "[A-Za-z0-9-]+" + + GitHubBranch: + Type: String + AllowedPattern: '[A-Za-z0-9-]+' + Default: 12-fidelis + + StackBucketName: + Type: String + Default: stelligent-u-fidelis.ogunsanmi.labs-codepipeline + + PipelineName: + Type: String + Default: 12-1-1-fidelis-pipeline + + GitHubToken: + NoEcho: true + Type: String + Default: '{{resolve:secretsmanager:FIDELIS_GITHUB_ACCESS:SecretString:GITHUB_ACCESS_TOKEN}}' + Description: GitHub Token. Must be defined in AWS Secrets Manager and here https://github.com/settings/tokens + + ApplicationStackName: + Type: String + Default: github-pipeline-app + + TemplatePath: + Type: String + Default: 12-codepipeline/application.yaml + +Resources: + +# Service Role For CodePipeline + + CodePipelineServiceRole: + Type: AWS::IAM::Role + Properties: + Path: / + AssumeRolePolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Principal: + Service: codepipeline.amazonaws.com + Action: sts:AssumeRole + Policies: + - PolicyName: root + PolicyDocument: + Version: 2012-10-17 + Statement: + - Resource: "*" + Effect: Allow + Action: + - codebuild:StartBuild + - codebuild:BatchGetBuilds + - iam:PassRole + - cloudformation:Describe* + - cloudFormation:List* + - cloudformation:CreateStack + - cloudformation:DeleteStack + - cloudformation:DescribeStacks + - cloudformation:UpdateStack + - cloudformation:CreateChangeSet + - cloudformation:DeleteChangeSet + - cloudformation:DescribeChangeSet + - cloudformation:ExecuteChangeSet + - cloudformation:SetStackPolicy + - cloudformation:ValidateTemplate + - cloudformation:UpdateTerminationProtection + - cloudformation:TagResource + - cloudformation:UntagResource + - codedeploy:CreateDeployment + - codedeploy:CreateDeploymentGroup + - codedeploy:GetApplication + - codedeploy:GetApplicationRevision + - codedeploy:GetDeployment + - codedeploy:GetDeploymentConfig + - codedeploy:RegisterApplicationRevision + - ssm:GetParameters + - Resource: + - !Sub "arn:aws:s3:::${ArtifactBucket}/*" + - !Sub "arn:aws:s3:::${ArtifactBucket}" + Effect: Allow + Action: + - s3:PutObject + - s3:GetBucketPolicy + - s3:GetObject + - s3:GetObjectVersion + - s3:GetBucketVersioning + - s3:ListBucket + + CFNdeployerRole: + Type: AWS::IAM::Role + Properties: + RoleName: !Sub "${AWS::StackName}-cfn-deployer-role" + AssumeRolePolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: Allow + Principal: + Service: + - cloudformation.amazonaws.com + Action: + - sts:AssumeRole + CFNexecPolicy: + Type: AWS::IAM::Policy + Properties: + PolicyName: !Sub "${AWS::StackName}-create-s3-policy" + PolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: Allow + Action: + - s3:CreateBucket + - s3:ListAllMyBuckets + - s3:GetBucketLocation + - s3:DeleteBucket + Resource: "*" + - Effect: Allow + Action: + - dynamodb:Create* + - dynamodb:Describe* + - dynamodb:Update* + - dynamodb:DeleteTable + Resource: "*" + - Effect: Allow + Action: + - iam:ListRoles + - iam:ListPolicies + - iam:CreateRole + - iam:CreatePolicy + - iam:GetRole + - iam:DeleteRole + - iam:PutRolePolicy + - iam:PassRole + - iam:getRolePolicy + - iam:TagResource + - iam:DeleteRolePolicy + - iam:AttachRolePolicy + - iam:DetachRolePolicy + Resource: "*" + Roles: + - !Ref CFNdeployerRole + + ArtifactBucket: + Type: AWS::S3::Bucket + DeletionPolicy: Delete + Properties: + BucketName: !Ref StackBucketName + + ArtifactBucketPolicy: + Type: AWS::S3::BucketPolicy + Properties: + Bucket: !Ref ArtifactBucket + PolicyDocument: + Statement: + - Effect: Allow + Action: + - s3:* + Resource: + - !Sub arn:aws:s3:::${ArtifactBucket} + - !Sub arn:aws:s3:::${ArtifactBucket}/* + Principal: + AWS: + - !GetAtt [CodePipelineServiceRole, Arn] + - !GetAtt [CFNdeployerRole, Arn] + +# Create the pipeline + + CodePipeline: + Type: AWS::CodePipeline::Pipeline + Properties: + ArtifactStore: + Type: S3 + Location: !Ref ArtifactBucket + RestartExecutionOnUpdate: true + RoleArn: !GetAtt CodePipelineServiceRole.Arn + Stages: + - Name: Source + Actions: + - Name: Source + InputArtifacts: [] + ActionTypeId: + Category: Source + Owner: ThirdParty + Version: "1" + Provider: GitHub + OutputArtifacts: + - Name: SourceCode + Configuration: + Owner: !Ref GitHubOwner + Repo: !Ref GitHubRepo + Branch: !Ref GitHubBranch + PollForSourceChanges: false + OAuthToken: !Ref GitHubToken + RunOrder: 1 + # Build and Deploy, etc., stages would follow. Here is an example + - Name: Deploy + Actions: + - Name: CloudFormationDeploy + ActionTypeId: + Category: Deploy + Owner: AWS + Provider: CloudFormation + Version: '1' + InputArtifacts: + - Name: SourceCode + Configuration: + ActionMode: CREATE_UPDATE + Capabilities: CAPABILITY_IAM + RoleArn: !GetAtt CFNdeployerRole.Arn + StackName: !Ref ApplicationStackName + TemplatePath: !Sub "SourceCode::${TemplatePath}" + RunOrder: 1 + + + GitHubWebHook: + Type: AWS::CodePipeline::Webhook + Properties: + Authentication: GITHUB_HMAC + AuthenticationConfiguration: + SecretToken: !Ref GitHubToken + RegisterWithThirdParty: true + Filters: + - JsonPath: '$.ref' + MatchEquals: refs/heads/{Branch} + - JsonPath: '$.repository.name' + MatchEquals: '{Repo}' + TargetPipeline: !Ref CodePipeline + TargetAction: Source + TargetPipelineVersion: !GetAtt CodePipeline.Version + Name: fidelis-pipeline-hook + + \ No newline at end of file diff --git a/12-codepipeline/12-1-2.yaml b/12-codepipeline/12-1-2.yaml new file mode 100644 index 00000000..ad08b702 --- /dev/null +++ b/12-codepipeline/12-1-2.yaml @@ -0,0 +1,396 @@ +AWSTemplateFormatVersion: '2010-09-09' +Description: github-codepipeline + +Parameters: + GitHubOwner: + Type: String + Default: fidelisogunsanmi + AllowedPattern: "[A-Za-z0-9-]+" + + GitHubRepo: + Type: String + Default: stelligent-u + AllowedPattern: "[A-Za-z0-9-]+" + + GitHubBranch: + Type: String + AllowedPattern: '[A-Za-z0-9-]+' + Default: 12-fidelis + + StackBucketName: + Type: String + Default: stelligent-u-fidelis.ogunsanmi.labs-codepipeline + + PipelineName: + Type: String + Default: 12-1-1-fidelis-pipeline + + GitHubToken: + NoEcho: true + Type: String + Default: '{{resolve:secretsmanager:FIDELIS_GITHUB_ACCESS:SecretString:GITHUB_ACCESS_TOKEN}}' + Description: GitHub Token. Must be defined in AWS Secrets Manager and here https://github.com/settings/tokens + + ApplicationStackName: + Type: String + Default: github-pipeline-app + + TemplatePath: + Type: String + Default: 12-codepipeline/application.yaml + + +Resources: + +# Service Roles For CodePipeline and CodeBuild + CodeBuildServiceRole: + Type: AWS::IAM::Role + Properties: + Path: / + AssumeRolePolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Principal: + Service: codebuild.amazonaws.com + Action: sts:AssumeRole + Policies: + - PolicyName: "logs" + PolicyDocument: + Version: "2012-10-17" + Statement: + - Resource: "*" + Effect: "Allow" + Action: + - logs:CreateLogGroup + - logs:CreateLogStream + - logs:PutLogEvents + - ecr:GetAuthorizationToken + - ssm:GetParameters + - PolicyName: "S3" + PolicyDocument: + Version: "2012-10-17" + Statement: + - Resource: + - !Sub "arn:aws:s3:::${ArtifactBucket}/*" + - !Sub "arn:aws:s3:::${ArtifactBucket}" + Effect: Allow + Action: + - s3:PutObject + - s3:GetBucketPolicy + - s3:GetObject + - s3:GetObjectVersion + - s3:GetBucketVersioning + - s3:ListBucket + - PolicyName: "cfn" + PolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: Allow + Action: + - cloudformation:ValidateTemplate + - cloudformation:ListStacks + - cloudformation:Describe* + Resource: "*" + - PolicyName: "codebuild" + PolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: Allow + Action: + - codebuild:ListBuilds + - codebuild:UpdateProject + - codebuild:ListProjects + - codebuild:CreateReportGroup + - codebuild:CreateReport + - codebuild:BatchPutTestCases + - codebuild:UpdateReport + Resource: "*" + + CodePipelineServiceRole: + Type: AWS::IAM::Role + Properties: + Path: / + AssumeRolePolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Principal: + Service: codepipeline.amazonaws.com + Action: sts:AssumeRole + Policies: + - PolicyName: root + PolicyDocument: + Version: 2012-10-17 + Statement: + - Resource: "*" + Effect: Allow + Action: + - codebuild:StartBuild + - codebuild:BatchGetBuilds + - iam:PassRole + - cloudformation:Describe* + - cloudFormation:List* + - cloudformation:CreateStack + - cloudformation:DeleteStack + - cloudformation:DescribeStacks + - cloudformation:UpdateStack + - cloudformation:CreateChangeSet + - cloudformation:DeleteChangeSet + - cloudformation:DescribeChangeSet + - cloudformation:ExecuteChangeSet + - cloudformation:SetStackPolicy + - cloudformation:ValidateTemplate + - cloudformation:UpdateTerminationProtection + - cloudformation:TagResource + - cloudformation:UntagResource + - codedeploy:CreateDeployment + - codedeploy:CreateDeploymentGroup + - codedeploy:GetApplication + - codedeploy:GetApplicationRevision + - codedeploy:GetDeployment + - codedeploy:GetDeploymentConfig + - codedeploy:RegisterApplicationRevision + - Resource: + - !Sub "arn:aws:s3:::${ArtifactBucket}/*" + - !Sub "arn:aws:s3:::${ArtifactBucket}" + Effect: Allow + Action: + - s3:PutObject + - s3:GetBucketPolicy + - s3:GetObject + - s3:GetObjectVersion + - s3:GetBucketVersioning + - s3:ListBucket + + CFNdeployerRole: + Type: AWS::IAM::Role + Properties: + RoleName: !Sub "${AWS::StackName}-cfn-deployer-role" + AssumeRolePolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: Allow + Principal: + Service: + - cloudformation.amazonaws.com + Action: + - sts:AssumeRole + CFNexecPolicy: + Type: AWS::IAM::Policy + Properties: + PolicyName: !Sub "${AWS::StackName}-create-s3-policy" + PolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: Allow + Action: + - s3:CreateBucket + - s3:ListAllMyBuckets + - s3:GetBucketLocation + - s3:DeleteBucket + Resource: "*" + - Effect: Allow + Action: + - dynamodb:Create* + - dynamodb:Describe* + - dynamodb:Update* + - dynamodb:DeleteTable + Resource: "*" + - Effect: Allow + Action: + - iam:ListRoles + - iam:ListPolicies + - iam:CreateRole + - iam:CreatePolicy + - iam:GetRole + - iam:DeleteRole + - iam:PutRolePolicy + - iam:PassRole + - iam:getRolePolicy + - iam:TagResource + - iam:DeleteRolePolicy + - iam:AttachRolePolicy + - iam:DetachRolePolicy + Resource: "*" + Roles: + - !Ref CFNdeployerRole + + ArtifactBucket: + Type: AWS::S3::Bucket + DeletionPolicy: Delete + Properties: + BucketName: !Ref StackBucketName + + ArtifactBucketPolicy: + Type: AWS::S3::BucketPolicy + Properties: + Bucket: !Ref ArtifactBucket + PolicyDocument: + Statement: + - Effect: Allow + Action: + - s3:* + Resource: + - !Sub arn:aws:s3:::${ArtifactBucket} + - !Sub arn:aws:s3:::${ArtifactBucket}/* + Principal: + AWS: + - !GetAtt [CodePipelineServiceRole,Arn] + - !GetAtt [CFNdeployerRole,Arn] + +# --- Create the Codebuild Projects ---- + + CodeBuild: + Type: AWS::CodeBuild::Project + Properties: + Name: !Ref AWS::StackName-codebuild-project + ServiceRole: !GetAtt CodeBuildServiceRole.Arn + Artifacts: + Type: CODEPIPELINE + Environment: + Type: LINUX_CONTAINER + ComputeType: BUILD_GENERAL1_SMALL + Image: aws/codebuild/amazonlinux2-x86_64-standard:4.0 + EnvironmentVariables: + - Name: S3_BUCKET + Type: PLAINTEXT + Value: !Ref StackBucketName + + - Name: TEMPLATE_FILE_NAME + Value: !Ref TemplateFileName + + - Name: REGION + Value: !Ref AWS::Region + Source: + Type: GITHUB + BuildSpec: buildspec.yaml + + CodeBuildLogGroup: + Type: AWS::Logs::LogGroup + Properties: + LogGroupName: !Sub "/aws/codebuild/${CodeBuild}" + RetentionInDays: 7 + + TestCodeBuild: + Type: AWS::CodeBuild::Project + Properties: + Name: !Ref AWS::StackName + ServiceRole: !GetAtt CodeBuildServiceRole.Arn + Artifacts: + Type: CODEPIPELINE + Environment: + Type: LINUX_CONTAINER + ComputeType: BUILD_GENERAL1_SMALL + Image: aws/codebuild/amazonlinux2-x86_64-standard:4.0 + EnvironmentVariables: + - Name: S3_BUCKET + Type: PLAINTEXT + Value: !Ref StackBucketName + + - Name: REGION + Value: !Ref AWS::Region + + - Name: TEMPLATE_FILE_NAME + Value: !Ref TemplateFileName + Source: + Type: GITHUB + BuildSpec: 12-codepipeline/testspec.yaml + TestCodeBuildLogGroup: + Type: AWS::Logs::LogGroup + Properties: + LogGroupName: !Sub "/aws/codebuild/${TestCodeBuild}" + RetentionInDays: 7 + +# Create the pipeline + + Pipeline: + Type: AWS::CodePipeline::Pipeline + Properties: + RoleArn: !GetAtt CodePipelineServiceRole.Arn + ArtifactStore: + Type: S3 + Location: !Ref ArtifactBucket + Stages: + - Name: Source + Actions: + - Name: AppSource + InputArtifacts: [] + ActionTypeId: + Category: Source + Owner: ThirdParty + Version: '1' + Provider: GitHub + OutputArtifacts: + - Name: SourceCode + Configuration: + Owner: !Ref GitHubOwner + Repo: !Ref GitHubRepo + Branch: !Ref GitHubBranch + PollForSourceChanges: false + OAuthToken: !Ref GitHubToken + RunOrder: 1 + - Name: BuildIt + Actions: + - Name: BuildIt + ActionTypeId: + Category: Build + Owner: AWS + Version: '1' + Provider: CodeBuild + Configuration: + ProjectName: !Ref CodeBuild + InputArtifacts: + - Name: SourceCode + RunOrder: 1 + - Name: Deploy + Actions: + - Name: CloudFormationDeploy + ActionTypeId: + Category: Deploy + Owner: AWS + Provider: CloudFormation + Version: '1' + InputArtifacts: + - Name: SourceCode + Configuration: + ActionMode: CREATE_UPDATE + Capabilities: CAPABILITY_IAM + RoleArn: !GetAtt CfnRole.Arn + StackName: !Ref AppStackName + TemplatePath: !Sub SourceCode::${TemplatePath} + OutputArtifacts: + - Name: S3Bucket + RunOrder: 1 + + - Name: Test + Actions: + - Name: CheckBucket + ActionTypeId: + Category: Build + Owner: AWS + Provider: CodeBuild + Version: '1' + InputArtifacts: + - Name: SourceCode + Configuration: + ProjectName: !Ref TestCodeBuild + RunOrder: 1 + + GitHubWebHook: + Type: AWS::CodePipeline::Webhook + Properties: + Authentication: GITHUB_HMAC + AuthenticationConfiguration: + SecretToken: !Ref GitHubToken + RegisterWithThirdParty: true + Filters: + - JsonPath: '$.ref' + MatchEquals: refs/heads/{Branch} + - JsonPath: '$.repository.name' + MatchEquals: '{Repo}' + TargetPipeline: !Ref CodePipeline + TargetAction: Source + TargetPipelineVersion: !GetAtt CodePipeline.Version + Name: fidelis-pipeline-hook + \ No newline at end of file diff --git a/12-codepipeline/app-code.yaml b/12-codepipeline/app-code.yaml new file mode 100644 index 00000000..2dafbdef --- /dev/null +++ b/12-codepipeline/app-code.yaml @@ -0,0 +1,52 @@ +AWSTemplateFormatVersion: '2010-09-09' + +Parameters: + TableNameParam: + Type: String + Description: DynamoDB Table Name + Default: demo-table + BucketNameParam: + Type: String + Description: S3 Bucket Name + Default: fidelis-codebuild-bucket-sapaniceone + +Resources: +# create demo s3 bucket + S3Bucket: + Type: AWS::S3::Bucket + Properties: + BucketName: !Ref BucketNameParam + DeletionPolicy: Delete + +# Create DynamoDB table + AppTable: + Type: AWS::DynamoDB::Table + DeletionPolicy: Delete + Properties: + TableName: !Ref TableNameParam + KeySchema: + - AttributeName: "id" + KeyType: "HASH" + AttributeDefinitions: + - AttributeName: "id" + AttributeType: "S" + ProvisionedThroughput: + ReadCapacityUnits: 5 + WriteCapacityUnits: 5 + +# IAM Role that will allow access to the DynamoDB : read and write + AppRole: + Type: AWS::IAM::Role + Properties: + RoleName: !Sub "${AWS::StackName}-app-role" + AssumeRolePolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: Allow + Principal: + Service: + - lambda.amazonaws.com + Action: + - sts:AssumeRole + ManagedPolicyArns: + - arn:aws:iam::aws:policy/AmazonDynamoDBReadOnlyAccess \ No newline at end of file diff --git a/12-codepipeline/application.yaml b/12-codepipeline/application.yaml new file mode 100644 index 00000000..ad75b6b0 --- /dev/null +++ b/12-codepipeline/application.yaml @@ -0,0 +1,11 @@ +AWSTemplateFormatVersion: '2010-09-09' +# *** Change this to something useful for you! +Description: github-codepipeline-app + +# This is just here as an example resource + +Resources: + ApplicationBucket: + Type: AWS::S3::Bucket + Properties: + BucketName: !Join ["-", [AWS::StackName, "fidelis"]] \ No newline at end of file diff --git a/12-codepipeline/buildspec.yml b/12-codepipeline/buildspec.yml new file mode 100644 index 00000000..2e2e8b78 --- /dev/null +++ b/12-codepipeline/buildspec.yml @@ -0,0 +1,30 @@ +version: 0.2 + +phases: + install: + runtime-versions: + python: 3.x + commands: + - echo "Entered the INSTALL phase" + - yum update -y + - yum install jq git -y -q + - echo Configuring aws cli... + - pip3 install awsebcli --upgrade + - pip install --upgrade awscli + - aws configure set default.region $REGION + build: + commands: + - echo "=====================" + - echo TEMPLATE_FILE_NAME = $TEMPLATE_FILE_NAME REGION = $REGION + - echo validate template ... + - aws cloudformation validate-template --template-body file://$TEMPLATE_FILE_NAME --region $REGION + + post_build: + commands: + - echo "=====================" + - echo project was successfully built! +artifacts: + files: + # export artifacts needed for deployments to an S3 bucket + - $TEMPLATE_FILE_NAME + - check_stat_status.sh \ No newline at end of file diff --git a/12-codepipeline/exec.sh b/12-codepipeline/exec.sh new file mode 100755 index 00000000..e230863a --- /dev/null +++ b/12-codepipeline/exec.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +PROFILE="labmfa" +STACK_NAME="github-pipeline-fidelis" +TEMPLATE="12-1-1.yaml" +REGION="us-east-1" + +# deploy stack +aws cloudformation deploy --template-file $TEMPLATE \ + --stack-name $STACK_NAME --profile $PROFILE \ + --capabilities CAPABILITY_NAMED_IAM \ + --region $REGION + + + diff --git a/12-codepipeline/main/12-2.yaml b/12-codepipeline/main/12-2.yaml new file mode 100644 index 00000000..3b5ad9eb --- /dev/null +++ b/12-codepipeline/main/12-2.yaml @@ -0,0 +1,444 @@ +AWSTemplateFormatVersion: '2010-09-09' +Description: github-codepipeline + +Parameters: + GitHubOwner: + Type: String + Default: fidelisogunsanmi + AllowedPattern: "[A-Za-z0-9-]+" + + GitHubRepo: + Type: String + Default: stelligent-u + AllowedPattern: "[A-Za-z0-9-]+" + + GitHubBranch: + Type: String + AllowedPattern: '[A-Za-z0-9-]+' + Default: 12-fidelis + + StackBucketName: + Type: String + Default: stelligent-u-fidelis.ogunsanmi.labs-codepipeline + + PipelineName: + Type: String + Default: 12-1-1-fidelis-pipeline + + GitHubToken: + NoEcho: true + Type: String + Default: '{{resolve:secretsmanager:FIDELIS_GITHUB_ACCESS:SecretString:GITHUB_ACCESS_TOKEN}}' + Description: GitHub Token. Must be defined in AWS Secrets Manager and here https://github.com/settings/tokens + + ApplicationStackName: + Type: String + Default: github-pipeline-app + + StackName: + Type: String + Default: demo-create-resources-stack + + TemplateFileName: + Type: String + Default: app-code.yaml + + +Resources: + +# Service Roles For CodePipeline and CodeBuild + CodeBuildServiceRole: + Type: AWS::IAM::Role + Properties: + Path: / + AssumeRolePolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Principal: + Service: codebuild.amazonaws.com + Action: sts:AssumeRole + Policies: + - PolicyName: "logs" + PolicyDocument: + Version: "2012-10-17" + Statement: + - Resource: "*" + Effect: "Allow" + Action: + - logs:CreateLogGroup + - logs:CreateLogStream + - logs:PutLogEvents + - ecr:GetAuthorizationToken + - ssm:GetParameters + - PolicyName: "S3" + PolicyDocument: + Version: "2012-10-17" + Statement: + - Resource: + - !Sub "arn:aws:s3:::${ArtifactBucket}/*" + - !Sub "arn:aws:s3:::${ArtifactBucket}" + Effect: Allow + Action: + - s3:PutObject + - s3:GetBucketPolicy + - s3:GetObject + - s3:GetObjectVersion + - s3:GetBucketVersioning + - s3:ListBucket + - PolicyName: "cfn" + PolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: Allow + Action: + - cloudformation:ValidateTemplate + - cloudformation:ListStacks + - cloudformation:Describe* + Resource: "*" + - PolicyName: "codebuild" + PolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: Allow + Action: + - codebuild:ListBuilds + - codebuild:UpdateProject + - codebuild:ListProjects + - codebuild:CreateReportGroup + - codebuild:CreateReport + - codebuild:BatchPutTestCases + - codebuild:UpdateReport + Resource: "*" + + CodePipelineServiceRole: + Type: AWS::IAM::Role + Properties: + Path: / + AssumeRolePolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Principal: + Service: codepipeline.amazonaws.com + Action: sts:AssumeRole + Policies: + - PolicyName: root + PolicyDocument: + Version: 2012-10-17 + Statement: + - Resource: "*" + Effect: Allow + Action: + - codebuild:StartBuild + - codebuild:BatchGetBuilds + - iam:PassRole + - cloudformation:Describe* + - cloudFormation:List* + - cloudformation:CreateStack + - cloudformation:DeleteStack + - cloudformation:DescribeStacks + - cloudformation:UpdateStack + - cloudformation:CreateChangeSet + - cloudformation:DeleteChangeSet + - cloudformation:DescribeChangeSet + - cloudformation:ExecuteChangeSet + - cloudformation:SetStackPolicy + - cloudformation:ValidateTemplate + - cloudformation:UpdateTerminationProtection + - cloudformation:TagResource + - cloudformation:UntagResource + - codedeploy:CreateDeployment + - codedeploy:CreateDeploymentGroup + - codedeploy:GetApplication + - codedeploy:GetApplicationRevision + - codedeploy:GetDeployment + - codedeploy:GetDeploymentConfig + - codedeploy:RegisterApplicationRevision + - Resource: + - !Sub "arn:aws:s3:::${ArtifactBucket}/*" + - !Sub "arn:aws:s3:::${ArtifactBucket}" + Effect: Allow + Action: + - s3:PutObject + - s3:GetBucketPolicy + - s3:GetObject + - s3:GetObjectVersion + - s3:GetBucketVersioning + - s3:ListBucket + + CFNdeployerRole: + Type: AWS::IAM::Role + Properties: + RoleName: !Sub "${AWS::StackName}-cfn-deployer-role" + AssumeRolePolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: Allow + Principal: + Service: + - cloudformation.amazonaws.com + Action: + - sts:AssumeRole + CFNexecPolicy: + Type: AWS::IAM::Policy + Properties: + PolicyName: !Sub "${AWS::StackName}-create-s3-policy" + PolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: Allow + Action: + - s3:CreateBucket + - s3:ListAllMyBuckets + - s3:GetBucketLocation + - s3:DeleteBucket + Resource: "*" + - Effect: Allow + Action: + - dynamodb:Create* + - dynamodb:Describe* + - dynamodb:Update* + - dynamodb:DeleteTable + Resource: "*" + - Effect: Allow + Action: + - iam:ListRoles + - iam:ListPolicies + - iam:CreateRole + - iam:CreatePolicy + - iam:GetRole + - iam:DeleteRole + - iam:PutRolePolicy + - iam:PassRole + - iam:getRolePolicy + - iam:TagResource + - iam:DeleteRolePolicy + - iam:AttachRolePolicy + - iam:DetachRolePolicy + Resource: "*" + Roles: + - !Ref CFNdeployerRole + + ArtifactBucket: + Type: AWS::S3::Bucket + DeletionPolicy: Delete + Properties: + BucketName: !Ref StackBucketName + + ArtifactBucketPolicy: + Type: AWS::S3::BucketPolicy + Properties: + Bucket: !Ref ArtifactBucket + PolicyDocument: + Statement: + - Effect: Allow + Action: + - s3:* + Resource: + - !Sub arn:aws:s3:::${ArtifactBucket} + - !Sub arn:aws:s3:::${ArtifactBucket}/* + Principal: + AWS: + - !GetAtt [CodePipelineServiceRole,Arn] + - !GetAtt [CFNdeployerRole,Arn] + +# --- Create the Codebuild Projects ---- + + CodeBuildProject: + Type: AWS::CodeBuild::Project + Properties: + Name: !Ref AWS::StackName-codebuild-project + ServiceRole: !GetAtt CodeBuildServiceRole.Arn + Artifacts: + Type: CODEPIPELINE + Environment: + Type: LINUX_CONTAINER + ComputeType: BUILD_GENERAL1_SMALL + Image: aws/codebuild/amazonlinux2-x86_64-standard:4.0 + EnvironmentVariables: + - Name: S3_BUCKET + Type: PLAINTEXT + Value: !Ref StackBucketName + + - Name: TEMPLATE_FILE_NAME + Value: !Ref TemplateFileName + + - Name: REGION + Value: !Ref AWS::Region + Source: + Type: CODEPIPELINE + BuildSpec: buildspec.yaml + + CodeBuildLogGroup: + Type: AWS::Logs::LogGroup + Properties: + LogGroupName: !Sub "/aws/codebuild/${CodeBuild}" + RetentionInDays: 7 + + TestCodeBuild: + Type: AWS::CodeBuild::Project + Properties: + Name: !Ref AWS::StackName + ServiceRole: !GetAtt CodeBuildServiceRole.Arn + Artifacts: + Type: CODEPIPELINE + Environment: + Type: LINUX_CONTAINER + ComputeType: BUILD_GENERAL1_SMALL + Image: aws/codebuild/amazonlinux2-x86_64-standard:4.0 + EnvironmentVariables: + - Name: S3_BUCKET + Type: PLAINTEXT + Value: !Ref StackBucketName + + - Name: REGION + Value: !Ref AWS::Region + + - Name: TEMPLATE_FILE_NAME + Value: !Ref TemplateFileName + Source: + Type: GITHUB + BuildSpec: 12-codepipeline/testspec.yaml + TestCodeBuildLogGroup: + Type: AWS::Logs::LogGroup + Properties: + LogGroupName: !Sub "/aws/codebuild/${TestCodeBuild}" + RetentionInDays: 7 + +# Create the pipeline + + Pipeline: + Type: AWS::CodePipeline::Pipeline + Properties: + RoleArn: !GetAtt CodePipelineServiceRole.Arn + ArtifactStore: + Type: S3 + Location: !Ref ArtifactBucket + Stages: + # 1 stage - source - github + - Name: Source + Actions: + - Name: SourceAction + ActionTypeId: + Category: Source + Owner: ThirdParty + Version: '1' + Provider: GitHub + OutputArtifacts: + - Name: SourceOutput + Configuration: + Owner: !Ref GitHubOwner + Repo: !Ref GitHubRepo + Branch: !Ref GitHubBranch + PollForSourceChanges: false + OAuthToken: !Ref GitHubToken + RunOrder: 1 + # 2 stage - build - Codebuild + - Name: Build + Actions: + - Name: ValidateTemplate + ActionTypeId: + Category: Build + Owner: AWS + Version: '1' + Provider: CodeBuild + Configuration: + ProjectName: !Ref CodeBuildProject + InputArtifacts: + - Name: SourceCode + OutputArtifacts: + - Name: BuildOutput + RunOrder: 1 + # 3 stage - deploy - cloudformation + - Name: Creation + Actions: + # 3.1 - create changeset + - Name: CreateChangeSet + RunOrder: 1 + ActionTypeId: + Category: Deploy + Owner: AWS + Provider: CloudFormation + Version: '1' + InputArtifacts: + - Name: SourceOutput + Configuration: + ActionMode: CHANGE_SET_REPLACE + StackName: !Ref StackName + ChangeSetName: !Sub "${StackName}-changeset" + Capabilities: CAPABILITY_IAM,CAPABILITY_NAMED_IAM + RoleArn: !GetAtt CFNdeployerRole.Arn + TemplatePath: !Sub "SourceOutput::${TemplateFileName}" + # 4 stage - Approval action + - Name: ApproveDeploy + Actions: + - Name: ApproveDeployProd + ActionTypeId: + Category: Approval + Owner: AWS + Version: '1' + Provider: Manual + Configuration: + CustomData: "Check CFN stack changeset before approving." + # 5 stage - execution - cloudformation + - Name: Execution + Actions: + - Name: DeployChangeSet + RunOrder: 1 + ActionTypeId: + Category: Deploy + Owner: AWS + Provider: CloudFormation + Version: '1' + InputArtifacts: + - Name: SourceOutput + Configuration: + ActionMode: CHANGE_SET_EXECUTE + StackName: !Ref StackName + ChangeSetName: !Sub "${StackName}-changeset" + RoleArn: !GetAtt CFNdeployerRole.Arn + OutputArtifacts: + - Name: DeployOutput + # 6 stage - test - CodeBuild + - Name: Test + Actions: + - Name: CheckStackStatus + RunOrder: 1 + ActionTypeId: + Category: Build + Owner: AWS + Provider: CodeBuild + Version: '1' + InputArtifacts: + - Name: SourceOutput + Configuration: + ProjectName: !Ref TestCodeBuild + OutputArtifacts: + - Name: TestOutput + + GitHubWebHook: + Type: AWS::CodePipeline::Webhook + Properties: + Authentication: GITHUB_HMAC + AuthenticationConfiguration: + SecretToken: !Ref GitHubToken + RegisterWithThirdParty: true + Filters: + - JsonPath: '$.ref' + MatchEquals: refs/heads/{Branch} + - JsonPath: '$.repository.name' + MatchEquals: '{Repo}' + TargetPipeline: !Ref CodePipeline + TargetAction: Source + TargetPipelineVersion: !GetAtt CodePipeline.Version + Name: fidelis-pipeline-hook + + +Outputs: + CFNdeployerRole: + Value: !Ref CFNdeployerRole + CodeBuildRole: + Value: !Ref CodeBuildServiceRole + PipeLineRole: + Value: !Ref CodePipelineServiceRole \ No newline at end of file diff --git a/12-codepipeline/mynotes.md b/12-codepipeline/mynotes.md new file mode 100644 index 00000000..248c8b39 --- /dev/null +++ b/12-codepipeline/mynotes.md @@ -0,0 +1,339 @@ +# Create a codepipeline with cloudformation + +Pre-req of the project + +- Ec2 Instance and Postgresql db have been provisioned + +## Project aim + +- Use cloudformation to provision a codepipeline that will automate the build, test and deploy process of our app release + +### Steps + +- Create Ec2 Instance Role + + - InstanceRole + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Statement: - Effect: Allow + Principal: + Service: - ec2.amazonaws.com + Action: - sts:AssumeRole + Path: / + + - InstanceRolePolicies + Type: AWS::IAM::Policy + Properties: + PolicyName: InstanceRole + PolicyDocument: + Statement: - Effect: Allow + Action: - autoscaling:Describe* - cloudformation:Describe* - cloudformation:GetTemplate - s3:Get* + Resource: '*' + Roles: - !Ref 'InstanceRole' + + - InstanceRoleInstanceProfile: + Type: AWS::IAM::InstanceProfile + Properties: + Path: / + Roles: - !Ref 'InstanceRole' + + - These instanceprofile gives ec2 instance permission to get codedeploy agent from s3 + - attach the IamInstanceProfile to the ec2 instance + WebAppInstance: + Properties: + ... + IamInstanceProfile: !Ref 'InstanceRoleInstanceProfile' + +- INSTALL CODEDEPLOY AGENT + + - the codedeploy agent will be installed on each ec2 instances you want to deploy your app to and helps codedeploy communicate with your ec2 instances for deployments. first you will include the metadata in the AWS::CloudFormation::Init key, which will be used by the cfn-init helper script. + + WebAppInstance: + ... + Metadata: + AWS::CloudFormation::Init: + services: + sysvint: + codedeploy-agent: + enabled: 'true' + ensureRunning: 'true' + + - then we will add the UserData key, which allows us to pass user data to the ec2 instance to perform automated configuration tasks and run scripts after the instance starts up + + WebAppInstance: + Properties: + ... + UserData: !Base64 + Fn::Join: - '' - - "#!/bin/bash -ex\n" - "yum update -y aws-cfn-bootstrap\n" - "yum install -y aws-cli\n" - "yum install -y ruby\n" - "iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 3000\n" - "echo 'iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 3000' >> /etc/rc.local\n" - "# Helper function.\n" - "function error_exit\n" - "{\n" - ' /opt/aws/bin/cfn-signal -e 1 -r "$1" ''' - !Ref 'WaitHandle' - "'\n" - " exit 1\n" - "}\n" - "# Install the AWS CodeDeploy Agent.\n" - "cd /home/ec2-user/\n" - "aws s3 cp 's3://aws-codedeploy-us-east-1/latest/codedeploy-agent.noarch.rpm'\ + \ . || error_exit 'Failed to download AWS CodeDeploy Agent.'\n" - "yum -y install codedeploy-agent.noarch.rpm || error_exit 'Failed to\ + \ install AWS CodeDeploy Agent.' \n" - '/opt/aws/bin/cfn-init -s ' - !Ref 'AWS::StackId' - ' -r WebAppInstance --region ' - !Ref 'AWS::Region' - " || error_exit 'Failed to run cfn-init.'\n" - "# All is well, so signal success.\n" - /opt/aws/bin/cfn-signal -e 0 -r "AWS CodeDeploy Agent setup complete." + ' - !Ref 'WaitHandle' - "'\n" + + - add the waithandle resource + WaitHandle: + Type: AWS::CloudFormation::WaitConditionHandle + WaitCondition: + Type: AWS::CloudFormation::WaitCondition + Properties: + Handle: !Ref 'WaitHandle' + Timeout: '900' + + - Next lets tag ec2 instances. Codedeploy will use these tags to identify which instances to deploy to + WebAppInstance: + Properties: + ... + Tags: - Key: 'CodeDeployTag' + Value: 'CodeDeployDemo' + + - Now we have setup iam permissions for ec2 tp communicate with codedeploy and s3, and we have installed codedeploy agent on ec2 instances and also added tags for codeploy on all ec2 instances + +- CREATE CODDEDEPLOY TRUST ROLE + + - This will give codedeploy access to ec2 instances + CodeDeployTrustRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Statement: - Sid: '1' + Effect: Allow + Principal: + Service: - codedeploy.us-east-1.amazonaws.com - codedeploy.us-west-2.amazonaws.com + Action: sts:AssumeRole + Path: / + CodeDeployRolePolicies: + Type: AWS::IAM::Policy + Properties: + PolicyName: CodeDeployPolicy + PolicyDocument: + Statement: - Effect: Allow + Resource: - '_' + Action: - ec2:Describe_ - Effect: Allow + Resource: - '\*' + Action: - autoscaling:CompleteLifecycleAction - autoscaling:DeleteLifecycleHook - autoscaling:DescribeLifecycleHooks - autoscaling:DescribeAutoScalingGroups - autoscaling:PutLifecycleHook - autoscaling:RecordLifecycleActionHeartbeat + Roles: - !Ref 'CodeDeployTrustRole' + + Outputs: + ... + CodeDeployTrustRoleARN: + Value: !GetAtt 'CodeDeployTrustRole.Arn' + + - create this stack by updating the stack from part 2(stack of ec2 instances and db instance) + +- CREATE CODEPIPELINE PIPELINE + + - the pipeline we are building will have 3 stages: + + - a source stage to pull our code from the github repo. the source stage will use a codestarconnection and an s3 bucket + + - a build stage to build the source code into an artifact. The build stage will use a codebuild project and the same s3 bucket + + - a deploy stage to deploy the artifact to the ec2 instance. The deploy stage will use a codedeploy app and a codedeploy deploymentgroup + + - PREPARE THE APP TO DEPLOY + + - sample app: [hello-express-app](https://github.com/jennapederson/hello-express) forked into my github account. + + - for the purpose of this demo, the most interesting parts are the ffg: + + - buildspec.yaml: + is a spec file that contains build commands and configurations that are used to build a codebuild project + + - appspec.yaml + is a spec file that defines a series of lifecycle hooks for a codedeploy deployment + + - bin directory(storing scripts) + contains the www start script for the app, and the scripts for each of the lifecycle hooks. + + - ADD PARAMETERS + Parameters: + GitHubRepo: + Type: String + + GitHubBranch: + Type: String + Default: main + + GitHubUser: + Type: String + + CodeDeployServiceRole: + Type: String + Description: A service role ARN granting CodeDeploy permission to make calls to EC2 instances with CodeDeploy agent installed. + + TagKey: + Description: The EC2 tag key that identifies this as a target for deployments. + Type: String + Default: CodeDeployTag + AllowedPattern: '[\x20-\x7E]\*' + ConstraintDescription: Can contain only ASCII characters. + + TagValue: + Description: The EC2 tag value that identifies this as a target for deployments. + Type: String + Default: CodeDeployDemo + AllowedPattern: '[\x20-\x7E]\*' + ConstraintDescription: Can contain only ASCII characters. + +- CREATE SERVICE ROLES + + - In order for codebuild to access s3 to put the artifact into the bucket, we will need to create a service role: CodeBuildServiceRole + + - we also need a service role to allow codepipeline to get the source code from the github connection, to start builds, to get the artifact from bucjet and to create and deploy the app: CodePipelineServiceRole + + CodeBuildServiceRole: + Type: AWS::IAM::Role + Properties: + Path: / + AssumeRolePolicyDocument: + Version: 2012-10-17 + Statement: - Effect: Allow + Principal: + Service: codebuild.amazonaws.com + Action: sts:AssumeRole + Policies: - PolicyName: "logs" + PolicyDocument: + Version: "2012-10-17" + Statement: - + Effect: "Allow" + Action: - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents - ecr:GetAuthorizationToken - ssm:GetParameters + Resource: "_" - PolicyName: "S3" + PolicyDocument: + Version: "2012-10-17" + Statement: - + Effect: "Allow" + Action: - s3:GetObject - s3:PutObject - s3:GetObjectVersion + Resource: !Sub arn:aws:s3:::${ArtifactBucket}/_ + + CodePipelineServiceRole: + Type: AWS::IAM::Role + Properties: + Path: / + AssumeRolePolicyDocument: + Version: 2012-10-17 + Statement: - Effect: Allow + Principal: + Service: codepipeline.amazonaws.com + Action: sts:AssumeRole + Policies: - PolicyName: root + PolicyDocument: + Version: 2012-10-17 + Statement: - Resource: - !Sub arn:aws:s3:::${ArtifactBucket}/* + - !Sub arn:aws:s3:::${ArtifactBucket} + Effect: Allow + Action: - s3:_ - Resource: "_" + Effect: Allow + Action: - codebuild:StartBuild - codebuild:BatchGetBuilds - iam:PassRole - Resource: - !Ref CodeStarConnection + Effect: Allow + Action: - codestar-connections:UseConnection - Resource: "\*" + Effect: Allow + Action: - codedeploy:CreateDeployment - codedeploy:CreateDeploymentGroup - codedeploy:GetApplication - codedeploy:GetApplicationRevision - codedeploy:GetDeployment - codedeploy:GetDeploymentConfig - codedeploy:RegisterApplicationRevision + +- CREATE THE SOURCE STAGE + For the source stage, we will create a codestar connection and an s3 bucket. + + - create a ccodestarconnection + when we set up the pipeline, we will have a source stage that pulls our source code from github. To do this, we will need to create a codestarconnection for github. This will give our pipeline access to a github repo. we will use cloudformation to create this by adding the resource to our template, but there will be a manual step to change the connection from pending to available after the first time we apply the template + + CodeStarConnection: + Type: 'AWS::CodeStarConnections::Connection' + Properties: + ConnectionName: CfnExamplesGitHubConnection + ProviderType: GitHub + +- CREATE THE S3 BUCKET + ArtifactBucket: + Type: AWS::S3::Bucket + DeletionPolicy: Delete + +- CREATE THE STAGE + fIRST stage of the pipeline: source stage + Pipeline: + Type: AWS::CodePipeline::Pipeline + Properties: + RoleArn: !GetAtt CodePipelineServiceRole.Arn + ArtifactStore: + Type: S3 + Location: !Ref ArtifactBucket + Stages: - Name: Source + Actions: - Name: App + ActionTypeId: + Category: Source + Owner: AWS + Version: '1' + Provider: CodeStarSourceConnection + Configuration: + ConnectionArn: !Ref CodeStarConnection + BranchName: !Ref GitHubBranch + FullRepositoryId: !Sub ${GitHubUser}/${GitHubRepo} + OutputArtifacts: - Name: AppArtifact + RunOrder: 1 + + - Name: Build + Actions: + - Name: Build + ActionTypeId: + Category: Build + Owner: AWS + Version: '1' + Provider: CodeBuild + Configuration: + ProjectName: !Ref CodeBuildProject + InputArtifacts: + - Name: AppArtifact + OutputArtifacts: + - Name: BuildOutput + RunOrder: 1 + + - Name: Deploy + Actions: + - Name: Deploy + ActionTypeId: + Category: Deploy + Owner: AWS + Version: '1' + Provider: CodeDeploy + Configuration: + ApplicationName: !Ref CodeDeployApplication + DeploymentGroupName: !Ref CodeDeployGroup + InputArtifacts: + - Name: BuildOutput + RunOrder: 1 + +- create the build stage + For the build stage, we will create a codebuild project that indicates what kind of environment to build the code in. Here we are using a docker container. we will also set the service role to the service role we created vbefore + + CodeBuildProject: + Type: AWS::CodeBuild::Project + Properties: + Artifacts: + Type: CODEPIPELINE + Source: + Type: CODEPIPELINE + BuildSpec: buildspec.yml + Environment: + ComputeType: BUILD_GENERAL1_SMALL + Image: aws/codebuild/docker:17.09.0 + Type: LINUX_CONTAINER + Name: !Ref AWS::StackName + ServiceRole: !Ref CodeBuildServiceRole + +- CREATE THE DEPLOY STAGE + we will need a codedeploy app and a codedeploy deployment group + CodeDeployApplication: + Type: AWS::CodeDeploy::Application + + CodeDeployGroup: + Type: AWS::CodeDeploy::DeploymentGroup + Properties: + ApplicationName: !Ref CodeDeployApplication + Ec2TagFilters: - Key: !Ref 'TagKey' + Value: !Ref 'TagValue' + Type: KEY_AND_VALUE + ServiceRoleArn: !Ref 'CodeDeployServiceRole' + +- ADD OUTPUTS + + Outputs: + PipelineUrl: + Value: !Sub https://console.aws.amazon.com/codepipeline/home?region=${AWS::Region}