AWSTemplateFormatVersion: 2010-09-09
Description: >-
  AWS CloudFormation Sample Template LAMP_Single_Instance: Create a LAMP stack
  using a single EC2 instance and a local MySQL database for storage. This
  template demonstrates using the AWS CloudFormation bootstrap scripts to
  install the packages and files necessary to deploy the Apache web server, PHP
  and MySQL at instance launch time. **WARNING** This template creates an Amazon
  EC2 instance. You will be billed for the AWS resources used if you create a
  stack from this template.
Parameters:
  VPC:
    Type: 'AWS::EC2::VPC::Id'
    Description: VpcId of your existing Virtual Private Cloud (VPC)
    ConstraintDescription: must be the VPC Id of an existing Virtual Private Cloud.
  WebSubnetId:
    Description: Select a public subnet-id to use for EC2 instance
    Type: 'AWS::EC2::Subnet::Id'
  DBName:
    Default: MyDatabase
    Description: MySQL database name
    Type: String
    MinLength: '1'
    MaxLength: '64'
    AllowedPattern: '[a-zA-Z][a-zA-Z0-9]*'
    ConstraintDescription: must begin with a letter and contain only alphanumeric characters.
  DBUser:
    Default: MyDatabase
    NoEcho: 'true'
    Description: Username for MySQL database access
    Type: String
    MinLength: '1'
    MaxLength: '16'
    AllowedPattern: '[a-zA-Z][a-zA-Z0-9]*'
    ConstraintDescription: must begin with a letter and contain only alphanumeric characters.
  InstanceType:
    Description: WebServer EC2 instance type
    Type: String
    Default: t3.small
    AllowedValues:
      - t3.large
      - t3.medium
      - t3.micro
      - t3.small
      - t3.xlarge
    ConstraintDescription: must be a valid EC2 instance type.
  SSHLocation:
    Description: ' The IP address range that can be used to SSH to the EC2 instances'
    Type: String
    MinLength: '9'
    MaxLength: '18'
    Default: 0.0.0.0/0
    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.
Mappings:
  AWSInstanceType2Arch:
    t3.micro:
      Arch: HVM64
    t3.small:
      Arch: HVM64
    t3.medium:
      Arch: HVM64
    t3.large:
      Arch: HVM64
    t3.xlarge:
      Arch: HVM64
  AWSInstanceType2NATArch:
    t3.micro:
      Arch: NATHVM64
    t3.small:
      Arch: NATHVM64
    t3.medium:
      Arch: NATHVM64
    t3.large:
      Arch: NATHVM64
    t3.xlarge:
      Arch: NATHVM64
  AWSRegionArch2AMI:
    us-east-1:
      HVM64: ami-0080e4c5bc078760e
      HVMG2: ami-0aeb704d503081ea6
    us-west-2:
      HVM64: ami-01e24be29428c15b2
      HVMG2: ami-0fe84a5b4563d8f27
    us-west-1:
      HVM64: ami-0ec6517f6edbf8044
      HVMG2: ami-0a7fc72dc0e51aa77
    eu-west-1:
      HVM64: ami-08935252a36e25f85
      HVMG2: ami-0d5299b1c6112c3c7
    eu-west-2:
      HVM64: ami-01419b804382064e4
      HVMG2: NOT_SUPPORTED
    eu-west-3:
      HVM64: ami-0dd7e7ed60da8fb83
      HVMG2: NOT_SUPPORTED
    eu-central-1:
      HVM64: ami-0cfbf4f6db41068ac
      HVMG2: ami-0aa1822e3eb913a11
    eu-north-1:
      HVM64: ami-86fe70f8
      HVMG2: ami-32d55b4c
    ap-northeast-1:
      HVM64: ami-00a5245b4816c38e6
      HVMG2: ami-09d0e0e099ecabba2
    ap-northeast-2:
      HVM64: ami-00dc207f8ba6dc919
      HVMG2: NOT_SUPPORTED
    ap-northeast-3:
      HVM64: ami-0b65f69a5c11f3522
      HVMG2: NOT_SUPPORTED
    ap-southeast-1:
      HVM64: ami-05b3bcf7f311194b3
      HVMG2: ami-0e46ce0d6a87dc979
    ap-southeast-2:
      HVM64: ami-02fd0b06f06d93dfc
      HVMG2: ami-0c0ab057a101d8ff2
    ap-south-1:
      HVM64: ami-0ad42f4f66f6c1cc9
      HVMG2: ami-0244c1d42815af84a
    us-east-2:
      HVM64: ami-0cd3dfa4e37921605
      HVMG2: NOT_SUPPORTED
    ca-central-1:
      HVM64: ami-07423fb63ea0a0930
      HVMG2: NOT_SUPPORTED
    sa-east-1:
      HVM64: ami-05145e0b28ad8e0b2
      HVMG2: NOT_SUPPORTED
    cn-north-1:
      HVM64: ami-053617c9d818c1189
      HVMG2: NOT_SUPPORTED
    cn-northwest-1:
      HVM64: ami-0f7937761741dc640
      HVMG2: NOT_SUPPORTED
Resources:
  MyDBSecret:
    Type: 'AWS::SecretsManager::Secret'
    Properties:
      Name: RandomDBPassword
      Description: Random password to be used for DB
      GenerateSecretString:
        ExcludePunctuation: 'true'
        PasswordLength: '12'

  WebServerInstance:
    Type: 'AWS::EC2::Instance'
    Metadata:
      'AWS::CloudFormation::Init':
        configSets:
          InstallAndRun:
            - Install
            - Configure
        Install:
          packages:
            yum:
              mysql: []
              mysql-server: []
              mysql-libs: []
              httpd: []
              php: []
              php-mysql: []
          files:
            /var/www/html/index.php:
              content: !Join 
                - ''
                - - |
                    <html>
                  - |2
                      <head>
                  - |2
                        <title>AWS CloudFormation PHP Sample</title>
                  - |2
                        <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
                  - |2
                      </head>
                  - |2
                      <body>
                  - |2
                        <h1>Welcome to the AWS CloudFormation PHP Sample</h1>
                  - |2
                        <p/>
                  - |2
                        <?php
                  - |2
                          // Print out the current data and time
                  - |2
                          print "The Current Date and Time is: <br/>";
                  - |2
                          print date("g:i A l, F j Y.");
                  - |2
                        ?>
                  - |2
                        <p/>
                  - |2
                        <?php
                  - |2
                          // Setup a handle for CURL
                  - |2
                          $curl_handle=curl_init();
                  - |2
                          curl_setopt($curl_handle,CURLOPT_CONNECTTIMEOUT,2);
                  - |2
                          curl_setopt($curl_handle,CURLOPT_RETURNTRANSFER,1);
                  - |2
                          // Get the hostname of the intance from the instance metadata
                  - |2
                          curl_setopt($curl_handle,CURLOPT_URL,'http://169.254.169.254/latest/meta-data/public-hostname');
                  - |2
                          $hostname = curl_exec($curl_handle);
                  - |2
                          if (empty($hostname))
                  - |2
                          {
                  - |2
                            print "Sorry, for some reason, we got no hostname back <br />";
                  - |2
                          }
                  - |2
                          else
                  - |2
                          {
                  - |2
                            print "Server = " . $hostname . "<br />";
                  - |2
                          }
                  - |2
                          // Get the instance-id of the intance from the instance metadata
                  - |2
                          curl_setopt($curl_handle,CURLOPT_URL,'http://169.254.169.254/latest/meta-data/instance-id');
                  - |2
                          $instanceid = curl_exec($curl_handle);
                  - |2
                          if (empty($instanceid))
                  - |2
                          {
                  - |2
                            print "Sorry, for some reason, we got no instance id back <br />";
                  - |2
                          }
                  - |2
                          else
                  - |2
                          {
                  - |2
                            print "EC2 instance-id = " . $instanceid . "<br />";
                  - |2
                          }
                  - |2
                          $Database   = "localhost";
                  - '      $DBUser     = "'
                  - !Ref DBUser
                  - |
                    ";
                  - '      $DBPassword = "'
                  - !Ref MyDBSecret
                  - |
                    ";
                  - |2
                          print "Database = " . $Database . "<br />";
                  - |2
                          $dbconnection = mysql_connect($Database, $DBUser, $DBPassword)
                  - |2
                                          or die("Could not connect: " . mysql_error());
                  - |2
                          print ("Connected to $Database successfully");
                  - |2
                          mysql_close($dbconnection);
                  - |2
                        ?>
                  - |2
                        <h2>PHP Information</h2>
                  - |2
                        <p/>
                  - |2
                        <?php
                  - |2
                          phpinfo();
                  - |2
                        ?>
                  - |2
                      </body>
                  - |
                    </html>
              mode: '000600'
              owner: apache
              group: apache
            /tmp/setup.mysql:
              content: !Join 
                - ''
                - - 'CREATE DATABASE '
                  - !Ref DBName
                  - |
                    ;
                  - 'GRANT ALL ON '
                  - !Ref DBName
                  - .* TO '
                  - !Ref DBUser
                  - '''@localhost IDENTIFIED BY '''
                  - !Ref MyDBSecret
                  - |
                    ';
              mode: '000400'
              owner: root
              group: root
            /etc/cfn/cfn-hup.conf:
              content: !Join 
                - ''
                - - |
                    [main]
                  - stack=
                  - !Ref 'AWS::StackId'
                  - |+

                  - region=
                  - !Ref 'AWS::Region'
                  - |+

              mode: '000400'
              owner: root
              group: root
            /etc/cfn/hooks.d/cfn-auto-reloader.conf:
              content: !Join 
                - ''
                - - |
                    [cfn-auto-reloader-hook]
                  - |
                    triggers=post.update
                  - >
                    path=Resources.WebServerInstance.Metadata.AWS::CloudFormation::Init
                  - 'action=/opt/aws/bin/cfn-init -v '
                  - '         --stack '
                  - !Ref 'AWS::StackName'
                  - '         --resource WebServerInstance '
                  - '         --configsets InstallAndRun '
                  - '         --region '
                  - !Ref 'AWS::Region'
                  - |+

                  - |
                    runas=root
              mode: '000400'
              owner: root
              group: root
          services:
            sysvinit:
              mysqld:
                enabled: 'true'
                ensureRunning: 'true'
              httpd:
                enabled: 'true'
                ensureRunning: 'true'
              cfn-hup:
                enabled: 'true'
                ensureRunning: 'true'
                files:
                  - /etc/cfn/cfn-hup.conf
                  - /etc/cfn/hooks.d/cfn-auto-reloader.conf
        Configure:
          commands:
            01_set_mysql_root_password:
              command: !Join 
                - ''
                - - mysqladmin -u root password '
                  - !Ref MyDBSecret
                  - ''''
              test: !Join 
                - ''
                - - '$(mysql '
                  - !Ref DBName
                  - ' -u root --password='''
                  - !Ref MyDBSecret
                  - ''' >/dev/null 2>&1 </dev/null); (( $? != 0 ))'
            02_create_database:
              command: !Join 
                - ''
                - - mysql -u root --password='
                  - !Ref MyDBSecret
                  - ''' < /tmp/setup.mysql'
              test: !Join 
                - ''
                - - '$(mysql '
                  - !Ref DBName
                  - ' -u root --password='''
                  - !Ref MyDBSecret
                  - ''' >/dev/null 2>&1 </dev/null); (( $? != 0 ))'
    Properties:
      ImageId: !FindInMap 
        - AWSRegionArch2AMI
        - !Ref 'AWS::Region'
        - !FindInMap 
          - AWSInstanceType2Arch
          - !Ref InstanceType
          - Arch
      InstanceType: !Ref InstanceType
      SecurityGroupIds:
        - !GetAtt 
          - WebServerSecurityGroup
          - GroupId
      SubnetId: !Ref WebSubnetId
      UserData: !Base64 
        'Fn::Join':
          - ''
          - - |
              #!/bin/bash -xe
            - |
              yum update -y aws-cfn-bootstrap
            - |
              # Install the files and packages from the metadata
            - '/opt/aws/bin/cfn-init -v '
            - '         --stack '
            - !Ref 'AWS::StackName'
            - '         --resource WebServerInstance '
            - '         --configsets InstallAndRun '
            - '         --region '
            - !Ref 'AWS::Region'
            - |+

            - |
              # Signal the status from cfn-init
            - '/opt/aws/bin/cfn-signal -e $? '
            - '         --stack '
            - !Ref 'AWS::StackName'
            - '         --resource WebServerInstance '
            - '         --region '
            - !Ref 'AWS::Region'
            - |+

    CreationPolicy:
      ResourceSignal:
        Timeout: PT5M
  WebServerSecurityGroup:
    Type: 'AWS::EC2::SecurityGroup'
    Properties:
      GroupDescription: Enable HTTP access via port 80
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: '80'
          ToPort: '80'
          CidrIp: 0.0.0.0/0
        - IpProtocol: tcp
          FromPort: '22'
          ToPort: '22'
          CidrIp: !Ref SSHLocation
        - IpProtocol: icmp
          CidrIp: 172.16.0.0/12
          FromPort: "-1"
          ToPort: "-1"
Outputs:
  WebsiteURL:
    Description: URL for newly created LAMP stack
    Value: !Join 
      - ''
      - - 'http://'
        - !GetAtt 
          - WebServerInstance
          - PublicDnsName
