From 2b30a858852db82732f5dbe41a5fb59bb4aa5869 Mon Sep 17 00:00:00 2001 From: Loren Gordon Date: Tue, 11 Apr 2017 14:12:19 -0400 Subject: [PATCH 1/5] Adds cfn template for a linux autoscaling group --- .../watchmaker-lx-autoscale.template | 1118 +++++++++++++++++ 1 file changed, 1118 insertions(+) create mode 100644 docs/files/cfn/templates/watchmaker-lx-autoscale.template diff --git a/docs/files/cfn/templates/watchmaker-lx-autoscale.template b/docs/files/cfn/templates/watchmaker-lx-autoscale.template new file mode 100644 index 000000000..fe788465f --- /dev/null +++ b/docs/files/cfn/templates/watchmaker-lx-autoscale.template @@ -0,0 +1,1118 @@ +{ + "AWSTemplateFormatVersion" : "2010-09-09", + "Description" : "This template creates an Autoscaling Group and Launch Configuration that deploys Linux instances with Watchmaker, which applies the DISA STIG.", + "Parameters" : + { + "AmiId" : + { + "Description" : "ID of the AMI to launch", + "Type" : "String", + "AllowedPattern" : "^ami-[0-9a-z]{8}$|^ami-[0-9a-z]{17}$" + }, + "AmiDistro" : + { + "Description" : "Linux distro of the AMI", + "Type" : "String", + "AllowedValues" : + [ + "AmazonLinux", + "CentOS", + "RedHat" + ] + }, + "AppScriptParams" : + { + "Description" : "Parameter string to pass to the application script. Ignored if \"AppScriptUrl\" is blank", + "Type" : "String" + }, + "AppScriptShell" : + { + "Description" : "Shell with which to execute the application script. Ignored if \"AppScriptUrl\" is blank", + "Type" : "String", + "Default" : "bash", + "AllowedValues" : + [ + "bash", + "python" + ] + }, + "AppScriptUrl" : + { + "Description" : "(Optional) URL to the application script. Leave blank to launch without an application script", + "Type" : "String", + "Default" : "", + "AllowedPattern" : "^$|^http[s]?://.*$" + }, + "AppVolumeDevice" : + { + "Description" : "(Optional) Device to mount an extra EBS volume. Leave blank to launch without an extra application volume", + "Type" : "String", + "Default" : "", + "AllowedValues" : + [ + "", + "/dev/xvdf", + "/dev/xvdg", + "/dev/xvdh", + "/dev/xvdi", + "/dev/xvdj" + ] + }, + "AppVolumeMountPath" : + { + "Description" : "Filesystem path to mount the extra app volume. Ignored if \"AppVolumeDevice\" is blank", + "Type" : "String", + "Default" : "/opt/data", + "AllowedPattern" : "/.*" + }, + "AppVolumeType" : + { + "Description" : "Type of EBS volume to create. Ignored if \"AppVolumeDevice\" is blank", + "Type" : "String", + "Default" : "gp2", + "AllowedValues" : + [ + "gp2", + "io1", + "sc1", + "st1", + "standard" + ] + }, + "AppVolumeSize" : + { + "Description" : "Size in GB of the EBS volume to create. Ignored if \"AppVolumeDevice\" is blank", + "Type" : "Number", + "Default" : "1", + "MinValue": "1", + "MaxValue": "16384", + "ConstraintDescription" : "Must be between 1GB and 16384GB." + }, + "KeyPairName" : + { + "Description" : "Public/private key pairs allow you to securely connect to your instance after it launches", + "Type" : "AWS::EC2::KeyPair::KeyName" + }, + "InstanceType" : + { + "Description" : "Amazon EC2 instance type", + "Type" : "String", + "Default" : "t2.micro", + "AllowedValues" : + [ + "t2.micro", + "t2.small", + "t2.medium", + "t2.large", + "c4.large", + "c4.xlarge", + "m4.large", + "m4.xlarge" + ] + }, + "InstanceRole" : + { + "Description" : "(Optional) IAM instance role to apply to the instance(s)", + "Type" : "String", + "Default" : "" + }, + "MinCapacity" : + { + "Description" : "Minimum number of instances in the Autoscaling Group", + "Type" : "Number", + "Default" : "1" + }, + "MaxCapacity" : + { + "Description" : "Maximum number of instances in the Autoscaling Group", + "Type" : "Number", + "Default" : "2" + }, + "DesiredCapacity" : + { + "Description" : "Desired number of instances in the Autoscaling Group", + "Type" : "Number", + "Default" : "1" + }, + "NoPublicIp" : + { + "Description" : "Controls whether to assign the instance a public IP. Recommended to leave at \"true\" _unless_ launching in a public subnet", + "Type" : "String", + "Default" : "true", + "AllowedValues" : + [ + "false", + "true" + ] + }, + "NoReboot" : + { + "Description" : "Controls whether to reboot the instance as the last step of cfn-init execution", + "Type" : "String", + "Default" : "false", + "AllowedValues" : + [ + "false", + "true" + ] + }, + "NoUpdates" : + { + "Description" : "Controls whether to run yum update during a stack update (on the initial instance launch, Watchmaker _always_ installs updates)", + "Type" : "String", + "Default" : "false", + "AllowedValues" : + [ + "false", + "true" + ] + }, + "SecurityGroupIds" : + { + "Description" : "List of security groups to apply to the instance(s)", + "Type" : "List" + }, + "SubnetIds" : + { + "Type" : "List", + "Description" : "List of subnets to associate to the Autoscaling Group" + }, + "PypiIndexUrl" : + { + "Description" : "URL to the PyPi Index", + "Type" : "String", + "Default" : "https://pypi.org/simple", + "AllowedPattern" : "^http[s]?://.*$" + }, + "WatchmakerConfig" : + { + "Description" : "(Optional) URL to a Watchmaker config file", + "Type" : "String", + "Default" : "", + "AllowedPattern" : "^$|^http[s]?://.*$" + }, + "WatchmakerEnvironment" : + { + "Description" : "Environment in which the instance is being deployed", + "Type" : "String", + "Default" : "", + "AllowedValues" : + [ + "", + "dev", + "test", + "prod" + ] + }, + "WatchmakerOuPath" : + { + "Description" : "(Optional) DN of the OU to place the instance when joining a domain. If blank and \"WatchmakerEnvironment\" enforces a domain join, the instance will be placed in a default container. Leave blank if not joining a domain, or if \"WatchmakerEnvironment\" is \"false\"", + "Type" : "String", + "Default" : "", + "AllowedPattern" : "^$|^(OU=.+,)+(DC=.+)+$" + }, + "WatchmakerAdminGroups" : + { + "Description" : "(Optional) Colon-separated list of domain groups that should have admin permissions on the EC2 instance", + "Type" : "String", + "Default" : "" + }, + "CfnEndpointUrl" : + { + "Description" : "(Optional) URL to the CloudFormation Endpoint. e.g. https://cloudformation.us-east-1.amazonaws.com", + "Type" : "String", + "Default" : "https://cloudformation.us-east-1.amazonaws.com", + "AllowedPattern" : "^$|^http[s]?://.*$" + }, + "CfnGetPipUrl" : + { + "Description" : "URL to get-pip.py", + "Type" : "String", + "Default" : "https://bootstrap.pypa.io/get-pip.py", + "AllowedPattern" : "^http[s]?://.*\\.py$" + }, + "CfnBootstrapUtilsUrl" : + { + "Description" : "URL to aws-cfn-bootstrap-latest.tar.gz", + "Type" : "String", + "Default" : "https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-latest.tar.gz", + "AllowedPattern" : "^http[s]?://.*\\.tar\\.gz$" + }, + "ToggleCfnInitUpdate" : + { + "Description" : "A/B toggle that forces a change to instance metadata, triggering the cfn-init update sequence", + "Type" : "String", + "Default" : "A", + "AllowedValues" : + [ + "A", + "B" + ] + }, + "ToggleNewInstances" : + { + "Description" : "A/B toggle that forces a change to instance userdata, triggering new instances via the Autoscale update policy", + "Type" : "String", + "Default" : "A", + "AllowedValues" : + [ + "A", + "B" + ] + } + }, + "Conditions" : + { + "ExecuteAppScript" : + { + "Fn::Not" : [ { "Fn::Equals" : [ { "Ref" : "AppScriptUrl" }, "" ] } ] + }, + "CreateAppVolume" : + { + "Fn::Not" : [ { "Fn::Equals" : [ { "Ref" : "AppVolumeDevice" }, "" ] } ] + }, + "UseWamConfig" : + { + "Fn::Not" : [ { "Fn::Equals" : [ { "Ref" : "WatchmakerConfig" }, "" ] } ] + }, + "UseOuPath" : + { + "Fn::Not" : [ { "Fn::Equals" : [ { "Ref" : "WatchmakerOuPath" }, "" ] } ] + }, + "UseAdminGroups" : + { + "Fn::Not" : [ { "Fn::Equals" : [ { "Ref" : "WatchmakerAdminGroups" }, "" ] } ] + }, + "UseEnvironment" : + { + "Fn::Not" : [ { "Fn::Equals" : [ { "Ref" : "WatchmakerEnvironment" }, "" ] } ] + }, + "UseCfnUrl" : + { + "Fn::Not" : [ { "Fn::Equals" : [ { "Ref" : "CfnEndpointUrl" }, "" ] } ] + }, + "InstallUpdates" : + { + "Fn::Not" : [ { "Fn::Equals" : [ { "Ref" : "NoUpdates" }, "true" ] } ] + }, + "Reboot" : + { + "Fn::Not" : [ { "Fn::Equals" : [ { "Ref" : "NoReboot" }, "true" ] } ] + }, + "AssignInstanceRole" : + { + "Fn::Not" : [ { "Fn::Equals" : [ { "Ref" : "InstanceRole" }, "" ] } ] + }, + "AssignPublicIp" : + { + "Fn::Not" : [ { "Fn::Equals" : [ { "Ref" : "NoPublicIp" }, "true" ] } ] + } + }, + "Mappings" : + { + "Distro2RootDevice" : + { + "AmazonLinux" : { "DeviceName" : "xvda" }, + "RedHat" : { "DeviceName" : "sda1" }, + "CentOS" : { "DeviceName" : "sda1" } + } + }, + "Metadata" : + { + "AWS::CloudFormation::Interface" : + { + "ParameterGroups" : + [ + { + "Label" : + { + "default" : "EC2 Instance Configuration" + }, + "Parameters" : + [ + "AmiId", + "AmiDistro", + "InstanceType", + "InstanceRole", + "KeyPairName", + "NoPublicIp", + "NoReboot", + "NoUpdates", + "SecurityGroupIds" + ] + }, + { + "Label" : + { + "default" : "EC2 Watchmaker Configuration" + }, + "Parameters" : + [ + "PypiIndexUrl", + "WatchmakerConfig", + "WatchmakerEnvironment", + "WatchmakerOuPath", + "WatchmakerAdminGroups" + ] + }, + { + "Label" : + { + "default" : "EC2 Application Configuration" + }, + "Parameters" : + [ + "AppScriptUrl", + "AppScriptParams", + "AppScriptShell" + ] + }, + { + "Label" : + { + "default" : "EC2 Application EBS Volume" + }, + "Parameters" : + [ + "AppVolumeDevice", + "AppVolumeMountPath", + "AppVolumeSize", + "AppVolumeType" + ] + }, + { + "Label" : + { + "default" : "AutoScale Configuration" + }, + "Parameters" : + [ + "DesiredCapacity", + "MinCapacity", + "MaxCapacity" + ] + }, + { + "Label" : + { + "default" : "Network Configuration" + }, + "Parameters" : + [ + "SubnetIds" + ] + }, + { + "Label" : + { + "default" : "CloudFormation Configuration" + }, + "Parameters" : + [ + "CfnEndpointUrl", + "CfnGetPipUrl", + "CfnBootstrapUtilsUrl", + "ToggleCfnInitUpdate", + "ToggleNewInstances" + ] + } + ], + "ParameterLabels" : + { + "ToggleCfnInitUpdate" : + { + "default" : "Force Cfn Init Update" + }, + "ToggleNewInstances" : + { + "default" : "Force New Instances" + } + } + } + }, + "Resources" : + { + "WatchmakerAutoScalingGroup" : + { + "Type" : "AWS::AutoScaling::AutoScalingGroup", + "UpdatePolicy" : { + "AutoScalingRollingUpdate" : { + "MinInstancesInService" : "1", + "MaxBatchSize" : "2", + "WaitOnResourceSignals" : "true", + "PauseTime" : "PT30M" + } + }, + "CreationPolicy" : + { + "ResourceSignal" : + { + "Count" : { "Ref" : "DesiredCapacity" }, + "Timeout" : "PT30M" + } + }, + "Properties" : + { + "VPCZoneIdentifier" : { "Ref" : "SubnetIds" }, + "LaunchConfigurationName" : { "Ref" : "WatchmakerLaunchConfig" }, + "MinSize" : { "Ref" : "MinCapacity" }, + "MaxSize" : { "Ref" : "MaxCapacity" }, + "DesiredCapacity" : { "Ref" : "DesiredCapacity" }, + "Tags" : + [ + { + "Key" : "Name", + "Value" : + { "Fn::Join" : [ "", [ + { "Ref" : "AWS::StackName" } + ] ] }, + "PropagateAtLaunch" : "true" + } + ] + } + }, + "WatchmakerLaunchConfig" : + { + "Type" : "AWS::AutoScaling::LaunchConfiguration", + "Metadata" : { + "ToggleCfnInitUpdate" : { "Ref" : "ToggleCfnInitUpdate" }, + "AWS::CloudFormation::Init" : + { + "configSets" : + { + "launch" : + [ + "setup", + "watchmaker-install", + "watchmaker-launch", + { + "Fn::If" : + [ + "ExecuteAppScript", + "make-app", + { "Ref" : "AWS::NoValue" } + ] + }, + "finalize", + { + "Fn::If" : + [ + "Reboot", + "reboot", + { "Ref" : "AWS::NoValue" } + ] + } + ], + "update" : + [ + "setup", + { + "Fn::If" : + [ + "InstallUpdates", + "install-updates", + { "Ref" : "AWS::NoValue" } + ] + }, + "watchmaker-install", + "watchmaker-update", + { + "Fn::If" : + [ + "ExecuteAppScript", + "make-app", + { "Ref" : "AWS::NoValue" } + ] + }, + "finalize", + { + "Fn::If" : + [ + "Reboot", + "reboot", + { "Ref" : "AWS::NoValue" } + ] + } + ] + }, + "setup" : + { + "files" : + { + "/etc/cfn/cfn-hup.conf" : + { + "content" : + { "Fn::Join" : ["", [ + "[main]\n", + "stack=", { "Ref" : "AWS::StackId" }, "\n", + "region=", { "Ref" : "AWS::Region" }, "\n", + { + "Fn::If" : + [ + "AssignInstanceRole", + { "Fn::Join" : [ "", [ + "role=", + { "Ref" : "InstanceRole" }, + "\n" + ] ] }, + "" + ] + }, + { + "Fn::If" : + [ + "UseCfnUrl", + { "Fn::Join" : [ "", [ + "url=", + { "Ref" : "CfnEndpointUrl" }, + "\n" + ] ] }, + "" + ] + }, + "interval=1", "\n", + "verbose=true", "\n" + ]]}, + "mode" : "000400", + "owner" : "root", + "group" : "root" + }, + "/etc/cfn/hooks.d/cfn-auto-reloader.conf" : + { + "content" : + { "Fn::Join" : ["", [ + "[cfn-auto-reloader-hook]\n", + "triggers=post.update\n", + "path=Resources.WatchmakerLaunchConfig.Metadata\n", + "action=/opt/aws/bin/cfn-init -v -c update", + " --stack ", { "Ref" : "AWS::StackName" }, + " --resource WatchmakerLaunchConfig", + { + "Fn::If" : + [ + "AssignInstanceRole", + { "Fn::Join" : [ "", [ + " --role ", + { "Ref" : "InstanceRole" } + ] ] }, + "" + ] + }, + { + "Fn::If" : + [ + "UseCfnUrl", + { "Fn::Join" : [ "", [ + " --url ", + { "Ref" : "CfnEndpointUrl" } + ] ] }, + "" + ] + }, + " --region ", { "Ref" : "AWS::Region" }, "\n", + "runas=root\n" + ]]}, + "mode" : "000400", + "owner" : "root", + "group" : "root" + }, + "/etc/cfn/scripts/watchmaker-install.sh" : + { + "content" : + { "Fn::Join" : [ "", [ + "#!/bin/bash\n\n", + + "PYPI_URL=", { "Ref" : "PypiIndexUrl" }, "\n", + "PYPI_HOST=$(echo $PYPI_URL |sed -e \"s/[^/]*\\/\\/\\([^@]*@\\)\\?\\([^:/]*\\).*/\\2/\")\n", + + "pip install", + " --index-url=\"$PYPI_URL\"", + " --trusted-host=\"$PYPI_HOST\"", + " --allow-all-external", + " --upgrade pip setuptools watchmaker\n\n", + ]]}, + "mode" : "000700", + "owner" : "root", + "group" : "root" + } + }, + "services" : + { + "sysvinit" : + { + "cfn-hup" : + { + "enabled" : "true", + "ensureRunning" : "true", + "files" : + [ + "/etc/cfn/cfn-hup.conf", + "/etc/cfn/hooks.d/cfn-auto-reloader.conf" + ] + } + } + } + }, + "install-updates" : + { + "commands" : + { + "10-install-updates" : + { + "command" : "yum -y update" + } + } + }, + "watchmaker-install" : + { + "commands" : + { + "10-watchmaker-install" : + { + "command" : "bash -xe /etc/cfn/scripts/watchmaker-install.sh" + } + } + }, + "watchmaker-launch" : + { + "commands" : + { + "10-watchmaker-launch" : + { + "command" : + { "Fn::Join" : [ "", [ + "watchmaker -vv", + " --log-dir /var/log/watchmaker", + " --noreboot", + { + "Fn::If" : + [ + "UseWamConfig", + { "Fn::Join" : [ "", [ + " --config \"", + { "Ref" : "WatchmakerConfig" }, + "\"" + ]]}, + "" + ] + }, + { + "Fn::If" : + [ + "UseEnvironment", + { "Fn::Join" : [ "", [ + " --environment \"", + { "Ref" : "WatchmakerEnvironment" }, + "\"" + ]]}, + "" + ] + }, + { + "Fn::If" : + [ + "UseOuPath", + { "Fn::Join" : [ "", [ + " --ou-path \"", + { "Ref" : "WatchmakerOuPath" }, + "\"" + ]]}, + "" + ] + }, + { + "Fn::If" : + [ + "UseAdminGroups", + { "Fn::Join" : [ "", [ + " --admin-groups \"", + { "Ref" : "WatchmakerAdminGroups" }, + "\"" + ]]}, + "" + ] + } + ]]} + } + } + }, + "watchmaker-update" : + { + "commands" : + { + "10-watchmaker-update" : + { + "command" : + { "Fn::Join" : [ "", [ + "watchmaker -vv", + " --log-dir /var/log/watchmaker", + " --saltstates None", + " --noreboot", + { + "Fn::If" : + [ + "UseWamConfig", + { "Fn::Join" : [ "", [ + " --config \"", + { "Ref" : "WatchmakerConfig" }, + "\"" + ]]}, + "" + ] + }, + { + "Fn::If" : + [ + "UseEnvironment", + { "Fn::Join" : [ "", [ + " --environment \"", + { "Ref" : "WatchmakerEnvironment" }, + "\"" + ]]}, + "" + ] + }, + { + "Fn::If" : + [ + "UseOuPath", + { "Fn::Join" : [ "", [ + " --oupath \"", + { "Ref" : "WatchmakerOuPath" }, + "\"" + ]]}, + "" + ] + }, + { + "Fn::If" : + [ + "UseAdminGroups", + { "Fn::Join" : [ "", [ + " --admingroups \"", + { "Ref" : "WatchmakerAdminGroups" }, + "\"" + ]]}, + "" + ] + } + ]]} + } + } + }, + "make-app" : + { + "files" : + { + "/etc/cfn/scripts/make-app" : + { + "source" : { "Ref" : "AppScriptUrl" }, + "mode" : "000700", + "owner" : "root", + "group" : "root" + } + }, + "commands" : + { + "10-make-app" : + { + "command" : + { "Fn::Join" : [ "", [ + { "Ref" : "AppScriptShell" }, + " /etc/cfn/scripts/make-app ", + { "Ref" : "AppScriptParams" } + ]]} + } + } + }, + "finalize" : + { + "commands" : + { + "10-signal-success" : + { + "command" : + { "Fn::Join" : [ "", [ + "/opt/aws/bin/cfn-signal -e 0", + " --stack ", { "Ref" : "AWS::StackName" }, + " --resource WatchmakerAutoScalingGroup", + { + "Fn::If" : + [ + "AssignInstanceRole", + { "Fn::Join" : [ "", [ + " --role ", + { "Ref" : "InstanceRole" } + ] ] }, + "" + ] + }, + { + "Fn::If" : + [ + "UseCfnUrl", + { "Fn::Join" : [ "", [ + " --url ", + { "Ref" : "CfnEndpointUrl" } + ] ] }, + "" + ] + }, + " --region ", { "Ref" : "AWS::Region"}, "\n" + ]]}, + "ignoreErrors" : "true" + } + } + }, + "reboot" : + { + "commands" : + { + "10-reboot" : + { + "command" : "shutdown -r +1 &" + } + } + } + } + }, + "Properties" : + { + "ImageId" : { "Ref" : "AmiId" }, + "InstanceType" : { "Ref" : "InstanceType" }, + "IamInstanceProfile" : + { + "Fn::If" : + [ + "AssignInstanceRole", + { "Ref" : "InstanceRole" }, + { "Ref" : "AWS::NoValue" } + ] + }, + "AssociatePublicIpAddress" : + { + "Fn::If" : + [ + "AssignPublicIp", + "true", + "false" + ] + }, + "BlockDeviceMappings" : + [ + { + "DeviceName" : + { "Fn::Join" : [ "", [ + "/dev/", + { "Fn::FindInMap" : + [ + "Distro2RootDevice", + { "Ref" : "AmiDistro" }, + "DeviceName" + ] + } + ]]}, + "Ebs" : + { + "VolumeType" : "gp2", + "DeleteOnTermination" : "true" + } + }, + { + "Fn::If" : + [ + "CreateAppVolume", + { + "DeviceName" : { "Ref" : "AppVolumeDevice" }, + "Ebs" : + { + "VolumeSize" : { "Ref" : "AppVolumeSize" }, + "VolumeType" : { "Ref" : "AppVolumeType" }, + "DeleteOnTermination" : "true" + } + }, + { "Ref" : "AWS::NoValue" } + ] + } + ], + "KeyName" : + { + "Ref" : "KeyPairName" + }, + "SecurityGroups" : + { + "Ref" : "SecurityGroupIds" + }, + "UserData" : + { + "Fn::Base64" : + { "Fn::Join" : [ "", [ + "Content-Type: multipart/mixed; boundary=\"===============3585321300151562773==\"\n", + "MIME-Version: 1.0\n", + "\n", + + "--===============3585321300151562773==\n", + "Content-Type: text/cloud-config; charset=\"us-ascii\"\n", + "MIME-Version: 1.0\n", + "Content-Transfer-Encoding: 7bit\n", + "Content-Disposition: attachment; filename=\"cloud.cfg\"\n", + "\n", + + "#cloud-config\n", + { + "Fn::If" : + [ + "CreateAppVolume", + { "Fn::Join" : [ "", [ + "bootcmd:\n", + "- cloud-init-per instance mkfs-appvolume mkfs -t ext4 ", + { "Ref" : "AppVolumeDevice" }, + "\n", + "mounts:\n", + "- [ ", + { "Ref" : "AppVolumeDevice" }, ", ", + { "Ref" : "AppVolumeMountPath" }, + " ]\n" + ]]}, + { "Ref" : "AWS::NoValue" } + ] + }, + + "\n", + + "--===============3585321300151562773==\n", + "Content-Type: text/x-shellscript; charset=\"us-ascii\"\n", + "MIME-Version: 1.0\n", + "Content-Transfer-Encoding: 7bit\n", + "Content-Disposition: attachment; filename=\"script.sh\"\n", + "\n", + + "#!/bin/bash -xe\n\n", + + "# CFN LaunchConfig Update Toggle: ", + { "Ref" : "ToggleNewInstances" }, + "\n\n", + + "# Export cert bundle ENVs\n", + "export AWS_CA_BUNDLE=/etc/pki/tls/certs/ca-bundle.crt\n", + "export REQUESTS_CA_BUNDLE=/etc/pki/tls/certs/ca-bundle.crt\n\n", + + "# Get pip\n", + "curl --silent --show-error --retry 5 -L ", + { "Ref" : "CfnGetPipUrl" }, + " | python", "\n\n", + + "# Add pip to path\n", + "hash pip 2> /dev/null || ", + "PATH=\"${PATH}:/usr/local/bin\"", "\n\n", + + "# Upgrade pip and setuptools\n", + "PYPI_URL=", { "Ref" : "PypiIndexUrl" }, "\n", + "PYPI_HOST=$(echo $PYPI_URL |sed -e \"s/[^/]*\\/\\/\\([^@]*@\\)\\?\\([^:/]*\\).*/\\2/\")\n", + "pip install", + " --index-url=\"$PYPI_URL\"", + " --trusted-host=\"$PYPI_HOST\"", + " --allow-all-external", + " --upgrade pip setuptools\n\n", + + "# Fix python urllib3 warnings\n", + "yum -y install gcc python-devel libffi-devel openssl-devel\n", + "pip install", + " --index-url=\"$PYPI_URL\"", + " --trusted-host=\"$PYPI_HOST\"", + " --allow-all-external", + " --upgrade pyopenssl ndg-httpsclient pyasn1\n\n", + + "# Get cfn utils\n", + "pip install", + " --index-url=\"$PYPI_URL\"", + " --trusted-host=\"$PYPI_HOST\"", + " --allow-all-external", + " --upgrade ", + { "Ref" : "CfnBootstrapUtilsUrl" }, + "\n\n", + + "# Remove gcc now that it is no longer needed\n", + "yum -y remove gcc --setopt=clean_requirements_on_remove=1\n\n", + + "# Fixup cfn utils\n", + "INITDIR=$(find -L /opt/aws/apitools/cfn-init/init -name redhat ", + "2> /dev/null || echo /usr/init/redhat)\n", + "chmod 775 ${INITDIR}/cfn-hup\n", + "ln -f -s ${INITDIR}/cfn-hup /etc/rc.d/init.d/cfn-hup\n", + "chkconfig --add cfn-hup\n", + "chkconfig cfn-hup on\n", + "mkdir -p /opt/aws/bin\n", + "BINDIR=$(find -L /opt/aws/apitools/cfn-init -name bin ", + "2> /dev/null || echo /usr/bin)\n", + "for SCRIPT in cfn-elect-cmd-leader cfn-get-metadata cfn-hup ", + "cfn-init cfn-send-cmd-event cfn-send-cmd-result cfn-signal\n", + "do\n", + " ln -s ${BINDIR}/${SCRIPT} /opt/aws/bin/${SCRIPT} 2> /dev/null || ", + " echo Skipped symbolic link, /opt/aws/bin/${SCRIPT} already exists\n", + "done\n\n", + + "# Add cfn-signal to path\n", + "hash cfn-signal 2> /dev/null || ", + "PATH=\"${PATH}:/usr/local/bin:/opt/aws/bin\"", + "\n\n", + + "# Execute cfn-init\n", + "/opt/aws/bin/cfn-init -v -c launch", + " --stack ", { "Ref" : "AWS::StackName" }, + " --resource WatchmakerLaunchConfig", + { + "Fn::If" : + [ + "AssignInstanceRole", + { "Fn::Join" : [ "", [ + " --role ", { "Ref" : "InstanceRole" } + ] ] }, + "" + ] + }, + { + "Fn::If" : + [ + "UseCfnUrl", + { "Fn::Join" : [ "", [ + " --url ", { "Ref" : "CfnEndpointUrl" } + ] ] }, + "" + ] + }, + " --region ", { "Ref" : "AWS::Region" }, " ||", + " ( echo 'ERROR: cfn-init failed! Aborting!';", + " /opt/aws/bin/cfn-signal -e 1", + " --stack ", { "Ref" : "AWS::StackName" }, + " --resource WatchmakerAutoScalingGroup", + { + "Fn::If" : + [ + "AssignInstanceRole", + { "Fn::Join" : [ "", [ + " --role ", { "Ref" : "InstanceRole" } + ] ] }, + "" + ] + }, + { + "Fn::If" : + [ + "UseCfnUrl", + { "Fn::Join" : [ "", [ + " --url ", { "Ref" : "CfnEndpointUrl" } + ] ] }, + "" + ] + }, + " --region ", { "Ref" : "AWS::Region"}, ";", + " exit 1", + " )\n\n", + "--===============3585321300151562773==--" + ] ] } + } + } + } + } +} From de576e212021a5010582043c8a6b261b7e7bbd5d Mon Sep 17 00:00:00 2001 From: Loren Gordon Date: Tue, 11 Apr 2017 15:38:37 -0400 Subject: [PATCH 2/5] Adds cfn template for a linux standalone instance --- .../templates/watchmaker-lx-instance.template | 1114 +++++++++++++++++ 1 file changed, 1114 insertions(+) create mode 100644 docs/files/cfn/templates/watchmaker-lx-instance.template diff --git a/docs/files/cfn/templates/watchmaker-lx-instance.template b/docs/files/cfn/templates/watchmaker-lx-instance.template new file mode 100644 index 000000000..5cd575b31 --- /dev/null +++ b/docs/files/cfn/templates/watchmaker-lx-instance.template @@ -0,0 +1,1114 @@ +{ + "AWSTemplateFormatVersion" : "2010-09-09", + "Description" : "This template deploys a Linux instance using Watchmaker, which applies the DISA STIG.", + "Parameters" : + { + "AmiId" : + { + "Description" : "ID of the AMI to launch", + "Type" : "String", + "AllowedPattern" : "^ami-[0-9a-z]{8}$|^ami-[0-9a-z]{17}$" + }, + "AmiDistro" : + { + "Description" : "Linux distro of the AMI", + "Type" : "String", + "AllowedValues" : + [ + "AmazonLinux", + "CentOS", + "RedHat" + ] + }, + "AppScriptParams" : + { + "Description" : "Parameter string to pass to the application script. Ignored if \"AppScriptUrl\" is blank", + "Type" : "String" + }, + "AppScriptShell" : + { + "Description" : "Shell with which to execute the application script. Ignored if \"AppScriptUrl\" is blank", + "Type" : "String", + "Default" : "bash", + "AllowedValues" : + [ + "bash", + "python" + ] + }, + "AppScriptUrl" : + { + "Description" : "(Optional) URL to the application script. Leave blank to launch without an application script", + "Type" : "String", + "Default" : "", + "AllowedPattern" : "^$|^http[s]?://.*$" + }, + "AppVolumeDevice" : + { + "Description" : "(Optional) Device to mount an extra EBS volume. Leave blank to launch without an extra application volume", + "Type" : "String", + "Default" : "", + "AllowedValues" : + [ + "", + "/dev/xvdf", + "/dev/xvdg", + "/dev/xvdh", + "/dev/xvdi", + "/dev/xvdj" + ] + }, + "AppVolumeMountPath" : + { + "Description" : "Filesystem path to mount the extra app volume. Ignored if \"AppVolumeDevice\" is blank", + "Type" : "String", + "Default" : "/opt/data", + "AllowedPattern" : "/.*" + }, + "AppVolumeType" : + { + "Description" : "Type of EBS volume to create. Ignored if \"AppVolumeDevice\" is blank", + "Type" : "String", + "Default" : "gp2", + "AllowedValues" : + [ + "gp2", + "io1", + "sc1", + "st1", + "standard" + ] + }, + "AppVolumeSize" : + { + "Description" : "Size in GB of the EBS volume to create. Ignored if \"AppVolumeDevice\" is blank", + "Type" : "Number", + "Default" : "1", + "MinValue": "1", + "MaxValue": "16384", + "ConstraintDescription" : "Must be between 1GB and 16384GB." + }, + "KeyPairName" : + { + "Description" : "Public/private key pairs allow you to securely connect to your instance after it launches", + "Type" : "AWS::EC2::KeyPair::KeyName" + }, + "InstanceType" : + { + "Description" : "Amazon EC2 instance type", + "Type" : "String", + "Default" : "t2.micro", + "AllowedValues" : + [ + "t2.micro", + "t2.small", + "t2.medium", + "t2.large", + "c4.large", + "c4.xlarge", + "m4.large", + "m4.xlarge" + ] + }, + "InstanceRole" : + { + "Description" : "(Optional) IAM instance role to apply to the instance", + "Type" : "String", + "Default" : "" + }, + "PrivateIp" : + { + "Description" : "(Optional) Set a static, primary private IP. Leave blank to auto-select a free IP", + "Type" : "String", + "Default" : "" + }, + "NoPublicIp" : + { + "Description" : "Controls whether to assign the instance a public IP. Recommended to leave at \"true\" _unless_ launching in a public subnet", + "Type" : "String", + "Default" : "true", + "AllowedValues" : + [ + "false", + "true" + ] + }, + "NoReboot" : + { + "Description" : "Controls whether to reboot the instance as the last step of cfn-init execution", + "Type" : "String", + "Default" : "false", + "AllowedValues" : + [ + "false", + "true" + ] + }, + "NoUpdates" : + { + "Description" : "Controls whether to run yum update during a stack update (on the initial instance launch, Watchmaker _always_ installs updates)", + "Type" : "String", + "Default" : "false", + "AllowedValues" : + [ + "false", + "true" + ] + }, + "SecurityGroupIds" : + { + "Description" : "List of security groups to apply to the instance", + "Type" : "List" + }, + "SubnetId" : + { + "Type" : "AWS::EC2::Subnet::Id", + "Description" : "ID of the subnet to assign to the instance" + }, + "PypiIndexUrl" : + { + "Description" : "URL to the PyPi Index", + "Type" : "String", + "Default" : "https://pypi.org/simple", + "AllowedPattern" : "^http[s]?://.*$" + }, + "WatchmakerConfig" : + { + "Description" : "(Optional) URL to a Watchmaker config file", + "Type" : "String", + "Default" : "", + "AllowedPattern" : "^$|^http[s]?://.*$" + }, + "WatchmakerEnvironment" : + { + "Description" : "Environment in which the instance is being deployed", + "Type" : "String", + "Default" : "", + "AllowedValues" : + [ + "", + "dev", + "test", + "prod" + ] + }, + "WatchmakerOuPath" : + { + "Description" : "(Optional) DN of the OU to place the instance when joining a domain. If blank and \"WatchmakerEnvironment\" enforces a domain join, the instance will be placed in a default container. Leave blank if not joining a domain, or if \"WatchmakerEnvironment\" is \"false\"", + "Type" : "String", + "Default" : "", + "AllowedPattern" : "^$|^(OU=.+,)+(DC=.+)+$" + }, + "WatchmakerComputerName" : + { + "Description" : "(Optional) Sets the hostname/computername within the OS", + "Type" : "String", + "Default" : "" + }, + "WatchmakerAdminGroups" : + { + "Description" : "(Optional) Colon-separated list of domain groups that should have admin permissions on the EC2 instance", + "Type" : "String", + "Default" : "" + }, + "CfnEndpointUrl" : + { + "Description" : "(Optional) URL to the CloudFormation Endpoint. e.g. https://cloudformation.us-east-1.amazonaws.com", + "Type" : "String", + "Default" : "https://cloudformation.us-east-1.amazonaws.com", + "AllowedPattern" : "^$|^http[s]?://.*$" + }, + "CfnGetPipUrl" : + { + "Description" : "URL to get-pip.py", + "Type" : "String", + "Default" : "https://bootstrap.pypa.io/get-pip.py", + "AllowedPattern" : "^http[s]?://.*\\.py$" + }, + "CfnBootstrapUtilsUrl" : + { + "Description" : "URL to aws-cfn-bootstrap-latest.tar.gz", + "Type" : "String", + "Default" : "https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-latest.tar.gz", + "AllowedPattern" : "^http[s]?://.*\\.tar\\.gz$" + }, + "ToggleCfnInitUpdate" : + { + "Description" : "A/B toggle that forces a change to instance metadata, triggering the cfn-init update sequence", + "Type" : "String", + "Default" : "A", + "AllowedValues" : + [ + "A", + "B" + ] + } + }, + "Conditions" : + { + "ExecuteAppScript" : + { + "Fn::Not" : [ { "Fn::Equals" : [ { "Ref" : "AppScriptUrl" }, "" ] } ] + }, + "CreateAppVolume" : + { + "Fn::Not" : [ { "Fn::Equals" : [ { "Ref" : "AppVolumeDevice" }, "" ] } ] + }, + "UseWamConfig" : + { + "Fn::Not" : [ { "Fn::Equals" : [ { "Ref" : "WatchmakerConfig" }, "" ] } ] + }, + "UseOuPath" : + { + "Fn::Not" : [ { "Fn::Equals" : [ { "Ref" : "WatchmakerOuPath" }, "" ] } ] + }, + "UseComputerName" : + { + "Fn::Not" : [ { "Fn::Equals" : [ { "Ref" : "WatchmakerComputerName" }, "" ] } ] + }, + "UseAdminGroups" : + { + "Fn::Not" : [ { "Fn::Equals" : [ { "Ref" : "WatchmakerAdminGroups" }, "" ] } ] + }, + "UseEnvironment" : + { + "Fn::Not" : [ { "Fn::Equals" : [ { "Ref" : "WatchmakerEnvironment" }, "" ] } ] + }, + "UseCfnUrl" : + { + "Fn::Not" : [ { "Fn::Equals" : [ { "Ref" : "CfnEndpointUrl" }, "" ] } ] + }, + "InstallUpdates" : + { + "Fn::Not" : [ { "Fn::Equals" : [ { "Ref" : "NoUpdates" }, "true" ] } ] + }, + "Reboot" : + { + "Fn::Not" : [ { "Fn::Equals" : [ { "Ref" : "NoReboot" }, "true" ] } ] + }, + "AssignInstanceRole" : + { + "Fn::Not" : [ { "Fn::Equals" : [ { "Ref" : "InstanceRole" }, "" ] } ] + }, + "AssignStaticPrivateIp" : + { + "Fn::Not" : [ { "Fn::Equals" : [ { "Ref" : "PrivateIp" }, "" ] } ] + }, + "AssignPublicIp" : + { + "Fn::Not" : [ { "Fn::Equals" : [ { "Ref" : "NoPublicIp" }, "true" ] } ] + } + }, + "Mappings" : + { + "Distro2RootDevice" : + { + "AmazonLinux" : { "DeviceName" : "xvda" }, + "RedHat" : { "DeviceName" : "sda1" }, + "CentOS" : { "DeviceName" : "sda1" } + } + }, + "Metadata" : + { + "AWS::CloudFormation::Interface" : + { + "ParameterGroups" : + [ + { + "Label" : + { + "default" : "EC2 Instance Configuration" + }, + "Parameters" : + [ + "AmiId", + "AmiDistro", + "InstanceType", + "InstanceRole", + "KeyPairName", + "NoPublicIp", + "NoReboot", + "NoUpdates", + "SecurityGroupIds" + ] + }, + { + "Label" : + { + "default" : "EC2 Watchmaker Configuration" + }, + "Parameters" : + [ + "PypiIndexUrl", + "WatchmakerConfig", + "WatchmakerEnvironment", + "WatchmakerOuPath", + "WatchmakerComputerName", + "WatchmakerAdminGroups" + ] + }, + { + "Label" : + { + "default" : "EC2 Application Configuration" + }, + "Parameters" : + [ + "AppScriptUrl", + "AppScriptParams", + "AppScriptShell" + ] + }, + { + "Label" : + { + "default" : "EC2 Application EBS Volume" + }, + "Parameters" : + [ + "AppVolumeDevice", + "AppVolumeMountPath", + "AppVolumeSize", + "AppVolumeType" + ] + }, + { + "Label" : + { + "default" : "Network Configuration" + }, + "Parameters" : + [ + "PrivateIp", + "SubnetId" + ] + }, + { + "Label" : + { + "default" : "CloudFormation Configuration" + }, + "Parameters" : + [ + "CfnEndpointUrl", + "CfnGetPipUrl", + "CfnBootstrapUtilsUrl", + "ToggleCfnInitUpdate" + ] + } + ], + "ParameterLabels" : + { + "ToggleCfnInitUpdate" : + { + "default" : "Force Cfn Init Update" + } + } + } + }, + "Resources" : + { + "WatchmakerInstance" : + { + "Type" : "AWS::EC2::Instance", + "CreationPolicy" : + { + "ResourceSignal" : + { + "Count" : "1", + "Timeout" : "PT30M" + } + }, + "Metadata" : { + "ToggleCfnInitUpdate" : { "Ref" : "ToggleCfnInitUpdate" }, + "AWS::CloudFormation::Init" : + { + "configSets" : + { + "launch" : + [ + "setup", + "watchmaker-install", + "watchmaker-launch", + { + "Fn::If" : + [ + "ExecuteAppScript", + "make-app", + { "Ref" : "AWS::NoValue" } + ] + }, + "finalize", + { + "Fn::If" : + [ + "Reboot", + "reboot", + { "Ref" : "AWS::NoValue" } + ] + } + ], + "update" : + [ + "setup", + { + "Fn::If" : + [ + "InstallUpdates", + "install-updates", + { "Ref" : "AWS::NoValue" } + ] + }, + "watchmaker-install", + "watchmaker-update", + { + "Fn::If" : + [ + "ExecuteAppScript", + "make-app", + { "Ref" : "AWS::NoValue" } + ] + }, + "finalize", + { + "Fn::If" : + [ + "Reboot", + "reboot", + { "Ref" : "AWS::NoValue" } + ] + } + ] + }, + "setup" : + { + "files" : + { + "/etc/cfn/cfn-hup.conf" : + { + "content" : + { "Fn::Join" : ["", [ + "[main]\n", + "stack=", { "Ref" : "AWS::StackId" }, "\n", + "region=", { "Ref" : "AWS::Region" }, "\n", + { + "Fn::If" : + [ + "AssignInstanceRole", + { "Fn::Join" : [ "", [ + "role=", + { "Ref" : "InstanceRole" }, + "\n" + ] ] }, + "" + ] + }, + { + "Fn::If" : + [ + "UseCfnUrl", + { "Fn::Join" : [ "", [ + "url=", + { "Ref" : "CfnEndpointUrl" }, + "\n" + ] ] }, + "" + ] + }, + "interval=1", "\n", + "verbose=true", "\n" + ]]}, + "mode" : "000400", + "owner" : "root", + "group" : "root" + }, + "/etc/cfn/hooks.d/cfn-auto-reloader.conf" : + { + "content" : + { "Fn::Join" : ["", [ + "[cfn-auto-reloader-hook]\n", + "triggers=post.update\n", + "path=Resources.WatchmakerInstance.Metadata\n", + "action=/opt/aws/bin/cfn-init -v -c update", + " --stack ", { "Ref" : "AWS::StackName" }, + " --resource WatchmakerInstance", + { + "Fn::If" : + [ + "AssignInstanceRole", + { "Fn::Join" : [ "", [ + " --role ", + { "Ref" : "InstanceRole" } + ] ] }, + "" + ] + }, + { + "Fn::If" : + [ + "UseCfnUrl", + { "Fn::Join" : [ "", [ + " --url ", + { "Ref" : "CfnEndpointUrl" } + ] ] }, + "" + ] + }, + " --region ", { "Ref" : "AWS::Region" }, "\n", + "runas=root\n" + ]]}, + "mode" : "000400", + "owner" : "root", + "group" : "root" + }, + "/etc/cfn/scripts/watchmaker-install.sh" : + { + "content" : + { "Fn::Join" : [ "", [ + "#!/bin/bash\n\n", + + "PYPI_URL=", { "Ref" : "PypiIndexUrl" }, "\n", + "PYPI_HOST=$(echo $PYPI_URL |sed -e \"s/[^/]*\\/\\/\\([^@]*@\\)\\?\\([^:/]*\\).*/\\2/\")\n", + + "pip install", + " --index-url=\"$PYPI_URL\"", + " --trusted-host=\"$PYPI_HOST\"", + " --allow-all-external", + " --upgrade pip setuptools watchmaker\n\n", + ]]}, + "mode" : "000700", + "owner" : "root", + "group" : "root" + } + }, + "services" : + { + "sysvinit" : + { + "cfn-hup" : + { + "enabled" : "true", + "ensureRunning" : "true", + "files" : + [ + "/etc/cfn/cfn-hup.conf", + "/etc/cfn/hooks.d/cfn-auto-reloader.conf" + ] + } + } + } + }, + "install-updates" : + { + "commands" : + { + "10-install-updates" : + { + "command" : "yum -y update" + } + } + }, + "watchmaker-install" : + { + "commands" : + { + "10-watchmaker-install" : + { + "command" : "bash -xe /etc/cfn/scripts/watchmaker-install.sh" + } + } + }, + "watchmaker-launch" : + { + "commands" : + { + "10-watchmaker-launch" : + { + "command" : + { "Fn::Join" : [ "", [ + "watchmaker -vv", + " --log-dir /var/log/watchmaker", + " --noreboot", + { + "Fn::If" : + [ + "UseWamConfig", + { "Fn::Join" : [ "", [ + " --config \"", + { "Ref" : "WatchmakerConfig" }, + "\"" + ]]}, + "" + ] + }, + { + "Fn::If" : + [ + "UseEnvironment", + { "Fn::Join" : [ "", [ + " --environment \"", + { "Ref" : "WatchmakerEnvironment" }, + "\"" + ]]}, + "" + ] + }, + { + "Fn::If" : + [ + "UseOuPath", + { "Fn::Join" : [ "", [ + " --ou-path \"", + { "Ref" : "WatchmakerOuPath" }, + "\"" + ]]}, + "" + ] + }, + { + "Fn::If" : + [ + "UseComputerName", + { "Fn::Join" : [ "", [ + " --computer-name \"", + { "Ref" : "WatchmakerComputerName" }, + "\"" + ]]}, + "" + ] + }, + { + "Fn::If" : + [ + "UseAdminGroups", + { "Fn::Join" : [ "", [ + " --admin-groups \"", + { "Ref" : "WatchmakerAdminGroups" }, + "\"" + ]]}, + "" + ] + } + ]]} + } + } + }, + "watchmaker-update" : + { + "commands" : + { + "10-watchmaker-update" : + { + "command" : + { "Fn::Join" : [ "", [ + "watchmaker -vv", + " --log-dir /var/log/watchmaker", + " --saltstates None", + " --noreboot", + { + "Fn::If" : + [ + "UseWamConfig", + { "Fn::Join" : [ "", [ + " --config \"", + { "Ref" : "WatchmakerConfig" }, + "\"" + ]]}, + "" + ] + }, + { + "Fn::If" : + [ + "UseEnvironment", + { "Fn::Join" : [ "", [ + " --environment \"", + { "Ref" : "WatchmakerEnvironment" }, + "\"" + ]]}, + "" + ] + }, + { + "Fn::If" : + [ + "UseOuPath", + { "Fn::Join" : [ "", [ + " --oupath \"", + { "Ref" : "WatchmakerOuPath" }, + "\"" + ]]}, + "" + ] + }, + { + "Fn::If" : + [ + "UseComputerName", + { "Fn::Join" : [ "", [ + " --computer-name \"", + { "Ref" : "WatchmakerComputerName" }, + "\"" + ]]}, + "" + ] + }, + { + "Fn::If" : + [ + "UseAdminGroups", + { "Fn::Join" : [ "", [ + " --admingroups \"", + { "Ref" : "WatchmakerAdminGroups" }, + "\"" + ]]}, + "" + ] + } + ]]} + } + } + }, + "make-app" : + { + "files" : + { + "/etc/cfn/scripts/make-app" : + { + "source" : { "Ref" : "AppScriptUrl" }, + "mode" : "000700", + "owner" : "root", + "group" : "root" + } + }, + "commands" : + { + "10-make-app" : + { + "command" : + { "Fn::Join" : [ "", [ + { "Ref" : "AppScriptShell" }, + " /etc/cfn/scripts/make-app ", + { "Ref" : "AppScriptParams" } + ]]} + } + } + }, + "finalize" : + { + "commands" : + { + "10-signal-success" : + { + "command" : + { "Fn::Join" : [ "", [ + "/opt/aws/bin/cfn-signal -e 0", + " --stack ", { "Ref" : "AWS::StackName" }, + " --resource WatchmakerInstance", + { + "Fn::If" : + [ + "AssignInstanceRole", + { "Fn::Join" : [ "", [ + " --role ", + { "Ref" : "InstanceRole" } + ] ] }, + "" + ] + }, + { + "Fn::If" : + [ + "UseCfnUrl", + { "Fn::Join" : [ "", [ + " --url ", + { "Ref" : "CfnEndpointUrl" } + ] ] }, + "" + ] + }, + " --region ", { "Ref" : "AWS::Region"}, "\n" + ]]}, + "ignoreErrors" : "true" + } + } + }, + "reboot" : + { + "commands" : + { + "10-reboot" : + { + "command" : "shutdown -r +1 &" + } + } + } + } + }, + "Properties" : + { + "ImageId" : { "Ref" : "AmiId" }, + "InstanceType" : { "Ref" : "InstanceType" }, + "IamInstanceProfile" : + { + "Fn::If" : + [ + "AssignInstanceRole", + { "Ref" : "InstanceRole" }, + { "Ref" : "AWS::NoValue" } + ] + }, + "Tags" : + [ + { + "Key" : "Name", + "Value" : + { "Fn::Join" : [ "", [ + { "Ref" : "AWS::StackName" } + ]]} + } + ], + "BlockDeviceMappings" : + [ + { + "DeviceName" : + { "Fn::Join" : [ "", [ + "/dev/", + { "Fn::FindInMap" : + [ + "Distro2RootDevice", + { "Ref" : "AmiDistro" }, + "DeviceName" + ] + } + ]]}, + "Ebs" : + { + "VolumeType" : "gp2", + "DeleteOnTermination" : "true" + } + }, + { + "Fn::If" : + [ + "CreateAppVolume", + { + "DeviceName" : { "Ref" : "AppVolumeDevice" }, + "Ebs" : + { + "VolumeSize" : { "Ref" : "AppVolumeSize" }, + "VolumeType" : { "Ref" : "AppVolumeType" }, + "DeleteOnTermination" : "true" + } + }, + { "Ref" : "AWS::NoValue" } + ] + } + ], + "KeyName" : + { + "Ref" : "KeyPairName" + }, + "NetworkInterfaces": + [ + { + "DeviceIndex" : "0", + "AssociatePublicIpAddress" : + { + "Fn::If" : + [ + "AssignPublicIp", + "true", + "false" + ] + }, + "PrivateIpAddress" : + { + "Fn::If" : + [ + "AssignStaticPrivateIp", + { "Ref" : "PrivateIp" }, + { "Ref" : "AWS::NoValue" } + ] + }, + "GroupSet" : { "Ref": "SecurityGroupIds" }, + "SubnetId": { "Ref" : "SubnetId" } + } + ], + "UserData" : + { + "Fn::Base64" : + { "Fn::Join" : [ "", [ + "Content-Type: multipart/mixed; boundary=\"===============3585321300151562773==\"\n", + "MIME-Version: 1.0\n", + "\n", + + "--===============3585321300151562773==\n", + "Content-Type: text/cloud-config; charset=\"us-ascii\"\n", + "MIME-Version: 1.0\n", + "Content-Transfer-Encoding: 7bit\n", + "Content-Disposition: attachment; filename=\"cloud.cfg\"\n", + "\n", + + "#cloud-config\n", + { + "Fn::If" : + [ + "CreateAppVolume", + { "Fn::Join" : [ "", [ + "bootcmd:\n", + "- cloud-init-per instance mkfs-appvolume mkfs -t ext4 ", + { "Ref" : "AppVolumeDevice" }, + "\n", + "mounts:\n", + "- [ ", + { "Ref" : "AppVolumeDevice" }, ", ", + { "Ref" : "AppVolumeMountPath" }, + " ]\n" + ]]}, + { "Ref" : "AWS::NoValue" } + ] + }, + + "\n", + + "--===============3585321300151562773==\n", + "Content-Type: text/x-shellscript; charset=\"us-ascii\"\n", + "MIME-Version: 1.0\n", + "Content-Transfer-Encoding: 7bit\n", + "Content-Disposition: attachment; filename=\"script.sh\"\n", + "\n", + + "#!/bin/bash -xe\n\n", + + "# Export cert bundle ENVs\n", + "export AWS_CA_BUNDLE=/etc/pki/tls/certs/ca-bundle.crt\n", + "export REQUESTS_CA_BUNDLE=/etc/pki/tls/certs/ca-bundle.crt\n\n", + + "# Get pip\n", + "curl --silent --show-error --retry 5 -L ", + { "Ref" : "CfnGetPipUrl" }, + " | python", "\n\n", + + "# Add pip to path\n", + "hash pip 2> /dev/null || ", + "PATH=\"${PATH}:/usr/local/bin\"", "\n\n", + + "# Upgrade pip and setuptools\n", + "PYPI_URL=", { "Ref" : "PypiIndexUrl" }, "\n", + "PYPI_HOST=$(echo $PYPI_URL |sed -e \"s/[^/]*\\/\\/\\([^@]*@\\)\\?\\([^:/]*\\).*/\\2/\")\n", + "pip install", + " --index-url=\"$PYPI_URL\"", + " --trusted-host=\"$PYPI_HOST\"", + " --allow-all-external", + " --upgrade pip setuptools\n\n", + + "# Fix python urllib3 warnings\n", + "yum -y install gcc python-devel libffi-devel openssl-devel\n", + "pip install", + " --index-url=\"$PYPI_URL\"", + " --trusted-host=\"$PYPI_HOST\"", + " --allow-all-external", + " --upgrade pyopenssl ndg-httpsclient pyasn1\n\n", + + "# Get cfn utils\n", + "pip install", + " --index-url=\"$PYPI_URL\"", + " --trusted-host=\"$PYPI_HOST\"", + " --allow-all-external", + " --upgrade ", + { "Ref" : "CfnBootstrapUtilsUrl" }, + "\n\n", + + "# Remove gcc now that it is no longer needed\n", + "yum -y remove gcc --setopt=clean_requirements_on_remove=1\n\n", + + "# Fixup cfn utils\n", + "INITDIR=$(find -L /opt/aws/apitools/cfn-init/init -name redhat ", + "2> /dev/null || echo /usr/init/redhat)\n", + "chmod 775 ${INITDIR}/cfn-hup\n", + "ln -f -s ${INITDIR}/cfn-hup /etc/rc.d/init.d/cfn-hup\n", + "chkconfig --add cfn-hup\n", + "chkconfig cfn-hup on\n", + "mkdir -p /opt/aws/bin\n", + "BINDIR=$(find -L /opt/aws/apitools/cfn-init -name bin ", + "2> /dev/null || echo /usr/bin)\n", + "for SCRIPT in cfn-elect-cmd-leader cfn-get-metadata cfn-hup ", + "cfn-init cfn-send-cmd-event cfn-send-cmd-result cfn-signal\n", + "do\n", + " ln -s ${BINDIR}/${SCRIPT} /opt/aws/bin/${SCRIPT} 2> /dev/null || ", + " echo Skipped symbolic link, /opt/aws/bin/${SCRIPT} already exists\n", + "done\n\n", + + "# Add cfn-signal to path\n", + "hash cfn-signal 2> /dev/null || ", + "PATH=\"${PATH}:/usr/local/bin:/opt/aws/bin\"", + "\n\n", + + "# Execute cfn-init\n", + "/opt/aws/bin/cfn-init -v -c launch", + " --stack ", { "Ref" : "AWS::StackName" }, + " --resource WatchmakerInstance", + { + "Fn::If" : + [ + "AssignInstanceRole", + { "Fn::Join" : [ "", [ + " --role ", { "Ref" : "InstanceRole" } + ] ] }, + "" + ] + }, + { + "Fn::If" : + [ + "UseCfnUrl", + { "Fn::Join" : [ "", [ + " --url ", { "Ref" : "CfnEndpointUrl" } + ] ] }, + "" + ] + }, + " --region ", { "Ref" : "AWS::Region" }, " ||", + " ( echo 'ERROR: cfn-init failed! Aborting!';", + " /opt/aws/bin/cfn-signal -e 1", + " --stack ", { "Ref" : "AWS::StackName" }, + " --resource WatchmakerInstance", + { + "Fn::If" : + [ + "AssignInstanceRole", + { "Fn::Join" : [ "", [ + " --role ", { "Ref" : "InstanceRole" } + ] ] }, + "" + ] + }, + { + "Fn::If" : + [ + "UseCfnUrl", + { "Fn::Join" : [ "", [ + " --url ", { "Ref" : "CfnEndpointUrl" } + ] ] }, + "" + ] + }, + " --region ", { "Ref" : "AWS::Region"}, ";", + " exit 1", + " )\n\n", + "--===============3585321300151562773==--" + ] ] } + } + } + } + }, + "Outputs" : + { + "WatchmakerInstanceId" : + { + "Value" : { "Ref" : "WatchmakerInstance" }, + "Description" : "Instance ID" + } + } +} From 876b160f2b0a787a03781388ca8b970245f70e7e Mon Sep 17 00:00:00 2001 From: Loren Gordon Date: Tue, 11 Apr 2017 20:42:04 -0400 Subject: [PATCH 3/5] Adds cfn template for a windows autoscaling group --- .../watchmaker-win-autoscale.template | 963 ++++++++++++++++++ 1 file changed, 963 insertions(+) create mode 100644 docs/files/cfn/templates/watchmaker-win-autoscale.template diff --git a/docs/files/cfn/templates/watchmaker-win-autoscale.template b/docs/files/cfn/templates/watchmaker-win-autoscale.template new file mode 100644 index 000000000..71a280ee0 --- /dev/null +++ b/docs/files/cfn/templates/watchmaker-win-autoscale.template @@ -0,0 +1,963 @@ +{ + "AWSTemplateFormatVersion" : "2010-09-09", + "Description" : "This template creates an Autoscaling Group and Launch Configuration that deploys Windows instances with Watchmaker, which applies the DISA STIG.", + "Parameters" : + { + "AmiId" : + { + "Description" : "ID of the AMI to launch", + "Type" : "String", + "AllowedPattern" : "^ami-[0-9a-z]{8}$|^ami-[0-9a-z]{17}$" + }, + "AppScriptParams" : + { + "Description" : "Parameter string to pass to the application script. Ignored if \"AppScriptUrl\" is blank", + "Type" : "String" + }, + "AppScriptShell" : + { + "Description" : "Shell with which to execute the application script. Ignored if \"AppScriptUrl\" is blank", + "Type" : "String", + "Default" : "powershell", + "AllowedValues" : + [ + "cmd", + "powershell" + ] + }, + "AppScriptUrl" : + { + "Description" : "(Optional) URL to the application script. Leave blank to launch without an application script", + "Type" : "String", + "Default" : "", + "AllowedPattern" : "^$|^http[s]?://.*$" + }, + "AppVolumeDevice" : + { + "Description" : "(Optional) Device to mount an extra EBS volume. Leave blank to launch without an extra application volume", + "Type" : "String", + "Default" : "", + "AllowedValues" : + [ + "", + "xvdf", + "xvde", + "xvdg", + "xvdh", + "xvdi" + ] + }, + "AppVolumeType" : + { + "Description" : "Type of EBS volume to create. Ignored if \"AppVolumeDevice\" is blank", + "Type" : "String", + "Default" : "gp2", + "AllowedValues" : + [ + "gp2", + "io1", + "sc1", + "st1", + "standard" + ] + }, + "AppVolumeSize" : + { + "Description" : "Size in GB of the EBS volume to create. Ignored if \"AppVolumeDevice\" is blank", + "Type" : "Number", + "Default" : "1", + "MinValue": "1", + "MaxValue": "16384", + "ConstraintDescription" : "Must be between 1GB and 16384GB." + }, + "KeyPairName" : + { + "Description" : "Public/private key pairs allow you to securely connect to your instance after it launches", + "Type" : "AWS::EC2::KeyPair::KeyName" + }, + "InstanceType" : + { + "Description" : "Amazon EC2 instance type", + "Type" : "String", + "Default" : "t2.micro", + "AllowedValues" : + [ + "t2.micro", + "t2.small", + "t2.medium", + "t2.large", + "c4.large", + "c4.xlarge", + "m4.large", + "m4.xlarge" + ] + }, + "InstanceRole" : + { + "Description" : "(Optional) IAM instance role to apply to the instance(s)", + "Type" : "String", + "Default" : "" + }, + "MinCapacity" : + { + "Description" : "Minimum number of instances in the Autoscaling Group", + "Type" : "Number", + "Default" : "1" + }, + "MaxCapacity" : + { + "Description" : "Maximum number of instances in the Autoscaling Group", + "Type" : "Number", + "Default" : "2" + }, + "DesiredCapacity" : + { + "Description" : "Desired number of instances in the Autoscaling Group", + "Type" : "Number", + "Default" : "1" + }, + "NoPublicIp" : + { + "Description" : "Controls whether to assign the instance a public IP. Recommended to leave at \"true\" _unless_ launching in a public subnet", + "Type" : "String", + "Default" : "true", + "AllowedValues" : + [ + "false", + "true" + ] + }, + "NoReboot" : + { + "Description" : "Controls whether to reboot the instance as the last step of cfn-init execution", + "Type" : "String", + "Default" : "false", + "AllowedValues" : + [ + "false", + "true" + ] + }, + "SecurityGroupIds" : + { + "Description" : "List of security groups to apply to the instance", + "Type" : "List" + }, + "SubnetIds" : + { + "Type" : "List", + "Description" : "List of subnets to associate to the Autoscaling Group" + }, + "PypiIndexUrl" : + { + "Description" : "URL to the PyPi Index", + "Type" : "String", + "Default" : "https://pypi.org/simple", + "AllowedPattern" : "^http[s]?://.*$" + }, + "PythonInstaller" : + { + "Description" : "URL to the Python Installer Executable", + "Type" : "String", + "Default" : "https://www.python.org/ftp/python/3.6.0/python-3.6.0-amd64.exe", + "AllowedPattern" : "^http[s]?://.*\\.exe$" + }, + "WatchmakerBootstrapper" : + { + "Description" : "URL to the Watchmaker PowerShell bootstrapper for Windows", + "Type" : "String", + "Default" : "https://raw.githubusercontent.com/plus3it/watchmaker/master/docs/files/bootstrap/watchmaker-bootstrap.ps1", + "AllowedPattern" : "^$|^http[s]?://.*\\.ps1$" + }, + "WatchmakerConfig" : + { + "Description" : "(Optional) URL to a Watchmaker config file", + "Type" : "String", + "Default" : "", + "AllowedPattern" : "^$|^http[s]?://.*$" + }, + "WatchmakerEnvironment" : + { + "Description" : "Environment in which the instance is being deployed", + "Type" : "String", + "Default" : "", + "AllowedValues" : + [ + "", + "dev", + "test", + "prod" + ] + }, + "WatchmakerOuPath" : + { + "Description" : "(Optional) DN of the OU to place the instance when joining a domain. If blank and \"WatchmakerEnvironment\" enforces a domain join, the instance will be placed in a default container. Leave blank if not joining a domain, or if \"WatchmakerEnvironment\" is \"$false\"", + "Type" : "String", + "Default" : "", + "AllowedPattern" : "^$|^(OU=.+,)+(DC=.+)+$" + }, + "WatchmakerAdminGroups" : + { + "Description" : "(Optional) Colon-separated list of domain groups that should have admin permissions on the EC2 instance", + "Type" : "String", + "Default" : "" + }, + "CfnEndpointUrl" : + { + "Description" : "(Optional) URL to the CloudFormation Endpoint. e.g. https://cloudformation.us-east-1.amazonaws.com", + "Type" : "String", + "Default" : "https://cloudformation.us-east-1.amazonaws.com", + "AllowedPattern" : "^$|^http[s]?://.*$" + }, + "ToggleCfnInitUpdate" : + { + "Description" : "A/B toggle that forces a change to instance metadata, triggering the cfn-init update sequence", + "Type" : "String", + "Default" : "A", + "AllowedValues" : + [ + "A", + "B" + ] + }, + "ToggleNewInstances" : + { + "Description" : "A/B toggle that forces a change to instance userdata, triggering new instances via the Autoscale update policy", + "Type" : "String", + "Default" : "A", + "AllowedValues" : + [ + "A", + "B" + ] + } + }, + "Conditions" : + { + "ExecuteAppScript" : + { + "Fn::Not" : [ { "Fn::Equals" : [ { "Ref" : "AppScriptUrl" }, "" ] } ] + }, + "CreateAppVolume" : + { + "Fn::Not" : [ { "Fn::Equals" : [ { "Ref" : "AppVolumeDevice" }, "" ] } ] + }, + "UseWamConfig" : + { + "Fn::Not" : [ { "Fn::Equals" : [ { "Ref" : "WatchmakerConfig" }, "" ] } ] + }, + "UseOuPath" : + { + "Fn::Not" : [ { "Fn::Equals" : [ { "Ref" : "WatchmakerOuPath" }, "" ] } ] + }, + "UseAdminGroups" : + { + "Fn::Not" : [ { "Fn::Equals" : [ { "Ref" : "WatchmakerAdminGroups" }, "" ] } ] + }, + "UseEnvironment" : + { + "Fn::Not" : [ { "Fn::Equals" : [ { "Ref" : "WatchmakerEnvironment" }, "" ] } ] + }, + "UseCfnUrl" : + { + "Fn::Not" : [ { "Fn::Equals" : [ { "Ref" : "CfnEndpointUrl" }, "" ] } ] + }, + "Reboot" : + { + "Fn::Not" : [ { "Fn::Equals" : [ { "Ref" : "NoReboot" }, "true" ] } ] + }, + "AssignInstanceRole" : + { + "Fn::Not" : [ { "Fn::Equals" : [ { "Ref" : "InstanceRole" }, "" ] } ] + }, + "AssignPublicIp" : + { + "Fn::Not" : [ { "Fn::Equals" : [ { "Ref" : "NoPublicIp" }, "true" ] } ] + } + }, + "Mappings" : + { + "ShellCommandMap" : + { + "powershell" : + { + "command" : "powershell.exe -NoLogo -NoProfile -NonInteractive -ExecutionPolicy Bypass" + }, + "cmd" : + { + "command" : "cmd.exe" + } + } + }, + "Metadata" : + { + "AWS::CloudFormation::Interface" : + { + "ParameterGroups" : + [ + { + "Label" : + { + "default" : "EC2 Instance Configuration" + }, + "Parameters" : + [ + "AmiId", + "InstanceType", + "InstanceRole", + "KeyPairName", + "NoPublicIp", + "NoReboot", + "NoUpdates", + "SecurityGroupIds" + ] + }, + { + "Label" : + { + "default" : "EC2 Watchmaker Configuration" + }, + "Parameters" : + [ + "PythonInstaller", + "PypiIndexUrl", + "WatchmakerBootstrapper", + "WatchmakerConfig", + "WatchmakerEnvironment", + "WatchmakerOuPath", + "WatchmakerAdminGroups" + ] + }, + { + "Label" : + { + "default" : "EC2 Application Configuration" + }, + "Parameters" : + [ + "AppScriptUrl", + "AppScriptParams", + "AppScriptShell" + ] + }, + { + "Label" : + { + "default" : "EC2 Application EBS Volume" + }, + "Parameters" : + [ + "AppVolumeDevice", + "AppVolumeSize", + "AppVolumeType" + ] + }, + { + "Label" : + { + "default" : "AutoScale Configuration" + }, + "Parameters" : + [ + "DesiredCapacity", + "MinCapacity", + "MaxCapacity" + ] + }, + { + "Label" : + { + "default" : "Network Configuration" + }, + "Parameters" : + [ + "SubnetIds" + ] + }, + { + "Label" : + { + "default" : "CloudFormation Configuration" + }, + "Parameters" : + [ + "CfnEndpointUrl", + "ToggleCfnInitUpdate", + "ToggleNewInstances" + ] + } + ], + "ParameterLabels" : + { + "ToggleCfnInitUpdate" : + { + "default" : "Force Cfn Init Update" + }, + "ToggleNewInstances" : + { + "default" : "Force New Instances" + } + } + } + }, + "Resources" : + { + "WatchmakerAutoScalingGroup" : + { + "Type" : "AWS::AutoScaling::AutoScalingGroup", + "UpdatePolicy" : { + "AutoScalingRollingUpdate" : { + "MinInstancesInService" : "1", + "MaxBatchSize" : "2", + "WaitOnResourceSignals" : "true", + "PauseTime" : "PT60M" + } + }, + "CreationPolicy" : + { + "ResourceSignal" : + { + "Count" : { "Ref" : "DesiredCapacity" }, + "Timeout" : "PT60M" + } + }, + "Properties" : + { + "VPCZoneIdentifier" : { "Ref" : "SubnetIds" }, + "LaunchConfigurationName" : { "Ref" : "WatchmakerLaunchConfig" }, + "MinSize" : { "Ref" : "MinCapacity" }, + "MaxSize" : { "Ref" : "MaxCapacity" }, + "DesiredCapacity" : { "Ref" : "DesiredCapacity" }, + "Tags" : + [ + { + "Key" : "Name", + "Value" : + { "Fn::Join" : [ "", [ + { "Ref" : "AWS::StackName" } + ] ] }, + "PropagateAtLaunch" : "true" + } + ] + } + }, + "WatchmakerLaunchConfig" : + { + "Type" : "AWS::AutoScaling::LaunchConfiguration", + "Metadata" : { + "ToggleCfnInitUpdate" : { "Ref" : "ToggleCfnInitUpdate" }, + "AWS::CloudFormation::Init" : + { + "configSets" : + { + "launch" : + [ + "setup", + "watchmaker-launch", + { + "Fn::If" : + [ + "ExecuteAppScript", + "make-app", + { "Ref" : "AWS::NoValue" } + ] + }, + { + "Fn::If" : + [ + "Reboot", + "reboot", + { "Ref" : "AWS::NoValue" } + ] + }, + "finalize" + ], + "update" : + [ + "setup", + "watchmaker-update", + { + "Fn::If" : + [ + "ExecuteAppScript", + "make-app", + { "Ref" : "AWS::NoValue" } + ] + }, + { + "Fn::If" : + [ + "Reboot", + "reboot", + { "Ref" : "AWS::NoValue" } + ] + }, + "finalize" + ] + }, + "setup" : + { + "files" : + { + "c:\\cfn\\cfn-hup.conf" : + { + "content" : + { "Fn::Join" : ["", [ + "[main]\n", + "stack=", { "Ref" : "AWS::StackId" }, "\n", + "region=", { "Ref" : "AWS::Region" }, "\n", + { + "Fn::If" : + [ + "AssignInstanceRole", + { "Fn::Join" : [ "", [ + "role=", + { "Ref" : "InstanceRole" }, + "\n" + ] ] }, + "" + ] + }, + { + "Fn::If" : + [ + "UseCfnUrl", + { "Fn::Join" : [ "", [ + "url=", + { "Ref" : "CfnEndpointUrl" }, + "\n" + ] ] }, + "" + ] + }, + "interval=1", "\n", + "verbose=true", "\n" + ]]} + }, + "c:\\cfn\\hooks.d\\cfn-auto-reloader.conf" : + { + "content" : + { "Fn::Join" : ["", [ + "[cfn-auto-reloader-hook]\n", + "triggers=post.update\n", + "path=Resources.WatchmakerLaunchConfig.Metadata\n", + "action=cfn-init.exe -v -c update", + " --stack ", { "Ref" : "AWS::StackName" }, + " --resource WatchmakerLaunchConfig", + { + "Fn::If" : + [ + "AssignInstanceRole", + { "Fn::Join" : [ "", [ + " --role ", + { "Ref" : "InstanceRole" } + ] ] }, + "" + ] + }, + { + "Fn::If" : + [ + "UseCfnUrl", + { "Fn::Join" : [ "", [ + " --url ", + { "Ref" : "CfnEndpointUrl" } + ] ] }, + "" + ] + }, + " --region ", { "Ref" : "AWS::Region" }, "\n" + ]]} + }, + "c:\\cfn\\scripts\\watchmaker-install.ps1" : + { + "content" : + { "Fn::Join" : ["", [ + "$BootstrapUrl = \"", { "Ref" : "WatchmakerBootstrapper" }, "\"\n", + "$PythonUrl = \"", { "Ref" : "PythonInstaller" }, "\"\n", + "$PypiUrl = \"", { "Ref" : "PypiIndexUrl" }, "\"\n\n", + + "# Get the host\n", + "$PypiHost=\"$(([System.Uri]$PypiUrl).Host)\"\n\n", + + "# Download bootstrap file\n", + "$BootstrapFile = \"${Env:Temp}\\$(${BootstrapUrl}.split('/')[-1])\"\n", + "(New-Object System.Net.WebClient).DownloadFile(\"$BootstrapUrl\", \"$BootstrapFile\")\n\n", + + "# Install python\n", + "& \"$BootstrapFile\" -PythonUrl \"$PythonUrl\" -Verbose -ErrorAction Stop\n\n", + + "# Install watchmaker\n", + "pip install --index-url=\"$PypiUrl\" --trusted-host=\"$PypiHost\" --allow-all-external --upgrade pip setuptools watchmaker\n\n" + ]]} + } + }, + "services" : + { + "windows" : + { + "cfn-hup" : + { + "enabled" : "true", + "ensureRunning" : "true", + "files" : + [ + "c:\\cfn\\cfn-hup.conf", + "c:\\cfn\\hooks.d\\cfn-auto-reloader.conf" + ] + } + } + } + }, + "watchmaker-launch" : + { + "commands" : + { + "10-watchmaker-launch" : + { + "command" : + { "Fn::Join" : [ "", [ + { "Fn::FindInMap" : + [ + "ShellCommandMap", + "powershell", + "command" + ] + }, + " \"& {", + " c:\\cfn\\scripts\\watchmaker-install.ps1;", + " watchmaker -vv", + " --log-dir C:\\Watchmaker\\Logs", + " --no-reboot", + { + "Fn::If" : + [ + "UseWamConfig", + { "Fn::Join" : [ "", [ + " --config \\\"", + { "Ref" : "WatchmakerConfig" }, + "\\\"" + ]]}, + "" + ] + }, + { + "Fn::If" : + [ + "UseEnvironment", + { "Fn::Join" : [ "", [ + " --env \\\"", + { "Ref" : "WatchmakerEnvironment" }, + "\\\"" + ]]}, + "" + ] + }, + { + "Fn::If" : + [ + "UseOuPath", + { "Fn::Join" : [ "", [ + " --ou-path \\\"", + { "Ref" : "WatchmakerOuPath" }, + "\\\"" + ]]}, + "" + ] + }, + { + "Fn::If" : + [ + "UseAdminGroups", + { "Fn::Join" : [ "", [ + " --admin-groups \\\"", + { "Ref" : "WatchmakerAdminGroups" }, + "\\\"" + ]]}, + "" + ] + }, + " }\"" + ]]} + } + } + }, + "watchmaker-update" : + { + "commands" : + { + "10-watchmaker-update" : + { + "command" : + { "Fn::Join" : [ "", [ + { "Fn::FindInMap" : + [ + "ShellCommandMap", + "powershell", + "command" + ] + }, + " \"& {", + " c:\\cfn\\scripts\\watchmaker-install.ps1;", + " watchmaker -vv", + " --log-dir C:\\Watchmaker\\Logs", + " --salt-states None", + " --no-reboot", + { + "Fn::If" : + [ + "UseWamConfig", + { "Fn::Join" : [ "", [ + " --config \\\"", + { "Ref" : "WatchmakerConfig" }, + "\\\"" + ]]}, + "" + ] + }, + { + "Fn::If" : + [ + "UseEnvironment", + { "Fn::Join" : [ "", [ + " --env \\\"", + { "Ref" : "WatchmakerEnvironment" }, + "\\\"" + ]]}, + "" + ] + }, + { + "Fn::If" : + [ + "UseOuPath", + { "Fn::Join" : [ "", [ + " --ou-path \\\"", + { "Ref" : "WatchmakerOuPath" }, + "\\\"" + ]]}, + "" + ] + }, + { + "Fn::If" : + [ + "UseAdminGroups", + { "Fn::Join" : [ "", [ + " --admin-groups \\\"", + { "Ref" : "WatchmakerAdminGroups" }, + "\\\"" + ]]}, + "" + ] + }, + " }\"" + ]]} + } + } + }, + "make-app" : + { + "files" : + { + "c:\\cfn\\scripts\\make-app" : + { + "source" : { "Ref" : "AppScriptUrl" } + } + }, + "commands" : + { + "10-make-app" : + { + "command" : + { "Fn::Join" : [ "", [ + { "Fn::FindInMap" : + [ + "ShellCommandMap", + { "Ref" : "AppScriptShell" }, + "command" + ] + }, + " c:\\cfn\\scripts\\make-app ", + { "Ref" : "AppScriptParams" } + ]]}, + "waitAfterCompletion" : "0" + } + } + }, + "reboot" : + { + "commands" : + { + "10-reboot" : + { + "command" : "powershell.exe \"Restart-Computer -Force -Verbose\"", + "waitAfterCompletion" : "forever" + } + } + }, + "finalize" : + { + "commands" : + { + "10-signal-success" : + { + "command" : + { "Fn::Join" : [ "", [ + "cfn-signal.exe -e 0", + " --stack ", { "Ref" : "AWS::StackName" }, + " --resource WatchmakerAutoScalingGroup", + { + "Fn::If" : + [ + "AssignInstanceRole", + { "Fn::Join" : [ "", [ + " --role ", + { "Ref" : "InstanceRole" } + ] ] }, + "" + ] + }, + { + "Fn::If" : + [ + "UseCfnUrl", + { "Fn::Join" : [ "", [ + " --url ", + { "Ref" : "CfnEndpointUrl" } + ] ] }, + "" + ] + }, + " --region ", { "Ref" : "AWS::Region"}, "\n" + ]]}, + "ignoreErrors" : "true", + "waitAfterCompletion" : "0" + } + } + } + } + }, + "Properties" : + { + "ImageId" : { "Ref" : "AmiId" }, + "InstanceType" : { "Ref" : "InstanceType" }, + "IamInstanceProfile" : + { + "Fn::If" : + [ + "AssignInstanceRole", + { "Ref" : "InstanceRole" }, + { "Ref" : "AWS::NoValue" } + ] + }, + "AssociatePublicIpAddress" : "true", + "BlockDeviceMappings" : + [ + { + "DeviceName" : "/dev/sda1", + "Ebs" : + { + "VolumeType" : "gp2", + "DeleteOnTermination" : "true" + } + }, + { + "Fn::If" : + [ + "CreateAppVolume", + { + "DeviceName" : { "Ref" : "AppVolumeDevice" }, + "Ebs" : + { + "VolumeSize" : { "Ref" : "AppVolumeSize" }, + "VolumeType" : { "Ref" : "AppVolumeType" }, + "DeleteOnTermination" : "true" + } + }, + { "Ref" : "AWS::NoValue" } + ] + } + ], + "KeyName" : + { + "Ref" : "KeyPairName" + }, + "SecurityGroups" : + { + "Ref" : "SecurityGroupIds" + }, + "UserData" : + { + "Fn::Base64" : + { "Fn::Join" : [ "", [ + "" + ] ] } + } + } + } + } +} From 599e9c93c01825888fc32602f12fbf7a72e445d2 Mon Sep 17 00:00:00 2001 From: Loren Gordon Date: Tue, 11 Apr 2017 20:42:29 -0400 Subject: [PATCH 4/5] Adds cfn template for a windows standalone instance --- .../watchmaker-win-instance.template | 967 ++++++++++++++++++ 1 file changed, 967 insertions(+) create mode 100644 docs/files/cfn/templates/watchmaker-win-instance.template diff --git a/docs/files/cfn/templates/watchmaker-win-instance.template b/docs/files/cfn/templates/watchmaker-win-instance.template new file mode 100644 index 000000000..d453499f3 --- /dev/null +++ b/docs/files/cfn/templates/watchmaker-win-instance.template @@ -0,0 +1,967 @@ +{ + "AWSTemplateFormatVersion" : "2010-09-09", + "Description" : "This template deploys a Windows instance using Watchmaker, which applies the DISA STIG.", + "Parameters" : + { + "AmiId" : + { + "Description" : "ID of the AMI to launch", + "Type" : "String", + "AllowedPattern" : "^ami-[0-9a-z]{8}$|^ami-[0-9a-z]{17}$" + }, + "AppScriptParams" : + { + "Description" : "Parameter string to pass to the application script. Ignored if \"AppScriptUrl\" is blank", + "Type" : "String" + }, + "AppScriptShell" : + { + "Description" : "Shell with which to execute the application script. Ignored if \"AppScriptUrl\" is blank", + "Type" : "String", + "Default" : "powershell", + "AllowedValues" : + [ + "cmd", + "powershell" + ] + }, + "AppScriptUrl" : + { + "Description" : "(Optional) URL to the application script. Leave blank to launch without an application script", + "Type" : "String", + "Default" : "", + "AllowedPattern" : "^$|^http[s]?://.*$" + }, + "AppVolumeDevice" : + { + "Description" : "(Optional) Device to mount an extra EBS volume. Leave blank to launch without an extra application volume", + "Type" : "String", + "Default" : "", + "AllowedValues" : + [ + "", + "xvdf", + "xvde", + "xvdg", + "xvdh", + "xvdi" + ] + }, + "AppVolumeType" : + { + "Description" : "Type of EBS volume to create. Ignored if \"AppVolumeDevice\" is blank", + "Type" : "String", + "Default" : "gp2", + "AllowedValues" : + [ + "gp2", + "io1", + "sc1", + "st1", + "standard" + ] + }, + "AppVolumeSize" : + { + "Description" : "Size in GB of the EBS volume to create. Ignored if \"AppVolumeDevice\" is blank", + "Type" : "Number", + "Default" : "1", + "MinValue": "1", + "MaxValue": "16384", + "ConstraintDescription" : "Must be between 1GB and 16384GB." + }, + "KeyPairName" : + { + "Description" : "Public/private key pairs allow you to securely connect to your instance after it launches", + "Type" : "AWS::EC2::KeyPair::KeyName" + }, + "InstanceType" : + { + "Description" : "Amazon EC2 instance type", + "Type" : "String", + "Default" : "t2.micro", + "AllowedValues" : + [ + "t2.micro", + "t2.small", + "t2.medium", + "t2.large", + "c4.large", + "c4.xlarge", + "m4.large", + "m4.xlarge" + ] + }, + "InstanceRole" : + { + "Description" : "(Optional) IAM instance role to apply to the instance(s)", + "Type" : "String", + "Default" : "" + }, + "PrivateIp" : + { + "Description" : "(Optional) Set a static, primary private IP. Leave blank to auto-select a free IP", + "Type" : "String", + "Default" : "" + }, + "NoPublicIp" : + { + "Description" : "Controls whether to assign the instance a public IP. Recommended to leave at \"true\" _unless_ launching in a public subnet", + "Type" : "String", + "Default" : "true", + "AllowedValues" : + [ + "false", + "true" + ] + }, + "NoReboot" : + { + "Description" : "Controls whether to reboot the instance as the last step of cfn-init execution", + "Type" : "String", + "Default" : "false", + "AllowedValues" : + [ + "false", + "true" + ] + }, + "SecurityGroupIds" : + { + "Description" : "List of security groups to apply to the instance", + "Type" : "List" + }, + "SubnetId" : + { + "Type" : "AWS::EC2::Subnet::Id", + "Description" : "ID of the subnet to assign to the instance" + }, + "PypiIndexUrl" : + { + "Description" : "URL to the PyPi Index", + "Type" : "String", + "Default" : "https://pypi.org/simple", + "AllowedPattern" : "^http[s]?://.*$" + }, + "PythonInstaller" : + { + "Description" : "URL to the Python Installer Executable", + "Type" : "String", + "Default" : "https://www.python.org/ftp/python/3.6.0/python-3.6.0-amd64.exe", + "AllowedPattern" : "^http[s]?://.*\\.exe$" + }, + "WatchmakerBootstrapper" : + { + "Description" : "URL to the Watchmaker PowerShell bootstrapper for Windows", + "Type" : "String", + "Default" : "https://raw.githubusercontent.com/plus3it/watchmaker/master/docs/files/bootstrap/watchmaker-bootstrap.ps1", + "AllowedPattern" : "^$|^http[s]?://.*\\.ps1$" + }, + "WatchmakerConfig" : + { + "Description" : "(Optional) URL to a Watchmaker config file", + "Type" : "String", + "Default" : "", + "AllowedPattern" : "^$|^http[s]?://.*$" + }, + "WatchmakerEnvironment" : + { + "Description" : "Environment in which the instance is being deployed", + "Type" : "String", + "Default" : "", + "AllowedValues" : + [ + "", + "dev", + "test", + "prod" + ] + }, + "WatchmakerOuPath" : + { + "Description" : "(Optional) DN of the OU to place the instance when joining a domain. If blank and \"WatchmakerEnvironment\" enforces a domain join, the instance will be placed in a default container. Leave blank if not joining a domain, or if \"WatchmakerEnvironment\" is \"$false\"", + "Type" : "String", + "Default" : "", + "AllowedPattern" : "^$|^(OU=.+,)+(DC=.+)+$" + }, + "WatchmakerComputerName" : + { + "Description" : "(Optional) Sets the hostname/computername within the OS", + "Type" : "String", + "Default" : "" + }, + "WatchmakerAdminGroups" : + { + "Description" : "(Optional) Colon-separated list of domain groups that should have admin permissions on the EC2 instance", + "Type" : "String", + "Default" : "" + }, + "CfnEndpointUrl" : + { + "Description" : "(Optional) URL to the CloudFormation Endpoint. e.g. https://cloudformation.us-east-1.amazonaws.com", + "Type" : "String", + "Default" : "https://cloudformation.us-east-1.amazonaws.com", + "AllowedPattern" : "^$|^http[s]?://.*$" + }, + "ToggleCfnInitUpdate" : + { + "Description" : "A/B toggle that forces a change to instance metadata, triggering the cfn-init update sequence", + "Type" : "String", + "Default" : "A", + "AllowedValues" : + [ + "A", + "B" + ] + } + }, + "Conditions" : + { + "ExecuteAppScript" : + { + "Fn::Not" : [ { "Fn::Equals" : [ { "Ref" : "AppScriptUrl" }, "" ] } ] + }, + "CreateAppVolume" : + { + "Fn::Not" : [ { "Fn::Equals" : [ { "Ref" : "AppVolumeDevice" }, "" ] } ] + }, + "UseWamConfig" : + { + "Fn::Not" : [ { "Fn::Equals" : [ { "Ref" : "WatchmakerConfig" }, "" ] } ] + }, + "UseOuPath" : + { + "Fn::Not" : [ { "Fn::Equals" : [ { "Ref" : "WatchmakerOuPath" }, "" ] } ] + }, + "UseComputerName" : + { + "Fn::Not" : [ { "Fn::Equals" : [ { "Ref" : "WatchmakerComputerName" }, "" ] } ] + }, + "UseAdminGroups" : + { + "Fn::Not" : [ { "Fn::Equals" : [ { "Ref" : "WatchmakerAdminGroups" }, "" ] } ] + }, + "UseEnvironment" : + { + "Fn::Not" : [ { "Fn::Equals" : [ { "Ref" : "WatchmakerEnvironment" }, "" ] } ] + }, + "UseCfnUrl" : + { + "Fn::Not" : [ { "Fn::Equals" : [ { "Ref" : "CfnEndpointUrl" }, "" ] } ] + }, + "Reboot" : + { + "Fn::Not" : [ { "Fn::Equals" : [ { "Ref" : "NoReboot" }, "true" ] } ] + }, + "AssignInstanceRole" : + { + "Fn::Not" : [ { "Fn::Equals" : [ { "Ref" : "InstanceRole" }, "" ] } ] + }, + "AssignStaticPrivateIp" : + { + "Fn::Not" : [ { "Fn::Equals" : [ { "Ref" : "PrivateIp" }, "" ] } ] + }, + "AssignPublicIp" : + { + "Fn::Not" : [ { "Fn::Equals" : [ { "Ref" : "NoPublicIp" }, "true" ] } ] + } + }, + "Mappings" : + { + "ShellCommandMap" : + { + "powershell" : + { + "command" : "powershell.exe -NoLogo -NoProfile -NonInteractive -ExecutionPolicy Bypass" + }, + "cmd" : + { + "command" : "cmd.exe" + } + } + }, + "Metadata" : + { + "AWS::CloudFormation::Interface" : + { + "ParameterGroups" : + [ + { + "Label" : + { + "default" : "EC2 Instance Configuration" + }, + "Parameters" : + [ + "AmiId", + "InstanceType", + "InstanceRole", + "KeyPairName", + "NoPublicIp", + "NoReboot", + "NoUpdates", + "SecurityGroupIds" + ] + }, + { + "Label" : + { + "default" : "EC2 Watchmaker Configuration" + }, + "Parameters" : + [ + "PythonInstaller", + "PypiIndexUrl", + "WatchmakerBootstrapper", + "WatchmakerConfig", + "WatchmakerEnvironment", + "WatchmakerOuPath", + "WatchmakerComputerName", + "WatchmakerAdminGroups" + ] + }, + { + "Label" : + { + "default" : "EC2 Application Configuration" + }, + "Parameters" : + [ + "AppScriptUrl", + "AppScriptParams", + "AppScriptShell" + ] + }, + { + "Label" : + { + "default" : "EC2 Application EBS Volume" + }, + "Parameters" : + [ + "AppVolumeDevice", + "AppVolumeSize", + "AppVolumeType" + ] + }, + { + "Label" : + { + "default" : "Network Configuration" + }, + "Parameters" : + [ + "PrivateIp", + "SubnetId" + ] + }, + { + "Label" : + { + "default" : "CloudFormation Configuration" + }, + "Parameters" : + [ + "CfnEndpointUrl", + "ToggleCfnInitUpdate" + ] + } + ], + "ParameterLabels" : + { + "ToggleCfnInitUpdate" : + { + "default" : "Force Cfn Init Update" + } + } + } + }, + "Resources" : + { + "WatchmakerInstance" : + { + "Type" : "AWS::EC2::Instance", + "CreationPolicy" : + { + "ResourceSignal" : + { + "Count" : "1", + "Timeout" : "PT60M" + } + }, + "Metadata" : { + "ToggleCfnInitUpdate" : { "Ref" : "ToggleCfnInitUpdate" }, + "AWS::CloudFormation::Init" : + { + "configSets" : + { + "launch" : + [ + "setup", + "watchmaker-launch", + { + "Fn::If" : + [ + "ExecuteAppScript", + "make-app", + { "Ref" : "AWS::NoValue" } + ] + }, + { + "Fn::If" : + [ + "Reboot", + "reboot", + { "Ref" : "AWS::NoValue" } + ] + }, + "finalize" + ], + "update" : + [ + "setup", + "watchmaker-update", + { + "Fn::If" : + [ + "ExecuteAppScript", + "make-app", + { "Ref" : "AWS::NoValue" } + ] + }, + { + "Fn::If" : + [ + "Reboot", + "reboot", + { "Ref" : "AWS::NoValue" } + ] + }, + "finalize" + ] + }, + "setup" : + { + "files" : + { + "c:\\cfn\\cfn-hup.conf" : + { + "content" : + { "Fn::Join" : ["", [ + "[main]\n", + "stack=", { "Ref" : "AWS::StackId" }, "\n", + "region=", { "Ref" : "AWS::Region" }, "\n", + { + "Fn::If" : + [ + "AssignInstanceRole", + { "Fn::Join" : [ "", [ + "role=", + { "Ref" : "InstanceRole" }, + "\n" + ] ] }, + "" + ] + }, + { + "Fn::If" : + [ + "UseCfnUrl", + { "Fn::Join" : [ "", [ + "url=", + { "Ref" : "CfnEndpointUrl" }, + "\n" + ] ] }, + "" + ] + }, + "interval=1", "\n", + "verbose=true", "\n" + ]]} + }, + "c:\\cfn\\hooks.d\\cfn-auto-reloader.conf" : + { + "content" : + { "Fn::Join" : ["", [ + "[cfn-auto-reloader-hook]\n", + "triggers=post.update\n", + "path=Resources.WatchmakerInstance.Metadata\n", + "action=cfn-init.exe -v -c update", + " --stack ", { "Ref" : "AWS::StackName" }, + " --resource WatchmakerInstance", + { + "Fn::If" : + [ + "AssignInstanceRole", + { "Fn::Join" : [ "", [ + " --role ", + { "Ref" : "InstanceRole" } + ] ] }, + "" + ] + }, + { + "Fn::If" : + [ + "UseCfnUrl", + { "Fn::Join" : [ "", [ + " --url ", + { "Ref" : "CfnEndpointUrl" } + ] ] }, + "" + ] + }, + " --region ", { "Ref" : "AWS::Region" }, "\n" + ]]} + }, + "c:\\cfn\\scripts\\watchmaker-install.ps1" : + { + "content" : + { "Fn::Join" : ["", [ + "$BootstrapUrl = \"", { "Ref" : "WatchmakerBootstrapper" }, "\"\n", + "$PythonUrl = \"", { "Ref" : "PythonInstaller" }, "\"\n", + "$PypiUrl = \"", { "Ref" : "PypiIndexUrl" }, "\"\n\n", + + "# Get the host\n", + "$PypiHost=\"$(([System.Uri]$PypiUrl).Host)\"\n\n", + + "# Download bootstrap file\n", + "$BootstrapFile = \"${Env:Temp}\\$(${BootstrapUrl}.split('/')[-1])\"\n", + "(New-Object System.Net.WebClient).DownloadFile(\"$BootstrapUrl\", \"$BootstrapFile\")\n\n", + + "# Install python\n", + "& \"$BootstrapFile\" -PythonUrl \"$PythonUrl\" -Verbose -ErrorAction Stop\n\n", + + "# Install watchmaker\n", + "pip install --index-url=\"$PypiUrl\" --trusted-host=\"$PypiHost\" --allow-all-external --upgrade pip setuptools watchmaker\n\n" + ]]} + } + }, + "services" : + { + "windows" : + { + "cfn-hup" : + { + "enabled" : "true", + "ensureRunning" : "true", + "files" : + [ + "c:\\cfn\\cfn-hup.conf", + "c:\\cfn\\hooks.d\\cfn-auto-reloader.conf" + ] + } + } + } + }, + "watchmaker-launch" : + { + "commands" : + { + "10-watchmaker-launch" : + { + "command" : + { "Fn::Join" : [ "", [ + { "Fn::FindInMap" : + [ + "ShellCommandMap", + "powershell", + "command" + ] + }, + " \"& {", + " c:\\cfn\\scripts\\watchmaker-install.ps1;", + " watchmaker -vv", + " --log-dir C:\\Watchmaker\\Logs", + " --no-reboot", + { + "Fn::If" : + [ + "UseWamConfig", + { "Fn::Join" : [ "", [ + " --config \\\"", + { "Ref" : "WatchmakerConfig" }, + "\\\"" + ]]}, + "" + ] + }, + { + "Fn::If" : + [ + "UseEnvironment", + { "Fn::Join" : [ "", [ + " --env \\\"", + { "Ref" : "WatchmakerEnvironment" }, + "\\\"" + ]]}, + "" + ] + }, + { + "Fn::If" : + [ + "UseOuPath", + { "Fn::Join" : [ "", [ + " --ou-path \\\"", + { "Ref" : "WatchmakerOuPath" }, + "\\\"" + ]]}, + "" + ] + }, + { + "Fn::If" : + [ + "UseComputerName", + { "Fn::Join" : [ "", [ + " --computer-name \"", + { "Ref" : "WatchmakerComputerName" }, + "\"" + ]]}, + "" + ] + }, + { + "Fn::If" : + [ + "UseAdminGroups", + { "Fn::Join" : [ "", [ + " --admin-groups \\\"", + { "Ref" : "WatchmakerAdminGroups" }, + "\\\"" + ]]}, + "" + ] + }, + " }\"" + ]]} + } + } + }, + "watchmaker-update" : + { + "commands" : + { + "10-watchmaker-update" : + { + "command" : + { "Fn::Join" : [ "", [ + { "Fn::FindInMap" : + [ + "ShellCommandMap", + "powershell", + "command" + ] + }, + " \"& {", + " c:\\cfn\\scripts\\watchmaker-install.ps1;", + " watchmaker -vv", + " --log-dir C:\\Watchmaker\\Logs", + " --salt-states None", + " --no-reboot", + { + "Fn::If" : + [ + "UseWamConfig", + { "Fn::Join" : [ "", [ + " --config \\\"", + { "Ref" : "WatchmakerConfig" }, + "\\\"" + ]]}, + "" + ] + }, + { + "Fn::If" : + [ + "UseEnvironment", + { "Fn::Join" : [ "", [ + " --env \\\"", + { "Ref" : "WatchmakerEnvironment" }, + "\\\"" + ]]}, + "" + ] + }, + { + "Fn::If" : + [ + "UseOuPath", + { "Fn::Join" : [ "", [ + " --ou-path \\\"", + { "Ref" : "WatchmakerOuPath" }, + "\\\"" + ]]}, + "" + ] + }, + { + "Fn::If" : + [ + "UseComputerName", + { "Fn::Join" : [ "", [ + " --computer-name \"", + { "Ref" : "WatchmakerComputerName" }, + "\"" + ]]}, + "" + ] + }, + { + "Fn::If" : + [ + "UseAdminGroups", + { "Fn::Join" : [ "", [ + " --admin-groups \\\"", + { "Ref" : "WatchmakerAdminGroups" }, + "\\\"" + ]]}, + "" + ] + }, + " }\"" + ]]} + } + } + }, + "make-app" : + { + "files" : + { + "c:\\cfn\\scripts\\make-app" : + { + "source" : { "Ref" : "AppScriptUrl" } + } + }, + "commands" : + { + "10-make-app" : + { + "command" : + { "Fn::Join" : [ "", [ + { "Fn::FindInMap" : + [ + "ShellCommandMap", + { "Ref" : "AppScriptShell" }, + "command" + ] + }, + " c:\\cfn\\scripts\\make-app ", + { "Ref" : "AppScriptParams" } + ]]}, + "waitAfterCompletion" : "0" + } + } + }, + "reboot" : + { + "commands" : + { + "10-reboot" : + { + "command" : "powershell.exe \"Restart-Computer -Force -Verbose\"", + "waitAfterCompletion" : "forever" + } + } + }, + "finalize" : + { + "commands" : + { + "10-signal-success" : + { + "command" : + { "Fn::Join" : [ "", [ + "cfn-signal.exe -e 0", + " --stack ", { "Ref" : "AWS::StackName" }, + " --resource WatchmakerInstance", + { + "Fn::If" : + [ + "AssignInstanceRole", + { "Fn::Join" : [ "", [ + " --role ", + { "Ref" : "InstanceRole" } + ] ] }, + "" + ] + }, + { + "Fn::If" : + [ + "UseCfnUrl", + { "Fn::Join" : [ "", [ + " --url ", + { "Ref" : "CfnEndpointUrl" } + ] ] }, + "" + ] + }, + " --region ", { "Ref" : "AWS::Region"}, "\n" + ]]}, + "ignoreErrors" : "true", + "waitAfterCompletion" : "0" + } + } + } + } + }, + "Properties" : + { + "ImageId" : { "Ref" : "AmiId" }, + "InstanceType" : { "Ref" : "InstanceType" }, + "IamInstanceProfile" : + { + "Fn::If" : + [ + "AssignInstanceRole", + { "Ref" : "InstanceRole" }, + { "Ref" : "AWS::NoValue" } + ] + }, + "Tags" : + [ + { + "Key" : "Name", + "Value" : + { "Fn::Join" : [ "", [ + { "Ref" : "AWS::StackName" } + ]]} + } + ], + "BlockDeviceMappings" : + [ + { + "DeviceName" : "/dev/sda1", + "Ebs" : + { + "VolumeType" : "gp2", + "DeleteOnTermination" : "true" + } + }, + { + "Fn::If" : + [ + "CreateAppVolume", + { + "DeviceName" : { "Ref" : "AppVolumeDevice" }, + "Ebs" : + { + "VolumeSize" : { "Ref" : "AppVolumeSize" }, + "VolumeType" : { "Ref" : "AppVolumeType" }, + "DeleteOnTermination" : "true" + } + }, + { "Ref" : "AWS::NoValue" } + ] + } + ], + "KeyName" : + { + "Ref" : "KeyPairName" + }, + "NetworkInterfaces": + [ + { + "DeviceIndex" : "0", + "AssociatePublicIpAddress" : + { + "Fn::If" : + [ + "AssignPublicIp", + "true", + "false" + ] + }, + "PrivateIpAddress" : + { + "Fn::If" : + [ + "AssignStaticPrivateIp", + { "Ref" : "PrivateIp" }, + { "Ref" : "AWS::NoValue" } + ] + }, + "GroupSet" : { "Ref": "SecurityGroupIds" }, + "SubnetId": { "Ref" : "SubnetId" } + } + ], + "UserData" : + { + "Fn::Base64" : + { "Fn::Join" : [ "", [ + "" + ] ] } + } + } + } + }, + "Outputs" : + { + "WatchmakerInstanceId" : + { + "Value" : { "Ref" : "WatchmakerInstance" }, + "Description" : "Instance ID" + } + } +} From f0c0d4104ffd1b4cf28c0c2adf536df4865dd9f6 Mon Sep 17 00:00:00 2001 From: Loren Gordon Date: Fri, 14 Apr 2017 09:46:30 -0400 Subject: [PATCH 5/5] Creates parameter maps for each cfn template --- .../watchmaker-lx-autoscale.params.json | 122 ++++++++++++++++++ .../watchmaker-lx-instance.params.json | 114 ++++++++++++++++ .../watchmaker-win-autoscale.params.json | 110 ++++++++++++++++ .../watchmaker-win-instance.params.json | 114 ++++++++++++++++ 4 files changed, 460 insertions(+) create mode 100644 docs/files/cfn/parameter-maps/watchmaker-lx-autoscale.params.json create mode 100644 docs/files/cfn/parameter-maps/watchmaker-lx-instance.params.json create mode 100644 docs/files/cfn/parameter-maps/watchmaker-win-autoscale.params.json create mode 100644 docs/files/cfn/parameter-maps/watchmaker-win-instance.params.json diff --git a/docs/files/cfn/parameter-maps/watchmaker-lx-autoscale.params.json b/docs/files/cfn/parameter-maps/watchmaker-lx-autoscale.params.json new file mode 100644 index 000000000..72b614ce7 --- /dev/null +++ b/docs/files/cfn/parameter-maps/watchmaker-lx-autoscale.params.json @@ -0,0 +1,122 @@ +[ + { + "ParameterKey": "AmiId", + "ParameterValue": "__AMIID__" + }, + { + "ParameterKey": "AmiDistro", + "ParameterValue": "__AMIDISTRO__" + }, + { + "ParameterKey": "AppScriptParams", + "ParameterValue": "__APPSCRIPTPARAMS__" + }, + { + "ParameterKey": "AppScriptShell", + "ParameterValue": "__APPSCRIPTSHELL__" + }, + { + "ParameterKey": "AppScriptUrl", + "ParameterValue": "__APPSCRIPTURL__" + }, + { + "ParameterKey": "AppVolumeDevice", + "ParameterValue": "__APPVOLUMEDEVICE__" + }, + { + "ParameterKey": "AppVolumeMountPath", + "ParameterValue": "__APPVOLUMEMOUNTPATH__" + }, + { + "ParameterKey": "AppVolumeType", + "ParameterValue": "__APPVOLUMETYPE__" + }, + { + "ParameterKey": "AppVolumeSize", + "ParameterValue": "__APPVOLUMESIZE__" + }, + { + "ParameterKey": "KeyPairName", + "ParameterValue": "__KEYPAIRNAME__" + }, + { + "ParameterKey": "InstanceRole", + "ParameterValue": "__INSTANCEROLE__" + }, + { + "ParameterKey": "InstanceType", + "ParameterValue": "__INSTANCETYPE__" + }, + { + "ParameterKey": "MinCapacity", + "ParameterValue": "__MINCAPACITY__" + }, + { + "ParameterKey": "MaxCapacity", + "ParameterValue": "__MAXCAPACITY__" + }, + { + "ParameterKey": "DesiredCapacity", + "ParameterValue": "__DESIREDCAPACITY__" + }, + { + "ParameterKey": "NoPublicIp", + "ParameterValue": "__NOPUBLICIP__" + }, + { + "ParameterKey": "NoReboot", + "ParameterValue": "__NOREBOOT__" + }, + { + "ParameterKey": "NoUpdates", + "ParameterValue": "__NOUPDATES__" + }, + { + "ParameterKey": "SecurityGroupIds", + "ParameterValue": "__SECURITYGROUPIDS__" + }, + { + "ParameterKey": "SubnetIds", + "ParameterValue": "__SUBNETIDS__" + }, + { + "ParameterKey": "PypiIndexUrl", + "ParameterValue": "__PYPIINDEXURL__" + }, + { + "ParameterKey": "WatchmakerConfig", + "ParameterValue": "__WATCHMAKERCONFIG__" + }, + { + "ParameterKey": "WatchmakerEnvironment", + "ParameterValue": "__WATCHMAKERENVIRONMENT__" + }, + { + "ParameterKey": "WatchmakerOuPath", + "ParameterValue": "__WATCHMAKEROUPATH__" + }, + { + "ParameterKey": "WatchmakerAdminGroups", + "ParameterValue": "__WATCHMAKERADMINGROUPS__" + }, + { + "ParameterKey": "CfnEndpointUrl", + "ParameterValue": "__CFNENDPOINTURL__" + }, + { + "ParameterKey": "CfnGetPipUrl", + "ParameterValue": "__CFNGETPIPURL__" + }, + { + "ParameterKey": "CfnBootstrapUtilsUrl", + "ParameterValue": "__CFNBOOTSTRAPUTILSURL__" + }, + { + "ParameterKey": "ToggleCfnInitUpdate", + "ParameterValue": "__TOGGLECFNINITUPDATE__" + }, + { + "ParameterKey": "ToggleNewInstances", + "ParameterValue": "__TOGGLENEWINSTANCES__" + } +] diff --git a/docs/files/cfn/parameter-maps/watchmaker-lx-instance.params.json b/docs/files/cfn/parameter-maps/watchmaker-lx-instance.params.json new file mode 100644 index 000000000..33177ffa0 --- /dev/null +++ b/docs/files/cfn/parameter-maps/watchmaker-lx-instance.params.json @@ -0,0 +1,114 @@ +[ + { + "ParameterKey": "AmiId", + "ParameterValue": "__AMIID__" + }, + { + "ParameterKey": "AmiDistro", + "ParameterValue": "__AMIDISTRO__" + }, + { + "ParameterKey": "AppScriptParams", + "ParameterValue": "__APPSCRIPTPARAMS__" + }, + { + "ParameterKey": "AppScriptShell", + "ParameterValue": "__APPSCRIPTSHELL__" + }, + { + "ParameterKey": "AppScriptUrl", + "ParameterValue": "__APPSCRIPTURL__" + }, + { + "ParameterKey": "AppVolumeDevice", + "ParameterValue": "__APPVOLUMEDEVICE__" + }, + { + "ParameterKey": "AppVolumeMountPath", + "ParameterValue": "__APPVOLUMEMOUNTPATH__" + }, + { + "ParameterKey": "AppVolumeType", + "ParameterValue": "__APPVOLUMETYPE__" + }, + { + "ParameterKey": "AppVolumeSize", + "ParameterValue": "__APPVOLUMESIZE__" + }, + { + "ParameterKey": "KeyPairName", + "ParameterValue": "__KEYPAIRNAME__" + }, + { + "ParameterKey": "InstanceRole", + "ParameterValue": "__INSTANCEROLE__" + }, + { + "ParameterKey": "InstanceType", + "ParameterValue": "__INSTANCETYPE__" + }, + { + "ParameterKey": "NoPublicIp", + "ParameterValue": "__NOPUBLICIP__" + }, + { + "ParameterKey": "NoReboot", + "ParameterValue": "__NOREBOOT__" + }, + { + "ParameterKey": "NoUpdates", + "ParameterValue": "__NOUPDATES__" + }, + { + "ParameterKey": "PrivateIp", + "ParameterValue": "__PRIVATEIP__" + }, + { + "ParameterKey": "SecurityGroupIds", + "ParameterValue": "__SECURITYGROUPIDS__" + }, + { + "ParameterKey": "SubnetId", + "ParameterValue": "__SUBNETID__" + }, + { + "ParameterKey": "PypiIndexUrl", + "ParameterValue": "__PYPIINDEXURL__" + }, + { + "ParameterKey": "WatchmakerAdminGroups", + "ParameterValue": "__WATCHMAKERADMINGROUPS__" + }, + { + "ParameterKey": "WatchmakerComputerName", + "ParameterValue": "__COMPUTERNAME__" + }, + { + "ParameterKey": "WatchmakerConfig", + "ParameterValue": "__WATCHMAKERCONFIG__" + }, + { + "ParameterKey": "WatchmakerEnvironment", + "ParameterValue": "__WATCHMAKERENVIRONMENT__" + }, + { + "ParameterKey": "WatchmakerOuPath", + "ParameterValue": "__WATCHMAKEROUPATH__" + }, + { + "ParameterKey": "CfnBootstrapUtilsUrl", + "ParameterValue": "__CFNBOOTSTRAPUTILSURL__" + }, + { + "ParameterKey": "CfnEndpointUrl", + "ParameterValue": "__CFNENDPOINTURL__" + }, + { + "ParameterKey": "CfnGetPipUrl", + "ParameterValue": "__CFNGETPIPURL__" + }, + { + "ParameterKey": "ToggleCfnInitUpdate", + "ParameterValue": "__TOGGLECFNINITUPDATE__" + } +] diff --git a/docs/files/cfn/parameter-maps/watchmaker-win-autoscale.params.json b/docs/files/cfn/parameter-maps/watchmaker-win-autoscale.params.json new file mode 100644 index 000000000..7b109120e --- /dev/null +++ b/docs/files/cfn/parameter-maps/watchmaker-win-autoscale.params.json @@ -0,0 +1,110 @@ +[ + { + "ParameterKey": "AmiId", + "ParameterValue": "__AMIID__" + }, + { + "ParameterKey": "AppScriptParams", + "ParameterValue": "__APPSCRIPTPARAMS__" + }, + { + "ParameterKey": "AppScriptShell", + "ParameterValue": "__APPSCRIPTSHELL__" + }, + { + "ParameterKey": "AppScriptUrl", + "ParameterValue": "__APPSCRIPTURL__" + }, + { + "ParameterKey": "AppVolumeDevice", + "ParameterValue": "__APPVOLUMEDEVICE__" + }, + { + "ParameterKey": "AppVolumeType", + "ParameterValue": "__APPVOLUMETYPE__" + }, + { + "ParameterKey": "AppVolumeSize", + "ParameterValue": "__APPVOLUMESIZE__" + }, + { + "ParameterKey": "KeyPairName", + "ParameterValue": "__KEYPAIRNAME__" + }, + { + "ParameterKey": "InstanceRole", + "ParameterValue": "__INSTANCEROLE__" + }, + { + "ParameterKey": "InstanceType", + "ParameterValue": "__INSTANCETYPE__" + }, + { + "ParameterKey": "MinCapacity", + "ParameterValue": "__MINCAPACITY__" + }, + { + "ParameterKey": "MaxCapacity", + "ParameterValue": "__MAXCAPACITY__" + }, + { + "ParameterKey": "DesiredCapacity", + "ParameterValue": "__DESIREDCAPACITY__" + }, + { + "ParameterKey": "NoPublicIp", + "ParameterValue": "__NOPUBLICIP__" + }, + { + "ParameterKey": "NoReboot", + "ParameterValue": "__NOREBOOT__" + }, + { + "ParameterKey": "SecurityGroupIds", + "ParameterValue": "__SECURITYGROUPIDS__" + }, + { + "ParameterKey": "SubnetIds", + "ParameterValue": "__SUBNETIDS__" + }, + { + "ParameterKey": "PypiIndexUrl", + "ParameterValue": "__PYPIINDEXURL__" + }, + { + "ParameterKey": "PythonInstaller", + "ParameterValue": "__PYTHONINSTALLER__" + }, + { + "ParameterKey": "WatchmakerAdminGroups", + "ParameterValue": "__WATCHMAKERADMINGROUPS__" + }, + { + "ParameterKey": "WatchmakerBootstrapper", + "ParameterValue": "__WATCHMAKERBOOTSTRAPPER__" + }, + { + "ParameterKey": "WatchmakerConfig", + "ParameterValue": "__WATCHMAKERCONFIG__" + }, + { + "ParameterKey": "WatchmakerEnvironment", + "ParameterValue": "__WATCHMAKERENVIRONMENT__" + }, + { + "ParameterKey": "WatchmakerOuPath", + "ParameterValue": "__WATCHMAKEROUPATH__" + }, + { + "ParameterKey": "CfnEndpointUrl", + "ParameterValue": "__CFNENDPOINTURL__" + }, + { + "ParameterKey": "ToggleCfnInitUpdate", + "ParameterValue": "__TOGGLECFNINITUPDATE__" + }, + { + "ParameterKey": "ToggleNewInstances", + "ParameterValue": "__TOGGLENEWINSTANCES__" + } +] diff --git a/docs/files/cfn/parameter-maps/watchmaker-win-instance.params.json b/docs/files/cfn/parameter-maps/watchmaker-win-instance.params.json new file mode 100644 index 000000000..1112c3756 --- /dev/null +++ b/docs/files/cfn/parameter-maps/watchmaker-win-instance.params.json @@ -0,0 +1,114 @@ +[ + { + "ParameterKey": "AmiId", + "ParameterValue": "__AMIID__" + }, + { + "ParameterKey": "AppScriptParams", + "ParameterValue": "__APPSCRIPTPARAMS__" + }, + { + "ParameterKey": "AppScriptShell", + "ParameterValue": "__APPSCRIPTSHELL__" + }, + { + "ParameterKey": "AppScriptUrl", + "ParameterValue": "__APPSCRIPTURL__" + }, + { + "ParameterKey": "AppVolumeDevice", + "ParameterValue": "__APPVOLUMEDEVICE__" + }, + { + "ParameterKey": "AppVolumeType", + "ParameterValue": "__APPVOLUMETYPE__" + }, + { + "ParameterKey": "AppVolumeSize", + "ParameterValue": "__APPVOLUMESIZE__" + }, + { + "ParameterKey": "KeyPairName", + "ParameterValue": "__KEYPAIRNAME__" + }, + { + "ParameterKey": "InstanceRole", + "ParameterValue": "__INSTANCEROLE__" + }, + { + "ParameterKey": "InstanceType", + "ParameterValue": "__INSTANCETYPE__" + }, + { + "ParameterKey": "MinCapacity", + "ParameterValue": "__MINCAPACITY__" + }, + { + "ParameterKey": "MaxCapacity", + "ParameterValue": "__MAXCAPACITY__" + }, + { + "ParameterKey": "DesiredCapacity", + "ParameterValue": "__DESIREDCAPACITY__" + }, + { + "ParameterKey": "NoPublicIp", + "ParameterValue": "__NOPUBLICIP__" + }, + { + "ParameterKey": "NoReboot", + "ParameterValue": "__NOREBOOT__" + }, + { + "ParameterKey": "PrivateIp", + "ParameterValue": "__PRIVATEIP__" + }, + { + "ParameterKey": "SecurityGroupIds", + "ParameterValue": "__SECURITYGROUPIDS__" + }, + { + "ParameterKey": "SubnetId", + "ParameterValue": "__SUBNETID__" + }, + { + "ParameterKey": "PypiIndexUrl", + "ParameterValue": "__PYPIINDEXURL__" + }, + { + "ParameterKey": "PythonInstaller", + "ParameterValue": "__PYTHONINSTALLER__" + }, + { + "ParameterKey": "WatchmakerAdminGroups", + "ParameterValue": "__WATCHMAKERADMINGROUPS__" + }, + { + "ParameterKey": "WatchmakerBootstrapper", + "ParameterValue": "__WATCHMAKERBOOTSTRAPPER__" + }, + { + "ParameterKey": "WatchmakerComputerName", + "ParameterValue": "__COMPUTERNAME__" + }, + { + "ParameterKey": "WatchmakerConfig", + "ParameterValue": "__WATCHMAKERCONFIG__" + }, + { + "ParameterKey": "WatchmakerEnvironment", + "ParameterValue": "__WATCHMAKERENVIRONMENT__" + }, + { + "ParameterKey": "WatchmakerOuPath", + "ParameterValue": "__WATCHMAKEROUPATH__" + }, + { + "ParameterKey": "CfnEndpointUrl", + "ParameterValue": "__CFNENDPOINTURL__" + }, + { + "ParameterKey": "ToggleCfnInitUpdate", + "ParameterValue": "__TOGGLECFNINITUPDATE__" + } +]