{
	"AWSTemplateFormatVersion": "2010-09-09",
	"Description": "ArcGIS CloudFormation Template: Provisions an ArcGIS Mission Server site on EC2 instances running Ubuntu. **WARNING** You will be billed by AWS for the AWS resources if you create a stack from this template.",
	"Metadata": {
		"AWS::CloudFormation::Interface": {
			"ParameterGroups": [{
					"Label": {
						"default": "Network Configuration"
					},
					"Parameters": [
						"VPCId",
						"Subnet",
						"SiteEIPAllocationID",
						"SiteDomain",
						"SSLCertificateFile",
						"SSLCertPassword"
					]
				},
				{
					"Label": {
						"default": "Amazon EC2 Configuration"
					},
					"Parameters": [
						"BaseAMI",
						"InstanceType",
						"DriveSizeRoot",
						"KeyName"
					]
				},
				{
					"Label": {
						"default": "ArcGIS Enterprise Configuration"
					},
					"Parameters": [
						"DeploymentBucket",
						"ServerLicenseFile",
						"SiteAdmin",
						"SiteAdminPassword"
					]
				}
			]
		}
	},
	"Parameters": {
		"DeploymentBucket": {
			"Type": "String",
			"Description": "S3 bucket with ArcGIS Server authorization file",
			"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": {
			"Type": "Number",
			"Default": 100,
			"Description": "Size of root drive in GB.",
			"MinValue": 100,
			"MaxValue": 1024,
			"ConstraintDescription": "Must be between 100 and 1024 GB."
		},
		"InstanceType": {
			"Type": "String",
			"Description": "ArcGIS Mission Server EC2 instance type",
			"Default": "c5.2xlarge",
			"AllowedValues": [
				"c4.2xlarge",
				"c4.4xlarge",
				"c4.8xlarge",
				"c5.2xlarge",
				"c5.4xlarge",
				"c5.9xlarge",
				"c5.18xlarge",
				"c5.xlarge",
				"c5d.2xlarge",
				"c5d.4xlarge",
				"c5d.9xlarge",
				"c5d.18xlarge",
				"c5n.2xlarge",
				"c5n.4xlarge",
				"c5n.9xlarge",
				"c5n.18xlarge",
				"m4.xlarge",
				"m4.2xlarge",
				"m4.4xlarge",
				"m4.10xlarge",
				"m5.xlarge",
				"m5.2xlarge",
				"m5.4xlarge",
				"m5.12xlarge",
				"m5.24xlarge",
				"m5.metal",
				"m5d.xlarge",
				"m5d.2xlarge",
				"m5d.4xlarge",
				"m5d.12xlarge",
				"m5d.24xlarge",
				"m5d.metal",
				"m5a.xlarge",
				"m5a.2xlarge",
				"m5a.4xlarge",
				"m5a.12xlarge",
				"m5a.24xlarge",
				"m4.xlarge",
				"m4.2xlarge",
				"m4.4xlarge",
				"m4.10xlarge",
				"m4.16xlarge",
				"p3.2xlarge",
				"p3.8xlarge",
				"p3.16xlarge",
				"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.xlarge",
				"t2.2xlarge",
				"t3.xlarge",
				"t3.2xlarge",
				"t3a.xlarge",
				"t3a.2xlarge",
				"x1.16xlarge",
				"x1.32xlarge",
				"x1e.xlarge",
				"x1e.2xlarge",
				"x1e.4xlarge",
				"x1e.8xlarge",
				"x1e.16xlarge",
				"x1e.32xlarge"
			]
		},
		"KeyName": {
			"Type": "AWS::EC2::KeyPair::KeyName",
			"Description": "EC2 Key Pair to allow RemoteDesktop access to the instances"
		},
		"ServerLicenseFile": {
			"Type": "String",
			"Description": "ArcGIS Mission Server authorization file (must be uploaded to DeploymentBucket)",
			"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": {
			"Type": "String",
			"Default": "siteadmin",
			"Description": "User name of ArcGIS Mission Server primary site administrator",
			"AllowedPattern": "^[a-zA-Z][a-zA-Z0-9_]{6,}$",
			"ConstraintDescription": "User name must be 6 or more alphanumeric or underscore (_) characters and must start with a letter."
		},
		"SiteAdminPassword": {
			"Type": "String",
			"Description": "Password of ArcGIS Mission Server primary site administrator",
			"NoEcho": true,
			"AllowedPattern": "^[a-zA-Z0-9_\\.@]{8,}$",
			"ConstraintDescription": "Password must be 8 or more alphanumeric, underscore (_), at ('@'), or dot (.) characters."
		},
		"SSLCertificateFile": {
			"Type": "String",
			"Description": "SSL certificate file issued to the site domain (must be uploaded to DeploymentBucket)",
			"AllowedPattern": "^([/\\w\\-\\.]+)+\\.(pfx)$",
			"ConstraintDescription": "Certificate file name must be alphanumeric. It can contain slash ('/'), dash ('-'), dot ('.'), and underscore ('_') characters. The file name must end with '.pfx'"
		},
		"SSLCertPassword": {
			"Type": "String",
			"Description": "SSL certificate file password",
			"NoEcho": true,
			"AllowedPattern": "[^\\\"]{1,128}",
			"ConstraintDescription": "Password must be between 1 and 128 characters and must not contain backslashes (\\) or quotation marks (\")."
		},
		"VPCId": {
			"Type": "AWS::EC2::VPC::Id",
			"Description": "VPC ID"
		},
		"Subnet": {
			"Type": "AWS::EC2::Subnet::Id",
			"Description": "VPC Subnet"
		},
		"SiteEIPAllocationID": {
			"Type": "String",
			"Default": "",
			"Description": "Allocation ID of Elastic IP address for VPC (eipalloc-XXXXXXXX)",
			"AllowedPattern": "^$|eipalloc-.*"
		},
		"SiteDomain": {
			"Type": "String",
			"Description": "Domain name of ArcGIS Mission Server site",
			"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."
		},
		"BaseAMI": {
			"Type": "String",
			"Description": "(Optional) Base AMI Id derived from Canonical Ubuntu 18.04 LTS amd64 image",
			"Default": ""
		},
		"PostInstallationScript": {
			"Type": "String",
			"Default": "none",
			"Description": "(Optional) ZIP archive file with custom post installation script",
			"AllowedPattern": "[^\"]{1,1024}",
			"ConstraintDescription": "S3 object key name must be between 1 and 1024 characters."
		}
	},
	"Mappings": {
		"Repositories": {
			"ap-south-1": {
				"bucket": "arcgisstore1081-ap-south-1",
				"region": "ap-south-1"
			},
			"eu-north-1": {
				"bucket": "arcgisstore1081-eu-north-1",
				"region": "eu-north-1"
			},
			"eu-west-3": {
				"bucket": "arcgisstore1081-eu-west-3",
				"region": "eu-west-3"
			},
			"eu-west-2": {
				"bucket": "arcgisstore1081-eu-west-2",
				"region": "eu-west-2"
			},
			"eu-west-1": {
				"bucket": "arcgisstore1081-eu-west-1",
				"region": "eu-west-1"
			},
			"ap-northeast-2": {
				"bucket": "arcgisstore1081-ap-northeast-2",
				"region": "ap-northeast-2"
			},
			"ap-northeast-1": {
				"bucket": "arcgisstore1081-ap-northeast-1",
				"region": "ap-northeast-1"
			},
			"sa-east-1": {
				"bucket": "arcgisstore1081-sa-east-1",
				"region": "sa-east-1"
			},
			"ca-central-1": {
				"bucket": "arcgisstore1081-ca-central-1",
				"region": "ca-central-1"
			},
			"ap-southeast-1": {
				"bucket": "arcgisstore1081-ap-southeast-1",
				"region": "ap-southeast-1"
			},
			"ap-southeast-2": {
				"bucket": "arcgisstore1081-ap-southeast-2",
				"region": "ap-southeast-2"
			},
			"eu-central-1": {
				"bucket": "arcgisstore1081-eu-central-1",
				"region": "eu-central-1"
			},
			"us-east-1": {
				"bucket": "arcgisstore1081-us-east-1",
				"region": "us-east-1"
			},
			"us-east-2": {
				"bucket": "arcgisstore1081-us-east-2",
				"region": "us-east-2"
			},
			"us-west-1": {
				"bucket": "arcgisstore1081-us-west-1",
				"region": "us-west-1"
			},
			"us-west-2": {
				"bucket": "arcgisstore1081-us-west-2",
				"region": "us-west-2"
			},
			"us-gov-east-1": {
				"bucket": "arcgisstore1081-us-gov-east-1",
				"region": "us-gov-east-1"
			},
			"us-gov-west-1": {
				"bucket": "arcgisstore1081-us-gov-west-1",
				"region": "us-gov-west-1"
			}
		},
		"RegionMap": {
	      "ap-east-1": {
	        "en": "ami-0a908d32be355f897"
	      },
	      "ap-northeast-1": {
	        "en": "ami-02fce661b938024d2"
	      },
	      "ap-northeast-2": {
	        "en": "ami-018807f597543a2de"
	      },
	      "ap-south-1": {
	        "en": "ami-0060b6c91eb8b1475"
	      },
	      "ap-southeast-1": {
	        "en": "ami-099ecfd42bd5d32a4"
	      },
	      "ap-southeast-2": {
	        "en": "ami-0f0bd2b430af0f5fc"
	      },
	      "ca-central-1": {
	        "en": "ami-0daa2389c645945fc"
	      },
	      "eu-central-1": {
	        "en": "ami-0e73bd30a22a7164d"
	      },
	      "eu-north-1": {
	        "en": "ami-05190f5e864864f6b"
	      },
	      "eu-west-1": {
	        "en": "ami-078bbce609b4fbfcf"
	      },
	      "eu-west-2": {
	        "en": "ami-0ceaf21e7ce2c6bcd"
	      },
	      "eu-west-3": {
	        "en": "ami-00ece6d6c02447765"
	      },
	      "sa-east-1": {
	        "en": "ami-0b413faeb309196a4"
	      },
	      "us-east-1": {
	        "en": "ami-05493378a2ab1d54a"
	      },
	      "us-east-2": {
	        "en": "ami-007adc0d43045782f"
	      },
	      "us-west-1": {
	        "en": "ami-0b6a256e06852866c"
	      },
	      "us-west-2": {
	        "en": "ami-0a5a46fa2b3064aa9"
	      },
	      "us-gov-east-1": {
	        "en": "ami-04d63d15fac7b4729"
	      },
	      "us-gov-west-1": {
	        "en": "ami-0c1bb8e3167200087"
	      }
		}
	},
	"Conditions": {
		"CustomAMI": {
			"Fn::Not": [{
				"Fn::Equals": [{
						"Ref": "BaseAMI"
					},
					""
				]
			}]
		},
		"AttachEIP": {
			"Fn::Not": [{
				"Fn::Equals": [{
						"Ref": "SiteEIPAllocationID"
					},
					""
				]
			}]
		}
	},
	"Resources": {
		"SiteAdminPasswordSecret": {
			"Type": "AWS::SecretsManager::Secret",
			"Properties": {
				"Description": "Password of ArcGIS Mission Server primary site administrator",
				"SecretString": {
					"Ref": "SiteAdminPassword"
				}
			}
		},
		"SSLCertPasswordSecret": {
			"Type": "AWS::SecretsManager::Secret",
			"Properties": {
				"Description": "SSL certificate file password",
				"SecretString": {
					"Ref": "SSLCertPassword"
				}
			}
		},
		"StopStackFunction": {
			"Type": "AWS::Lambda::Function",
			"DependsOn": "IAMRole",
			"Properties": {
				"Code": {
					"S3Bucket": {"Fn::Join" : ["", ["arcgisstore1081", "-", {"Ref": "AWS::Region"}]]},
					"S3Key": "14362/lambda/arcgis-cfn-lambda-python3.zip"
				},
				"Environment": {
					"Variables": {
						"StackName": {
							"Ref": "AWS::StackName"
						}
					}
				},
				"Handler": "stop_start.stop_mission_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" : ["", ["arcgisstore1081", "-", {"Ref": "AWS::Region"}]]},
					"S3Key": "14362/lambda/arcgis-cfn-lambda-python3.zip"
				},
				"Environment": {
					"Variables": {
						"StackName": {
							"Ref": "AWS::StackName"
						}
					}
				},
				"Handler": "stop_start.start_mission_server_stack",
				"Runtime": "python3.8",
				"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": "/"
			}
		},
		"LambdaExecutionPolicy": {
			"Type": "AWS::IAM::Policy",
			"Properties": {
				"PolicyName": "ArcGISMissionServerLambda",
				"PolicyDocument": {
					"Statement": [{
							"Effect": "Allow",
							"Action": ["logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents"],
							"Resource": "*"
						},
						{
							"Effect": "Allow",
							"Action": [
								"ec2:DescribeInstances",
								"ec2:StartInstances",
								"ec2:DescribeTags",
								"ec2:DescribeRegions",
								"ec2:StopInstances",
								"ec2:DescribeInstanceStatus"
							],
							"Resource": "*"
						},
						{
							"Effect": "Allow",
							"Action": [
								"cloudformation:DescribeStacks",
								"cloudformation:DescribeStackResources",
								"cloudformation:DescribeStackResource"
							],
							"Resource": "*"
						}
					]
				},
				"Roles": [{
					"Ref": "LambdaExecutionRole"
				}]
			}
		},
		"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",
			"Properties": {
				"PolicyName": "ArcGISMissionServer",
				"PolicyDocument": {
					"Statement": [{
							"Action": [
								"cloudformation:DescribeStacks",
								"cloudformation:DescribeStackResources",
								"cloudformation:DescribeStackResource",
								"cloudformation:SignalResource"
							],
							"Effect": "Allow",
							"Resource": "*"
						},
						{
							"Action": [
								"logs:DescribeLogGroups",
								"logs:DescribeLogStreams",
								"logs:PutLogEvents",
								"logs:PutMetricFilter",
								"logs:CreateLogGroup",
								"logs:CreateLogStream"
							],
							"Effect": "Allow",
							"Resource": "*"
						},
						{
							"Action": [
								"ssm:DeleteAssociation",
								"ssm:DescribeAssociation",
								"ssm:DescribeInstanceInformation",
								"ssm:GetDeployablePatchSnapshotForInstance",
								"ssm:GetDocument",
								"ssm:DescribeDocument",
								"ssm:GetManifest",
								"ssm:GetParameter",
								"ssm:GetParameters",
								"ssm:ListAssociations",
								"ssm:ListCommands",
								"ssm:ListCommandInvocations",
								"ssm:ListInstanceAssociations",
								"ssm:PutInventory",
								"ssm:PutComplianceItems",
								"ssm:PutConfigurePackageResult",
								"ssm:SendCommand",
								"ssm:UpdateAssociationStatus",
								"ssm:UpdateInstanceAssociationStatus",
								"ssm:UpdateInstanceInformation"
							],
							"Effect": "Allow",
							"Resource": "*"
						},
						{
							"Action": [
								"ec2:DescribeTags",
								"ec2:DescribeInstances",
								"ec2:ModifyInstanceMetadataOptions"
							],
							"Effect": "Allow",
							"Resource": "*"
						},
						{
							"Action": [
								"ec2messages:AcknowledgeMessage",
								"ec2messages:DeleteMessage",
								"ec2messages:FailMessage",
								"ec2messages:GetEndpoint",
								"ec2messages:GetMessages",
								"ec2messages:SendReply"
							],
							"Effect": "Allow",
							"Resource": "*"
						},
						{
							"Action": [
								"ssmmessages:CreateControlChannel",
								"ssmmessages:CreateDataChannel",
								"ssmmessages:OpenControlChannel",
								"ssmmessages:OpenDataChannel"
							],
							"Effect": "Allow",
							"Resource": "*"
						},
						{
							"Action": [
								"s3:DeleteObjectTagging",
								"s3:PutObject",
								"s3:GetObject",
								"s3:ListAllMyBuckets",
								"s3:PutBucketTagging",
								"s3:ListBucket",
								"s3:PutObjectTagging",
								"s3:DeleteObject",
								"s3:HeadBucket",
								"s3:GetBucketLocation",
								"s3:GetBucketPolicy"
							],
							"Effect": "Allow",
							"Resource": "*"
						},
						{
							"Action": [
								"secretsmanager:GetSecretValue"
							],
							"Effect": "Allow",
							"Resource": [{
									"Ref": "SiteAdminPasswordSecret"
								},
								{
									"Ref": "SSLCertPasswordSecret"
								}
							]
						}
					]
				},
				"Roles": [{
					"Ref": "IAMRole"
				}]
			}
		},
		"IAMInstanceProfile": {
			"Type": "AWS::IAM::InstanceProfile",
			"Properties": {
				"Path": "/",
				"Roles": [{
					"Ref": "IAMRole"
				}]
			}
		},
		"SecurityGroup": {
			"Type": "AWS::EC2::SecurityGroup",
			"Properties": {
				"GroupDescription": "Allow HTTP and HTTPS for all client IPs",
				"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"
				}
			}
		},
		"PrimaryEC2Instance": {
			"Type": "AWS::EC2::Instance",
			"Properties": {
				"IamInstanceProfile": {
					"Ref": "IAMInstanceProfile"
				},
				"ImageId": {
					"Fn::If": [
						"CustomAMI",
						{
							"Ref": "BaseAMI"
						},
						{
							"Fn::FindInMap": [
								"RegionMap",
								{
									"Ref": "AWS::Region"
								},
								"en"
							]
						}
					]
				},
				"InstanceType": {
					"Ref": "InstanceType"
				},
				"BlockDeviceMappings": [{
					"DeviceName": "/dev/sda1",
					"Ebs": {
						"VolumeSize": {
							"Ref": "DriveSizeRoot"
						}
					}
				}],
				"KeyName": {
					"Ref": "KeyName"
				},
				"Monitoring": true,
				"NetworkInterfaces": [{
					"AssociatePublicIpAddress": true,
					"DeleteOnTermination": true,
					"DeviceIndex": "0",
					"GroupSet": [{
						"Ref": "SecurityGroup"
					}],
					"SubnetId": {
						"Ref": "Subnet"
					}
				}],
				"Tags": [{
						"Key": "Name",
						"Value": {
							"Fn::Sub": "${AWS::StackName}-primary"
						}
					},
					{
						"Key": "arcgis:role",
						"Value": "mission-server-primary"
					}
				]
			}
		},
		"EIPAssociation": {
			"Type": "AWS::EC2::EIPAssociation",
			"Condition": "AttachEIP",
			"Properties": {
				"AllocationId": {
					"Ref": "SiteEIPAllocationID"
				},
				"InstanceId": {
					"Ref": "PrimaryEC2Instance"
				}
			}
		},
		"PrimaryInstanceRecoveryAlarm": {
			"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::Sub": "arn:${AWS::Partition}:automate:${AWS::Region}:ec2:recover"
				}],
				"Dimensions": [{
					"Name": "InstanceId",
					"Value": {
						"Ref": "PrimaryEC2Instance"
					}
				}]
			}
		},
		"DeploymentLogs": {
			"Type": "AWS::Logs::LogGroup",
			"Properties": {
				"LogGroupName": {
					"Fn::Sub": [
						"/ESRI/MissionServerUbuntu/${LogName}",
						{
							"LogName": {
								"Ref": "AWS::StackName"
							}
						}
					]
				}
			}
		},
		"InstallMissionServerCommand": {
			"Type": "AWS::SSM::Document",
			"Properties": {
				"DocumentType": "Command",
				"Content": {
					"schemaVersion": "2.2",
					"description": "Installs and configures ArcGIS Mission Server",
					"parameters": {
						"chefClientUrl": {
							"type": "String",
							"default": {
								"Fn::Sub": [
									"s3://${bucket}/chefclient/chef_14.14.29-1_amd64.deb",
									{
										"bucket": {
											"Fn::FindInMap": [
												"Repositories",
												{
													"Ref": "AWS::Region"
												},
												"bucket"
											]
										}
									}
								]
							},
							"description": "S3 URL of Chef Client package"
						},
						"cookbooksUrl": {
							"type": "String",
							"default": "https://arcgisstore1081.s3.amazonaws.com/14362/cookbooks/arcgis-3.6.0-cookbooks.tar.gz",
							"description": "ArcGIS Chef cookbooks URL"
						},
						"region": {
							"type": "String",
							"default": {
								"Ref": "AWS::Region"
							},
							"description": "AWS region"
						},
						"arcgisVersion": {
							"type": "String",
							"default": "10.8.1",
							"description": "ArcGIS Mission Server version"
						},
						"machineRole": {
							"type": "String",
							"description": "ArcGIS Mission machine role",
							"allowedValues": [
								"mission-server-primary"
							]
						},
						"repositoryBucket": {
							"type": "String",
							"default": {
								"Fn::FindInMap": [
									"Repositories",
									{
										"Ref": "AWS::Region"
									},
									"bucket"
								]
							},
							"description": "ArcGIS software repository S3 bucket"
						},
						"repositoryBucketRegion": {
							"type": "String",
							"default": {
								"Fn::FindInMap": [
									"Repositories",
									{
										"Ref": "AWS::Region"
									},
									"region"
								]
							},
							"description": "Region of ArcGIS software repository  S3 bucket"
						},
						"deploymentBucket": {
							"type": "String",
							"default": {
								"Ref": "DeploymentBucket"
							},
							"description": "S3 bucket with authorization files and SSL certificates"
						},
						"licenseFile": {
							"type": "String",
							"default": {
								"Ref": "ServerLicenseFile"
							},
							"description": "S3 key of ArcGIS Mission Server software authorization file"
						},
						"certificateFile": {
							"type": "String",
							"default": {
								"Ref": "SSLCertificateFile"
							},
							"description": "S3 key of SSL certificate file in PKSC12 format"
						},
						"certificatePasswordSecretId": {
							"type": "String",
							"default": {
								"Ref": "SSLCertPasswordSecret"
							},
							"description": "Secret ID of SSL certificate file password"
						},
						"siteAdmin": {
							"type": "String",
							"default": {
								"Ref": "SiteAdmin"
							},
							"description": "ArcGIS Mission Server primary site administrator username"
						},
						"siteAdminPasswordSecretId": {
							"type": "String",
							"default": {
								"Ref": "SiteAdminPasswordSecret"
							},
							"description": "Secret ID of ArcGIS Mission Server primary site administrator password"
						},
						"siteDomain": {
							"type": "String",
							"default": {
								"Ref": "SiteDomain"
							},
							"description": "Domain name of ArcGIS Mission Server site"
						},
						"instanceid": {
							"type": "String",
							"description": "AWS region"
						}
					},
					"mainSteps": [{
						"action": "aws:runShellScript",
						"name": "InstallMissionServeronUbuntu",
						"inputs": {
							"runCommand": [
								"#!/bin/bash",
								"/usr/bin/cloud-init status --wait",
								"signal_if_failed()",
								"{",
								"if [ $1 -ne 0 ]; then",
								"echo $2",
								"echo 'enable unattended upgrades'",
								"rm /etc/apt/apt.conf.d/20auto-upgrades",
								"mv /etc/apt/apt.conf.d/20auto-upgrades.original /etc/apt/apt.conf.d/20auto-upgrades",
								"/etc/init.d/unattended-upgrades restart",
								"exit $1",
								"fi",
								"}",
								"echo 'disable unattended upgrades'",
								"cp /etc/apt/apt.conf.d/20auto-upgrades /etc/apt/apt.conf.d/20auto-upgrades.original",
								"echo -e \"APT::Periodic::Update-Package-Lists \\\"0\\\";\\nAPT::Periodic::Unattended-Upgrade \\\"0\\\";\" > /etc/apt/apt.conf.d/20auto-upgrades",
								"/etc/init.d/unattended-upgrades restart",
								"lockdetails=$(sudo lsof /var/lib/dpkg/lock)",
								"while [ ! -z \"$lockdetails\" ]",
								"do",
								"echo 'Waiting for lock to release'",
								"sleep 1m",
								"lockdetails=$(sudo lsof /var/lib/dpkg/lock)",
								"done",
								"echo 'Install python, AWS CLI, jq, autofs Scripts'",
								"apt-get update -y",
								"apt-get install -y python3-pip python-setuptools jq autofs",
								"pip3 install awscli --upgrade --user",
								"echo 'export HOME=/root' >> ~/.profile",
								"echo 'export PATH=~/.local/bin:$PATH' >> ~/.profile",
								". ~/.profile",
								"aws --version",
								"sed -i 's/#\\/net/\\/net/g' /etc/auto.master",
								"service autofs reload",
								"mkdir -p /opt/aws/bin",
								"echo 'Updating SSM Agent'",
								"sudo snap refresh --candidate amazon-ssm-agent",
								"echo 'Install Chef Client'",
								"aws s3 cp {{chefClientUrl}} /tmp/chef-client.deb --source-region {{repositoryBucketRegion}} --region {{region}}",
								"sudo dpkg -i /tmp/chef-client.deb",
								"signal_if_failed $? \"Chef installation failed.\"",
								"rm /tmp/chef-client.deb",
								"echo 'Install ArcGIS Chef cookbooks'",
								"wget -c {{cookbooksUrl}} -O - | sudo tar -xz -C /opt/chef",
								"signal_if_failed $? \"ArcGIS Chef cookbooks installation failed.\"",
								"echo 'Download ArcGIS Mission Server license and SSL certificate from S3.'",
								". ~/.profile",
								"licenseFile='/opt/software/esri/{{licenseFile}}'",
								"deploymentbucketregion=$(aws s3api get-bucket-location --bucket {{deploymentBucket}} --region {{region}} | jq --raw-output '.LocationConstraint' )",
								"if [ \"${deploymentbucketregion}\" = \"null\" ]; then",
								"deploymentbucketregion='us-east-1'",
								"fi",
								". ~/.profile",
								"aws s3 cp s3://{{deploymentBucket}}/{{licenseFile}} $licenseFile --source-region ${deploymentbucketregion} --region {{region}}",
								"signal_if_failed $? \"Failed to get object '{{licenseFile}}' from S3 bucket '{{deploymentBucket}}'.\"",
								"certificateFile='/tomcat_arcgis/conf/{{certificateFile}}'",
								"aws s3 cp s3://{{deploymentBucket}}/{{certificateFile}} $certificateFile --source-region ${deploymentbucketregion} --region {{region}}",
								"signal_if_failed $? \"Failed to get object '{{certificateFile}}' from S3 bucket '{{deploymentBucket}}'.\"",
								"echo 'Get secrets from Secrets Manager.'",
								"siteAdminPassword=$(aws secretsmanager get-secret-value --secret-id {{siteAdminPasswordSecretId}} --region {{region}} | jq --raw-output '.SecretString')",
								"signal_if_failed $(expr \"$siteAdminPassword\" == \"\") \"Failed to get password of ArcGIS Mission Server primary site administrator from AWS Secrets Manager.\"",
								"certificatePassword=$(aws secretsmanager get-secret-value --secret-id {{certificatePasswordSecretId}} --region {{region}} | jq --raw-output '.SecretString')",
								"signal_if_failed $(expr \"$certificatePassword\" == \"\") \"Failed to get SSL certificate file password from AWS Secrets Manager.\"",
								"templatejson=\"/opt/chef/templates/arcgis-mission-server/{{arcgisVersion}}/ubuntu/{{machineRole}}.json\"",
								"test -e $templatejson",
								"signal_if_failed $? \"Chef deployment template '$templatejson' not found.\"",
								"nodejson='/opt/chef/{{machineRole}}.json'",
								"echo 'Replace attribute values in the Chef deployment template'",
								"cat $templatejson | \\",
								"jq \".tomcat.keystore_file=\\\"${certificateFile}\\\"\" | \\",
								"jq \".tomcat.keystore_password=\\\"${certificatePassword}\\\"\" | \\",
								"jq \".arcgis.repository.server.s3bucket=\\\"{{repositoryBucket}}\\\"\" | \\",
								"jq \".arcgis.repository.server.region=\\\"{{repositoryBucketRegion}}\\\"\" | \\",
								"jq \".arcgis.mission_server.authorization_file=\\\"${licenseFile}\\\"\" | \\",
								"jq \".arcgis.mission_server.system_properties.WebSocketContextURL=\\\"wss://{{siteDomain}}/mission\\\"\" | \\",
								"jq \".arcgis.mission_server.admin_username=\\\"{{siteAdmin}}\\\"\" | \\",
								"jq \".arcgis.mission_server.admin_password=\\\"${siteAdminPassword}\\\"\" > $nodejson",
								"echo 'Run Chef.'",
								"/opt/chef/bin/chef-client -z -F min --force-formatter --no-color -j $nodejson -L /var/log/chef-run.log -l info --config-option \"cookbook_path=/opt/chef/cookbooks\"",
								"exitcode=$?",
								"echo 'Allow SSH for arcgis user.'",
								"mkdir /home/arcgis/.ssh/",
								"chown arcgis:root /home/arcgis/.ssh/",
								"cp /home/ubuntu/.ssh/authorized_keys /home/arcgis/.ssh/",
								"chown arcgis:root /home/arcgis/.ssh/authorized_keys",
								"chmod 440 /home/arcgis/.ssh/authorized_keys",
								"echo 'Shred sensitive data used by the Chef run.'",
								"shred -vzu $nodejson",
								"find /opt/chef/nodes -type f -exec shred -vzu {} \\;",
								"signal_if_failed $exitcode 'ArcGIS Mission Server installation failed.'",
								"echo 'Enabling IMDS V2'",
								". ~/.profile",
								"aws ec2 modify-instance-metadata-options --instance-id {{instanceid}} --http-endpoint enabled --http-tokens required --region {{region}}",
								"echo 'enable unattended upgrades'",
								"rm /etc/apt/apt.conf.d/20auto-upgrades",
								"mv /etc/apt/apt.conf.d/20auto-upgrades.original /etc/apt/apt.conf.d/20auto-upgrades",
								"/etc/init.d/unattended-upgrades restart",
								"exit 0"
							]
						}
					}]
				}
			}
		},
		"InstallMissionServerAutomation": {
			"Type": "AWS::SSM::Document",
			"Properties": {
				"Content": {
					"schemaVersion": "0.3",
					"description": "Installs and configure ArcGIS Mission Server.",
					"assumeRole": {
						"Fn::GetAtt": [
							"IAMRole",
							"Arn"
						]
					},
					"parameters": {
						"InstanceId": {
							"type": "String",
							"description": "(Required) EC2 instance id"
						},
						"MachineRole": {
							"type": "String",
							"description": "(Required) Machine role for ArcGIS Mission server deployment"
						},
						"WaitCondition": {
							"type": "String",
							"description": "(Required) Wait condition for CloudFormation template",
							"default": ""
						}
					},
					"mainSteps": [{
							"name": "RunInstallMissionServerCommand",
							"action": "aws:runCommand",
							"onFailure": "step:SignalFailure",
							"nextStep": "SignalSuccess",
							"timeoutSeconds": 3600,
							"inputs": {
								"DocumentName": {
									"Ref": "InstallMissionServerCommand"
								},
								"InstanceIds": [
									"{{InstanceId}}"
								],
								"CloudWatchOutputConfig": {
									"CloudWatchOutputEnabled": "true",
									"CloudWatchLogGroupName": {
										"Ref": "DeploymentLogs"
									}
								},
								"Parameters": {
									"machineRole": "{{MachineRole}}",
                  "instanceid":"{{InstanceId}}"
								}
							}
						},
						{
							"name": "SignalFailure",
							"action": "aws:executeScript",
							"isEnd": true,
							"inputs": {
								"Runtime": "PowerShell Core 6.0",
								"Script": "Write-Host $env:InputPayload; \n$inputPayload = $env:InputPayload | ConvertFrom-Json; \n<#$parameter = $inputPayload.events.parameter;#>\n\nInstall-Module AWS.Tools.CloudFormation -Force\n\n$StackName = $inputPayload.StackName;\n$WaitCondition = $inputPayload.WaitCondition;\n$UniqueId = $inputPayload.UniqueId;\n$Status = $inputPayload.Status;\n\nif (!([string]::IsNullOrEmpty($WaitCondition))) {\n  try\n  {\n    $stackstatus=((Get-CFNStack -StackName $StackName).StackStatus).Value\n    Write-Output $stackstatus\n    if ($stackstatus -eq \"CREATE_IN_PROGRESS\") {\n      Send-CFNResourceSignal -StackName $StackName -LogicalResourceId $WaitCondition -Status $Status -UniqueId $UniqueId\n    }\n  }\n  catch\n  {\n    Write-Error $_.Exception | format-list -force\n  }\n}\n",
								"InputPayload": {
									"StackName": {
										"Ref": "AWS::StackName"
									},
									"UniqueId": "{{InstanceId}}",
									"WaitCondition": "{{WaitCondition}}",
									"Status": "FAILURE"
								}
							}
						},
						{
							"name": "SignalSuccess",
							"action": "aws:executeScript",
							"isEnd": true,
							"inputs": {
								"Runtime": "PowerShell Core 6.0",
								"Script": "Write-Host $env:InputPayload; \n$inputPayload = $env:InputPayload | ConvertFrom-Json; \n<#$parameter = $inputPayload.events.parameter;#>\n\nInstall-Module AWS.Tools.CloudFormation -Force\n\n$StackName = $inputPayload.StackName;\n$WaitCondition = $inputPayload.WaitCondition;\n$UniqueId = $inputPayload.UniqueId;\n$Status = $inputPayload.Status;\n\nif (!([string]::IsNullOrEmpty($WaitCondition))) {\n  try\n  {\n    $stackstatus=((Get-CFNStack -StackName $StackName).StackStatus).Value\n    Write-Output $stackstatus\n    if ($stackstatus -eq \"CREATE_IN_PROGRESS\") {\n      Send-CFNResourceSignal -StackName $StackName -LogicalResourceId $WaitCondition -Status $Status -UniqueId $UniqueId\n    }\n  }\n  catch\n  {\n    Write-Error $_.Exception | format-list -force\n  }\n}\n",
								"InputPayload": {
									"StackName": {
										"Ref": "AWS::StackName"
									},
									"UniqueId": "{{InstanceId}}",
									"WaitCondition": "{{WaitCondition}}",
									"Status": "SUCCESS"
								}
							}
						}
					]
				},
				"DocumentType": "Automation"
			}
		},
		"InstallMissionServerPrimary": {
			"Type": "AWS::SSM::Association",
			"DependsOn": [
				"PrimaryEC2Instance"
			],
			"Properties": {
				"Name": {
					"Ref": "InstallMissionServerAutomation"
				},
				"Parameters": {
					"InstanceId": [{
						"Ref": "PrimaryEC2Instance"
					}],
					"MachineRole": [
						"mission-server-primary"
					],
					"WaitCondition": [
						"InstallMissionServerPrimaryWaitCondition"
					]
				}
			}
		},
		"InstallMissionServerPrimaryWaitCondition": {
			"Type": "AWS::CloudFormation::WaitCondition",
			"DependsOn": [
				"PrimaryEC2Instance"
			],
			"CreationPolicy": {
				"ResourceSignal": {
					"Timeout": "PT1H",
					"Count": "1"
				}
			}
		}
	},
	"Outputs": {
		"AdminURL": {
			"Description": "ArcGIS Mission Server admin services URL",
			"Value": {
				"Fn::Sub": "https://${SiteDomain}/mission/admin/"
			}
		},
		"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."
		}
	}
}
