AWSTemplateFormatVersion: "2010-09-09" Description: This template creates an Amazon VPC and subnet with the required configuration and an EC2 Instance Parameters: paramKeyName: Description: Name of an existing EC2 KeyPair to enable SSH access to the instance Type: 'AWS::EC2::KeyPair::KeyName' ConstraintDescription: must be the name of an existing EC2 KeyPair. paramInstanceType: Description: EC2 instance specs configuration Type: String Default: t2.large AllowedValues: - t2.large - t2.xlarge paramPrefixS3Bucket: Description: Prefix of S3 bucket that will be created to store the certificates that will be created and these will be used later. Type: String Default: "aws-blog-beanstalk-gitlab-bucket" paramHostedZoneName: Description: Route 53 Hosted Zone - For simplicity, we will be using the default value and do not change. Type: String Default: "example.com" AllowedValues: - example.com paramSubDomainName: Description: Sub domain name for the A record - For simplicity, we will be using the default value and do not change. Type: String Default: "runner" AllowedValues: - runner Mappings: AMIs: us-east-1: Name: ami-06b263d6ceff0b3dd us-east-2: Name: ami-0010d386b82bc06f0 Resources: VPC: Type: AWS::EC2::VPC Properties: CidrBlock: 10.0.0.0/16 EnableDnsSupport: true EnableDnsHostnames: true InstanceTenancy: default Tags: - Key: Name Value: AWSBLOGBEANVPC PublicSubnetA: Type: AWS::EC2::Subnet Properties: VpcId: !Ref 'VPC' CidrBlock: 10.0.1.0/24 AvailabilityZone: "us-east-1a" MapPublicIpOnLaunch: 'True' Tags: - Key: Name Value: AWSBLOGBEANSubnetA PublicSubnetB: Type: AWS::EC2::Subnet Properties: VpcId: !Ref 'VPC' CidrBlock: 10.0.2.0/24 AvailabilityZone: "us-east-1b" MapPublicIpOnLaunch: 'True' Tags: - Key: Name Value: AWSBLOGBEANSubnetB PublicSubnetC: Type: AWS::EC2::Subnet Properties: VpcId: !Ref 'VPC' CidrBlock: 10.0.3.0/24 AvailabilityZone: "us-east-1c" MapPublicIpOnLaunch: 'True' Tags: - Key: Name Value: AWSBLOGBEANSubnetC InternetGateway: Type: AWS::EC2::InternetGateway Properties: Tags: - Key: Name Value: AWSBLOGBEANGateway MyGatewayAttachment: Type: AWS::EC2::VPCGatewayAttachment Properties: InternetGatewayId: !Ref 'InternetGateway' VpcId: !Ref 'VPC' PublicRouteTable: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref 'VPC' PublicRoute: Type: AWS::EC2::Route Properties: RouteTableId: !Ref 'PublicRouteTable' DestinationCidrBlock: '0.0.0.0/0' GatewayId: !Ref 'InternetGateway' DependsOn: - MyGatewayAttachment PublicSubnetRouteAssociationA: Type: AWS::EC2::SubnetRouteTableAssociation Properties: RouteTableId: !Ref 'PublicRouteTable' SubnetId: !Ref 'PublicSubnetA' PublicSubnetRouteAssociationB: Type: AWS::EC2::SubnetRouteTableAssociation Properties: RouteTableId: !Ref 'PublicRouteTable' SubnetId: !Ref 'PublicSubnetB' PublicSubnetRouteAssociationC: Type: AWS::EC2::SubnetRouteTableAssociation Properties: RouteTableId: !Ref 'PublicRouteTable' SubnetId: !Ref 'PublicSubnetC' AWSBLOGBEANAccessSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: CloudFormationGroup VpcId: !Ref 'VPC' SecurityGroupIngress: - IpProtocol: '-1' CidrIp: "10.0.0.0/16" - IpProtocol: tcp FromPort: 22 ToPort: 22 CidrIp: "10.0.0.0/16" - IpProtocol: tcp FromPort: 80 ToPort: 80 CidrIp: "0.0.0.0/0" - IpProtocol: tcp FromPort: 443 ToPort: 443 CidrIp: "0.0.0.0/0" - IpProtocol: icmp FromPort: -1 ToPort: -1 CidrIp: "10.0.0.0/16" Tags: - Key: Name Value: AWSBLOGBEANVPCMasterSecurityGroup VPCDefaultSecurityGroupIngress: Type: AWS::EC2::SecurityGroupIngress Properties: GroupId: !GetAtt 'VPC.DefaultSecurityGroup' IpProtocol: '-1' CidrIp: 10.0.0.0/16 S3Bucket: Type: AWS::S3::Bucket Properties: BucketName: !Join - "-" - - !Ref paramPrefixS3Bucket - !Select - 0 - !Split - "-" - !Select - 2 - !Split - "/" - !Ref "AWS::StackId" BucketEncryption: ServerSideEncryptionConfiguration: - ServerSideEncryptionByDefault: SSEAlgorithm: AES256 AccessControl: BucketOwnerFullControl AWSBLOGBEANEC2InstanceRole: Type: 'AWS::IAM::Role' Properties: AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - ec2.amazonaws.com Action: - 'sts:AssumeRole' Path: / AWSBlogBeanstalkS3BucketsPolicy: Type: 'AWS::IAM::Policy' Properties: PolicyName: AWS-BEANSTALK-BLOG-S3Buckets-Policy PolicyDocument: Statement: - Effect: Allow Action: - 's3:*' # We can just use the bucket that will get created in this CF template. Resource: '*' Roles: - !Ref AWSBLOGBEANEC2InstanceRole AWSBlogBeanstalkElasticBeanstalkPolicy: Type: 'AWS::IAM::Policy' Properties: PolicyName: AWS-BEANSTALK-BLOG-ElasticBeanstalk-Policy PolicyDocument: Statement: - Effect: Allow Action: - 'elasticbeanstalk:*' # arn:aws:elasticbeanstalk:us-east-1:246997141225:applicationversion/SampleAWSElasticBeanstalkApplication/version-ymFeXCyH Resource: '*' Roles: - !Ref AWSBLOGBEANEC2InstanceRole AWSBlogBeanstalkCloudFormationPolicy: Type: 'AWS::IAM::Policy' Properties: PolicyName: AWS-BEANSTALK-BLOG-CloudFormation-Policy PolicyDocument: Statement: - Effect: Allow Action: - 'cloudformation:*' # cloudformation:GetTemplate on resource: arn:aws:cloudformation:us-east-1:246997141225:stack/awseb-e-3eizpfmjmb-stack/d5b4fc10-835c-11eb-b68a-0ef29e620f87 Resource: '*' Roles: - !Ref AWSBLOGBEANEC2InstanceRole AWSBlogBeanstalkEC2Policy: Type: 'AWS::IAM::Policy' Properties: PolicyName: AWS-BEANSTALK-BLOG-EC2-Policy PolicyDocument: Statement: - Effect: Allow Action: - 'ec2:*' # Service:AmazonEC2, Message:You do not have permission to perform the 'ec2:DescribeSubnets' action. Resource: '*' Roles: - !Ref AWSBLOGBEANEC2InstanceRole AWSBlogBeanstalkCWLogsPolicy: Type: 'AWS::IAM::Policy' Properties: PolicyName: AWS-BEANSTALK-BLOG-CWLOGS-Policy PolicyDocument: Statement: - Effect: Allow Action: - 'logs:*' Resource: '*' Roles: - !Ref AWSBLOGBEANEC2InstanceRole AWSBlogBeanstalkAutoscalingPolicy: Type: 'AWS::IAM::Policy' Properties: PolicyName: AWS-BEANSTALK-BLOG-AUTOSCALING-Policy PolicyDocument: Statement: - Effect: Allow Action: - 'autoscaling:*' Resource: '*' Roles: - !Ref AWSBLOGBEANEC2InstanceRole AWSBlogBeanstalkELBPolicy: Type: 'AWS::IAM::Policy' Properties: PolicyName: AWS-BEANSTALK-BLOG-ELBG-Policy PolicyDocument: Statement: - Effect: Allow Action: - 'elasticloadbalancing:*' Resource: '*' Roles: - !Ref AWSBLOGBEANEC2InstanceRole AWSBlogBeanstalkIAMPolicy: Type: 'AWS::IAM::Policy' Properties: PolicyName: AWS-BEANSTALK-BLOG-IAM-Policy PolicyDocument: Statement: - Effect: Allow Action: - 'iam:*' Resource: '*' Roles: - !Ref AWSBLOGBEANEC2InstanceRole AWSBlogBeanstalkInstanceProfile: Type: 'AWS::IAM::InstanceProfile' Properties: Path: / Roles: - !Ref AWSBLOGBEANEC2InstanceRole GitLabEC2Instance: Type: "AWS::EC2::Instance" DependsOn: [VPC, PublicSubnetA, InternetGateway, PublicRoute, PublicSubnetRouteAssociationA, AWSBLOGBEANAccessSecurityGroup] CreationPolicy: # <--- creation policy with timeout of 5 minutes ResourceSignal: Timeout: PT20M Properties: InstanceType: !Ref paramInstanceType KeyName: !Ref paramKeyName IamInstanceProfile: !Ref AWSBlogBeanstalkInstanceProfile BlockDeviceMappings: - DeviceName: /dev/sda1 Ebs: VolumeType: "io1" VolumeSize: 30 DeleteOnTermination: 'true' Encrypted: 'true' Iops: 300 ImageId: !FindInMap - AMIs - !Ref 'AWS::Region' - Name NetworkInterfaces: - DeviceIndex: '0' AssociatePublicIpAddress: 'true' DeleteOnTermination: 'true' SubnetId: !Ref 'PublicSubnetA' GroupSet: [!GetAtt 'AWSBLOGBEANAccessSecurityGroup.GroupId'] Tags: - Key: Name Value: AWSBlogBeanstalk-EC2Instance UserData: Fn::Base64: !Sub | #!/bin/bash -xe cd /home/ubuntu/ touch test1 sudo apt update -y sudo apt install awscli -y aws s3 cp s3://aws-bigdata-blog/artifacts/awsblog-beanstalk-gitlab/shell/gitlab-setup.sh . chmod -R 777 gitlab-setup.sh sudo apt-get -y install python-pip sudo pip install https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-latest.tar.gz sh -x ./gitlab-setup.sh ${S3Bucket} ${paramSubDomainName}.${paramHostedZoneName} test > gitlab-setup-output.log # Start cfn-init /usr/local/bin/cfn-init --stack ${AWS::StackId} --resource GitLabEC2Instance --region ${AWS::Region} /usr/local/bin/cfn-signal -e $? --stack ${AWS::StackId} --resource GitLabEC2Instance --region ${AWS::Region} Metadata: Comment: Install and setup gitlab AWS::CloudFormation::Init: config: commands: gitlab_setup: command: "echo 'COMPLETED'" AWSBlogBeanstalkRoute53HostedZone: Type: 'AWS::Route53::HostedZone' Properties: HostedZoneConfig: Comment: 'AWS Blog GitLab Beanstalk hosted zone' Name: !Ref paramHostedZoneName VPCs: - VPCId: !Ref 'VPC' VPCRegion: 'us-east-1' DnsRecord: Type: AWS::Route53::RecordSet DependsOn: [GitLabEC2Instance, AWSBlogBeanstalkRoute53HostedZone] Properties: HostedZoneName: !Join ['', [!Ref 'paramHostedZoneName', .]] Comment: DNS name for my instance. Name: !Join ['', [!Ref 'paramSubDomainName', ., !Ref 'paramHostedZoneName']] Type: A TTL: '900' ResourceRecords: - !GetAtt GitLabEC2Instance.PublicIp Outputs: StackName: Value: !Ref 'AWS::StackName' SubnetIDA: Description: Public Subnet A. Value: !Ref 'PublicSubnetA' Export: Name: "awsblogbean-public-subnet-a" SubnetIDB: Description: Public Subnet B. Value: !Ref 'PublicSubnetB' Export: Name: "awsblogbean-public-subnet-b" SubnetIDC: Description: Public Subnet C. Value: !Ref 'PublicSubnetC' Export: Name: "awsblogbean-public-subnet-c" VPCSubnets: Description: All subnets Value: 'Fn::Join': [",", [!Ref 'PublicSubnetA', !Ref 'PublicSubnetB', !Ref 'PublicSubnetC']] Export: Name: "VPCSubnetsList" AWSBLOGBEANAccessSecurityGroup: Description: Use this security group ID for all your services. Value: !GetAtt 'AWSBLOGBEANAccessSecurityGroup.GroupId' Export: Name: "awsblogbean--securitygroup-id" VPCID: Description: Use this VPC ID for all your services. Value: !Ref 'VPC' Export: Name: "awsblogbean-vpc-id" ExpS3Bucket: Description: S3 Bucket created in your account. Value: !Ref 'S3Bucket' Export: Name: "exp-s3-bucket" GitEc2PublicDNS: Description: GitLab Ec2 instance's Public Dns Name. Value: !GetAtt GitLabEC2Instance.PublicDnsName Export: Name: !Sub "${AWS::StackName}-PublicDnsName" GitEc2PublicIp: Description: GitLab Ec2 instance's Public Ip Address. Value: !GetAtt GitLabEC2Instance.PublicIp Export: Name: !Sub "public-ip-for-A-recordset"