{
  "AWSTemplateFormatVersion": "2010-09-09",

  "Description": "AWS CloudFormation Sample Template ElasticBeanstalk_Simple: Configure and launch an AWS Elastic Beanstalk application that connects to an Amazon RDS database instance. Monitoring is setup on the database. **WARNING** This template creates one or more Amazon EC2 instances and an Amazon Relational Database Service database instance. You will be billed for the AWS resources used if you create a stack from this template.",

  "Parameters": {

    "DBUser": {
      "NoEcho": "true",
      "Type": "String",
      "Description": "Test database admin account name",
      "MinLength": "1",
      "MaxLength": "16",
      "AllowedPattern": "[a-zA-Z][a-zA-Z0-9]*",
      "ConstraintDescription": "must begin with a letter and contain only alphanumeric characters."
    },

    "DBPassword": {
      "NoEcho": "true",
      "Type": "String",
      "Description": "Test database admin account password",
      "MinLength": "8",
      "MaxLength": "41",
      "AllowedPattern": "[a-zA-Z0-9]*",
      "ConstraintDescription": "must contain only alphanumeric characters."
    },

    "OperatorEMail": {
      "Description": "EMail address to notify if there are any operational issues",
      "Type": "String",
      "AllowedPattern": "([a-zA-Z0-9_\\-\\.]+)@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.)|(([a-zA-Z0-9\\-]+\\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\\]?)",
      "ConstraintDescription": "must be a valid email address."
    }
  },

  "Mappings" : {
    "Region2Principal" : {
      "ap-east-1"      : { "EC2Principal" : "ec2.amazonaws.com", "OpsWorksPrincipal" : "opsworks.amazonaws.com" },
      "ap-northeast-1" : { "EC2Principal" : "ec2.amazonaws.com", "OpsWorksPrincipal" : "opsworks.amazonaws.com" },
      "ap-northeast-2" : { "EC2Principal" : "ec2.amazonaws.com", "OpsWorksPrincipal" : "opsworks.amazonaws.com" },
      "ap-northeast-3" : { "EC2Principal" : "ec2.amazonaws.com", "OpsWorksPrincipal" : "opsworks.amazonaws.com" },
      "ap-south-1"     : { "EC2Principal" : "ec2.amazonaws.com", "OpsWorksPrincipal" : "opsworks.amazonaws.com" },
      "ap-south-2"     : { "EC2Principal" : "ec2.amazonaws.com", "OpsWorksPrincipal" : "opsworks.amazonaws.com" },
      "ap-southeast-1" : { "EC2Principal" : "ec2.amazonaws.com", "OpsWorksPrincipal" : "opsworks.amazonaws.com" },
      "ap-southeast-2" : { "EC2Principal" : "ec2.amazonaws.com", "OpsWorksPrincipal" : "opsworks.amazonaws.com" },
      "ap-southeast-3" : { "EC2Principal" : "ec2.amazonaws.com", "OpsWorksPrincipal" : "opsworks.amazonaws.com" },
      "ap-southeast-4" : { "EC2Principal" : "ec2.amazonaws.com", "OpsWorksPrincipal" : "opsworks.amazonaws.com" },
      "il-central-1" : { "EC2Principal" : "ec2.amazonaws.com", "OpsWorksPrincipal" : "opsworks.amazonaws.com" },
      "ca-central-1"   : { "EC2Principal" : "ec2.amazonaws.com", "OpsWorksPrincipal" : "opsworks.amazonaws.com" },
      "cn-north-1"     : { "EC2Principal" : "ec2.amazonaws.com.cn", "OpsWorksPrincipal" : "opsworks.amazonaws.com.cn" },
      "cn-northwest-1" : { "EC2Principal" : "ec2.amazonaws.com.cn", "OpsWorksPrincipal" : "opsworks.amazonaws.com.cn" },
      "eu-central-1"   : { "EC2Principal" : "ec2.amazonaws.com", "OpsWorksPrincipal" : "opsworks.amazonaws.com" },
      "eu-north-1"     : { "EC2Principal" : "ec2.amazonaws.com", "OpsWorksPrincipal" : "opsworks.amazonaws.com" },
      "eu-west-1"      : { "EC2Principal" : "ec2.amazonaws.com", "OpsWorksPrincipal" : "opsworks.amazonaws.com" },
      "eu-west-2"      : { "EC2Principal" : "ec2.amazonaws.com", "OpsWorksPrincipal" : "opsworks.amazonaws.com" },
      "eu-west-3"      : { "EC2Principal" : "ec2.amazonaws.com", "OpsWorksPrincipal" : "opsworks.amazonaws.com" },
      "me-south-1"     : { "EC2Principal" : "ec2.amazonaws.com", "OpsWorksPrincipal" : "opsworks.amazonaws.com" },
      "me-central-1"   : { "EC2Principal" : "ec2.amazonaws.com", "OpsWorksPrincipal" : "opsworks.amazonaws.com" },
      "eu-south-2"     : { "EC2Principal" : "ec2.amazonaws.com", "OpsWorksPrincipal" : "opsworks.amazonaws.com" },
      "eu-central-2"   : { "EC2Principal" : "ec2.amazonaws.com", "OpsWorksPrincipal" : "opsworks.amazonaws.com" },
      "sa-east-1"      : { "EC2Principal" : "ec2.amazonaws.com", "OpsWorksPrincipal" : "opsworks.amazonaws.com" },
      "us-east-1"      : { "EC2Principal" : "ec2.amazonaws.com", "OpsWorksPrincipal" : "opsworks.amazonaws.com" },
      "us-east-2"      : { "EC2Principal" : "ec2.amazonaws.com", "OpsWorksPrincipal" : "opsworks.amazonaws.com" },
      "us-west-1"      : { "EC2Principal" : "ec2.amazonaws.com", "OpsWorksPrincipal" : "opsworks.amazonaws.com" },
      "us-west-2"      : { "EC2Principal" : "ec2.amazonaws.com", "OpsWorksPrincipal" : "opsworks.amazonaws.com" }
    }

  },

  "Conditions" : {
    "Is-EC2-VPC"     : { "Fn::Or" : [ {"Fn::Equals" : [{"Ref" : "AWS::Region"}, "eu-central-1" ]},
                                      {"Fn::Equals" : [{"Ref" : "AWS::Region"}, "cn-north-1" ]}]},
    "Is-EC2-Classic" : { "Fn::Not" : [{ "Condition" : "Is-EC2-VPC"}]}
  },

  "Resources": {
    "WebServerRole": {
      "Type": "AWS::IAM::Role",
      "Properties" : {
        "AssumeRolePolicyDocument" : {
          "Statement"  : [{
            "Effect"   : "Allow",
            "Principal": { "Service": [{ "Fn::FindInMap" : ["Region2Principal", {"Ref" : "AWS::Region"}, "EC2Principal"]}] },
            "Action"   : [ "sts:AssumeRole" ]
          } ]
        },
        "Path": "/"
      }
    },

    "WebServerRolePolicy": {
      "Type": "AWS::IAM::Policy",
      "Properties": {
        "PolicyName" : "WebServerRole",
        "PolicyDocument" : {
          "Statement"  : [ {
            "Effect"    : "Allow",
            "NotAction" : "iam:*",
            "Resource"  : "*"
          } ]
        },
        "Roles": [ { "Ref": "WebServerRole" } ]
      }
    },

    "WebServerInstanceProfile": {
      "Type": "AWS::IAM::InstanceProfile",
      "Properties": {
        "Path": "/",
        "Roles": [ { "Ref": "WebServerRole" } ]
      }
    },

    "SampleApplication": {
      "Type": "AWS::ElasticBeanstalk::Application",
      "Properties": {
        "Description": "AWS Elastic Beanstalk Sample Application"
      }
    },

    "SampleApplicationVersion" : {
      "Type" : "AWS::ElasticBeanstalk::ApplicationVersion",
      "Properties" : {
        "Description" : "Version 1.0",
        "ApplicationName" : { "Ref" : "SampleApplication" },
        "SourceBundle" : {
          "S3Bucket": { "Fn::Join" : ["-", ["cloudformation-examples", {"Ref" : "AWS::Region" }]]},
          "S3Key": "CloudFormationBeanstalkRDSExample.war"
        }
      }
    },

    "SampleConfigurationTemplate" : {
      "Type" : "AWS::ElasticBeanstalk::ConfigurationTemplate",
      "Properties" : {
        "ApplicationName" : { "Ref" : "SampleApplication" },
        "Description" : "Default Configuration Version 1.0",
        "SolutionStackName" : "64bit Amazon Linux 2018.03 v3.0.7 running Tomcat 7 Java 7",
        "OptionSettings" : [{
          "Namespace": "aws:elasticbeanstalk:application:environment",
          "OptionName": "JDBC_CONNECTION_STRING",
          "Value": {
            "Fn::Join": ["", ["jdbc:mysql://", { "Fn::GetAtt": ["SampleDB", "Endpoint.Address"] }, ":", { "Fn::GetAtt": ["SampleDB", "Endpoint.Port"] }, "/beanstalkdb" ]] }
        }, {
          "Namespace": "aws:elasticbeanstalk:application:environment",
          "OptionName": "PARAM1",
          "Value": { "Ref": "DBUser" }
        }, {
          "Namespace": "aws:elasticbeanstalk:application:environment",
          "OptionName": "PARAM2",
          "Value": { "Ref": "DBPassword" }
        }, {
          "Namespace": "aws:autoscaling:launchconfiguration",
          "OptionName": "SecurityGroups",
          "Value": { "Ref": "InstanceSecurityGroup" }
        }, {
          "Namespace": "aws:autoscaling:launchconfiguration",
          "OptionName": "IamInstanceProfile",
          "Value": { "Ref": "WebServerInstanceProfile" }
        }]
      }
    },

    "SampleEnvironment": {
      "Type": "AWS::ElasticBeanstalk::Environment",
      "Properties": {
        "Description": "AWS Elastic Beanstalk Environment running Sample Application",
        "ApplicationName": { "Ref": "SampleApplication" },
        "TemplateName": { "Ref" : "SampleConfigurationTemplate" },
        "VersionLabel": { "Ref" : "SampleApplicationVersion" }
      }
    },

    "InstanceSecurityGroup": {
      "Type": "AWS::EC2::SecurityGroup",
      "Properties": {
        "GroupDescription": "RDS allows ingress from EC2 instances in this group.",
        "SecurityGroupIngress": []
      }
    },

    "DBEC2SecurityGroup": {
      "Type": "AWS::EC2::SecurityGroup",
      "Condition" : "Is-EC2-VPC",
      "Properties" : {
        "GroupDescription": "Open database for access",
        "SecurityGroupIngress" : [{
          "IpProtocol" : "tcp",
          "FromPort" : "3306", 
          "ToPort" : "3306",
          "SourceSecurityGroupName" : { "Ref" : "InstanceSecurityGroup" }
        }]
      }
    },

    "DBSecurityGroup": {
      "Type": "AWS::RDS::DBSecurityGroup",
      "Condition" : "Is-EC2-Classic",
      "Properties": {
        "DBSecurityGroupIngress": {
          "EC2SecurityGroupName": { "Ref": "InstanceSecurityGroup" }
        },
        "GroupDescription": "database access"
      }
    },

    "SampleDB": {
      "Type": "AWS::RDS::DBInstance",
      "Properties": {
        "Engine": "MySQL",
        "DBName": "beanstalkdb",
        "MasterUsername": { "Ref": "DBUser" },
        "DBInstanceClass": "db.t2.small",
        "AllocatedStorage": "5",
        "MasterUserPassword": { "Ref": "DBPassword" },
        "VPCSecurityGroups": { "Fn::If" : [ "Is-EC2-VPC", [ { "Fn::GetAtt": [ "DBEC2SecurityGroup", "GroupId" ] } ], { "Ref" : "AWS::NoValue" }]},
        "DBSecurityGroups": { "Fn::If" : [ "Is-EC2-Classic", [ { "Ref": "DBSecurityGroup" } ], { "Ref" : "AWS::NoValue" }]}
      }
    },

    "AlarmTopic": {
      "Type": "AWS::SNS::Topic",
      "Properties": {
        "Subscription": [{ "Endpoint": { "Ref": "OperatorEMail" }, "Protocol": "email" }]
      }
    },

    "CPUAlarmHigh": {
      "Type": "AWS::CloudWatch::Alarm",
      "Properties": {
        "EvaluationPeriods": "10",
        "Statistic": "Average",
        "Threshold": "50",
        "AlarmDescription": "Alarm if CPU too high or metric disappears indicating the RDS database instance is having issues",
        "Period": "60",
        "Namespace": "AWS/RDS",
        "MetricName": "CPUUtilization",
        "Dimensions": [{
          "Name": "DBInstanceIdentifier",
          "Value": { "Ref": "SampleDB" }
        }],
        "ComparisonOperator": "GreaterThanThreshold",
        "AlarmActions": [{ "Ref": "AlarmTopic" }],
        "InsufficientDataActions": [{ "Ref": "AlarmTopic" }]
      }
    }
  },

  "Outputs": {
    "URL": {
      "Description": "URL of the AWS Elastic Beanstalk Environment",
      "Value": { "Fn::Join": ["", ["http://", { "Fn::GetAtt": ["SampleEnvironment", "EndpointURL"] }]]
      }
    }
  }
}
