{ "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" } } }