{
"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. **WARNING** You will be billed by AWS for the AWS resources if you create a stack from this template.",
"Mappings" : {
"RegionMap" : {
"ap-northeast-1": {
"en": "ami-0f1e8569"
},
"ap-northeast-2": {
"en": "ami-0a7ede64"
},
"ap-south-1": {
"en": "ami-5f7f2830"
},
"ap-southeast-1": {
"en": "ami-bc5321c0"
},
"ap-southeast-2": {
"en": "ami-386b965a"
},
"ca-central-1": {
"en": "ami-cca124a8"
},
"eu-central-1": {
"en": "ami-29b82546"
},
"eu-west-1": {
"en": "ami-a68d10df"
},
"eu-west-2": {
"en": "ami-6878630c"
},
"sa-east-1": {
"en": "ami-6c96d400"
},
"us-east-1": {
"en": "ami-1a507560"
},
"us-east-2": {
"en": "ami-917b51f4"
},
"us-west-1": {
"en": "ami-e0c1c280"
},
"us-west-2": {
"en": "ami-edc87e95"
}
}
},
"Parameters": {
"DeploymentBucket": {
"Description": "S3 bucket for license files and SSL certificates",
"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. "
},
"DriveSizeData": {
"Default": "100",
"Description": " The size of the D: Drive in GB. ",
"Type": "Number",
"MinValue": "10",
"MaxValue": "1024",
"ConstraintDescription": " Must be between 10 and 1024 GB. "
},
"InstanceType": {
"Description": "The EC2 instance type",
"Type": "String",
"AllowedValues": [
"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",
"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",
"r3.large", "r3.xlarge", "r3.2xlarge", "r3.4xlarge", "r3.8xlarge",
"r4.large", "r4.xlarge", "r4.2xlarge", "r4.4xlarge", "r4.8xlarge", "r4.16xlarge",
"t2.large", "t2.xlarge", "t2.2xlarge",
"x1.16xlarge", "x1.32xlarge"
],
"Default": "m4.xlarge"
},
"BDSInstanceType": {
"Description": "Spatio-temporal Big Data Store EC2 instance type",
"Type": "String",
"AllowedValues": [
"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",
"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",
"r3.large", "r3.xlarge", "r3.2xlarge", "r3.4xlarge", "r3.8xlarge",
"r4.large", "r4.xlarge", "r4.2xlarge", "r4.4xlarge", "r4.8xlarge", "r4.16xlarge",
"t2.large", "t2.xlarge", "t2.2xlarge",
"x1.16xlarge", "x1.32xlarge"
],
"Default": "m4.xlarge"
},
"BDSInstances" : {
"Description" : "Number of spatio-temporal Big Data Store EC2 instances",
"Type" : "Number",
"Default" : "0",
"AllowedValues" : [0, 1]
},
"KeyName": {
"Description": "The EC2 KeyPair to allow remote access to the instances",
"Type": "AWS::EC2::KeyPair::KeyName"
},
"StoreType": {
"Description": "ArcGIS Server config store and Portal for ArcGIS content store type",
"Type": "String",
"AllowedValues": ["CloudStore", "FileSystem"],
"Default": "FileSystem"
},
"ServerLicenseFile": {
"Description": "ArcGIS 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'."
},
"PortalLicenseFile": {
"Description": "Portal for ArcGIS 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 and Portal initial admin accounts",
"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."
},
"SiteEIPAllocationID": {
"Description": "Allocation ID of Elastic IP address for VPC (eipalloc-XXXXXXXX)",
"Type": "String",
"AllowedPattern": "eipalloc-.*"
},
"RunAsUserPassword" : {
"Description" : "Password for ArcGIS account",
"Type" : "String",
"NoEcho" : "true",
"AllowedPattern": "(?!.*arcgis)(?!.*Arc)(?!.*GIS)(?!.*user)(?!.*account)(?=[^\\\\\\\"]{8,})(?=.*?[^\\w\\s])(?=.*?[0-9])(?=.*?[A-Z]).*?[a-z].*",
"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."
},
"SiteDomain": {
"Description": "The domain name of your ArcGIS site",
"Type": "String",
"AllowedPattern": "^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9-]*[a-zA-Z0-9]).)*([a-zA-Z]|[a-zA-Z][a-zA-Z0-9-]*[a-zA-Z0-9])$",
"ConstraintDescription": "The domain name is invalid."
},
"SSLCertificateFile": {
"Description": "SSL certificate file issued to the site domain (must be uploaded to DeploymentBucket)",
"Type": "String",
"AllowedPattern": "^([\\w\\-\\.]+)+\\.(pfx)$",
"ConstraintDescription": "S3 object key name must be between 1 and 1024 characters."
},
"SSLCertPassword": {
"Description": "SSL certificate file password",
"Type": "String",
"NoEcho": "true",
"AllowedPattern": "[^\\\"]{1,128}",
"ConstraintDescription": "Password must be between 1 and 128 characters and must not contain backslashes (\\) or quotation marks (\")."
},
"VPCId" : {
"Description" : "VPC ID",
"Type" : "AWS::EC2::VPC::Id"
},
"Subnet" : {
"Description" : "VPC Subnet ID",
"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", "Subnet", "SiteDomain", "SiteEIPAllocationID" ]
},
{
"Label" : { "default":"Amazon EC2 Configuration" },
"Parameters" : [ "InstanceType", "BDSInstanceType", "BDSInstances", "DriveSizeRoot", "DriveSizeData", "KeyName" ]
},
{
"Label" : { "default":"ArcGIS Enterprise Configuration" },
"Parameters" : [ "DeploymentBucket", "ServerLicenseFile", "PortalLicenseFile", "StoreType", "SiteAdmin", "SiteAdminPassword", "RunAsUserPassword", "SSLCertificateFile", "SSLCertPassword" ]
} ]
}
},
"Conditions" : {
"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"]}]}]}
},
"Resources": {
"ValidateParametersFunction": {
"Type": "AWS::Lambda::Function",
"DependsOn": "IAMRole",
"Properties": {
"Code": {
"S3Bucket": {"Fn::Join" : ["", ["agsstore6", "-", {"Ref": "AWS::Region"}]]},
"S3Key": "8321/lambda/arcgis-cfn-lambda.zip"
},
"Handler": "parameters.handler",
"Runtime": "python2.7",
"Timeout": "300",
"Role": { "Fn::GetAtt" : ["LambdaExecutionRole", "Arn"] }
}
},
"StopStackFunction": {
"Type": "AWS::Lambda::Function",
"DependsOn": "IAMRole",
"Properties": {
"Code": {
"S3Bucket": {"Fn::Join" : ["", ["agsstore6", "-", {"Ref": "AWS::Region"}]]},
"S3Key": "8321/lambda/arcgis-cfn-lambda.zip"
},
"Environment" : {
"Variables" : {
"StackName" : {"Ref" : "AWS::StackName"}
}
},
"Handler": "stop_start.stop_allinone_stack",
"Runtime": "python2.7",
"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" : ["", ["agsstore6", "-", {"Ref": "AWS::Region"}]]},
"S3Key": "8321/lambda/arcgis-cfn-lambda.zip"
},
"Environment" : {
"Variables" : {
"StackName" : {"Ref" : "AWS::StackName"}
}
},
"Handler": "stop_start.start_allinone_stack",
"Runtime": "python2.7",
"Timeout": "300",
"Role": {"Fn::GetAtt" : ["LambdaExecutionRole", "Arn"]},
"Description" : "Starts all EC2 instances of the CloudFormation stack"
}
},
"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": [{
"Effect": "Allow",
"Action": ["logs:CreateLogGroup","logs:CreateLogStream","logs:PutLogEvents"],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": ["dynamodb:*"],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": ["s3:*"],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": ["ec2:*"],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": ["cloudformation:*"],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": ["autoscaling:*"],
"Resource": "*"
}]
}
}]
}
},
"ValidateServerLicenseFile": {
"Type": "Custom::ValidateParameters",
"Properties": {
"ServiceToken": {"Fn::GetAtt": ["ValidateParametersFunction", "Arn"]},
"DeploymentBucket": {"Ref": "DeploymentBucket"},
"S3Key": {"Ref": "ServerLicenseFile"}
}
},
"ValidatePortalLicenseFile": {
"Type": "Custom::ValidateParameters",
"DependsOn": "ValidateServerLicenseFile",
"Properties": {
"ServiceToken": {"Fn::GetAtt": ["ValidateParametersFunction", "Arn"]},
"DeploymentBucket": {"Ref": "DeploymentBucket"},
"S3Key": {"Ref": "PortalLicenseFile"}
}
},
"ValidateSSLCertificateFile": {
"Type": "Custom::ValidateParameters",
"DependsOn": "ValidatePortalLicenseFile",
"Properties": {
"ServiceToken": {"Fn::GetAtt": ["ValidateParametersFunction", "Arn"]},
"DeploymentBucket": {"Ref": "DeploymentBucket"},
"S3Key": {"Ref": "SSLCertificateFile"}
}
},
"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" : ["", ["agsstore6", "-", {"Ref": "AWS::Region"}]]},
"S3Key": "8321/lambda/arcgis-cfn-lambda.zip"
},
"Handler": "server_config_store.handler",
"Runtime": "python2.7",
"Timeout": "30",
"Role": { "Fn::GetAtt" : ["LambdaExecutionRole", "Arn"] }
}
},
"ServerConfigStore": {
"Type": "Custom::ServerConfigStore",
"Properties": {
"ServiceToken": {"Fn::GetAtt": ["ServerConfigStoreFunction", "Arn"]},
"Namespace": {"Fn::Join" : ["", [{"Ref" : "AWS::StackName"}]]}
}
},
"DeploymentLogs": {
"Type": "AWS::Logs::LogGroup",
"DependsOn": "ValidateSSLCertificateFile",
"Properties": {
"RetentionInDays": 7
}
},
"EIPAssociation": {
"Type": "AWS::EC2::EIPAssociation",
"DependsOn": "WaitCondition",
"Properties": {
"AllocationId": {"Ref": "SiteEIPAllocationID"},
"InstanceId": {"Ref": "AllInOneEC2Instance"}
}
},
"IAMRole": {
"Type": "AWS::IAM::Role",
"DependsOn": "LambdaExecutionRole",
"Properties": {
"AssumeRolePolicyDocument": {
"Statement": [ {
"Effect": "Allow",
"Principal": {
"Service": [ "ec2.amazonaws.com", "ssm.amazonaws.com" ]
},
"Action": [ "sts:AssumeRole" ]
} ]
},
"Path": "/"
}
},
"IAMPolicy": {
"Type": "AWS::IAM::Policy",
"Properties": {
"PolicyName": "IAMRole",
"PolicyDocument": {
"Statement": [ {
"Action": [ "s3:*", "dynamodb:*", "cloudformation:*", "logs:*", "ssm:*", "ec2messages:*" ],
"Effect": "Allow",
"Resource": "*"
}
]
},
"Roles": [ {"Ref": "IAMRole"} ]
}
},
"IAMInstanceProfile": {
"Type": "AWS::IAM::InstanceProfile",
"Properties": {
"Path": "/",
"Roles": [ {"Ref": "IAMRole"} ]
}
},
"SecurityGroup" : {
"Type" : "AWS::EC2::SecurityGroup",
"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"
} ]
}
},
"SecurityGroupIngress" : {
"Type" : "AWS::EC2::SecurityGroupIngress",
"Properties" : {
"GroupId" : {"Ref" : "SecurityGroup"},
"IpProtocol" : "tcp",
"FromPort" : "0",
"ToPort" : "65535",
"SourceSecurityGroupId" : {"Ref" : "SecurityGroup"}
}
},
"PortalContent": {
"Type": "AWS::S3::Bucket",
"Condition" : "UseCloudStore",
"DeletionPolicy": "Retain",
"Properties": {
"Tags": [ {
"Key": "Name",
"Value": {"Ref": "AWS::StackName"}
}, {
"Key": "Application",
"Value": "arcgis-allinone-windows"
}]
}
},
"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": {"Ref": "AWS::StackName"}
}, {
"Key": "Application",
"Value": "arcgis-allinone-windows"
}],
"Monitoring": true,
"BlockDeviceMappings": [ {
"DeviceName": "/dev/sda1",
"Ebs": {
"VolumeSize": {"Ref": "DriveSizeRoot"},
"DeleteOnTermination": true,
"VolumeType": "gp2"
}
}, {
"DeviceName": "xvdg",
"Ebs": {
"VolumeSize": {"Ref": "DriveSizeData"},
"DeleteOnTermination": true,
"VolumeType": "gp2"
}
},{
"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": {}
} ],
"NetworkInterfaces": [ {
"GroupSet": [ {"Ref": "SecurityGroup"} ],
"AssociatePublicIpAddress": "true",
"DeviceIndex": "0",
"DeleteOnTermination": "true",
"SubnetId": {"Ref": "Subnet"}
} ],
"UserData": {
"Fn::Base64": {
"Fn::Join": [
"",
[
"\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": "WaitHandle"}, "' \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 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",
"\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::GetAtt": [ "ValidateServerLicenseFile", "S3ObjectURL" ]},
"authentication": "S3AccessCreds"
},
"C:\\Temp\\portal_license.tmp": {
"source": {"Fn::GetAtt": [ "ValidatePortalLicenseFile", "S3ObjectURL" ]},
"authentication": "S3AccessCreds"
},
"C:\\Temp\\keystore.pfx": {
"source": {"Fn::GetAtt": [ "ValidateSSLCertificateFile", "S3ObjectURL" ]},
"authentication": "S3AccessCreds"
},
"C:\\chef\\node.json": {
"content": {
"Fn::Join": [
"",
[
"{\r\n",
" \"arcgis\" : {\r\n",
" \"run_as_password\" : \"", {"Ref" : "RunAsUserPassword"}, "\",\r\n",
" \"post_install_script\" : \"D:\\\\PostInstallScripts\\\\deploy.bat\",\r\n",
" \"hosts\" : {\r\n",
" \"", {"Ref": "SiteDomain"}, "\" : \"\"\r\n",
" },\r\n",
" \"iis\" : {\r\n",
" \"keystore_file\" : \"C:\\\\Temp\\\\keystore.pfx\",\r\n",
" \"keystore_password\" : \"", {"Ref": "SSLCertPassword"}, "\",\r\n",
" \"replace_https_binding\" : true\r\n",
" },\r\n",
" \"server\" : {\r\n",
" \"domain_name\" : \"", {"Ref": "SiteDomain"}, "\",\r\n",
" \"wa_url\" : \"https://", {"Ref": "SiteDomain"}, "/server\",\r\n",
" \"private_url\" : \"https://", {"Ref": "SiteDomain"}, "/server\",\r\n",
" \"web_context_url\" : \"https://", {"Ref": "SiteDomain"}, "/server\",\r\n",
" \"admin_username\" : \"", {"Ref": "SiteAdmin"}, "\",\r\n",
" \"admin_password\" : \"", {"Ref": "SiteAdminPassword"}, "\",\r\n",
" \"directories_root\" : \"D:\\\\arcgisserver\",\r\n",
" \"log_dir\" : \"D:\\\\arcgisserver\\\\logs\",\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" } ]]},
"D:\\\\arcgisserver\\\\config-store"]}, "\",\r\n",
" \"authorization_file\" : \"C:\\\\Temp\\\\", {"Ref": "ServerLicenseFile"}, "\"\r\n",
" },\r\n",
" \"web_adaptor\" : {\r\n",
" \"admin_access\" : true\r\n",
" },\r\n",
" \"data_store\" : {\r\n",
" \"data_dir\" : \"D:\\\\arcgisdatastore\"\r\n",
" },\r\n",
" \"portal\" : {\r\n",
" \"domain_name\" : \"", {"Ref": "SiteDomain"}, "\",\r\n",
" \"wa_url\" : \"https://", {"Ref": "SiteDomain"}, "/portal\",\r\n",
" \"private_url\" : \"https://", {"Ref": "SiteDomain"}, "/portal\",\r\n",
" \"web_context_url\" : \"https://", {"Ref": "SiteDomain"}, "/portal\",\r\n",
" \"admin_username\" : \"", {"Ref": "SiteAdmin"}, "\",\r\n",
" \"admin_password\" : \"", {"Ref": "SiteAdminPassword"}, "\",\r\n",
" \"data_dir\" : \"D:\\\\arcgisportal\",\r\n",
" \"content_store_type\" : \"", {"Fn::If": ["UseCloudStore", "cloudStore", "fileStore"]}, "\",\r\n",
" \"content_store_provider\" : \"", {"Fn::If": ["UseCloudStore", "Amazon", "FileSystem"]}, "\",\r\n",
" \"content_store_connection_string\" : ", {"Fn::If": ["UseCloudStore",
{"Fn::Join" : ["", ["{\"region\": \"", {"Ref" : "AWS::Region"}, "\", \"credentialType\": \"IAMRole\"}"]]},
"\"D:\\\\arcgisportal\\\\content\""]}, ",\r\n",
" \"object_store\" : \"", {"Fn::If": ["UseCloudStore", {"Ref": "PortalContent"}, ""]}, "\",\r\n",
" \"authorization_file\" : \"C:\\\\Temp\\\\", {"Ref": "PortalLicenseFile"}, "\"\r\n",
" }\r\n",
" },\r\n",
" \"run_list\" : [\r\n",
" \"recipe[arcgis-enterprise::system]\",\r\n",
" \"recipe[esri-iis]\",\r\n",
" \"recipe[arcgis-enterprise::server]\",\r\n",
" \"recipe[arcgis-enterprise::server_wa]\",\r\n",
" \"recipe[arcgis-enterprise::datastore]\",\r\n",
" \"recipe[arcgis-enterprise::portal]\",\r\n",
" \"recipe[arcgis-enterprise::portal_wa]\",\r\n",
" \"recipe[arcgis-enterprise::federation]\",\r\n",
" \"recipe[arcgis-enterprise::post_install]\"]\r\n",
"}\r\n"
]
]
}
}
}
}
}
}
},
"EC2InstanceRecoveryAlarm" : {
"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" : "AllInOneEC2Instance"}
} ]
}
},
"WaitHandle": {
"Type": "AWS::CloudFormation::WaitConditionHandle",
"Properties": {}
},
"WaitCondition": {
"Type": "AWS::CloudFormation::WaitCondition",
"Properties": {
"Handle": {"Ref": "WaitHandle"},
"Timeout": "7200"
}
},
"LaunchConfig" : {
"Type" : "AWS::AutoScaling::LaunchConfiguration",
"DependsOn" : "WaitCondition",
"Properties" : {
"AssociatePublicIpAddress" : true,
"ImageId" : {"Fn::FindInMap" : ["RegionMap", {"Ref":"AWS::Region"}, "en"]},
"InstanceType" : {"Ref" : "BDSInstanceType"},
"KeyName" : {"Ref" : "KeyName"},
"IamInstanceProfile" : {"Ref" : "IAMInstanceProfile"},
"SecurityGroups" : [ {"Ref": "SecurityGroup"} ],
"InstanceMonitoring" : true,
"BlockDeviceMappings": [ {
"DeviceName": "/dev/sda1",
"Ebs": {
"VolumeSize": {"Ref": "DriveSizeRoot"},
"DeleteOnTermination": true,
"VolumeType": "gp2"
}
}, {
"DeviceName": "xvdg",
"Ebs": {
"VolumeSize": {"Ref": "DriveSizeData"},
"DeleteOnTermination": true,
"VolumeType": "gp2"
}
}],
"UserData" : {
"Fn::Base64" : {
"Fn::Join" : [
"",
[
"\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 -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",
"\r\n"
]
]
}
}
},
"Metadata" : {
"AWS::CloudFormation::Authentication" : {
"S3AccessCreds" : {
"type" : "S3",
"buckets" : [ {"Ref" : "DeploymentBucket"} ],
"roleName" : {"Ref" : "IAMRole"}
}
},
"AWS::CloudFormation::Init" : {
"config" : {
"files" : {
"C:\\chef\\node.json" : {
"content" : {
"Fn::Join" : [ "", [
"{\r\n",
" \"arcgis\" : {\r\n",
" \"run_as_password\" : \"", {"Ref" : "RunAsUserPassword"}, "\",\r\n",
" \"post_install_script\" : \"D:\\\\PostInstallScripts\\\\deploy.bat\",\r\n",
" \"server\" : {\r\n",
" \"admin_username\" : \"", {"Ref" : "SiteAdmin"}, "\",\r\n",
" \"admin_password\" : \"", {"Ref" : "SiteAdminPassword" }, "\",\r\n",
" \"domain_name\" : \"", { "Fn::GetAtt" : [ "AllInOneEC2Instance", "PrivateIp" ] }, "\",\r\n",
" \"private_url\" : \"https://", { "Fn::GetAtt" : [ "AllInOneEC2Instance", "PrivateIp" ] }, ":6443/arcgis\"\r\n",
" },\r\n",
" \"data_store\" : {\r\n",
" \"types\" : \"spatiotemporal\",\r\n",
" \"preferredidentifier\" : \"ip\",\r\n",
" \"data_dir\" : \"D:\\\\arcgisdatastore\",\r\n",
" \"backup_dir\" : \"\\\\\\\\", { "Fn::GetAtt" : [ "AllInOneEC2Instance", "PrivateIp" ] }, "\\\\data\\\\arcgisdatastore\\\\backup\"\r\n",
" }\r\n",
" },\r\n",
" \"run_list\" : [\r\n",
" \"recipe[arcgis-enterprise::datastore]\",\r\n",
" \"recipe[arcgis-enterprise::post_install]\"]\r\n",
"}\r\n" ] ]
}
}
}
}
}
}
},
"AutoScalingGroup" : {
"Type" : "AWS::AutoScaling::AutoScalingGroup",
"Properties" : {
"VPCZoneIdentifier" : [ {"Ref" : "Subnet"} ],
"Cooldown" : "300",
"MaxSize" : {"Ref" : "BDSInstances"},
"MinSize" : {"Ref" : "BDSInstances"},
"LaunchConfigurationName" : {"Ref" : "LaunchConfig"},
"HealthCheckType" : "EC2",
"HealthCheckGracePeriod" : "3600",
"Tags" : [ {
"Key" : "Name",
"Value" : {"Fn::Join" : ["", [{"Ref" : "AWS::StackName"}, "-bds"]]},
"PropagateAtLaunch" : true
} ]
},
"UpdatePolicy": {
"AutoScalingReplacingUpdate": {
"WillReplace": "true"
}
}
},
"AutoScalingGroupWaitHandle" : {
"Type" : "AWS::CloudFormation::WaitConditionHandle",
"Properties" : {}
},
"AutoScalingGroupWaitCondition" : {
"Type" : "AWS::CloudFormation::WaitCondition",
"DependsOn" : "LaunchConfig",
"Properties" : {
"Count" : {"Ref" : "BDSInstances"},
"Handle" : {"Ref" : "AutoScalingGroupWaitHandle"},
"Timeout" : "10800"
}
},
"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" : {
"D:\\PostInstallScripts" : {"Fn::If": ["RunPostInstall", {"Fn::GetAtt": [ "ValidatePostInstallationScript", "S3ObjectURL" ]}, ""]}
}
},
"config": {
"sources": {
"C:\\chef": "https://agsstore6.s3.amazonaws.com/8321/cookbooks/arcgis-3.2.0-cookbooks.zip",
"C:\\Program Files\\Amazon\\cfn-bootstrap" : "https://arcgisstore106.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"
}
}
}
}
}
}
},
"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"
},
"LogsURL": {
"Value": {"Fn::Join": ["", [ "https://console.aws.amazon.com/cloudwatch/home?region=", {"Ref": "AWS::Region"}, "#logStream:group=", {"Ref": "DeploymentLogs"} ] ]},
"Description": "Deployment Logs"
},
"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"
},
"Subnet" : {
"Value" : {"Ref" : "Subnet"},
"Description" : "VPC subnet"
},
"DeploymentBucket" : {
"Value" : {"Ref" : "DeploymentBucket"},
"Description" : "Deployment S3 bucket"
},
"SecurityGroup" : {
"Value" : {"Ref" : "SecurityGroup"},
"Description" : "Security group"
},
"AllInOneEC2InstancePrivateIp" : {
"Value" : { "Fn::GetAtt" : [ "AllInOneEC2Instance", "PrivateIp" ] },
"Description" : "Private IP address of the base ArcGIS Enterprise EC2 instance"
},
"StoreType" : {
"Value" : {"Ref" : "StoreType" },
"Description" : "ArcGIS Server config store and Portal for ArcGIS content store type"
}
}
}