AWSTemplateFormatVersion: "2010-09-09" Description: Autoscaling Group set to trigger an SSM Active Directory (AD) Document at creation and termination. (qs-1scnfaiha) Metadata: AWS::CloudFormation::Interface: ParameterGroups: - Label: default: Launch Template Configuration Parameters: - ImageId - IISServerInstanceType - Label: default: Amazon EC2 Auto Scaling Configuration Parameters: - ASGDesiredCapacity - ASGMinSize - ASGMaxSize - WorkloadSubnets - Label: default: Amazon ELB Configuration Parameters: - ELBSubnets - ELBSchemeParameter - VPCID - Label: default: Active Directory Configuration Parameters: - DomainDNSName ParameterLabels: ImageId: default: Amazon Machine Image (AMI) Id IISServerInstanceType: default: Instance Type WorkloadSubnets: default: VPC Subnets ASGMinSize: default: Minimum Size ASGMaxSize: default: Maximum Size ASGDesiredCapacity: default: Desired Capacity ELBSubnets: default: ELB Subnets ELBSchemeParameter: default: ELB Scheme VPCID: default: ELB VPC ID DomainDNSName: default: Domain DNS Name Parameters: DomainDNSName: AllowedPattern: '[a-zA-Z0-9\-]+\..+' Default: example.com Description: Fully qualified domain name (FQDN). MaxLength: "255" MinLength: "2" Type: String ImageId: Type: AWS::SSM::Parameter::Value Default: /aws/service/ami-windows-latest/Windows_Server-2019-English-Core-Base Description: "Enter an AMI Id. The default value is Windows Server 2019 Core: /aws/service/ami-windows-latest/Windows_Server-2019-English-Core-Base." IISServerInstanceType: AllowedValues: - t3.large - m5.large Default: t3.large Description: Amazon EC2 instance type for the Internet Information Services servers Type: String VPCID: Type: AWS::EC2::VPC::Id Description: List of Virtual Private Cloud (VPC) Ids in your account. ELBSchemeParameter: Type: String Default: internet-facing AllowedValues: - internet-facing - internal Description: Select whether the ELB is internet-facing (public) or internal (private). ASGMinSize: Type: Number Description: Minimum instance size for the Auto Scaling Group. ASGMaxSize: Type: Number Description: Maximum instance size for the Auto Scaling Group. ASGDesiredCapacity: Type: Number Description: Desired capacity instance size for the Auto Scaling Group. ELBSubnets: Description: IDs of the ELB subnets (e.g., subnet-a0246dcd) Type: List WorkloadSubnets: Description: IDs of the private subnets (e.g., subnet-a0246dcd) Type: List Resources: ###################### # Security Resources # ###################### EventBridgeSSMAutoRole: Type: AWS::IAM::Role Properties: Description: EventBridge IAM role which will trigger Automation Document & pass role to SSM role. Policies: - PolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Action: - ssm:StartAutomationExecution Resource: - !ImportValue SetupConfigurationDocArn - !ImportValue RemoveConfigurationDocArn - Effect: Allow Action: - iam:PassRole Resource: "*" Condition: StringLike: "iam:AssociatedResourceARN": - !ImportValue SetupConfigurationDocArn - !ImportValue RemoveConfigurationDocArn PolicyName: ssm-start-automation AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: - events.amazonaws.com Action: sts:AssumeRole ALBSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Security group for ALB SecurityGroupIngress: - IpProtocol: tcp FromPort: 80 ToPort: 80 CidrIp: 0.0.0.0/0 VpcId: !Ref "VPCID" ALBListenersSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Security group for listeners of ALB SecurityGroupIngress: - IpProtocol: tcp FromPort: 80 ToPort: 80 SourceSecurityGroupId: !GetAtt ALBSecurityGroup.GroupId VpcId: !Ref "VPCID" ####################### # ASG Resources # ####################### EC2LaunchTemplateResource: Type: AWS::EC2::LaunchTemplate DeletionPolicy: Delete Properties: LaunchTemplateData: InstanceType: !Ref "IISServerInstanceType" ImageId: !Ref "ImageId" SecurityGroupIds: - !ImportValue DomainMemberSG - !Ref ALBListenersSecurityGroup IamInstanceProfile: Name: !ImportValue InstanceProfile ALBResource: Type: AWS::ElasticLoadBalancingV2::LoadBalancer Properties: Scheme: !Ref "ELBSchemeParameter" Subnets: !Ref ELBSubnets SecurityGroups: - !Ref ALBSecurityGroup ALBTargetGroupResource: Type: AWS::ElasticLoadBalancingV2::TargetGroup Properties: Port: 80 Protocol: HTTP VpcId: !Ref "VPCID" HealthyThresholdCount: 5 HealthCheckTimeoutSeconds: 120 HealthCheckIntervalSeconds: 300 UnhealthyThresholdCount: 10 TargetGroupAttributes: - Key: deregistration_delay.timeout_seconds Value: "60" ALBListenerResource: Type: AWS::ElasticLoadBalancingV2::Listener Properties: LoadBalancerArn: !Ref "ALBResource" Port: 80 Protocol: HTTP DefaultActions: - Type: forward TargetGroupArn: !Ref "ALBTargetGroupResource" ASGResource: DependsOn: - ScaleUpEventBridgeResource - ScaleDownEventBridgeResource Type: AWS::AutoScaling::AutoScalingGroup Properties: AutoScalingGroupName: !Sub ASG-${AWS::StackName} MinSize: !Ref "ASGMinSize" MaxSize: !Ref "ASGMaxSize" DesiredCapacity: !Ref "ASGDesiredCapacity" HealthCheckType: EC2 HealthCheckGracePeriod: 60 Cooldown: "30" LaunchTemplate: LaunchTemplateId: !Ref "EC2LaunchTemplateResource" Version: !GetAtt "EC2LaunchTemplateResource.LatestVersionNumber" VPCZoneIdentifier: !Ref WorkloadSubnets TargetGroupARNs: - !Ref "ALBTargetGroupResource" LifecycleHookSpecificationList: - LifecycleTransition: autoscaling:EC2_INSTANCE_LAUNCHING LifecycleHookName: DomainJoinHook DefaultResult: ABANDON HeartbeatTimeout: 1200 - LifecycleTransition: autoscaling:EC2_INSTANCE_TERMINATING LifecycleHookName: DomainUnjoinHook DefaultResult: ABANDON HeartbeatTimeout: 600 Tags: - Key: Domain Value: !Ref "DomainDNSName" PropagateAtLaunch: true ######################### # EventBridge Resources # ######################### ScaleUpEventBridgeResource: Type: AWS::Events::Rule Properties: State: ENABLED Description: Run Configuration Document that Joins Domain and Configures IIS. EventPattern: source: - aws.autoscaling detail-type: - EC2 Instance-launch Lifecycle Action detail: AutoScalingGroupName: - !Sub ASG-${AWS::StackName} Targets: - Arn: !ImportValue SetupConfigurationDocArn Id: Windows-Scale-Out RoleArn: !GetAtt EventBridgeSSMAutoRole.Arn InputTransformer: InputPathsMap: InstanceId: $.detail.EC2InstanceId ASGName: $.detail.AutoScalingGroupName LCHName: $.detail.LifecycleHookName InputTemplate: Fn::Sub: - '{"InstanceId":[],"ASGName":[],"LCHName":[],"ConfigBucket":["${DSCBucket}"]}' - DSCBucket: !ImportValue DSCBucket ScaleDownEventBridgeResource: Type: AWS::Events::Rule Properties: State: ENABLED Description: Run Removal Document that Un-joins Domain. EventPattern: source: - aws.autoscaling detail-type: - EC2 Instance-terminate Lifecycle Action detail: AutoScalingGroupName: - !Sub ASG-${AWS::StackName} Targets: - Arn: !ImportValue RemoveConfigurationDocArn Id: Windows-Scale-In RoleArn: !GetAtt EventBridgeSSMAutoRole.Arn InputTransformer: InputPathsMap: InstanceId: $.detail.EC2InstanceId ASGName: $.detail.AutoScalingGroupName LCHName: $.detail.LifecycleHookName InputTemplate: Fn::Sub: - '{"InstanceId":[],"ASGName":[],"LCHName":[],"ConfigBucket":["${DSCBucket}"]}' - DSCBucket: !ImportValue DSCBucket Outputs: ELBUrl: Description: DNS name of the ELB. Value: !Sub http://${ALBResource.DNSName} LaunchTemplateId: Description: Launch template Id Value: !Ref "EC2LaunchTemplateResource"