接下来我们将添加想要部署的CloudFormation模板:
mkdir -p ./cloudformation
touch ./cloudformation/ec2-bastion.yml
ec2-bastion.yml
内容如下:
---
AWSTemplateFormatVersion: "2010-09-09"
Description: EC2 bastion for latest AWS Linux 2 EC2 deployment
Metadata:
AWS::CloudFormation::Interface:
ParameterGroups:
- Label:
default: "EC2 Configuration"
Parameters:
- pTagNameValue
- pOperatingSystem
- pInstanceType
- pVolumeSize
- pEbsDeleteOnTermination
- Label:
default: "Network Configuration"
Parameters:
- pVpc
- pSubnet
ParameterLabels:
pOperatingSystem:
default: "Operating System"
pInstanceType:
default: "Instance Type"
pTagNameValue:
default: "EC2 Name"
pVolumeSize:
default: "Volume Size"
pEbsDeleteOnTermination:
default: "Delete EBS Volume on Termination"
pSubnet:
default: "Subnet"
pVpc:
default: "VPC"
Parameters:
pSubnet:
Description: The subnet to launch the instance in to. It must be part of the VPC chosen above.
Type: AWS::EC2::Subnet::Id
pVpc:
Description: The VPC to launch the EC2 instance in to.
Type: AWS::EC2::VPC::Id
pOperatingSystem:
Type: "AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>"
Default: "/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-ebs"
pInstanceType:
Description: Desired Instance Size
Type: String
Default: m4.large
AllowedValues:
- m4.large
- t3.small
- t3.medium
- t3.large
- t3.xlarge
pTagNameValue:
Description: "Required: Enter the tag name you'd like applied to the instance. Tag Name gives the name to the EC2 instance."
Type: String
MinLength: 1
Default: "myBastion"
pVolumeSize:
Description:
Enter the number of GBs you want your volume to be. The minimum value
is 8 GBs
Type: Number
Default: 50
MinValue: 8
pEbsDeleteOnTermination:
Description: "Specify if the EBS volume should be deleted if EC2 is deleted."
Type: String
Default: true
AllowedValues:
- true
- false
Rules:
SubnetInVPC:
Assertions:
- Assert: !EachMemberIn
- !ValueOfAll
- AWS::EC2::Subnet::Id
- VpcId
- !RefAll "AWS::EC2::VPC::Id"
AssertDescription: All subnets must in the VPC
Resources:
rSecurityGroupDefault:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: !Sub "Default SG for SC Product ${pTagNameValue} "
VpcId: !Ref pVpc
SecurityGroupEgress:
- Description: Outbound unrestricted traffic
IpProtocol: "-1"
CidrIp: 0.0.0.0/0
Tags:
- Key: Name
Value: !Ref pTagNameValue
rLinuxEc2:
Type: AWS::EC2::Instance
Properties:
ImageId: !Ref pOperatingSystem
Monitoring: false
InstanceType: !Ref pInstanceType
EbsOptimized: true
SourceDestCheck: true
SubnetId: !Ref pSubnet
SecurityGroupIds:
- !Ref rSecurityGroupDefault
BlockDeviceMappings:
- DeviceName: "/dev/xvda"
Ebs:
VolumeSize: !Ref pVolumeSize
DeleteOnTermination: !Ref pEbsDeleteOnTermination
Tags:
- Key: Name
Value: !Ref pTagNameValue
UserData:
Fn::Base64:
yum update -y
## Instance Profiles
## EC2 IAM Roles
rEc2Role:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub "ec2-role-${AWS::StackName}"
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service: [ec2.amazonaws.com]
Action: ['sts:AssumeRole']
Path: /
ManagedPolicyArns:
- !Sub 'arn:${AWS::Partition}:iam::aws:policy/AmazonSSMManagedInstanceCore'
- !Sub 'arn:${AWS::Partition}:iam::aws:policy/CloudWatchAgentServerPolicy'
rec2InstanceProfile:
Type: AWS::IAM::InstanceProfile
Properties:
InstanceProfileName: !Sub "ec2-profile-${AWS::StackName}"
Path: /
Roles:
- !Ref rEc2Role
Outputs:
oLinuxEc2InstanceId:
Description: Resource ID of the newly created EC2 instance
Value: !Ref rLinuxEc2
oLinuxEc2PrivateIP:
Description: Private IP Address for EC2
Value: !GetAtt rLinuxEc2.PrivateIp
提交到Github仓库:
git add -A
git commit -m "init feat"
git push -u origin feat-init
第一次提交后,查看Github的Actions页面,会发现它通过了build
测试,但没有通过compliance
:
打开compliance检查,会发现它没有通过以下两项检查:
EC2_INSTANCE_PROFILE_ATTACHED
:EC2上没有绑定instance profileEC2_INSTANCE_DETAILED_MONITORING_ENABLED
:EC2没有开启detailed monitoring为了修复第一个问题,在原来的代码上加上如下部分,为EC2实例绑定instance profile:
IamInstanceProfile: !Ref rec2InstanceProfile
重新提交代码:
git add -A
git commit -m "fix instance profile"
git push -u origin feat-init
会发现新的提交现在依然有问题,但只有EC2_INSTANCE_DETAILED_MONITORING_ENABLED
问题:
上一节对功能分支 feat-init 的最后一次推送仍然存在合规性失败; 但这是由于Detailed Monitoring
属性设置不正确造成的。 但是我们并不希望启用详细监控,在这种情况下合规性要求不适用。 现在需要抑制 rEc2Linux 资源上的规则,以允许其通过所有合规性测试。
在ec2-bastion.yml
上添加以下规则:
Metadata:
guard:
SuppressedRules:
- 'EC2_INSTANCE_DETAILED_MONITORING_ENABLED'
重新提交代码:
git add -A
git commit -m "suppress detailed monitoring"
git push -u origin feat-init
Detailed Monitoring
合规检查已被抑制,现在build
和complicance
检查均已通过:
现在是时候继续执行后续步骤,来创建Pull request
、合并分支和触发自动部署了。
在创建deploy.yml
的时候,我们指定了它只对main分支生效,所以前面在执行合规性检查时并没有触发deploy.yml
里的命令:
上一节我们的功能分支测试已全部通过,现在将更新的代码合并到我们的主分支中。
所有代码都应经过pull / merge request
请求,这有助于促进审查并记录将部署到我们的 AWS 账户中的更改。 一旦 Pull-Request
获得批准,GitHub 部署操作将被触发并部署我们的 cloudformation 模板。
在github的Pull requests
页面点击Compare & pull request
:
main分支从feat-init
分支拉取最新的更改,设置Assignee
(由于当前只有自己在开发,设置成自己;在实际业务中建议设置为另外的开发者),点击Create pull request
:
将分支合并:
合并pull request
后,会触发deploy.yml
中的指令,在AWS上部署这个CloudFormation模板:
等一段时间后,部署成功。在Github的Actions页面中也能看到相关信息:
本章我们创建了一个简单的 git workflow,可自动执行所有CloudFormation代码的合规性测试以及在主分支代码上进行部署。