From 339a6321d5751757c9c3c05449e53c37653a4c46 Mon Sep 17 00:00:00 2001 From: Henry Bravo Date: Tue, 4 Apr 2023 11:39:30 +0200 Subject: [PATCH] adding artifacts for new blog post automate-ami-builds-aws-codepipeline --- .../linux-ami-codepipeline.yaml | 239 +++++++++++++++++ .../linux-ami-imagebuilder.yaml | 253 ++++++++++++++++++ .../stack-configuration.json | 12 + 3 files changed, 504 insertions(+) create mode 100644 blog-assets/automate-ami-builds-aws-codepipeline-D35708869/linux-ami-codepipeline.yaml create mode 100644 blog-assets/automate-ami-builds-aws-codepipeline-D35708869/linux-ami-imagebuilder.yaml create mode 100644 blog-assets/automate-ami-builds-aws-codepipeline-D35708869/stack-configuration.json 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 new file mode 100644 index 0000000..32c831f --- /dev/null +++ b/blog-assets/automate-ami-builds-aws-codepipeline-D35708869/linux-ami-codepipeline.yaml @@ -0,0 +1,239 @@ +--- +Description: | + AWS CloudFormation Template for Continuous Delivery: This template builds an AWS CodePipeline pipeline that implements a continuous delivery release process using an AWS CloudFormation stack that builds custom EC2 AMIs using EC2 ImageBuilder. Submit the CloudFormation template to CodeCommit and the pipeline will take the artifacts to automatically create the stack, run the pipeline, put an approval step, and clean up the stack. (qs-1tkj0sj93) +Parameters: + Email: + Default: my@email + Description: The email address where CodePipeline sends pipeline notifications + Type: String + S3BucketName: + Type: String + Default: test-ami-builder-blog-pipeline + Description: The S3 bucket for the temporary artifacts used in CodePipeline + CodeCommitRepositoryName: + Type: String + Default: test-ami-builder-blog-linux-pipeline + Description: name of the codecommit repository that must hold the files "linux-ami-imagebuilder.yaml" and "stack-configuration.json" + PipelineName: + Default: test-ami-builder-blog-linux-pipeline + Description: A name for pipeline + Type: String + TemplateFileName: + Default: linux-ami-imagebuilder.yaml + Description: The file name of the template + Type: String + StackName: + Default: test-amazon-linux2-arm64-ami + Description: A name for the stack which will also be the AMI name to be used in EC2 + Type: String + StackConfig: + Default: stack-configuration.json + Description: The configuration file name for the stack + Type: String +Metadata: + AWS::CloudFormation::Interface: + ParameterGroups: + - Label: + default: CodePipeline Settings + Parameters: + - PipelineName + - S3BucketName + - Email + - Label: + default: Stack Settings + Parameters: + - TemplateFileName + - StackName + - StackConfig +Resources: + S3Bucket: + Type: AWS::S3::Bucket + Properties: + BucketName: + Fn::Join: + - '-' + - - !Ref 'S3BucketName' + - Fn::Select: + - 4 + - Fn::Split: + - '-' + - Fn::Select: + - 2 + - Fn::Split: + - / + - Ref: AWS::StackId + BucketEncryption: + ServerSideEncryptionConfiguration: + - ServerSideEncryptionByDefault: + SSEAlgorithm: AES256 + DeletionPolicy: Delete + CodeCommitRepo: + Type: AWS::CodeCommit::Repository + Properties: + RepositoryName: !Ref 'CodeCommitRepositoryName' + CodePipelineSNSTopic: + Type: AWS::SNS::Topic + Properties: + Subscription: + - Endpoint: !Ref 'Email' + Protocol: email + Pipeline: + Type: AWS::CodePipeline::Pipeline + Properties: + ArtifactStore: + Location: !Ref 'S3Bucket' + Type: S3 + DisableInboundStageTransitions: [] + Name: !Ref 'PipelineName' + RoleArn: !GetAtt 'PipelineRole.Arn' + Stages: + - Name: Source + Actions: + - Name: Source + ActionTypeId: + Category: Source + Owner: AWS + Provider: CodeCommit + Version: '1' + Configuration: + BranchName: main + OutputArtifactFormat: CODE_ZIP + RepositoryName: !Ref 'CodeCommitRepositoryName' + RunOrder: 1 + OutputArtifacts: + - Name: TemplateSource + - Name: Build + Actions: + - Name: CreateStack + ActionTypeId: + Category: Deploy + Owner: AWS + Provider: CloudFormation + Version: '1' + InputArtifacts: + - Name: TemplateSource + Configuration: + ActionMode: REPLACE_ON_FAILURE + RoleArn: !GetAtt 'CFNRole.Arn' + StackName: !Ref 'StackName' + Capabilities: CAPABILITY_NAMED_IAM + TemplateConfiguration: !Sub 'TemplateSource::${StackConfig}' + TemplatePath: !Sub 'TemplateSource::${TemplateFileName}' + RunOrder: 1 + - Name: ApproveStack + ActionTypeId: + Category: Approval + Owner: AWS + Provider: Manual + Version: '1' + Configuration: + NotificationArn: !Ref 'CodePipelineSNSTopic' + CustomData: !Sub 'Perform checks on the AMI built and after approval the stack ${StackName} will be deleted' + RunOrder: 2 + - Name: DeleteStack + ActionTypeId: + Category: Deploy + Owner: AWS + Provider: CloudFormation + Version: '1' + Configuration: + ActionMode: DELETE_ONLY + RoleArn: !GetAtt 'CFNRole.Arn' + StackName: !Ref 'StackName' + RunOrder: 3 + CFNRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Statement: + - Action: + - sts:AssumeRole + Effect: Allow + Principal: + Service: + - cloudformation.amazonaws.com + Version: '2012-10-17' + Path: / + Policies: + - PolicyName: CloudFormationRole + PolicyDocument: + Version: '2012-10-17' + Statement: + - Action: + - ec2:* + Effect: Allow + Resource: '*' + - PolicyName: AdditionalPerms + PolicyDocument: + Version: '2012-10-17' + Statement: + - Action: + - iam:GetRole + - iam:CreateRole + - iam:DetachRolePolicy + - iam:AttachRolePolicy + - iam:DeleteRole + - iam:PassRole + - iam:GetPolicy + - iam:ListPolicyVersions + - iam:CreatePolicy + - iam:DeletePolicy + - iam:CreateInstanceProfile + - iam:DeleteInstanceProfile + - iam:AddRoleToInstanceProfile + - iam:RemoveRoleFromInstanceProfile + - imagebuilder:* + Effect: Allow + Resource: '*' + PipelineRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Statement: + - Action: sts:AssumeRole + Effect: Allow + Principal: + Service: codepipeline.amazonaws.com + Version: '2012-10-17' + Path: / + Policies: + - PolicyName: CodePipelineAccess + PolicyDocument: + Version: '2012-10-17' + Statement: + - Action: + - cloudformation:CreateStack + - cloudformation:DescribeStacks + - cloudformation:DeleteStack + - cloudformation:UpdateStack + - cloudformation:CreateChangeSet + - cloudformation:ExecuteChangeSet + - cloudformation:DeleteChangeSet + - cloudformation:DescribeChangeSet + - cloudformation:SetStackPolicy + - iam:PassRole + - sns:Publish + Effect: Allow + Resource: '*' + - PolicyName: codecommit + PolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Action: + - codecommit:Get* + - codecommit:UploadArchive + Resource: + - !GetAtt 'CodeCommitRepo.Arn' + - PolicyName: s3-artifacts + PolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Action: + - s3:GetObject + - s3:ListBucket + - s3:PutObject + Resource: + - !GetAtt 'S3Bucket.Arn' + - !Sub '${S3Bucket.Arn}/*' diff --git a/blog-assets/automate-ami-builds-aws-codepipeline-D35708869/linux-ami-imagebuilder.yaml b/blog-assets/automate-ami-builds-aws-codepipeline-D35708869/linux-ami-imagebuilder.yaml new file mode 100644 index 0000000..23d9f1d --- /dev/null +++ b/blog-assets/automate-ami-builds-aws-codepipeline-D35708869/linux-ami-imagebuilder.yaml @@ -0,0 +1,253 @@ +--- +AWSTemplateFormatVersion: '2010-09-09' +Description: | + This template builds an EC2 AMI based on Amazon Linux2 ARM64 and installs software to demonstrate an AWS CodePipeline driven AMI builing use-case using EC2 ImageBuilder. The automatically installed software includes the following packages: amazon-cloudwatch-agent-linux, aws-cli-version-2-linux, the stig-build-linux-high (https://docs.aws.amazon.com/imagebuilder/latest/userguide/toe-stig.html), and two custom components executing bash code. (qs-1tkj0sj93) +Parameters: + AWSRegion: + Type: String + Description: Define in which region you want to build and deploy the pipeline + VpcId: + Type: AWS::EC2::VPC::Id + Description: VpcId of your existing Virtual Private Cloud (VPC) to be used to build the AMI + ConstraintDescription: must be the VPC Id of an existing VPC + SubnetId: + Type: String + Description: SubnetId of an existing subnet in your VPC + ConstraintDescription: must be an existing subnet in the selected VPC + SSHKeyPairName: + Type: AWS::EC2::KeyPair::KeyName + Description: Name of an existing EC2 KeyPair to enable SSH access to the instances + ConstraintDescription: must be the name of an existing EC2 KeyPair + SSHLocation: + Type: String + Description: The IP address range that can be used to SSH to the EC2 instances + MinLength: '9' + MaxLength: '18' + AllowedPattern: (\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/(\d{1,2}) + ConstraintDescription: must be a valid IP CIDR range of the form x.x.x.x/x. + Default: 0.0.0.0/0 + Version: + Type: String + Description: Version number for the ImageBuilder Component, that the service needs, but the components will be removed after pipeline completion. + Default: 0.0.1 + Architecture: + Type: String + Description: Select between x86 and ARM instances + Default: arm64 + AllowedValues: + - x86 + - arm64 + InstanceType: + Type: String + Description: Instance Type for building the instances + Default: t4g.micro + AllowedValues: + - t2.micro + - t3.nano + - t3a.nano + - t3.large + - t3.2xlarge + - t4g.nano + - t4g.micro + - t4g.small + - t4g.medium + - t4g.large + - t4g.xlarge + - t4g.2xlarge + BaseImageId: + Type: String + Description: define the base AMI ID to build upon +Resources: + LinuxImage: + Type: AWS::ImageBuilder::Image + Properties: + ImageRecipeArn: !GetAtt 'LinuxImageRecipe.Arn' + InfrastructureConfigurationArn: !GetAtt 'InfrastructureConfiguration.Arn' + EnhancedImageMetadataEnabled: true + LinuxImageRecipe: + Type: AWS::ImageBuilder::ImageRecipe + Properties: + Name: !Sub + - ${AWS::StackName}-Image-${Uniqueval} + - Uniqueval: !Select + - 2 + - !Split + - / + - !Ref 'AWS::StackId' + Description: !Sub + - ${ShortName} Image (${Architecture}) version ${Version} + - ShortName: !Select + - 0 + - !Split + - '-' + - !Ref 'AWS::StackName' + Components: + - ComponentArn: !Sub 'arn:${AWS::Partition}:imagebuilder:${AWSRegion}:aws:component/amazon-cloudwatch-agent-linux/x.x.x' + - ComponentArn: !Sub 'arn:${AWS::Partition}:imagebuilder:${AWSRegion}:aws:component/aws-cli-version-2-linux/x.x.x' + - ComponentArn: !Sub 'arn:${AWS::Partition}:imagebuilder:${AWSRegion}:aws:component/stig-build-linux-high/x.x.x' + - ComponentArn: !GetAtt 'SetLocaleComponent.Arn' + - ComponentArn: !GetAtt 'YumUpdateComponent.Arn' + ParentImage: !Ref 'BaseImageId' + Version: !Sub '${Version}' + WorkingDirectory: /opt/aws/amibuilder/ + BlockDeviceMappings: + - DeviceName: /dev/sda1 + VirtualName: vol2 + Ebs: + DeleteOnTermination: true + VolumeSize: 20 + VolumeType: gp2 + InfrastructureConfiguration: + Type: AWS::ImageBuilder::InfrastructureConfiguration + Properties: + InstanceProfileName: !Ref 'InstanceProfile' + InstanceTypes: + - !Sub '${InstanceType}' + Name: !Sub + - ${AWS::StackName}-InfraConfig-${Uniqueval} + - Uniqueval: !Select + - 2 + - !Split + - / + - !Ref 'AWS::StackId' + KeyPair: !Ref 'SSHKeyPairName' + TerminateInstanceOnFailure: false + SecurityGroupIds: + - !GetAtt 'InstanceSecurityGroup.GroupId' + SubnetId: !Ref 'SubnetId' + SetLocaleComponent: + Type: AWS::ImageBuilder::Component + Properties: + ChangeDescription: !Sub + - Update ${ShortName} Image (${Architecture}) to version ${Version} + - ShortName: !Select + - 0 + - !Split + - '-' + - !Ref 'AWS::StackName' + Description: !Sub + - ${ShortName} Component configures the LC_CTYPE locale + - ShortName: !Select + - 0 + - !Split + - '-' + - !Ref 'AWS::StackName' + Name: !Sub + - ${AWS::StackName}-Component-Locale-${Uniqueval} + - Uniqueval: !Select + - 2 + - !Split + - / + - !Ref 'AWS::StackId' + Platform: Linux + Version: !Sub '${Version}' + Data: !Sub | + name: setlocale global + description: Current version - ${Version} + schemaVersion: 1.0 + phases: + - name: build + steps: + - name: Locale + action: ExecuteBash + onFailure: Continue + inputs: + commands: + - echo "LANG=en_US.utf-8" >> /etc/environment + - echo "LC_ALL=en_US.utf-8" >> /etc/environment + - localectl set-locale LANG=en_US.UTF-8 + - name: validate + steps: + - name: checkLocale + action: ExecuteBash + inputs: + commands: + - localectl status + YumUpdateComponent: + Type: AWS::ImageBuilder::Component + Properties: + ChangeDescription: !Sub + - Update ${ShortName} Image (${Architecture}) to version ${Version} + - ShortName: !Select + - 0 + - !Split + - '-' + - !Ref 'AWS::StackName' + Description: !Sub + - ${ShortName} Component performs a RPM package update + - ShortName: !Select + - 0 + - !Split + - '-' + - !Ref 'AWS::StackName' + Name: !Sub + - ${AWS::StackName}-Component-YumUpdate-${Uniqueval} + - Uniqueval: !Select + - 2 + - !Split + - / + - !Ref 'AWS::StackId' + Platform: Linux + Version: !Sub '${Version}' + Data: !Sub | + name: setlocale global + description: Current version - ${Version} + schemaVersion: 1.0 + phases: + - name: build + steps: + - name: Fail + onFailure: Continue + action: ExecuteBash + inputs: + commands: + - echo 1 + - name: Locale + action: ExecuteBash + onFailure: Continue + inputs: + commands: + - yum update -y + InstanceSecurityGroup: + Type: AWS::EC2::SecurityGroup + Properties: + VpcId: !Ref 'VpcId' + GroupName: !Sub + - ${AWS::StackName}-SG-${Uniqueval} + - Uniqueval: !Select + - 2 + - !Split + - / + - !Ref 'AWS::StackId' + GroupDescription: Enable SSH access via port 22 + SecurityGroupIngress: + - IpProtocol: tcp + FromPort: 22 + ToPort: 22 + CidrIp: !Ref 'SSHLocation' + InstanceProfile: + Type: AWS::IAM::InstanceProfile + Properties: + Roles: + - !Ref 'EC2Role' + EC2Role: + Type: AWS::IAM::Role + Properties: + RoleName: !Sub '${AWS::StackName}' + AssumeRolePolicyDocument: + Version: '2012-10-17' + Statement: + - Action: sts:AssumeRole + Effect: Allow + Principal: + Service: !Sub 'ec2.${AWS::URLSuffix}' + ManagedPolicyArns: + - !Sub 'arn:${AWS::Partition}:iam::aws:policy/AmazonSSMManagedInstanceCore' + - !Sub 'arn:${AWS::Partition}:iam::aws:policy/EC2InstanceProfileForImageBuilder' +Outputs: + ImageArn: + Description: Reference to EC2 Image Builder Output Arn + Value: !GetAtt 'LinuxImage.Arn' + ImageId: + Description: Reference to EC2 Image Builder Output ImageId + Value: !GetAtt 'LinuxImage.ImageId' diff --git a/blog-assets/automate-ami-builds-aws-codepipeline-D35708869/stack-configuration.json b/blog-assets/automate-ami-builds-aws-codepipeline-D35708869/stack-configuration.json new file mode 100644 index 0000000..d1b71d7 --- /dev/null +++ b/blog-assets/automate-ami-builds-aws-codepipeline-D35708869/stack-configuration.json @@ -0,0 +1,12 @@ +{ + "Parameters" : { + "AWSRegion" : "eu-west-1", + "VpcId" : "vpc-12345678", + "SubnetId" : "subnet-12345678", + "SSHKeyPairName" : "sshkeypairname", + "SSHLocation" : "0.0.0.0/0", + "Architecture" : "arm64", + "InstanceType" : "t4g.large", + "BaseImageId" : "ami-0331b64d8b89b4fef" + } +}