{
  "AWSTemplateFormatVersion" : "2010-09-09",
  "Description" : "ArcGIS CloudFormation Template: Provisions a ArcGIS site with Portal for ArcGIS, ArcGIS Server, ArcGIS Data Store and ArcGIS Web Adaptor on an EC2 instance running Windows Server 2012 R2. **WARNING** You will be billed by AWS for the AWS resources if you create a stack from this template.",
  "Mappings" : {
    "RegionMap" : {
      "us-gov-west-1" : { "en" : "ami-53442470", "jp" : "ami-53442470"}
    }
  },
  "Parameters" : {
    "DeploymentBucket" : {
      "Description" : "S3 bucket for license files and SSL certificates",
      "Type" : "String",
      "AllowedPattern" : "[a-zA-Z][0-9a-zA-Z-_.]{2,62}",
      "ConstraintDescription" : "S3 bucket name must be between 3 and 63 characters and and must start with a letter."
    },
    "InstanceType" : {
      "Description" : "The EC2 instance type",
      "Type" : "String",
      "AllowedValues" : ["m3.medium","m3.large","m3.xlarge","m3.2xlarge",

                         "c3.large","c3.xlarge","c3.2xlarge","c3.4xlarge","c3.8xlarge",

                         "cc2.8xlarge",
                         "r3.large","r3.xlarge","r3.2xlarge","r3.4xlarge","r3.8xlarge",

                         "i2.xlarge","i2.2xlarge","i2.4xlarge","i2.8xlarge","hs1.8xlarge"],
      "Default" : "m3.xlarge"
    },
    "KeyName" : {
      "Description" : "The EC2 KeyPair to allow remote access to the instances",
      "Type" : "AWS::EC2::KeyPair::KeyName"
    },
    "ServerLicenseFile" : {
      "Description" : "ArcGIS for Server authorization file (must be uploaded to DeploymentBucket)",
      "Type" : "String",
      "AllowedPattern" : "[^\"]{1,1024}",
      "ConstraintDescription" : "S3 object key name must be between 1 and 1024 characters."
    },
    "PortalLicenseFile" : {
      "Description" : "Portal for ArcGIS authorization file (must be uploaded to DeploymentBucket)",
      "Type" : "String",
      "AllowedPattern" : "[^\"]{1,1024}",
      "ConstraintDescription" : "S3 object key name must be between 1 and 1024 characters."
    },
    "SiteAdmin" : {
      "Description" : "User name for ArcGIS Server site admin and Portal initial admin accounts",
      "Type" : "String",
      "Default" : "admin",
      "AllowedPattern" : "[0-9a-zA-Z.]{4,24}",
      "ConstraintDescription" : "User name must be between 4 and 24 character and can only contain digits 0 through 9, ASCII letters A through Z (uppercase and lowercase), and a dot (.)."
    },
    "SiteAdminPassword" : {
      "Description" : "Password for the site admin account",
      "Type" : "String",
      "NoEcho" : "true",
      "AllowedPattern" : "[0-9a-zA-Z.]{4,24}",
      "ConstraintDescription" : "Password must be between 4 and 24 character and can only contain digits 0 through 9, ASCII letters A through Z (uppercase and lowercase), and a dot (.)."
    },
    "SiteEIPAllocationID" : {
      "Description" : "Allocation ID of Elastic IP address for VPC (eipalloc-XXXXXXXX)",
      "Type" : "String",
      "AllowedPattern" : "eipalloc-.*"
    },
    "SiteDomain" : {
      "Description" : "The domain name of your ArcGIS site",
      "Type" : "String",
      "AllowedPattern" : "[^\"]{1,1024}",
      "ConstraintDescription" : "The domain name is invalid."
    },
    "SSLCertificateFile" : {
      "Description" : "SSL certificate file issued to the site domain (must be uploaded to DeploymentBucket)",
      "Type" : "String",
      "AllowedPattern" : "[^\"]{1,1024}",
      "ConstraintDescription" : "S3 object key name must be between 1 and 1024 characters."
    },
    "SSLCertPassword" : {
      "Description" : "SSL certificate file password",
      "Type" : "String",
      "NoEcho" : "true",
      "AllowedPattern" : "[^\"]{1,1024}",
      "ConstraintDescription" : "The SSL certificate file password is invalid."
    }
  },
  "Resources" : {
    "VPC" : {
      "Type" : "AWS::EC2::VPC",
      "Properties" : {
        "CidrBlock" : "10.0.0.0/16",
        "Tags" : [{"Key" : "Application", "Value" : {"Ref":"AWS::StackName"}},
                  {"Key" : "Network", "Value" : "Public"}]
      }
    },
    "Subnet1" : {
      "Type" : "AWS::EC2::Subnet",
      "Properties" : {
        "VpcId" : {"Ref" : "VPC"},
        "CidrBlock" : "10.0.0.0/24",
        "AvailabilityZone" : {"Fn::Select" : [0, {"Fn::GetAZs" : ""}]},
        "Tags" : [{"Key" : "Application", "Value" : {"Ref":"AWS::StackName"}},
                  {"Key" : "Network", "Value" : "Public"}]
      }
    },
    "InternetGateway" : {
      "Type" : "AWS::EC2::InternetGateway",
      "Properties" : {
        "Tags" : [ {"Key" : "Application", "Value" : {"Ref":"AWS::StackName"}}, 
                   {"Key" : "Network", "Value" : "Public"} ]
      }
    },
    "AttachGateway" : {
      "Type" : "AWS::EC2::VPCGatewayAttachment",
      "Properties" : {
        "VpcId" : {"Ref":"VPC"},
        "InternetGatewayId" : {"Ref":"InternetGateway"}
      }
    },
    "RouteTable" : {
      "Type" : "AWS::EC2::RouteTable",
      "Properties" : {"VpcId" : {"Ref" : "VPC"},
        "Tags" : [ {"Key" : "Application", "Value" : {"Ref" : "AWS::StackName"}}, 
                   {"Key" : "Network", "Value" : "Public"} ]
      }
    },
    "Route" : {
      "Type" : "AWS::EC2::Route",
      "Properties" : {
        "RouteTableId" : {"Ref":"RouteTable"},
        "DestinationCidrBlock" : "0.0.0.0/0",
        "GatewayId" : {"Ref":"InternetGateway"}
      }
    },
    "Subnet1RouteTableAssociation" : {
      "Type" : "AWS::EC2::SubnetRouteTableAssociation",
      "Properties" : {
        "SubnetId" : {"Ref":"Subnet1"},
        "RouteTableId" : {"Ref" : "RouteTable"}
      }
    },
    "EC2SecurityGroup" : {
      "Type" : "AWS::EC2::SecurityGroup",
      "Properties" : {
        "GroupDescription" : {"Ref":"AWS::StackName"},
        "VpcId" : {"Ref":"VPC"},
        "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"
          }
        ]
      }
    },
    "EIPAssociation" : {
      "Type" : "AWS::EC2::EIPAssociation",
      "DependsOn" : "WaitCondition",
      "Properties" : {
        "AllocationId" : {"Ref" : "SiteEIPAllocationID"},
        "InstanceId" : {"Ref" : "AllInOneEC2Instance"}
      }
    },
    "IAMRole" : {
      "Type" : "AWS::IAM::Role",
      "Properties" : {
        "AssumeRolePolicyDocument" : {
          "Statement" : [
            {
              "Effect" : "Allow",
              "Principal" : {"Service" : ["ec2.amazonaws.com"]},
              "Action":["sts:AssumeRole"]
            }
          ]
        },
        "Path" : "/"
      }
    },
    "IAMPolicy" : {
      "Type" : "AWS::IAM::Policy",
      "Properties" : {
        "PolicyName" : "IAMRole",
        "PolicyDocument" : {
          "Statement" : [
            {
              "Action" : "s3:GetObject",
              "Effect" : "Allow",
              "Resource" : "arn:aws-us-gov:s3:::*"
            }
          ]
        },
        "Roles":[{"Ref":"IAMRole"}]
      }
    },
    "IAMInstanceProfile" : {
      "Type" : "AWS::IAM::InstanceProfile",
      "Properties" : {
        "Path" : "/",
        "Roles" : [{"Ref":"IAMRole"}]
      },
      "Metadata" : {
        "AWS::CloudFormation::Init" : {
          "config" : {
            "sources" : {
              "C:\\chef" : "https://s3.amazonaws.com/esriarcgisserverrepository/10.3.1/cookbooks/arcgis-1.1.0-cookbooks.zip"
            }
          }
        }
      }
	},
    "AllInOneEC2Instance" : {
      "Type" : "AWS::EC2::Instance",
      "Properties" : {
        "ImageId" : {"Fn::FindInMap" : ["RegionMap", {"Ref":"AWS::Region"}, "en"]},
        "InstanceType" : {"Ref":"InstanceType"},
        "KeyName" : {"Ref":"KeyName"},
        "IamInstanceProfile" : {"Ref":"IAMInstanceProfile"},
        "Tags" : [{"Key" : "Name", "Value" : "allinone"}],
        "Monitoring" : true,
        "NetworkInterfaces" : [{
          "PrivateIpAddress" : "10.0.0.5",
          "GroupSet" : [{"Ref" : "EC2SecurityGroup"}],
          "AssociatePublicIpAddress" : "true",
          "DeviceIndex" : "0",
          "DeleteOnTermination" : "true",
          "SubnetId" : {"Ref" : "Subnet1"}}],
        "UserData" : {
          "Fn::Base64" : {
            "Fn::Join" : ["", [
                "<powershell>\r\n",
				"try \r\n",
				"{  \r\n",
				"  $stackName   = '", {"Ref" : "AWS::StackName"}, "' \r\n",
				"  $region      = '", {"Ref" : "AWS::Region"}, "' \r\n",
				"  $waitHandle  = '", {"Ref" : "WaitHandle"}, "' \r\n",
				"  $setupScript = 'C:\\chef\\scripts\\esriVMSetup.ps1' \r\n",
				"  $InstanceName = 'AllInOneEC2Instance' \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 IAMInstanceProfile --region $region\" \r\n",
				"  Write-Output \"Executing : $execName\" \r\n",
				"  Write-Output \"Arguments : $execArgs\"  \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",
				"  . \"$setupScript\" -n 'EC2UserScriptTask' -s $stackName -r $region -w $waitHandle -i $InstanceName -j $NodeJSONPath -l $ChefLogFile \r\n",
				"   \r\n",
				"  Write-Output \"UserScript : completed\"  \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" : ["", [ "move C:\\Temp\\server_license.tmp C:\\Temp\\", {"Ref" : "ServerLicenseFile"} ]]}
              },
              "rename-portal-license" : {
                "command" : {"Fn::Join" : ["", [ "move C:\\Temp\\portal_license.tmp C:\\Temp\\", {"Ref" : "PortalLicenseFile"} ]]}
              }
            }, 
            "files" : {
              "C:\\Temp\\server_license.tmp" : {
                "source" : {"Fn::Join" : ["", [ "https://s3-us-gov-west-1.amazonaws.com/", {"Ref" : "DeploymentBucket"}, "/", {"Ref" : "ServerLicenseFile"} ]]},
                "authentication" : "S3AccessCreds"
              },
              "C:\\Temp\\portal_license.tmp" : {
                "source" : {"Fn::Join" : ["", [ "https://s3-us-gov-west-1.amazonaws.com/", {"Ref" : "DeploymentBucket"}, "/", {"Ref" : "PortalLicenseFile"} ]]},
                "authentication" : "S3AccessCreds"
              },
              "C:\\Temp\\keystore.pfx" : {
                "source" : {"Fn::Join" : ["", [ "https://s3-us-gov-west-1.amazonaws.com/", {"Ref" : "DeploymentBucket"}, "/", {"Ref" : "SSLCertificateFile"} ]]},
                "authentication" : "S3AccessCreds"
              },
              "C:\\chef\\node.json" : {
                "content" : { 
                  "Fn::Join" : ["", [
                  "{\r\n",
                  "  \"iis\" : {\r\n",
                  "    \"keystore_file\" : \"C:\\\\Temp\\\\keystore.pfx\",\r\n",
                  "    \"keystore_password\" : \"", {"Ref" : "SSLCertPassword"}, "\"\r\n",
                  "  },\r\n",
                  "  \"server\" : {\r\n",
                  "    \"domain_name\" : \"", {"Ref" : "SiteDomain"}, "\",\r\n",
                  "    \"admin_username\" : \"", {"Ref" : "SiteAdmin"}, "\",\r\n",
                  "    \"admin_password\" : \"", {"Ref" : "SiteAdminPassword"}, "\",\r\n",
                  "    \"directories_root\" : \"D:\\\\arcgisserver\",\r\n",
                  "    \"authorization_file\" : \"C:\\\\Temp\\\\", {"Ref" : "ServerLicenseFile"}, "\"\r\n",
                  "  },\r\n",
                  "  \"data_store\" : {\r\n",
                  "    \"data_dir\" : \"D:\\\\arcgisdatastore\\\\data\"\r\n",
                  "  },\r\n",
                  "  \"portal\" : {\r\n",
                  "    \"domain_name\" : \"", {"Ref" : "SiteDomain"}, "\",\r\n",
                  "    \"admin_username\" : \"", {"Ref" : "SiteAdmin"}, "\",\r\n",
                  "    \"admin_password\" : \"", {"Ref" : "SiteAdminPassword"}, "\",\r\n",
                  "    \"content_dir\" : \"D:\\\\arcgisportal\\\\content\",\r\n",                  
                  "    \"authorization_file\" : \"C:\\\\Temp\\\\", {"Ref" : "PortalLicenseFile"}, "\"\r\n",
                  "  },\r\n",
                  "  \"run_list\" : [\n",
                  "    \"recipe[arcgis::system]\",\n",
                  "    \"recipe[arcgis::iis]\",\n",
                  "    \"recipe[arcgis::server]\",\n", 
                  "    \"recipe[arcgis::server_wa]\",\n",
                  "    \"recipe[arcgis::datastore]\",\n",
                  "    \"recipe[arcgis::portal]\",\n", 
                  "    \"recipe[arcgis::portal_wa]\",\n",
                  "    \"recipe[arcgis::federation]\"]\r\n",
                  "}\r\n"]]
                }
              }
            }
          }
        }
      }
    },
    "WaitHandle" : {
      "Type" : "AWS::CloudFormation::WaitConditionHandle",
      "Properties" : {}
    },
    "WaitCondition" : {
      "Type" : "AWS::CloudFormation::WaitCondition",
      "Properties" : {
        "Handle" : { "Ref" : "WaitHandle" },
        "Timeout" : "7200"
      }
    }
  },
  "Outputs" : {
    "AdminURL" : {
      "Value" : {"Fn::Join":["", ["https://", {"Ref" : "SiteDomain"}, "/server/manager"]]},
      "Description" : "ArcGIS Server Administrator Directory URL"
    },
    "RestURL" : {
      "Value" : {"Fn::Join":["", ["https://", {"Ref" : "SiteDomain"}, "/server/rest"]]},
      "Description":"ArcGIS REST Services Directory URL"
    },
    "PortalURL" : {
      "Value" : {"Fn::Join":["", ["https://", {"Ref" : "SiteDomain"}, "/portal/home"]]},
      "Description" : "Portal for ArcGIS Home URL"
    }
  }
}
