{
  "AWSTemplateFormatVersion" : "2010-09-09",
  "Description" : "ArcGIS CloudFormation Template: Provisions an ArcGIS for Server site on EC2 instances running Windows. **WARNING** You will be billed by AWS for the AWS resources if you create a stack from this template.",
  "Mappings" : {
    "RegionMap" : {
		"eu-north-1": {
		  "en": "ami-081bd4277c98bdddc"
		},
		"ap-south-1": {
		  "en": "ami-02a0325939b20d144"
		},
		"eu-west-3": {
		  "en": "ami-0cdbfaec068a9049e"
		},
		"eu-west-2": {
		  "en": "ami-0191ece836f7de68b"
		},
		"eu-west-1": {
		  "en": "ami-0e1ff5a8b310babce"
		},
		"ap-northeast-2": {
		  "en": "ami-0897ea43ec4fac897"
		},
		"ap-northeast-1": {
		  "en": "ami-0ed327f44ec8ee756"
		},
		"sa-east-1": {
		  "en": "ami-0d601fef85390b80f"
		},
		"ca-central-1": {
		  "en": "ami-03562c37fdee04876"
		},
		"ap-southeast-1": {
		  "en": "ami-023d2c1bf326f5aae"
		},
		"ap-southeast-2": {
		  "en": "ami-027a2721e5109d8e0"
		},
		"eu-central-1": {
		  "en": "ami-09c53587d56e56b84"
		},
		"us-east-1": {
		  "en": "ami-011ea66e021380ef2"
		},
		"us-east-2": {
		  "en": "ami-076119782e9b6abce"
		},
		"us-west-1": {
		  "en": "ami-0091ada380dcdf5a9"
		},
		"us-west-2": {
		  "en": "ami-0c51ba87dfc0de785"
		}
    },
    "DBEngineProperties" : {
      "sqlserver-se" : {"MajorVersion": "13.00", "Version": "13.00.4422.0.v1", "License": "license-included"},
      "postgres" : {"MajorVersion": "9.6", "Version": "9.6.20", "License": "postgresql-license"},
      "aurora-postgresql" : {"MajorVersion": "9.6", "Version": "9.6.18", "License": "postgresql-license"}
    }
  },
  "Parameters" : {
    "DeploymentBucket" : {
      "Description" : "S3 bucket with software authorization and SSL certificate files",
      "Type" : "String",
      "AllowedPattern" : "^([a-z]|(\\d(?!\\d{0,2}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})))([a-z\\d]|(\\.(?!(\\.|-)))|(-(?!\\.))){1,61}[a-z\\d\\.]$",
      "ConstraintDescription" : "A Bucket's name can be between 6 and 63 characters long, containing lowercase characters, numbers, periods, and dashes and it must start with a lowercase letter or number."
    },
    "DriveSizeRoot" : {
      "Default" : "100",
      "Description" : "The size of the C: Drive in GB.",
      "Type" : "Number",
      "MinValue" : "100",
      "MaxValue" : "1024",
      "ConstraintDescription" : "Must be between 100 and 1024 GB."
    },
    "FSInstanceType": {
      "Description": "The file server EC2 instance type",
      "Type": "String",
      "AllowedValues": [
        "a1.2xlarge", "a1.4xlarge",
        "c3.large", "c3.xlarge", "c3.2xlarge", "c3.4xlarge", "c3.8xlarge",
        "c4.large", "c4.xlarge", "c4.2xlarge", "c4.4xlarge", "c4.8xlarge",
        "c5.xlarge", "c5.2xlarge", "c5.4xlarge", "c5.9xlarge", "c5.18xlarge", "c5.xlarge",
        "c5n.xlarge", "c5n.2xlarge", "c5n.4xlarge", "c5n.9xlarge", "c5n.18xlarge",
        "m3.large", "m3.xlarge", "m3.2xlarge",
        "m4.large", "m4.xlarge", "m4.2xlarge", "m4.4xlarge", "m4.10xlarge", "m4.16xlarge", 
        "m5.large", "m5.xlarge", "m5.2xlarge", "m5.4xlarge", "m5.12xlarge", "m5.24xlarge", "m5.metal",
        "m5a.large", "m5a.xlarge", "m5a.2xlarge", "m5a.4xlarge", "m5a.12xlarge", "m5a.24xlarge",
        "r3.large", "r3.xlarge", "r3.2xlarge", "r3.4xlarge", "r3.8xlarge",
        "r4.large", "r4.xlarge", "r4.2xlarge", "r4.4xlarge", "r4.8xlarge", "r4.16xlarge",
        "r5.large", "r5.xlarge", "r5.2xlarge", "r5.4xlarge", "r5.12xlarge", "r5.24xlarge", "r5.metal",
        "r5a.large", "r5a.xlarge", "r5a.2xlarge", "r5a.4xlarge", "r5a.12xlarge", "r5a.24xlarge",
        "t2.large", "t2.xlarge", "t2.2xlarge",
        "t3.large", "t3.xlarge", "t3.2xlarge",
        "x1.16xlarge", "x1.32xlarge",
        "x1e.xlarge", "x1e.2xlarge", "x1e.4xlarge", "x1e.8xlarge", "x1e.16xlarge", "x1e.32xlarge"
      ],
      "Default": "c4.large"
    },
    "ASInstanceType": {
      "Description": "The ArcGIS Server EC2 instance type",
      "Type": "String",
      "AllowedValues": [
        "a1.2xlarge", "a1.4xlarge",
        "c3.large", "c3.xlarge", "c3.2xlarge", "c3.4xlarge", "c3.8xlarge",
        "c4.large", "c4.xlarge", "c4.2xlarge", "c4.4xlarge", "c4.8xlarge", 
        "c5.large", "c5.xlarge", "c5.2xlarge", "c5.4xlarge", "c5.9xlarge", "c5.18xlarge", "c5.xlarge",
        "c5d.2xlarge", "c5d.4xlarge", "c5d.9xlarge", "c5d.18xlarge",
        "c5n.xlarge", "c5n.2xlarge", "c5n.4xlarge", "c5n.9xlarge", "c5n.18xlarge",
        "g3s.xlarge", "g3.4xlarge", "g3.8xlarge", "g3.16xlarge",
        "f1.2xlarge", "f1.4xlarge", "f1.16xlarge",
        "h1.2xlarge", "h1.4xlarge", "h1.8xlarge", "h1.16xlarge",
        "i3.large", "i3.xlarge", "i3.2xlarge", "i3.4xlarge", "i3.8xlarge", "i3.16xlarge", "i3.metal",
        "m3.large", "m3.xlarge", "m3.2xlarge",
        "m4.large", "m4.xlarge", "m4.2xlarge", "m4.4xlarge", "m4.10xlarge",
        "m5.large", "m5.xlarge", "m5.2xlarge", "m5.4xlarge", "m5.12xlarge", "m5.24xlarge", "m5.metal",
        "m5d.large", "m5d.xlarge", "m5d.2xlarge", "m5d.4xlarge", "m5d.12xlarge", "m5d.24xlarge", "m5d.metal",
        "m5a.large", "m5a.xlarge","m5a.2xlarge", "m5a.4xlarge", "m5a.12xlarge", "m5a.24xlarge",
        "m4.large", "m4.xlarge", "m4.2xlarge", "m4.4xlarge", "m4.10xlarge", "m4.16xlarge",
        "p2.xlarge", "p2.8xlarge", "p2.16xlarge",
        "p3.2xlarge", "p3.8xlarge", "p3.16xlarge",
        "p3dn.24xlarge",
        "r3.large", "r3.xlarge", "r3.2xlarge", "r3.4xlarge", "r3.8xlarge",
        "r4.large", "r4.xlarge", "r4.2xlarge", "r4.4xlarge", "r4.8xlarge", "r4.16xlarge",
        "r5.large", "r5.xlarge","r5.2xlarge", "r5.4xlarge", "r5.12xlarge", "r5.24xlarge", "r5.metal",
        "r5d.large", "r5d.xlarge", "r5d.2xlarge", "r5d.4xlarge", "r5d.12xlarge", "r5d.24xlarge", "r5d.metal",
        "r5a.large", "r5a.xlarge", "r5a.2xlarge", "r5a.4xlarge", "r5a.12xlarge", "r5a.24xlarge",
        "t2.large", "t2.xlarge", "t2.2xlarge",
        "t3.large", "t3.xlarge", "t3.2xlarge",
        "t3a.large", "t3a.xlarge", "t3a.2xlarge",
        "u-6tb1.metal", "u-9tb1.metal", "u-12tb1.metal",
        "x1e.xlarge", "x1e.2xlarge", "x1e.4xlarge", "x1e.8xlarge", "x1e.16xlarge", "x1e.32xlarge",
        "x1.16xlarge", "x1.32xlarge",
        "z1d.large","z1d.xlarge", "z1d.2xlarge", "z1d.3xlarge", "z1d.6xlarge", "z1d.12xlarge", "z1d.metal"
      ],
      "Default": "m4.large"
    },
    "ASInstances" : {
      "Description" : "Number of ArcGIS Server EC2 instances.",
      "Type" : "Number",
      "MinValue" : "1",
      "Default" : "2"
    },
    "KeyName" : {
      "Description" : "EC2 Key Pair to allow RemoteDesktop access to the instances",
      "Type" : "AWS::EC2::KeyPair::KeyName"
    },
    "StoreType": {
      "Description": "ArcGIS Server config store type",
      "Type": "String",
      "AllowedValues": ["CloudStore", "FileSystem"],
      "Default": "FileSystem"
    }, 
    "ServerLicenseFile": {
      "Description": "ArcGIS for Server authorization file (must be uploaded to DeploymentBucket)",
      "Type": "String",
      "AllowedPattern": "^([/\\w\\-\\.]+)+\\.(ecp|prvc)$",
      "ConstraintDescription": "License file name must be alphanumeric. It can contain dash ('-'), dot ('.'), and underscore ('_') characters. The file name must end with '.ecp' or '.prvc'."
    },
    "SiteAdmin" : {
      "Description" : "User name for ArcGIS Server site admin account",
      "Type" : "String",
      "Default" : "admin",
      "AllowedPattern": "^[a-zA-Z][a-zA-Z0-9_]{4,}$",
      "ConstraintDescription": "User name must be 4 or more alphanumeric or underscore (_) characters and must start with a letter."
    },
    "SiteAdminPassword" : {
      "Description" : "Password for the site admin account",
      "Type" : "String",
      "NoEcho" : "true",
      "AllowedPattern": "^[a-zA-Z0-9_\\.@]{8,}$",
      "ConstraintDescription": "Password must be 8 or more alphanumeric, underscore (_), at ('@'), or dot (.) characters."
    },
    "RunAsUserPassword" : {
      "Description" : "Password for ArcGIS Server account",
      "Type" : "String",
      "NoEcho" : "true",
      "AllowedPattern": "(?!.*arcgis)(?!.*Arc)(?!.*GIS)(?!.*user)(?!.*account)^((?=.*[a-z])(?=.*[A-Z])(?=.*\\d)|(?=.*[a-z])(?=.*[A-Z])(?=.*[^A-Za-z0-9])|(?=.*[a-z])(?=.*\\d)(?=.*[^A-Za-z0-9])|(?=.*[A-Z])(?=.*\\d)(?=.*[^A-Za-z0-9]))([A-Za-z\\d@#$%&�*\\-_+=\\[\\]{}|:\\',?~();!]|\\.(?!@)){8,}$",
      "ConstraintDescription": "Password must be at least eight characters in length and must contain characters from three of the following four categories: English uppercase characters (A through Z), English lowercase characters (a through z), digits (0 through 9), non-alphabetic characters (for example, !, $, #, %). Password must not contain backslashes (\\) or quotation marks (\"). Password must not contain the user's account name (arcgis) or parts of the user's full name (ArcGIS user account) that exceed two consecutive characters."
    },
    "ELBName": {
      "Description": "Name of an existing ELB or 'NEW_ELB' to create and use a new one.",
      "Type": "String",
      "Default" : "NEW_ELB"
    },
    "SSLCertificateARN": {
      "Description": "ARN of the SSL certificate issued to the site domain (not required if an existing ELB is used)",
      "Type": "String",
      "Default" : "",
      "ConstraintDescription": "arn:aws:acm:<region>:<account-id>:certificate/<resource>"
    },
    "DBEngine": {
      "Description": "RDS engine",
      "Type": "String",
      "AllowedValues": ["none", "sqlserver-se", "postgres", "aurora-postgresql"],
      "Default": "none"
    },
    "DBInstanceClass": {
      "Description": "The RDS instance class",
      "Type": "String",
      "AllowedValues": [
        "db.m3.medium", "db.m3.large", "db.m3.xlarge", "db.m3.2xlarge",
        "db.m4.large", "db.m4.xlarge", "db.m4.2xlarge", "db.m4.4xlarge", "db.m4.10xlarge", "db.m4.16xlarge",
        "db.m5.large", "db.m5.xlarge", "db.m5.2xlarge", "db.m5.4xlarge", "db.m5.12xlarge", "db.m5.24xlarge",
        "db.r3.large", "db.r3.xlarge", "db.r3.2xlarge", "db.r3.4xlarge", "db.r3.8xlarge",
        "db.r4.large", "db.r4.xlarge", "db.r4.2xlarge", "db.r4.4xlarge", "db.r4.8xlarge", "db.r4.16xlarge",
        "db.r5.large", "db.r5.xlarge", "db.r5.2xlarge", "db.r5.4xlarge", "db.r5.12xlarge", "db.r5.24xlarge",
        "db.t2.micro", "db.t2.small", "db.t2.medium", "db.t2.large", "db.t2.xlarge", "db.t2.2xlarge",
        "db.t3.micro", "db.t3.small", "db.t3.medium", "db.t3.large", "db.t3.xlarge", "db.t3.2xlarge",
        "db.x1e.xlarge", "db.x1e.2xlarge", "db.x1e.4xlarge", "db.x1e.8xlarge", "db.x1e.16xlarge", "db.x1e.32xlarge"
      ],
      "Default": "db.r4.large"
    },
    "DBAllocatedStorage" : {
      "Description" : "The allocated storage size of RDS instance specified in gigabytes (GB).",
      "Default" : "200",
      "Type" : "Number",
      "MinValue" : "200",
      "MaxValue" : "4096",
      "ConstraintDescription" : "Must be between 200 and 4096."
    },
    "VPCId" : {
      "Description" : "VPC ID",
      "Type" : "AWS::EC2::VPC::Id" 
    },
    "Subnet1" : {
      "Description" : "Subnet 1",
      "Type": "AWS::EC2::Subnet::Id"
    },
    "Subnet2" : {
      "Description" : "Subnet 2",
      "Type": "AWS::EC2::Subnet::Id"
    },
    "PostInstallationScript": {
      "Description": "ZIP archive file with custom post installation script (must be uploaded to DeploymentBucket).",
      "Type": "String",
      "AllowedPattern": "[^\"]{1,1024}",
      "ConstraintDescription": "S3 object key name must be between 1 and 1024 characters.",
      "Default": "none"
    }
  },
  "Metadata" : {
    "AWS::CloudFormation::Interface" : {
      "ParameterGroups" : [ {
        "Label" : { "default" : "Network Configuration" },
        "Parameters" : [ "VPCId", "Subnet1", "Subnet2", "ELBName","SSLCertificateARN" ]
      },
      {
        "Label" : { "default":"Amazon EC2 Configuration" },
        "Parameters" : [ "FSInstanceType", "ASInstanceType", "ASInstances", "DriveSizeRoot", "KeyName", "DBEngine", "DBInstanceClass", "DBAllocatedStorage" ]
      },
      {
        "Label" : { "default":"ArcGIS Enterprise Configuration" },
        "Parameters" : [ "DeploymentBucket", "ServerLicenseFile", "StoreType", "SiteAdmin", "SiteAdminPassword", "RunAsUserPassword" ]
      } ]
    }
  },
  "Conditions" : {
    "CreateDBInstance" : {"Fn::Or" : [{"Fn::Equals" : [{"Ref" : "DBEngine"}, "sqlserver-se"]},
                                      {"Fn::Equals" : [{"Ref" : "DBEngine"}, "postgres"]}]},
    "DBEngineSQLServer" : {"Fn::Equals" : [{"Ref" : "DBEngine"}, "sqlserver-se"]},
    "DBEnginePostgres" : {"Fn::Equals" : [{"Ref" : "DBEngine"}, "postgres"]},
    "DBEngineAurora" : {"Fn::Equals" : [{"Ref" : "DBEngine"}, "aurora-postgresql"]},
    "CreateDHCPOptions" : {"Fn::Equals" : [{"Ref" : "AWS::Region"}, "us-east-1"]},
    "UseCloudStore" : {"Fn::Equals" : [{"Ref" : "StoreType"}, "CloudStore"]},
    "RunPostInstall" : {"Fn::Not" : [{"Fn::Equals" : [{"Ref" : "PostInstallationScript"}, "none"]}]},
    "SSMSupported" : {"Fn::Not" : [{"Fn::Or": [{"Fn::Equals" : [{"Ref" : "AWS::Region"}, "eu-west-2"]},
                                               {"Fn::Equals" : [{"Ref" : "AWS::Region"}, "ap-south-1"]},
                                               {"Fn::Equals" : [{"Ref" : "AWS::Region"}, "ca-central-1"]}]}]},
    "NewELB" : {"Fn::Equals" : [{"Ref" : "ELBName"}, "NEW_ELB"]}
  },
  "Resources" : {
    "ValidateParametersFunction": {
      "Type": "AWS::Lambda::Function",
      "DependsOn": "IAMRole",
      "Properties": {
          "Code": {
          "S3Bucket": {"Fn::Join" : ["", ["arcgisstore107", "-", {"Ref": "AWS::Region"}]]},
          "S3Key": "10450/lambda/arcgis-cfn-lambda-python3.zip"
        },
        "Handler": "parameters.handler",
        "Runtime": "python3.8",
        "Timeout": "300",
        "Role": { "Fn::GetAtt" : ["LambdaExecutionRole", "Arn"] }
      }
    },
    "StopStackFunction": {
      "Type": "AWS::Lambda::Function",
      "DependsOn": "IAMRole",
      "Properties": {
        "Code": {
          "S3Bucket": {"Fn::Join" : ["", ["arcgisstore107", "-", {"Ref": "AWS::Region"}]]},
          "S3Key": "10450/lambda/arcgis-cfn-lambda-python3.zip"
        },
        "Environment" : {
          "Variables" : {
            "StackName" : {"Ref" : "AWS::StackName"}
          }
        }, 
        "Handler": "stop_start.stop_server_stack",
        "Runtime": "python3.8",
        "Timeout": "300",
        "Role": {"Fn::GetAtt" : ["LambdaExecutionRole", "Arn"]},
        "Description" : "Stops all EC2 instances of the CloudFormation stack"
      }
    },
    "StartStackFunction": {
      "Type": "AWS::Lambda::Function",
      "DependsOn": "IAMRole",
      "Properties": {
        "Code": {
          "S3Bucket": {"Fn::Join" : ["", ["arcgisstore107", "-", {"Ref": "AWS::Region"}]]},
          "S3Key": "10450/lambda/arcgis-cfn-lambda-python3.zip"
        },
        "Environment" : {
          "Variables" : {
            "StackName" : {"Ref" : "AWS::StackName"}
          }
        }, 
        "Handler": "stop_start.start_server_stack",
        "Runtime": "python3.8",
        "Timeout": "300",
        "Role": {"Fn::GetAtt" : ["LambdaExecutionRole", "Arn"]},
        "Description" : "Starts all EC2 instances of the CloudFormation stack"
      }
    },
    "GetELBAttributesFunction": {
      "Type": "AWS::Lambda::Function",
      "DependsOn": "IAMRole",
      "Properties": {
        "Code": {
          "S3Bucket": {"Fn::Join" : ["", ["arcgisstore107", "-", {"Ref": "AWS::Region"}]]},
          "S3Key": "10450/lambda/arcgis-cfn-lambda-python3.zip"
        },
        "Handler": "elb_attributes.handler",
        "Runtime": "python3.8",
        "Timeout": "300",
        "Role": {"Fn::GetAtt" : ["LambdaExecutionRole", "Arn"]},
        "Description" : "Retrieves DNSName and source security group name for the specified ELB"
      }
    },
    "ELBAttributes": {
      "Type": "Custom::ELBAttributes",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["GetELBAttributesFunction", "Arn"]},
        "ELBName" : {"Fn::If": ["NewELB", {"Ref" : "ELB"}, {"Ref" :"ELBName"}]},
        "ELBTemplate" : "server",
        "ELBSubnets" : [ {"Ref" : "Subnet1"}, {"Ref" : "Subnet2"} ]
      }
    },
    "ELBInstanceFunction": {
      "Type": "AWS::Lambda::Function",
      "DependsOn": "IAMRole",
      "Properties": {
        "Code": {
          "S3Bucket": {"Fn::Join" : ["", ["arcgisstore107", "-", {"Ref": "AWS::Region"}]]},
          "S3Key": "10450/lambda/arcgis-cfn-lambda-python3.zip"
        },
        "Handler": "elb_instance.handler",
        "Runtime": "python3.8",
        "Timeout": "300",
        "Role": {"Fn::GetAtt" : ["LambdaExecutionRole", "Arn"]},
        "Description" : "Registers EC2 instance with the specified ELB"
      }
    },
    "LambdaExecutionRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [{
            "Effect": "Allow",
            "Principal": {"Service": ["lambda.amazonaws.com"]},
            "Action": ["sts:AssumeRole"]
          }]
        },
        "Path": "/",
        "Policies": [{
          "PolicyName": "root",
          "PolicyDocument": {
            "Version": "2012-10-17",
            "Statement": [{
              "Sid" : "ConfigStoreS3Bucket",
              "Action" : [ "s3:*" ],
              "Effect" : "Allow",
              "Resource" : [ 
                "arn:aws:s3:::arcgis-config-store-*",
                "arn:aws:s3:::arcgis-config-store-*/*" 
              ]
            },
            {
              "Sid" : "DeploymentS3Bucket",
              "Action" : [ 
                "s3:GetObject",
                "s3:GetObjectVersion",
                "s3:GetBucketLocation" 
              ],
              "Effect" : "Allow",
              "Resource" : [ 
                {"Fn::Join" : ["", ["arn:aws:s3:::", {"Ref" : "DeploymentBucket"}]]},
                {"Fn::Join" : ["", ["arn:aws:s3:::", {"Ref" : "DeploymentBucket"}, "/*"]]} 
              ]
            },
            {
              "Sid" : "ConfigStoreDynamoDB",
              "Action" : [ "dynamodb:*" ],
              "Effect" : "Allow",
              "Resource" : [ 
                "arn:aws:dynamodb:*:*:table/ArcGISConfigStores",
                "arn:aws:dynamodb:*:*:table/ArcGISConfigStore.*" 
              ]
            },
            {
              "Sid" : "StopStartEC2",
              "Effect": "Allow",
              "Action": [ "ec2:*" ],
              "Resource": "*",
              "Condition" : {
                  "StringEquals" : {
                      "ec2:ResourceTag/aws:cloudformation:stack-name" : {"Ref" : "AWS::StackName"}
                  }
              }
            },
            {
              "Effect": "Allow",
              "Action": [ 
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents",
                "ec2:DescribeSecurityGroups", 
                "ec2:DescribeInstances",
                "ec2:DescribeInstanceStatus",
                "cloudformation:DescribeStackResource",
                "autoscaling:DescribeAutoScalingGroups",
                "autoscaling:UpdateAutoScalingGroup",
                "autoscaling:AttachInstances",
                "autoscaling:DetachInstances",
                "elasticloadbalancing:DescribeLoadBalancers" 
              ],
              "Resource": "*"
            }]
          }
        }]
      }
    },
    "ValidateServerLicenseFile": {
      "Type": "Custom::ValidateParameters",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["ValidateParametersFunction", "Arn"]},
        "DeploymentBucket": {"Ref": "DeploymentBucket"},
        "S3Key": {"Ref": "ServerLicenseFile"}
      }
    },
    "ValidatePostInstallationScript": {
      "Type": "Custom::ValidateParameters",
      "Condition": "RunPostInstall",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["ValidateParametersFunction", "Arn"]},
        "DeploymentBucket": {"Ref": "DeploymentBucket"},
        "S3Key": {"Ref": "PostInstallationScript"}
      }
    },
    "ServerConfigStoreFunction": {
      "Type": "AWS::Lambda::Function",
      "DependsOn": "IAMRole",
      "Properties": {
        "Code": {
          "S3Bucket": {"Fn::Join" : ["", ["arcgisstore107", "-", {"Ref": "AWS::Region"}]]},
          "S3Key": "10450/lambda/arcgis-cfn-lambda-python3.zip"
        },
        "Handler": "server_config_store.handler",
        "Runtime": "python3.8",
        "Timeout": "30",
        "Role": { "Fn::GetAtt" : ["LambdaExecutionRole", "Arn"] }
      }
    },
    "ServerConfigStore": {
      "Type": "Custom::ServerConfigStore",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["ServerConfigStoreFunction", "Arn"]},
        "Namespace": {"Fn::Join" : ["", [{"Ref" : "AWS::StackName"}]]}
      }
    },
    "ELB" : {
      "Type" : "AWS::ElasticLoadBalancing::LoadBalancer",
      "Condition": "NewELB",
      "Properties" : {
        "Subnets" : [ {"Ref" : "Subnet1"}, {"Ref" : "Subnet2"} ],
        "SecurityGroups" : [ {"Ref" : "ELBSecurityGroup"} ],
        "Scheme" : "internet-facing",
        "Listeners" : [ {
          "LoadBalancerPort" : "80",
          "InstancePort" : "6080",
          "Protocol" : "HTTP"
        }, {
          "LoadBalancerPort" : "443",
          "InstancePort" : "6443",
          "Protocol" : "HTTPS",
          "InstanceProtocol" : "HTTPS",
          "SSLCertificateId" : {"Ref" : "SSLCertificateARN"}
        } ],
        "HealthCheck" : {
          "Target" : "HTTPS:6443/arcgis/rest/info/healthcheck",
          "HealthyThreshold" : "3",
          "UnhealthyThreshold" : "5",
          "Interval" : "30",
          "Timeout" : "5"
        }
      }
    },
    "IAMRole" : {
      "Type" : "AWS::IAM::Role",
      "Properties" : {
        "AssumeRolePolicyDocument" : {
          "Statement" : [ {
            "Effect" : "Allow",
            "Principal" : {
              "Service" : [ "ec2.amazonaws.com", "ssm.amazonaws.com" ]
            },
            "Action" : [ "sts:AssumeRole" ]
          } ]
        },
        "Path" : "/"
      }
    },
    "IAMPolicy" : {
      "Type" : "AWS::IAM::Policy",
      "DependsOn" : "LambdaExecutionRole",
      "Properties" : {
        "PolicyName" : "IAMRole",
        "PolicyDocument" : {
          "Version": "2012-10-17",
          "Statement" : [ 
          {
            "Sid" : "ConfigStoreS3Bucket",
            "Action" : [ "s3:*" ],
            "Effect" : "Allow",
            "Resource" : [ 
              "arn:aws:s3:::arcgis-config-store-*",
              "arn:aws:s3:::arcgis-config-store-*/*" 
            ]
          },
          {
            "Sid" : "DeploymentS3Bucket",
            "Action" : [ "s3:GetObject" ],
            "Effect" : "Allow",
            "Resource" : [
              {"Fn::Join" : ["", ["arn:aws:s3:::", {"Ref" : "DeploymentBucket"}, "/*"]]}
            ]
          },
          {
            "Sid" : "ConfigStoreDynamoDB",
            "Action" : [ "dynamodb:*" ],
            "Effect" : "Allow",
            "Resource" : [
              "arn:aws:dynamodb:*:*:table/ArcGISConfigStores",
              "arn:aws:dynamodb:*:*:table/ArcGISConfigStore.*" 
            ]
          },
          {
            "Action" : [ 
              "cloudformation:SignalResource",
              "cloudformation:DescribeStackResource",
              "ssm:DescribeAssociation",
              "ssm:GetDeployablePatchSnapshotForInstance",
              "ssm:GetDocument",
              "ssm:GetManifest",
              "ssm:GetParameters",
              "ssm:ListAssociations",
              "ssm:ListInstanceAssociations",
              "ssm:PutInventory",
              "ssm:PutComplianceItems",
              "ssm:PutConfigurePackageResult",
              "ssm:UpdateAssociationStatus",
              "ssm:UpdateInstanceAssociationStatus",
              "ssm:UpdateInstanceInformation",
              "ssmmessages:CreateControlChannel",
              "ssmmessages:CreateDataChannel",
              "ssmmessages:OpenControlChannel",
              "ssmmessages:OpenDataChannel",
              "ec2messages:AcknowledgeMessage",
              "ec2messages:DeleteMessage",
              "ec2messages:FailMessage",
              "ec2messages:GetEndpoint",
              "ec2messages:GetMessages",
              "ec2messages:SendReply",
              "cloudwatch:PutMetricData",
              "ec2:DescribeInstanceStatus",
              "ds:CreateComputer",
              "ds:DescribeDirectories",
              "logs:CreateLogGroup",
              "logs:CreateLogStream",
              "logs:DescribeLogGroups",
              "logs:DescribeLogStreams",
              "logs:PutLogEvents"
            ],
            "Effect" : "Allow",
            "Resource":"*"
          },
          {
            "Sid" : "SSMAgentS3",
            "Effect": "Allow",
            "Action": "s3:GetObject",
            "Resource": [
              "arn:aws:s3:::aws-ssm-*/*",
              "arn:aws:s3:::aws-windows-downloads-*/*",
              "arn:aws:s3:::amazon-ssm-packages-*/*",
              "arn:aws:s3:::*-birdwatcher-prod/*"
            ]
          } ]
        },
        "Roles" : [ {
          "Ref" : "IAMRole"
        } ]
      }
    },
    "IAMInstanceProfile" : {
      "Type" : "AWS::IAM::InstanceProfile",
      "Properties" : {
        "Path" : "/",
        "Roles" : [ {
          "Ref" : "IAMRole"
        } ]
      }
    },
    "ELBSecurityGroup" : {
      "Type" : "AWS::EC2::SecurityGroup",
      "Condition": "NewELB",
      "Properties" : {
        "GroupDescription" : {"Ref" : "AWS::StackName"},
        "VpcId" : {"Ref" : "VPCId"},
        "SecurityGroupIngress" : [ {
          "IpProtocol" : "tcp",
          "FromPort" : "80",
          "ToPort" : "80",
          "CidrIp" : "0.0.0.0/0"
        }, {
          "IpProtocol" : "tcp",
          "FromPort" : "443",
          "ToPort" : "443",
          "CidrIp" : "0.0.0.0/0"
        } ]
      }
    },
    "SecurityGroup" : {
      "Type" : "AWS::EC2::SecurityGroup",
      "Properties" : {
        "GroupDescription" : {"Ref" : "AWS::StackName"},
        "VpcId" : {"Ref" : "VPCId"},
        "SecurityGroupIngress" : [ {
          "IpProtocol" : "tcp",
          "FromPort" : "6080",
          "ToPort" : "6080",
          "SourceSecurityGroupId" : {"Fn::If": ["NewELB", {"Ref" : "ELBSecurityGroup"}, {"Fn::GetAtt" : ["ELBAttributes", "SourceSecurityGroupId"]}]}
        }, {
          "IpProtocol" : "tcp",
          "FromPort" : "6443",
          "ToPort" : "6443",
          "SourceSecurityGroupId" : {"Fn::If": ["NewELB", {"Ref" : "ELBSecurityGroup"}, {"Fn::GetAtt" : ["ELBAttributes", "SourceSecurityGroupId"]}]}
        } ]
      }
    },
    "SecurityGroupIngress" : {
      "Type" : "AWS::EC2::SecurityGroupIngress",
      "Properties" : {
        "GroupId" : {"Ref" : "SecurityGroup"},
        "IpProtocol" : "tcp",
        "FromPort" : "0",
        "ToPort" : "65535",
        "SourceSecurityGroupId" : {"Ref" : "SecurityGroup"}
      }
    },
    "FileServerEC2Instance" : {
      "Type" : "AWS::EC2::Instance",
      "Properties" : {
        "ImageId" : {"Fn::FindInMap" : ["RegionMap", {"Ref":"AWS::Region"}, "en"]},
        "InstanceType" : {"Ref":"FSInstanceType"},
        "KeyName" : {"Ref":"KeyName"},
        "IamInstanceProfile" : {"Ref":"IAMInstanceProfile"},
        "Monitoring" : true,
        "BlockDeviceMappings": [ {
          "DeviceName": "/dev/sda1",
          "Ebs": {
            "VolumeSize": {"Ref": "DriveSizeRoot"},
            "DeleteOnTermination": true,
            "VolumeType": "gp2"
          }
        }, {
          "DeviceName": "xvdg",
          "NoDevice": {}
        },
        {"DeviceName": "xvdca", "NoDevice": {}}, {"DeviceName": "xvdcb", "NoDevice": {}},
        {"DeviceName": "xvdcc", "NoDevice": {}}, {"DeviceName": "xvdcd", "NoDevice": {}},
        {"DeviceName": "xvdce", "NoDevice": {}}, {"DeviceName": "xvdcf", "NoDevice": {}},
        {"DeviceName": "xvdcg", "NoDevice": {}}, {"DeviceName": "xvdch", "NoDevice": {}},
        {"DeviceName": "xvdci", "NoDevice": {}}, {"DeviceName": "xvdcj", "NoDevice": {}},
        {"DeviceName": "xvdck", "NoDevice": {}}, {"DeviceName": "xvdcl", "NoDevice": {}},
        {"DeviceName": "xvdcm", "NoDevice": {}}, {"DeviceName": "xvdcn", "NoDevice": {}},
        {"DeviceName": "xvdco", "NoDevice": {}}, {"DeviceName": "xvdcp", "NoDevice": {}},
        {"DeviceName": "xvdcq", "NoDevice": {}}, {"DeviceName": "xvdcr", "NoDevice": {}},
        {"DeviceName": "xvdcs", "NoDevice": {}}, {"DeviceName": "xvdct", "NoDevice": {}},
        {"DeviceName": "xvdcu", "NoDevice": {}}, {"DeviceName": "xvdcv", "NoDevice": {}},
        {"DeviceName": "xvdcw", "NoDevice": {}}, {"DeviceName": "xvdcx", "NoDevice": {}},
        {"DeviceName": "xvdcy", "NoDevice": {}}, {"DeviceName": "xvdcz", "NoDevice": {}}],
        "Tags" : [{"Key" : "Name", "Value" : {"Fn::Join" : ["", [{"Ref" : "AWS::StackName"}, "-fileserver"]]}}],
        "NetworkInterfaces" : [{
          "GroupSet" : [ {"Ref" : "SecurityGroup"} ],
          "AssociatePublicIpAddress" : "true",
          "DeviceIndex" : "0",
          "DeleteOnTermination" : "true",
          "SubnetId" : {"Ref" : "Subnet1"}}],
        "UserData" : {
          "Fn::Base64" : {
            "Fn::Join" : [
              "",
              [
                "<powershell>\r\n",
                "try \r\n",
                "{  \r\n",
                "  if (", {"Fn::If": ["RunPostInstall", "$true", "$false"]}, ") {\r\n",
                "    cfn-init -v -c post-install-script -s ", {"Ref": "AWS::StackName"}, " -r CloudWatchSettings", " --region ", {"Ref": "AWS::Region"}, "\r\n",
                "  } \r\n",
                "  $stackName   = '", {"Ref": "AWS::StackName"}, "' \r\n",
                "  $region      = '", {"Ref": "AWS::Region"}, "' \r\n",
                "  $waitHandle  = '", {"Ref": "FileServerWaitHandle"}, "' \r\n",
                "  $InstanceName = 'FileServerEC2Instance' \r\n",
                "  $NodeJSONPath = 'C:\\\\chef\\\\node.json' \r\n",
                "  $ChefLogFile  = 'C:\\\\chef\\\\chef-run.log' \r\n",
                "  $execName = \"cfn-init\" \r\n",
                "  $execArgs = \"-v -s $stackName -r CloudWatchSettings --region $region\" \r\n",
                "  $process = Start-Process $execName -PassThru -Wait -ArgumentList $execArgs.Split(' ') \r\n",
                "  if ($process.ExitCode -ne 0) { \r\n",
                "    throw \"Process 'cfn-init' exit code : $($process.ExitCode)\"   \r\n",
                "  } \r\n",
                " \r\n",
                "  $execArgs = \"-v -s $stackName -r $InstanceName --region $region\" \r\n",
                "  $process = Start-Process $execName -PassThru -Wait -ArgumentList $execArgs.Split(' ') \r\n",
                "  if ($process.ExitCode -ne 0) { \r\n",
                "    throw \"Process 'cfn-init' exit code : $($process.ExitCode)\" \r\n",
                "  } \r\n",
                " \r\n",
                "  $process = Start-Process chef-solo -PassThru -Wait  -ArgumentList (\"-j\", $NodeJSONPath, \"-L\",$ChefLogFile, \"-l\", \"info\") \r\n",
                "  if ($process.ExitCode -ne 0) { \r\n",
                "    throw \"Chef run failed. See 'C:\\\\chef\\\\chef-run.log' for details.\" \r\n",
                "  } \r\n",
                " \r\n",
                "  $process = Start-Process cfn-signal -PassThru -Wait -ArgumentList $waitHandle \r\n",
                "  if ($process.ExitCode -ne 0) { \r\n",
                "    throw \"Process 'cfn-signal' exit code : $($process.ExitCode)\" \r\n",
                "  } \r\n",
                "}   \r\n",
                "catch  \r\n",
                "{  \r\n",
                "  Write-Output \"ERROR: $($_.Exception.Message)\"  \r\n",
                "  cfn-signal -e 1  -r \"$($_.Exception.Message)\" \"$WaitHandle\"  \r\n",
                "}  \r\n",
                "</powershell>\r\n"
              ]
            ]
          }
        }
      },
      "Metadata" : {
        "AWS::CloudFormation::Authentication" : {
          "S3AccessCreds" : {
            "type" : "S3",
            "buckets" : [ {
              "Ref" : "DeploymentBucket"
            } ],
            "roleName" : {
              "Ref" : "IAMRole"
            }
          }
        },
        "AWS::CloudFormation::Init" : {
          "config" : {
            "commands": {
              "rename-server-license" : {
                "command": {"Fn::Join": ["", [
                  "md \"C:\\Temp\\", {"Ref": "ServerLicenseFile"}, 
                  "\" & rmdir \"C:\\Temp\\", {"Ref": "ServerLicenseFile"}, 
                  "\" & move C:\\Temp\\server_license.tmp \"C:\\Temp\\", {"Ref": "ServerLicenseFile"}, "\""
                ]]}
              }
            },
            "files" : {
              "C:\\Temp\\server_license.tmp": {
                "source": {"Fn::GetAtt": [ "ValidateServerLicenseFile", "S3ObjectURL" ]},
                "authentication": "S3AccessCreds"
              },
              "C:\\chef\\node.json" : {
                "content" : {
                  "Fn::Join" : ["", [
                  "{\r\n",
                  "  \"arcgis\" : {\r\n",
                  "    \"version\": \"10.7\",\r\n",
                  "    \"run_as_password\" : \"", {"Ref" : "RunAsUserPassword"}, "\",\r\n",
                  "    \"post_install_script\" : \"C:\\\\PostInstallScripts\\\\deploy.bat\",\r\n",
                  "    \"hosts\" : {\r\n",
                  "       \"FILESERVER\" : \"\",\r\n",
                  "       \"SITEHOST\" : \"\"\r\n",
                  "    },\r\n",
                  "    \"server\" : {\r\n",
                  "      \"admin_username\" : \"", {"Ref" : "SiteAdmin"}, "\",\r\n",
                  "      \"admin_password\" : \"", {"Ref" : "SiteAdminPassword" }, "\",\r\n",
                  "      \"authorization_file\" : \"C:\\\\Temp\\\\", {"Ref": "ServerLicenseFile"}, "\",\r\n",
                  "      \"log_level\" : \"WARNING\",\r\n",
                  "      \"soc_max_heap_size\" : 64,\r\n",
                  "      \"local_directories_root\" : \"C:\\\\arcgisserver\",\r\n",
                  "      \"directories_root\" : \"\\\\\\\\FILESERVER\",\r\n",
                  "      \"log_dir\" : \"C:\\\\arcgisserver\\\\logs\",\r\n",
                  "      \"unregister_machine\" : true,\r\n",
                  "      \"config_store_type\" : \"", {"Fn::If": ["UseCloudStore", "AMAZON", "FILESYSTEM"]}, "\",\r\n",
                  "      \"config_store_connection_string\" : \"", {"Fn::If": ["UseCloudStore",
                         {"Fn::Join" : ["", ["NAMESPACE=", {"Ref" : "AWS::StackName"}, ";REGION=", { "Ref" : "AWS::Region" } ]]},
                         "\\\\\\\\FILESERVER\\\\config-store"]}, "\"\r\n",
                  "    },\r\n",
                  "    \"egdb\" : {\r\n",
                  "      \"engine\" : \"", {"Fn::If": ["DBEngineAurora", "postgres", {"Ref" : "DBEngine"}]}, "\",\r\n",
                  "      \"endpoint\" : \"", {"Fn::If": ["CreateDBInstance", {"Fn::GetAtt": [ "DBInstance", "Endpoint.Address" ]},
                                             {"Fn::If": ["DBEngineAurora", {"Fn::GetAtt": [ "AuroraDBCluster", "Endpoint.Address" ]}, "" ]} ]}, "\",\r\n",
                  "      \"master_username\" : \"EsriRDSAdmin\",\r\n",
                  "      \"master_password\" : \"", {"Ref" : "SiteAdminPassword" }, "\"\r\n",
                  "    }\r\n",
                  "  },\r\n",
                  "  \"run_list\" : [\r\n",
                  "    \"recipe[arcgis-enterprise::system]\",\r\n",
                  "    \"recipe[arcgis-enterprise::fileserver]\",\r\n",
                  "    \"recipe[esri-iis]\",\r\n",
                  "    \"recipe[arcgis-enterprise::server]\",\r\n",
                  "    \"recipe[arcgis-egdb::sql_alias]\",\r\n",
                  "    \"recipe[arcgis-egdb]\",\r\n",
                  "    \"recipe[arcgis-enterprise::stop_server]\",\r\n",
                  "    \"recipe[arcgis-enterprise::start_server]\",\r\n",
                  "    \"recipe[arcgis-enterprise::post_install]\"]\r\n",
                  "}\r\n"]]
                }
              },
              "C:\\chef\\unregister_machine.json" : {
                "content" : {
                  "Fn::Join" : ["", [
                  "{\r\n",
                  "  \"arcgis\" : {\r\n",
                  "    \"version\": \"10.7\",\r\n",
                  "    \"server\" : {\r\n",
                  "      \"admin_username\" : \"", {"Ref" : "SiteAdmin"}, "\",\r\n",
                  "      \"admin_password\" : \"", {"Ref" : "SiteAdminPassword" }, "\"\r\n",
                  "    }\r\n",
                  "  },\r\n",
                  "  \"run_list\" : [\r\n",
                  "    \"recipe[arcgis-enterprise::unregister_machine]\"]\r\n",
                  "}\r\n"]]
                }
              }
            }
          }
        }
      }
    },
    "FileServerRecoveryAlarm" : {
      "Type" : "AWS::CloudWatch::Alarm",
      "Properties" : {
        "AlarmDescription" : "Trigger a recovery when instance status check fails for 5 consecutive minutes.",
        "MetricName" : "StatusCheckFailed_System",
        "Namespace" : "AWS/EC2",
        "Statistic" : "Minimum",
        "Period" : "60",
        "EvaluationPeriods" : "5",
        "Threshold" : "0",
        "ComparisonOperator" : "GreaterThanThreshold",
        "AlarmActions" : [ {"Fn::Join" : ["", ["arn:", {"Ref" : "AWS::Partition"}, ":automate:", { "Ref" : "AWS::Region" }, ":ec2:recover" ]]} ],
        "Dimensions" : [ {
          "Name" : "InstanceId",
          "Value" : {"Ref" : "FileServerEC2Instance"}
        } ]
      }
    },
    "LaunchConfig" : {
      "Type" : "AWS::AutoScaling::LaunchConfiguration",
      "DependsOn" : "FileServerWaitCondition",
      "Properties" : {
        "AssociatePublicIpAddress" : true,
        "ImageId" : {"Fn::FindInMap" : ["RegionMap", {"Ref":"AWS::Region"}, "en"]},
        "InstanceType" : {"Ref" : "ASInstanceType"},
        "KeyName" : {"Ref" : "KeyName"},
        "IamInstanceProfile" : {"Ref" : "IAMInstanceProfile"},
        "SecurityGroups" : [ {"Ref": "SecurityGroup" } ],
        "InstanceMonitoring" : true,
        "BlockDeviceMappings": [ {
          "DeviceName": "/dev/sda1",
          "Ebs": {
            "VolumeSize": {"Ref": "DriveSizeRoot"},
            "DeleteOnTermination": true,
            "VolumeType": "gp2"
          }
        }],
        "UserData" : {
          "Fn::Base64" : {
            "Fn::Join" : [
              "",
              [
                "<powershell>\r\n",
                "try \r\n",
                "{  \r\n",
                "  if (", {"Fn::If": ["RunPostInstall", "$true", "$false"]}, ") {\r\n",
                "    cfn-init -v -c post-install-script -s ", {"Ref": "AWS::StackName"}, " -r CloudWatchSettings", " --region ", {"Ref": "AWS::Region"}, "\r\n",
                "  } \r\n",
                "  $stackName   = '", {"Ref": "AWS::StackName"}, "' \r\n",
                "  $region      = '", {"Ref": "AWS::Region"}, "' \r\n",
                "  $waitHandle  = '", {"Ref": "AutoScalingGroupWaitHandle"}, "' \r\n",
                "  $InstanceName = 'LaunchConfig' \r\n",
                "  $NodeJSONPath = 'C:\\\\chef\\\\node.json' \r\n",
                "  $ChefLogFile  = 'C:\\\\chef\\\\chef-run.log' \r\n",
                "  $execName = \"cfn-init\" \r\n",
                "  $execArgs = \"-v -s $stackName -r CloudWatchSettings --region $region\" \r\n",
                "  $process = Start-Process $execName -PassThru -Wait -ArgumentList $execArgs.Split(' ') \r\n",
                "  if ($process.ExitCode -ne 0) { \r\n",
                "    throw \"Process 'cfn-init' exit code : $($process.ExitCode)\"   \r\n",
                "  } \r\n",
                " \r\n",
                "  $execArgs = \"-v -s $stackName -r $InstanceName --region $region\" \r\n",
                "  $process = Start-Process $execName -PassThru -Wait -ArgumentList $execArgs.Split(' ') \r\n",
                "  if ($process.ExitCode -ne 0) { \r\n",
                "    throw \"Process 'cfn-init' exit code : $($process.ExitCode)\" \r\n",
                "  } \r\n",
                " \r\n",
                "  $process = Start-Process chef-solo -PassThru -ArgumentList (\"-j\", $NodeJSONPath, \"-L\",$ChefLogFile, \"-l\", \"info\") \r\n",
                "  $handle = $process.Handle\r\n",
                "  $process.WaitForExit()\r\n",
                "  if ($process.ExitCode -ne 0) { \r\n",
                "    throw \"Chef run failed. See 'C:\\\\chef\\\\chef-run.log' for details.\" \r\n",
                "  } \r\n",
                " \r\n",
                "  $process = Start-Process cfn-signal -PassThru -Wait -ArgumentList $waitHandle \r\n",
                "  if ($process.ExitCode -ne 0) { \r\n",
                "    throw \"Process 'cfn-signal' exit code : $($process.ExitCode)\" \r\n",
                "  } \r\n",
                "}   \r\n",
                "catch  \r\n",
                "{  \r\n",
                "  Write-Output \"ERROR: $($_.Exception.Message)\"  \r\n",
                "  cfn-signal -e 1  -r \"$($_.Exception.Message)\" \"$WaitHandle\"  \r\n",
                "}  \r\n",
                "</powershell>\r\n"
              ]
            ]
          }
        }
      },
      "Metadata" : {
        "AWS::CloudFormation::Authentication" : {
          "S3AccessCreds" : {
            "type" : "S3",
            "buckets" : [ {"Ref" : "DeploymentBucket"} ],
            "roleName" : {"Ref" : "IAMRole"}
          }
        },
        "AWS::CloudFormation::Init" : {
          "config" : {
            "commands": {
              "rename-server-license" : {
                "command": {"Fn::Join": ["", [
                  "md \"C:\\Temp\\", {"Ref": "ServerLicenseFile"}, 
                  "\" & rmdir \"C:\\Temp\\", {"Ref": "ServerLicenseFile"}, 
                  "\" & move C:\\Temp\\server_license.tmp \"C:\\Temp\\", {"Ref": "ServerLicenseFile"}, "\""
                ]]}
              }
            },
            "files" : {
              "C:\\Temp\\server_license.tmp": {
                "source": {"Fn::GetAtt": [ "ValidateServerLicenseFile", "S3ObjectURL" ]},
                "authentication": "S3AccessCreds"
              },
              "C:\\chef\\node.json" : {
                "content" : {
                  "Fn::Join" : [ "", [
                    "{\r\n",
                    "  \"arcgis\" : {\r\n",
                    "    \"version\": \"10.7\",\r\n",
                    "    \"run_as_password\" : \"", {"Ref" : "RunAsUserPassword"}, "\",\r\n",
                    "    \"post_install_script\" : \"C:\\\\PostInstallScripts\\\\deploy.bat\",\r\n",
                    "    \"hosts\" : {\r\n",
                    "       \"FILESERVER\" : \"", {"Fn::GetAtt" : [ "FileServerEC2Instance", "PrivateIp" ]}, "\",\r\n",
                    "       \"SITEHOST\" : \"", {"Fn::GetAtt" : [ "FileServerEC2Instance", "PrivateIp" ]}, "\"\r\n",
                    "    },\r\n",
                    "    \"server\" : {\r\n",
                    "      \"admin_username\" : \"", {"Ref" : "SiteAdmin"}, "\",\r\n",
                    "      \"admin_password\" : \"", {"Ref" : "SiteAdminPassword" }, "\",\r\n",
                    "      \"authorization_file\" : \"C:\\\\Temp\\\\", {"Ref": "ServerLicenseFile"}, "\",\r\n",
                    "      \"use_join_site_tool\" : true,\r\n",
                    "      \"soc_max_heap_size\" : 64,\r\n",
                    "      \"config_store_type\" : \"", {"Fn::If": ["UseCloudStore", "AMAZON", "FILESYSTEM"]}, "\",\r\n",
                    "      \"config_store_connection_string\" : \"", {"Fn::If": ["UseCloudStore",
                      {"Fn::Join" : ["", ["NAMESPACE=", {"Ref" : "AWS::StackName"}, ";REGION=", { "Ref" : "AWS::Region" } ]]},
                      "\\\\\\\\FILESERVER\\\\config-store"]}, "\"\r\n",
                    "    },\r\n",
                    "    \"egdb\" : {\r\n",
                    "      \"engine\" : \"", {"Fn::If": ["DBEngineAurora", "postgres", {"Ref" : "DBEngine"}]}, "\",\r\n",
                    "      \"endpoint\" : \"", {"Fn::If": ["CreateDBInstance", {"Fn::GetAtt": [ "DBInstance", "Endpoint.Address" ]},
                                             {"Fn::If": ["DBEngineAurora", {"Fn::GetAtt": [ "AuroraDBCluster", "Endpoint.Address" ]}, "" ]} ]}, "\"\r\n",
                    "    }\r\n",
                    "  },\r\n",
                    "  \"run_list\" : [\r\n",
                    "    \"recipe[arcgis-enterprise::system]\",\r\n",
                    "    \"recipe[esri-iis]\",\r\n",
                    "    \"recipe[arcgis-egdb::sql_alias]\",\r\n",
                    "    \"recipe[arcgis-enterprise::server_node]\",\r\n",
                    "    \"recipe[arcgis-enterprise::stop_server]\",\r\n",
                    "    \"recipe[arcgis-enterprise::start_server]\",\r\n",
                    "    \"recipe[arcgis-enterprise::post_install]\"]\r\n",
                    "}\r\n" ] ]
                }
              }
            }
          }
        }
      }
    },
    "AutoScalingGroup" : {
      "Type" : "AWS::AutoScaling::AutoScalingGroup",
      "DependsOn" : "FileServerEC2Instance",
      "Properties" : {
        "VPCZoneIdentifier" : [ {"Ref" : "Subnet1"}, {"Ref" : "Subnet2"} ],
        "Cooldown" : "300",
        "MaxSize" : {"Ref" : "ASInstances"},
        "MinSize" : {"Ref" : "ASInstances"},
        "LaunchConfigurationName" : {"Ref" : "LaunchConfig"},
        "HealthCheckType" : "EC2",
        "HealthCheckGracePeriod" : "3600",
        "LoadBalancerNames" : [ {"Fn::If": ["NewELB", {"Ref" : "ELB"}, {"Ref" :"ELBName"}]} ],
        "Tags" : [ {
          "Key" : "Name",
          "Value" : {"Fn::Join" : ["", [{"Ref" : "AWS::StackName"}, "-node"]]},
          "PropagateAtLaunch" : true
        } ]
      },
      "UpdatePolicy": {
        "AutoScalingReplacingUpdate": {
          "WillReplace": "true"
        }
      }
    },
    "FileServerWaitHandle" : {
      "Type" : "AWS::CloudFormation::WaitConditionHandle",
      "Properties" : {}
    },
    "FileServerWaitCondition" : {
      "Type" : "AWS::CloudFormation::WaitCondition",
      "Properties" : {
        "Count" : "1",
        "Handle" : {"Ref" : "FileServerWaitHandle"},
        "Timeout" : "7200"
      }
    },
    "AutoScalingGroupWaitHandle" : {
      "Type" : "AWS::CloudFormation::WaitConditionHandle",
      "Properties" : {}
    },
    "AutoScalingGroupWaitCondition" : {
      "Type" : "AWS::CloudFormation::WaitCondition",
      "Properties" : {
        "Count" : {"Ref" : "ASInstances"},
        "Handle" : {"Ref" : "AutoScalingGroupWaitHandle"},
        "Timeout" : "10800"
      }
    },
    "DeploymentLogs": {
      "Type": "AWS::Logs::LogGroup",
      "Properties": {
        "RetentionInDays": 7
      }
    },
    "CloudWatchSettings" : {
      "Type" : "AWS::Logs::MetricFilter",
      "Properties": {
        "LogGroupName": {"Ref": "DeploymentLogs"},
        "FilterPattern": "[level=FATAL, message]",
        "MetricTransformations": [{
           "MetricValue": "1",
           "MetricNamespace": "ArcGIS/Deployment",
           "MetricName": "ErrorCount"
        }]
      },
      "Metadata" : {
        "AWS::CloudFormation::Authentication": {
          "S3AccessCreds": {
            "type": "S3",
            "buckets": [{"Ref": "DeploymentBucket"}],
            "roleName": {"Ref": "IAMRole"}
          }
        },
        "AWS::CloudFormation::Init" : {
          "configSets" : {
            "default": ["config"],
            "post-install-script": ["post-install-config"]
          },
          "post-install-config": {
            "sources" : {
              "C:\\PostInstallScripts" : {"Fn::If": ["RunPostInstall", {"Fn::GetAtt": [ "ValidatePostInstallationScript", "S3ObjectURL" ]}, ""]}
            }
          },
          "config" : {
            "sources" : {
              "C:\\chef" : "https://arcgisstore107.s3.amazonaws.com/10450/cookbooks/arcgis-3.3.0-cookbooks.zip",
              "C:\\Program Files\\Amazon\\cfn-bootstrap" : "https://arcgisstore1061.s3.amazonaws.com/endpoints.zip"
            },
            "files": {
              "C:\\Program Files\\Amazon\\SSM\\Plugins\\awsCloudWatch\\AWS.EC2.Windows.CloudWatch.json": {
                "content": {
                  "Fn::Join" : ["", [
                  "{\r\n",
                  "  \"IsEnabled\" : true,\r\n",
                  "  \"EngineConfiguration\": {\r\n",
                  "    \"PollInterval\": \"00:00:15\",\r\n",
                  "    \"Components\": [\r\n",
                  "    {\r\n",
                  "      \"Id\": \"CfnInitLogStream\",\r\n",
                  "      \"FullName\": \"AWS.EC2.Windows.CloudWatch.CloudWatchLogsOutput,AWS.EC2.Windows.CloudWatch\",\r\n",
                  "      \"Parameters\": {\r\n",
                  "        \"Region\": \"", {"Ref" : "AWS::Region"}, "\",\r\n",
                  "        \"LogGroup\": \"", {"Ref": "DeploymentLogs"}, "\",\r\n",
                  "        \"LogStream\": \"{instance_id}/cfn-init.log\"\r\n",
                  "      }\r\n",
                  "    },\r\n",
                  "    {\r\n",
                  "      \"Id\": \"ChefRunLogStream\",\r\n",
                  "      \"FullName\": \"AWS.EC2.Windows.CloudWatch.CloudWatchLogsOutput,AWS.EC2.Windows.CloudWatch\",\r\n",
                  "      \"Parameters\": {\r\n",
                  "        \"Region\": \"", {"Ref" : "AWS::Region"}, "\",\r\n",
                  "        \"LogGroup\": \"", {"Ref": "DeploymentLogs"}, "\",\r\n",
                  "        \"LogStream\": \"{instance_id}/chef-run.log\"\r\n",
                  "      }\r\n",
                  "    },\r\n",
                  "    {\r\n",
                  "      \"Id\": \"CfnInitLogs\",\r\n",
                  "      \"FullName\": \"AWS.EC2.Windows.CloudWatch.CustomLog.CustomLogInputComponent,AWS.EC2.Windows.CloudWatch\",\r\n",
                  "      \"Parameters\": {\r\n",
                  "        \"LogDirectoryPath\": \"C:\\\\cfn\\\\log\",\r\n",
                  "        \"TimestampFormat\": \"yyyy-MM-dd HH:mm:ss,fff\",\r\n",
                  "        \"Encoding\": \"UTF-8\",\r\n",
                  "        \"Filter\": \"cfn-init.log\",\r\n",
                  "        \"CultureName\": \"en-US\",\r\n",
                  "        \"TimeZoneKind\": \"Local\",\r\n",
                  "        \"LineCount\": \"1\"\r\n",
                  "      }\r\n",
                  "    },\r\n",
                  "    {\r\n",
                  "      \"Id\": \"ChefRunLogs\",\r\n",
                  "      \"FullName\": \"AWS.EC2.Windows.CloudWatch.CustomLog.CustomLogInputComponent,AWS.EC2.Windows.CloudWatch\",\r\n",
                  "      \"Parameters\": {\r\n",
                  "        \"LogDirectoryPath\": \"C:\\\\chef\",\r\n",
                  "        \"TimestampFormat\": \"[yyyy-MM-ddTHH:mm:sszzz]\",\r\n",
                  "        \"Encoding\": \"UTF-8\",\r\n",
                  "        \"Filter\": \"chef-run.log\",\r\n",
                  "        \"CultureName\": \"en-US\",\r\n",
                  "        \"TimeZoneKind\": \"Local\",\r\n",
                  "        \"LineCount\": \"1\"\r\n",
                  "      }\r\n",
                  "    }],\r\n",
                  "    \"Flows\": {\r\n",
                  "      \"Flows\":[\"CfnInitLogs,CfnInitLogStream\",\"ChefRunLogs,ChefRunLogStream\"]\r\n",
                  "    }\r\n",
                  "  }\r\n",
                  "}\r\n"]]
                 }
               }
             },
             "commands": {
                "0-enableSSM" : {
                  "command" : "powershell.exe -Command \"Set-Service -Name AmazonSSMAgent -StartupType Automatic\" ",
                  "waitAfterCompletion" : "0"
                },
                "1-restartSSM": {
                  "command" : "powershell.exe -Command \"Restart-Service AmazonSSMAgent \"",
                  "waitAfterCompletion" : "30"
                }
             }
          }
        }
      }
    },
    "DBSubnetGroup" : {
      "Type" : "AWS::RDS::DBSubnetGroup",
      "Properties" : {
        "DBSubnetGroupDescription" : "DB subnet group",
        "SubnetIds" : [ {"Ref": "Subnet1"}, {"Ref": "Subnet2"} ],
        "Tags" : [{"Key" : "Name", "Value" : {"Fn::Join" : ["", [{"Ref" : "AWS::StackName"}, "-db"]]}}]
      }
    },
    "DBInstance" : {
      "Type" : "AWS::RDS::DBInstance",
      "Condition": "CreateDBInstance",
      "Properties" : {
        "AllocatedStorage" : {"Ref": "DBAllocatedStorage"},
        "DBInstanceClass" : {"Ref" : "DBInstanceClass"},
        "Engine" : {"Ref": "DBEngine"},
        "EngineVersion" : {"Fn::FindInMap" : ["DBEngineProperties", {"Ref": "DBEngine"}, "Version"]},
        "LicenseModel": {"Fn::FindInMap" : ["DBEngineProperties", {"Ref": "DBEngine"}, "License"]},
        "MultiAZ" : {"Fn::If": ["DBEnginePostgres", "true", {"Ref": "AWS::NoValue"}]},
        "DBSubnetGroupName": {"Ref": "DBSubnetGroup"},
        "VPCSecurityGroups": [{"Ref" : "SecurityGroup"}],
        "StorageType": "gp2",
        "MasterUsername" : "EsriRDSAdmin",
        "MasterUserPassword" : { "Ref" : "SiteAdminPassword" },
        "Tags" : [{"Key" : "Name", "Value" : {"Fn::Join" : ["", [{"Ref" : "AWS::StackName"}, "-db"]]}}]
      }
    },
    "AuroraDBInstance" : {
      "Type" : "AWS::RDS::DBInstance",
      "Condition": "DBEngineAurora",
      "Properties" : {
        "DBInstanceClass" : {"Ref" : "DBInstanceClass"},
        "DBClusterIdentifier" : {"Ref" : "AuroraDBCluster"},
        "Engine" : {"Ref": "DBEngine"},
        "Tags" : [{"Key" : "Name", "Value" : {"Fn::Join" : ["", [{"Ref" : "AWS::StackName"}, "-db"]]}}]
      }
    },
    "AuroraDBCluster" : {
      "Type" : "AWS::RDS::DBCluster",
      "Condition": "DBEngineAurora",
      "Properties" : {
        "DBSubnetGroupName": {"Ref": "DBSubnetGroup"},
        "DBClusterParameterGroupName" : {"Ref" : "AuroraDBClusterParameterGroup"},
        "Engine" : {"Ref": "DBEngine"},
        "EngineVersion" : {"Fn::FindInMap" : ["DBEngineProperties", {"Ref": "DBEngine"}, "Version"]},
        "MasterUsername" : "EsriRDSAdmin",
        "MasterUserPassword" : { "Ref" : "SiteAdminPassword" },
        "Port" : 5432,
        "Tags" : [{"Key" : "Name", "Value" : {"Fn::Join" : ["", [{"Ref" : "AWS::StackName"}, "-db"]]}}],
        "VpcSecurityGroupIds" : [{"Ref" : "SecurityGroup"}]
      }
    },
    "AuroraDBClusterParameterGroup" : {
      "Type" : "AWS::RDS::DBClusterParameterGroup",
      "Condition": "DBEngineAurora",
      "Properties" : {
        "Description" : "Aurora postgresql 9.6 engine parameters",
        "Family" : "aurora-postgresql9.6",
        "Parameters" : {
          "client_encoding" : "UTF8"
        },
        "Tags" : [{"Key" : "Name", "Value" : {"Fn::Join" : ["", [{"Ref" : "AWS::StackName"}, "-db"]]}}]      }
    },
    "UnregisterMachineCommand" : {
      "Type" : "AWS::SSM::Document",
      "Properties" : {
        "Content" : {
          "schemaVersion" : "1.0",
          "description" : "Unregisters the machine from ArcGIS Server site.",
          "runtimeConfig" : {
            "aws:psModule" : {
              "properties" : [
                {
                  "runCommand" : "chef-solo -j C:\\chef\\unregister_machine.json"
                }
              ]
            }
          }
        }
      }
    },
    "UnregisterFileServer" : {
      "Type" : "AWS::SSM::Association",
      "DependsOn" : "AutoScalingGroupWaitCondition",
      "Properties" : {
        "Name" : {"Ref" : "UnregisterMachineCommand"},
        "Targets" : [ {
          "Key": "InstanceIds",
          "Values": [ {"Ref" : "FileServerEC2Instance"} ]
        } ]
      }
    }
  },
  "Outputs" : {
    "ManagerURL" : {
      "Value" : {"Fn::Join" : [ "", [ "https://", {"Fn::GetAtt" : ["ELBAttributes", "DNSName"]}, "/arcgis/manager" ]]},
      "Description" : "ArcGIS Server Manager URL"
    },
    "RestURL" : {
      "Value" : {"Fn::Join" : [ "", [ "https://", {"Fn::GetAtt" : ["ELBAttributes", "DNSName"]}, "/arcgis/rest" ]]},
      "Description" : "ArcGIS REST Services Directory URL"
    },
    "LogsURL" : {
      "Value" : {"Fn::Join" : [ "", [ "https://console.aws.amazon.com/cloudwatch/home?region=", {"Ref" : "AWS::Region"}, "#logStream:group=", {"Ref" : "DeploymentLogs"}]]},
      "Description" : "Deployment Logs"
    },
    "DNSName" : {
      "Description" : "Elastic load balancer DNS name",
      "Value" : {"Fn::GetAtt" : ["ELBAttributes", "DNSName"]}
    },
    "StopStackFunction": {
      "Value" : {"Fn::Join": ["", [ "https://console.aws.amazon.com/lambda/home?region=", {"Ref": "AWS::Region"}, "#/functions/", {"Ref": "StopStackFunction"} ] ]},
      "Description" : "Lambda function used to stop all EC2 instances in the stack."
    },
    "StartStackFunction": {
      "Value" : {"Fn::Join": ["", [ "https://console.aws.amazon.com/lambda/home?region=", {"Ref": "AWS::Region"}, "#/functions/", {"Ref": "StartStackFunction"} ] ]},
      "Description" : "Lambda function used to start all EC2 instances in the stack."
    },
    "VPCId" : {
      "Value" :  {"Ref" : "VPCId"},
      "Description" : "VPC ID"
    },
    "Subnet1" : {
      "Value" :  {"Ref" : "Subnet1"},
      "Description" : "VPC subnet 1" 
    },
    "Subnet2" : {
      "Value" :  {"Ref" : "Subnet2"},
      "Description" : "VPC subnet 2" 
    },
    "DeploymentBucket" : {
      "Value" :  {"Ref" : "DeploymentBucket"},
      "Description" : "Deployment S3 bucket"
    },
    "SecurityGroup" : {
      "Value" :  {"Ref" : "SecurityGroup"},
      "Description" : "Security group"
    },
    "ELBName" : {
      "Value" :  {"Fn::If": ["NewELB", {"Ref" : "ELB"}, {"Ref" :"ELBName"}]},
      "Description" : "ELB name"
    },
    "FileServerEC2InstancePrivateIp" : {
      "Value" :  { "Fn::GetAtt" : [ "FileServerEC2Instance", "PrivateIp" ] },
      "Description" : "Private IP address of the file server EC2 instance"
    },
    "StoreType" : {
      "Value" :  {"Ref" : "StoreType" },
      "Description" : "ArcGIS Server config store type"
    }
  }
}
