For AI agents: A markdown version of this page is available at https://docs.datadoghq.com/security/code_security/iac_security/iac_rules/cloudformation-aws-fully-open-ingress.md.
A documentation index is available at /llms.txt.
Security groups attached to ECS services must not allow ingress from 0.0.0.0/0 to all ports because unrestricted public access increases the attack surface of containerized workloads and enables unauthorized access or exploitation.
Check AWS::EC2::SecurityGroupIngress resources where Properties.CidrIp is 0.0.0.0/0 and Properties.ToPort is 0 for rules that apply to security groups used by ECS services. Such rules will be flagged. Restrict ingress by specifying trusted CIDR ranges or referencing other security groups and by narrowing FromPort/ToPort to only the ports required (or place services behind a load balancer and WAF).
Secure configuration example (restrict access to TCP port 80 from a specific CIDR):
AWSTemplateFormatVersion:'2010-09-09'Parameters:VpcId:Type:AWS::EC2::VPC::IdDescription:Select a VPC that allows instances access to the Internet.SubnetId:Type:List<AWS::EC2::Subnet::Id>Description:Select at two subnets in your selected VPC.Resources:ECSCluster:Type:AWS::ECS::ClusterEcsSecurityGroup:Type:AWS::EC2::SecurityGroupProperties:GroupDescription:ECS Security GroupVpcId:!Ref 'VpcId'EcsSecurityGroupHTTPinbound:Type:AWS::EC2::SecurityGroupIngressProperties:GroupId:!Ref 'EcsSecurityGroup'IpProtocol:tcpFromPort:80ToPort:80CidrIp:0.0.0.0/0EcsSecurityGroupSSHinbound:Type:AWS::EC2::SecurityGroupIngressProperties:GroupId:!Ref 'EcsSecurityGroup'IpProtocol:tcpFromPort:22ToPort:22CidrIp:0.0.0.0/0EcsSecurityGroupALBports:Type:AWS::EC2::SecurityGroupIngressProperties:GroupId:!Ref 'EcsSecurityGroup'IpProtocol:tcpFromPort:31000ToPort:61000SourceSecurityGroupId:!Ref 'EcsSecurityGroup'CloudwatchLogsGroup:Type:AWS::Logs::LogGroupProperties:LogGroupName:!Join ['-', [ECSLogGroup, !Ref 'AWS::StackName']]RetentionInDays:14TaskDefinition:Type:AWS::ECS::TaskDefinitionProperties:Family:!Join ['', [!Ref 'AWS::StackName', -ecs-demo-app]]ContainerDefinitions:- Name:simple-appCpu:10Essential:trueImage:httpd:2.4Memory:300LogConfiguration:LogDriver:awslogsOptions:awslogs-group:!Ref 'CloudwatchLogsGroup'awslogs-region:!Ref 'AWS::Region'awslogs-stream-prefix:ecs-demo-appMountPoints:- ContainerPath:/usr/local/apache2/htdocsSourceVolume:my-volPortMappings:- ContainerPort:80- Name:busyboxCpu:10Command:['/bin/sh -c "while true; do echo ''<html> <head> <title>Amazon ECS
Sample App</title></head><body></body></html>'' > bottom; cat top date bottom > /usr/local/apache2/htdocs/index.html
; sleep 1; done"']EntryPoint:[sh, -c]Essential:falseImage:busyboxMemory:200LogConfiguration:LogDriver:awslogsOptions:awslogs-group:!Ref 'CloudwatchLogsGroup'awslogs-region:!Ref 'AWS::Region'awslogs-stream-prefix:ecs-demo-appVolumesFrom:- SourceContainer:simple-appVolumes:- Name:my-volECSALB:Type:AWS::ElasticLoadBalancingV2::LoadBalancerProperties:Name:ECSALBScheme:internet-facingLoadBalancerAttributes:- Key:idle_timeout.timeout_secondsValue:'30'Subnets:!Ref 'SubnetId'SecurityGroups:[!Ref 'EcsSecurityGroup']ALBListener:Type:AWS::ElasticLoadBalancingV2::ListenerProperties:DefaultActions:- Type:forwardTargetGroupArn:!Ref 'ECSTG'LoadBalancerArn:!Ref 'ECSALB'Port:80Protocol:HTTPECSALBListenerRule:Type:AWS::ElasticLoadBalancingV2::ListenerRuleProperties:Actions:- Type:forwardTargetGroupArn:!Ref 'ECSTG'Conditions:- Field:path-patternValues:[/]ListenerArn:!Ref 'ALBListener'Priority:1ECSTG:Type:AWS::ElasticLoadBalancingV2::TargetGroupProperties:HealthCheckIntervalSeconds:10HealthCheckPath:/HealthCheckProtocol:HTTPHealthCheckTimeoutSeconds:5HealthyThresholdCount:2Name:ECSTGPort:80Protocol:HTTPUnhealthyThresholdCount:2VpcId:!Ref 'VpcId'ECSAutoScalingGroup:Type:AWS::AutoScaling::AutoScalingGroupProperties:VPCZoneIdentifier:!Ref 'SubnetId'LaunchConfigurationName:!Ref 'ContainerInstances'MinSize:'1'MaxSize:4DesiredCapacity:2CreationPolicy:ResourceSignal:Timeout:PT15MUpdatePolicy:AutoScalingReplacingUpdate:WillReplace:trueContainerInstances:Type:AWS::AutoScaling::LaunchConfigurationProperties:ImageId:ami-09bee01cc997a78a6SecurityGroups:[!Ref 'EcsSecurityGroup']InstanceType:t2.smallIamInstanceProfile:!Ref 'EC2InstanceProfile'KeyName:my-ssh-keyUserData:Fn::Base64:!Sub |#!/bin/bash -xeecho ECS_CLUSTER=${ECSCluster} >> /etc/ecs/ecs.configyum install -y aws-cfn-bootstrap/opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource ECSAutoScalingGroup --region ${AWS::Region}service:Type:AWS::ECS::ServiceProperties:Cluster:!Ref 'ECSCluster'DesiredCount:1LoadBalancers:- ContainerName:simple-appContainerPort:80TargetGroupArn:!Ref 'ECSTG'Role:!Ref 'ECSServiceRole'TaskDefinition:!Ref 'taskdefinition'ECSServiceRole:Type:AWS::IAM::RoleProperties:AssumeRolePolicyDocument:Statement:- Effect:AllowPrincipal:Service:[ecs.amazonaws.com]Action:['sts:AssumeRole']Path:/Policies:- PolicyName:ecs-servicePolicyDocument:Statement:- Effect:AllowAction:['elasticloadbalancing:DeregisterInstancesFromLoadBalancer','elasticloadbalancing:DeregisterTargets','elasticloadbalancing:Describe*','elasticloadbalancing:RegisterInstancesWithLoadBalancer','elasticloadbalancing:RegisterTargets','ec2:Describe*','ec2:AuthorizeSecurityGroupIngress']Resource:'*'ServiceScalingTarget:Type:AWS::ApplicationAutoScaling::ScalableTargetProperties:MaxCapacity:2MinCapacity:1ResourceId:!Join ['', [service/, !Ref 'ECSCluster', /, !GetAtt [service, Name]]]RoleARN:!GetAtt [AutoscalingRole, Arn]ScalableDimension:ecs:service:DesiredCountServiceNamespace:ecsServiceScalingPolicy:Type:AWS::ApplicationAutoScaling::ScalingPolicyProperties:PolicyName:AStepPolicyPolicyType:StepScalingScalingTargetId:!Ref 'ServiceScalingTarget'StepScalingPolicyConfiguration:AdjustmentType:PercentChangeInCapacityCooldown:60MetricAggregationType:AverageStepAdjustments:- MetricIntervalLowerBound:0ScalingAdjustment:200ALB500sAlarmScaleUp:Type:AWS::CloudWatch::AlarmProperties:EvaluationPeriods:1Statistic:AverageThreshold:10AlarmDescription:Alarm if our ALB generates too many HTTP 500s.Period:60AlarmActions:[!Ref 'ServiceScalingPolicy']Namespace:AWS/ApplicationELBDimensions:- Name:LoadBalancerValue:!GetAtt- ECSALB- LoadBalancerFullNameComparisonOperator:GreaterThanThresholdMetricName:HTTPCode_ELB_5XX_CountEC2Role:Type:AWS::IAM::RoleProperties:AssumeRolePolicyDocument:Statement:- Effect:AllowPrincipal:Service:[ec2.amazonaws.com]Action:['sts:AssumeRole']Path:/Policies:- PolicyName:ecs-servicePolicyDocument:Statement:- Effect:AllowAction:['ecs:CreateCluster','ecs:DeregisterContainerInstance','ecs:DiscoverPollEndpoint','ecs:Poll','ecs:RegisterContainerInstance','ecs:StartTelemetrySession','ecs:Submit*','logs:CreateLogStream','logs:PutLogEvents']Resource:'*'AutoscalingRole:Type:AWS::IAM::RoleProperties:AssumeRolePolicyDocument:Statement:- Effect:AllowPrincipal:Service:[application-autoscaling.amazonaws.com]Action:['sts:AssumeRole']Path:/Policies:- PolicyName:service-autoscalingPolicyDocument:Statement:- Effect:AllowAction:['application-autoscaling:*','cloudwatch:DescribeAlarms','cloudwatch:PutMetricAlarm','ecs:DescribeServices','ecs:UpdateService']Resource:'*'EC2InstanceProfile:Type:AWS::IAM::InstanceProfileProperties:Path:/Roles:[!Ref 'EC2Role']
{"AWSTemplateFormatVersion":"2010-09-09","Parameters":{"VpcId":{"Type":"AWS::EC2::VPC::Id","Description":"Select a VPC that allows instances access to the Internet."},"SubnetId":{"Description":"Select at two subnets in your selected VPC.","Type":"List\u003cAWS::EC2::Subnet::Id\u003e"}},"Resources":{"EcsSecurityGroupHTTPinbound":{"Type":"AWS::EC2::SecurityGroupIngress","Properties":{"CidrIp":"0.0.0.0/0","GroupId":"EcsSecurityGroup","IpProtocol":"tcp","FromPort":80,"ToPort":80}},"EcsSecurityGroupALBports":{"Type":"AWS::EC2::SecurityGroupIngress","Properties":{"GroupId":"EcsSecurityGroup","IpProtocol":"tcp","FromPort":31000,"ToPort":61000,"SourceSecurityGroupId":"EcsSecurityGroup"}},"CloudwatchLogsGroup":{"Type":"AWS::Logs::LogGroup","Properties":{"LogGroupName":["-",["ECSLogGroup","AWS::StackName"]],"RetentionInDays":14}},"ALBListener":{"Type":"AWS::ElasticLoadBalancingV2::Listener","Properties":{"DefaultActions":[{"Type":"forward","TargetGroupArn":"ECSTG"}],"LoadBalancerArn":"ECSALB","Port":80,"Protocol":"HTTP"}},"ECSALBListenerRule":{"Type":"AWS::ElasticLoadBalancingV2::ListenerRule","Properties":{"Actions":[{"TargetGroupArn":"ECSTG","Type":"forward"}],"Conditions":[{"Field":"path-pattern","Values":["/"]}],"ListenerArn":"ALBListener","Priority":1}},"ALB500sAlarmScaleUp":{"Properties":{"Dimensions":[{"Name":"LoadBalancer","Value":["ECSALB","LoadBalancerFullName"]}],"ComparisonOperator":"GreaterThanThreshold","MetricName":"HTTPCode_ELB_5XX_Count","Statistic":"Average","Threshold":10,"AlarmDescription":"Alarm if our ALB generates too many HTTP 500s.","Period":60,"EvaluationPeriods":1,"AlarmActions":["ServiceScalingPolicy"],"Namespace":"AWS/ApplicationELB"},"Type":"AWS::CloudWatch::Alarm"},"AutoscalingRole":{"Type":"AWS::IAM::Role","Properties":{"AssumeRolePolicyDocument":{"Statement":[{"Effect":"Allow","Principal":{"Service":["application-autoscaling.amazonaws.com"]},"Action":["sts:AssumeRole"]}]},"Path":"/","Policies":[{"PolicyName":"service-autoscaling","PolicyDocument":{"Statement":[{"Effect":"Allow","Action":["application-autoscaling:*","cloudwatch:DescribeAlarms","cloudwatch:PutMetricAlarm","ecs:DescribeServices","ecs:UpdateService"],"Resource":"*"}]}}]}},"ECSCluster":{"Type":"AWS::ECS::Cluster"},"ECSServiceRole":{"Type":"AWS::IAM::Role","Properties":{"AssumeRolePolicyDocument":{"Statement":[{"Effect":"Allow","Principal":{"Service":["ecs.amazonaws.com"]},"Action":["sts:AssumeRole"]}]},"Path":"/","Policies":[{"PolicyName":"ecs-service","PolicyDocument":{"Statement":[{"Effect":"Allow","Action":["elasticloadbalancing:DeregisterInstancesFromLoadBalancer","elasticloadbalancing:DeregisterTargets","elasticloadbalancing:Describe*","elasticloadbalancing:RegisterInstancesWithLoadBalancer","elasticloadbalancing:RegisterTargets","ec2:Describe*","ec2:AuthorizeSecurityGroupIngress"],"Resource":"*"}]}}]}},"ServiceScalingPolicy":{"Type":"AWS::ApplicationAutoScaling::ScalingPolicy","Properties":{"PolicyName":"AStepPolicy","PolicyType":"StepScaling","ScalingTargetId":"ServiceScalingTarget","StepScalingPolicyConfiguration":{"Cooldown":60,"MetricAggregationType":"Average","StepAdjustments":[{"MetricIntervalLowerBound":0,"ScalingAdjustment":200}],"AdjustmentType":"PercentChangeInCapacity"}}},"EC2InstanceProfile":{"Type":"AWS::IAM::InstanceProfile","Properties":{"Path":"/","Roles":["EC2Role"]}},"ECSAutoScalingGroup":{"Type":"AWS::AutoScaling::AutoScalingGroup","Properties":{"VPCZoneIdentifier":"SubnetId","LaunchConfigurationName":"ContainerInstances","MinSize":"1","MaxSize":4,"DesiredCapacity":2},"CreationPolicy":{"ResourceSignal":{"Timeout":"PT15M"}},"UpdatePolicy":{"AutoScalingReplacingUpdate":{"WillReplace":true}}},"ECSALB":{"Type":"AWS::ElasticLoadBalancingV2::LoadBalancer","Properties":{"Scheme":"internet-facing","LoadBalancerAttributes":[{"Key":"idle_timeout.timeout_seconds","Value":"30"}],"Subnets":"SubnetId","SecurityGroups":["EcsSecurityGroup"],"Name":"ECSALB"}},"ECSTG":{"Type":"AWS::ElasticLoadBalancingV2::TargetGroup","Properties":{"Name":"ECSTG","Protocol":"HTTP","HealthCheckPath":"/","HealthCheckTimeoutSeconds":5,"HealthyThresholdCount":2,"UnhealthyThresholdCount":2,"VpcId":"VpcId","HealthCheckIntervalSeconds":10,"HealthCheckProtocol":"HTTP","Port":80}},"EC2Role":{"Type":"AWS::IAM::Role","Properties":{"AssumeRolePolicyDocument":{"Statement":[{"Effect":"Allow","Principal":{"Service":["ec2.amazonaws.com"]},"Action":["sts:AssumeRole"]}]},"Path":"/","Policies":[{"PolicyName":"ecs-service","PolicyDocument":{"Statement":[{"Resource":"*","Effect":"Allow","Action":["ecs:CreateCluster","ecs:DeregisterContainerInstance","ecs:DiscoverPollEndpoint","ecs:Poll","ecs:RegisterContainerInstance","ecs:StartTelemetrySession","ecs:Submit*","logs:CreateLogStream","logs:PutLogEvents"]}]}}]}},"TaskDefinition":{"Properties":{"Volumes":[{"Name":"my-vol"}],"Family":["",["AWS::StackName","-ecs-demo-app"]],"ContainerDefinitions":[{"Image":"httpd:2.4","Memory":300,"LogConfiguration":{"LogDriver":"awslogs","Options":{"awslogs-group":"CloudwatchLogsGroup","awslogs-region":"AWS::Region","awslogs-stream-prefix":"ecs-demo-app"}},"MountPoints":[{"ContainerPath":"/usr/local/apache2/htdocs","SourceVolume":"my-vol"}],"PortMappings":[{"ContainerPort":80}],"Name":"simple-app","Cpu":10,"Essential":true},{"VolumesFrom":[{"SourceContainer":"simple-app"}],"Cpu":10,"EntryPoint":["sh","-c"],"Essential":false,"Image":"busybox","Memory":200,"LogConfiguration":{"LogDriver":"awslogs","Options":{"awslogs-stream-prefix":"ecs-demo-app","awslogs-group":"CloudwatchLogsGroup","awslogs-region":"AWS::Region"}},"Name":"busybox","Command":["/bin/sh -c \"while true; do echo '\u003chtml\u003e \u003chead\u003e \u003ctitle\u003eAmazon ECS Sample App\u003c/title\u003e\u003c/head\u003e\u003cbody\u003e\u003c/body\u003e\u003c/html\u003e' \u003e bottom; cat top date bottom \u003e /usr/local/apache2/htdocs/index.html ; sleep 1; done\""]}]},"Type":"AWS::ECS::TaskDefinition"},"EcsSecurityGroupSSHinbound":{"Type":"AWS::EC2::SecurityGroupIngress","Properties":{"ToPort":22,"CidrIp":"0.0.0.0/0","GroupId":"EcsSecurityGroup","IpProtocol":"tcp","FromPort":22}},"ContainerInstances":{"Type":"AWS::AutoScaling::LaunchConfiguration","Properties":{"ImageId":"ami-09bee01cc997a78a6","SecurityGroups":["EcsSecurityGroup"],"InstanceType":"t2.small","IamInstanceProfile":"EC2InstanceProfile","KeyName":"my-ssh-key","UserData":{"Fn::Base64":"#!/bin/bash -xe\necho ECS_CLUSTER=${ECSCluster} \u003e\u003e /etc/ecs/ecs.config\nyum install -y aws-cfn-bootstrap\n/opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource ECSAutoScalingGroup --region ${AWS::Region}\n"}}},"service":{"Type":"AWS::ECS::Service","Properties":{"Cluster":"ECSCluster","DesiredCount":1,"LoadBalancers":[{"ContainerPort":80,"TargetGroupArn":"ECSTG","ContainerName":"simple-app"}],"Role":"ECSServiceRole","TaskDefinition":"taskdefinition"}},"ServiceScalingTarget":{"Properties":{"MinCapacity":1,"ResourceId":["",["service/","ECSCluster","/",["service","Name"]]],"RoleARN":["AutoscalingRole","Arn"],"ScalableDimension":"ecs:service:DesiredCount","ServiceNamespace":"ecs","MaxCapacity":2},"Type":"AWS::ApplicationAutoScaling::ScalableTarget"},"EcsSecurityGroup":{"Type":"AWS::EC2::SecurityGroup","Properties":{"GroupDescription":"ECS Security Group","VpcId":"VpcId"}}}}
Non-Compliant Code Examples
AWSTemplateFormatVersion:'2010-09-09'Parameters:VpcId:Type:AWS::EC2::VPC::IdDescription:Select a VPC that allows instances access to the Internet.SubnetId:Type:List<AWS::EC2::Subnet::Id>Description:Select at two subnets in your selected VPC.Resources:ECSCluster:Type:AWS::ECS::ClusterEcsSecurityGroup:Type:AWS::EC2::SecurityGroupProperties:GroupDescription:ECS Security GroupVpcId:!Ref 'VpcId'EcsSecurityGroupHTTPinbound02:Type:AWS::EC2::SecurityGroupIngressProperties:GroupId:!Ref 'EcsSecurityGroup'IpProtocol:tcpFromPort:80ToPort:0CidrIp:0.0.0.0/0EcsSecurityGroupSSHinbound:Type:AWS::EC2::SecurityGroupIngressProperties:GroupId:!Ref 'EcsSecurityGroup'IpProtocol:tcpFromPort:22ToPort:0CidrIp:0.0.0.0/0EcsSecurityGroupALBports:Type:AWS::EC2::SecurityGroupIngressProperties:GroupId:!Ref 'EcsSecurityGroup'IpProtocol:tcpFromPort:31000ToPort:61000SourceSecurityGroupId:!Ref 'EcsSecurityGroup'CloudwatchLogsGroup:Type:AWS::Logs::LogGroupProperties:LogGroupName:!Join ['-', [ECSLogGroup, !Ref 'AWS::StackName']]RetentionInDays:14TaskDefinition:Type:AWS::ECS::TaskDefinitionProperties:Family:!Join ['', [!Ref 'AWS::StackName', -ecs-demo-app]]ContainerDefinitions:- Name:simple-appCpu:10Essential:trueImage:httpd:2.4Memory:300LogConfiguration:LogDriver:awslogsOptions:awslogs-group:!Ref 'CloudwatchLogsGroup'awslogs-region:!Ref 'AWS::Region'awslogs-stream-prefix:ecs-demo-appMountPoints:- ContainerPath:/usr/local/apache2/htdocsSourceVolume:my-volPortMappings:- ContainerPort:80- Name:busyboxCpu:10Command:['/bin/sh -c "while true; do echo ''<html> <head> <title>Amazon ECS
Sample App</title></head></html>'' > bottom; cat top date bottom > /usr/local/apache2/htdocs/index.html
; sleep 1; done"']EntryPoint:[sh, -c]Essential:falseImage:busyboxMemory:200LogConfiguration:LogDriver:awslogsOptions:awslogs-group:!Ref 'CloudwatchLogsGroup'awslogs-region:!Ref 'AWS::Region'awslogs-stream-prefix:ecs-demo-appVolumesFrom:- SourceContainer:simple-appVolumes:- Name:my-volECSALB:Type:AWS::ElasticLoadBalancingV2::LoadBalancerProperties:Name:ECSALBScheme:internet-facingLoadBalancerAttributes:- Key:idle_timeout.timeout_secondsValue:'30'Subnets:!Ref 'SubnetId'SecurityGroups:[!Ref 'EcsSecurityGroup']ALBListener:Type:AWS::ElasticLoadBalancingV2::ListenerProperties:DefaultActions:- Type:forwardTargetGroupArn:!Ref 'ECSTG'LoadBalancerArn:!Ref 'ECSALB'Port:80Protocol:HTTPECSALBListenerRule:Type:AWS::ElasticLoadBalancingV2::ListenerRuleProperties:Actions:- Type:forwardTargetGroupArn:!Ref 'ECSTG'Conditions:- Field:path-patternValues:[/]ListenerArn:!Ref 'ALBListener'Priority:1ECSTG:Type:AWS::ElasticLoadBalancingV2::TargetGroupProperties:HealthCheckIntervalSeconds:10HealthCheckPath:/HealthCheckProtocol:HTTPHealthCheckTimeoutSeconds:5HealthyThresholdCount:2Name:ECSTGPort:80Protocol:HTTPUnhealthyThresholdCount:2VpcId:!Ref 'VpcId'ECSAutoScalingGroup:Type:AWS::AutoScaling::AutoScalingGroupProperties:VPCZoneIdentifier:!Ref 'SubnetId'LaunchConfigurationName:!Ref 'ContainerInstances'MinSize:'1'MaxSize:4DesiredCapacity:2CreationPolicy:ResourceSignal:Timeout:PT15MUpdatePolicy:AutoScalingReplacingUpdate:WillReplace:trueContainerInstances:Type:AWS::AutoScaling::LaunchConfigurationProperties:ImageId:ami-128731982dhashSecurityGroups:[!Ref 'EcsSecurityGroup']InstanceType:t2.smallIamInstanceProfile:!Ref 'EC2InstanceProfile'KeyName:my-ssh-keyUserData:Fn::Base64:!Sub |#!/bin/bash -xeecho ECS_CLUSTER=${ECSCluster} >> /etc/ecs/ecs.configyum install -y aws-cfn-bootstrap/opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource ECSAutoScalingGroup --region ${AWS::Region}service:Type:AWS::ECS::ServiceProperties:Cluster:!Ref 'ECSCluster'DesiredCount:1LoadBalancers:- ContainerName:simple-appContainerPort:80TargetGroupArn:!Ref 'ECSTG'Role:!Ref 'ECSServiceRole'TaskDefinition:!Ref 'TaskDefinition'ECSServiceRole:Type:AWS::IAM::RoleProperties:AssumeRolePolicyDocument:Statement:- Effect:AllowPrincipal:Service:[ecs.amazonaws.com]Action:['sts:AssumeRole']Path:/Policies:- PolicyName:ecs-servicePolicyDocument:Statement:- Effect:AllowAction:['elasticloadbalancing:DeregisterInstancesFromLoadBalancer','elasticloadbalancing:DeregisterTargets','elasticloadbalancing:Describe*','elasticloadbalancing:RegisterInstancesWithLoadBalancer','elasticloadbalancing:RegisterTargets','ec2:Describe*','ec2:AuthorizeSecurityGroupIngress']Resource:'*'ServiceScalingTarget:Type:AWS::ApplicationAutoScaling::ScalableTargetProperties:MaxCapacity:2MinCapacity:1ResourceId:!Join ['', [service/, !Ref 'ECSCluster', /, !GetAtt [service, Name]]]RoleARN:!GetAtt [AutoscalingRole, Arn]ScalableDimension:ecs:service:DesiredCountServiceNamespace:ecsServiceScalingPolicy:Type:AWS::ApplicationAutoScaling::ScalingPolicyProperties:PolicyName:AStepPolicyPolicyType:StepScalingScalingTargetId:!Ref 'ServiceScalingTarget'StepScalingPolicyConfiguration:AdjustmentType:PercentChangeInCapacityCooldown:60MetricAggregationType:AverageStepAdjustments:- MetricIntervalLowerBound:0ScalingAdjustment:200ALB500sAlarmScaleUp:Type:AWS::CloudWatch::AlarmProperties:EvaluationPeriods:1Statistic:AverageThreshold:10AlarmDescription:Alarm if our ALB generates too many HTTP 500s.Period:60AlarmActions:[!Ref 'ServiceScalingPolicy']Namespace:AWS/ApplicationELBDimensions:- Name:LoadBalancerValue:!GetAtt- ECSALB- LoadBalancerFullNameComparisonOperator:GreaterThanThresholdMetricName:HTTPCode_ELB_5XX_CountEC2Role:Type:AWS::IAM::RoleProperties:AssumeRolePolicyDocument:Statement:- Effect:AllowPrincipal:Service:[ec2.amazonaws.com]Action:['sts:AssumeRole']Path:/Policies:- PolicyName:ecs-servicePolicyDocument:Statement:- Effect:AllowAction:['ecs:CreateCluster','ecs:DeregisterContainerInstance','ecs:DiscoverPollEndpoint','ecs:Poll','ecs:RegisterContainerInstance','ecs:StartTelemetrySession','ecs:Submit*','logs:CreateLogStream','logs:PutLogEvents']Resource:'*'AutoscalingRole:Type:AWS::IAM::RoleProperties:AssumeRolePolicyDocument:Statement:- Effect:AllowPrincipal:Service:[application-autoscaling.amazonaws.com]Action:['sts:AssumeRole']Path:/Policies:- PolicyName:service-autoscalingPolicyDocument:Statement:- Effect:AllowAction:['application-autoscaling:*','cloudwatch:DescribeAlarms','cloudwatch:PutMetricAlarm','ecs:DescribeServices','ecs:UpdateService']Resource:'*'EC2InstanceProfile:Type:AWS::IAM::InstanceProfileProperties:Path:/Roles:[!Ref 'EC2Role']Outputs:ecsservice:Value:!Ref 'service'ecscluster:Value:!Ref 'ECSCluster'ECSALB:Description:Your ALB DNS URLValue:!Join ['', [!GetAtt [ECSALB, DNSName]]]taskdef:Value:!Ref 'TaskDefinition'
AWSTemplateFormatVersion:'2010-09-09'Parameters:VpcId:Type:AWS::EC2::VPC::IdDescription:Select a VPC that allows instances access to the Internet.SubnetId:Type:List<AWS::EC2::Subnet::Id>Description:Select at two subnets in your selected VPC.Resources:ECSCluster:Type:AWS::ECS::ClusterEcsSecurityGroup:Type:AWS::EC2::SecurityGroupProperties:GroupDescription:ECS Security GroupVpcId:!Ref 'VpcId'EcsSecurityGroupHTTPinbound:Type:AWS::EC2::SecurityGroupIngressProperties:GroupId:!Ref 'EcsSecurityGroup'IpProtocol:tcpFromPort:80ToPort:0CidrIp:0.0.0.0/0EcsSecurityGroupSSHinbound:Type:AWS::EC2::SecurityGroupIngressProperties:GroupId:!Ref 'EcsSecurityGroup'IpProtocol:tcpFromPort:22ToPort:22CidrIp:0.0.0.0/0EcsSecurityGroupALBports:Type:AWS::EC2::SecurityGroupIngressProperties:GroupId:!Ref 'EcsSecurityGroup'IpProtocol:tcpFromPort:31000ToPort:61000SourceSecurityGroupId:!Ref 'EcsSecurityGroup'CloudwatchLogsGroup:Type:AWS::Logs::LogGroupProperties:LogGroupName:!Join ['-', [ECSLogGroup, !Ref 'AWS::StackName']]RetentionInDays:14TaskDefinition:Type:AWS::ECS::TaskDefinitionProperties:Family:!Join ['', [!Ref 'AWS::StackName', -ecs-demo-app]]ContainerDefinitions:- Name:simple-appCpu:10Essential:trueImage:httpd:2.4Memory:300LogConfiguration:LogDriver:awslogsOptions:awslogs-group:!Ref 'CloudwatchLogsGroup'awslogs-region:!Ref 'AWS::Region'awslogs-stream-prefix:ecs-demo-appMountPoints:- ContainerPath:/usr/local/apache2/htdocsSourceVolume:my-volPortMappings:- ContainerPort:80- Name:busyboxCpu:10Command:['/bin/sh -c "while true; do echo ''<html> <head> <title>Amazon ECS
Sample App</title></head><body></body></html>'' > bottom; cat top date bottom > /usr/local/apache2/htdocs/index.html
; sleep 1; done"']EntryPoint:[sh, -c]Essential:falseImage:busyboxMemory:200LogConfiguration:LogDriver:awslogsOptions:awslogs-group:!Ref 'CloudwatchLogsGroup'awslogs-region:!Ref 'AWS::Region'awslogs-stream-prefix:ecs-demo-appVolumesFrom:- SourceContainer:simple-appVolumes:- Name:my-volECSALB:Type:AWS::ElasticLoadBalancingV2::LoadBalancerProperties:Name:ECSALBScheme:internet-facingLoadBalancerAttributes:- Key:idle_timeout.timeout_secondsValue:'30'Subnets:!Ref 'SubnetId'SecurityGroups:[!Ref 'EcsSecurityGroup']ALBListener:Type:AWS::ElasticLoadBalancingV2::ListenerProperties:DefaultActions:- Type:forwardTargetGroupArn:!Ref 'ECSTG'LoadBalancerArn:!Ref 'ECSALB'Port:80Protocol:HTTPECSALBListenerRule:Type:AWS::ElasticLoadBalancingV2::ListenerRuleProperties:Actions:- Type:forwardTargetGroupArn:!Ref 'ECSTG'Conditions:- Field:path-patternValues:[/]ListenerArn:!Ref 'ALBListener'Priority:1ECSTG:Type:AWS::ElasticLoadBalancingV2::TargetGroupProperties:HealthCheckIntervalSeconds:10HealthCheckPath:/HealthCheckProtocol:HTTPHealthCheckTimeoutSeconds:5HealthyThresholdCount:2Name:ECSTGPort:80Protocol:HTTPUnhealthyThresholdCount:2VpcId:!Ref 'VpcId'ECSAutoScalingGroup:Type:AWS::AutoScaling::AutoScalingGroupProperties:VPCZoneIdentifier:!Ref 'SubnetId'LaunchConfigurationName:!Ref 'ContainerInstances'MinSize:'1'MaxSize:4DesiredCapacity:2CreationPolicy:ResourceSignal:Timeout:PT15MUpdatePolicy:AutoScalingReplacingUpdate:WillReplace:trueContainerInstances:Type:AWS::AutoScaling::LaunchConfigurationProperties:ImageId:ami-09bee01cc997a78a6SecurityGroups:[!Ref 'EcsSecurityGroup']InstanceType:t2.smallIamInstanceProfile:!Ref 'EC2InstanceProfile'KeyName:my-ssh-keyUserData:Fn::Base64:!Sub |#!/bin/bash -xeecho ECS_CLUSTER=${ECSCluster} >> /etc/ecs/ecs.configyum install -y aws-cfn-bootstrap/opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource ECSAutoScalingGroup --region ${AWS::Region}service:Type:AWS::ECS::ServiceProperties:Cluster:!Ref 'ECSCluster'DesiredCount:1LoadBalancers:- ContainerName:simple-appContainerPort:80TargetGroupArn:!Ref 'ECSTG'Role:!Ref 'ECSServiceRole'TaskDefinition:!Ref 'TaskDefinition'ECSServiceRole:Type:AWS::IAM::RoleProperties:AssumeRolePolicyDocument:Statement:- Effect:AllowPrincipal:Service:[ecs.amazonaws.com]Action:['sts:AssumeRole']Path:/Policies:- PolicyName:ecs-servicePolicyDocument:Statement:- Effect:AllowAction:['elasticloadbalancing:DeregisterInstancesFromLoadBalancer','elasticloadbalancing:DeregisterTargets','elasticloadbalancing:Describe*','elasticloadbalancing:RegisterInstancesWithLoadBalancer','elasticloadbalancing:RegisterTargets','ec2:Describe*','ec2:AuthorizeSecurityGroupIngress']Resource:'*'ServiceScalingTarget:Type:AWS::ApplicationAutoScaling::ScalableTargetProperties:MaxCapacity:2MinCapacity:1ResourceId:!Join ['', [service/, !Ref 'ECSCluster', /, !GetAtt [service, Name]]]RoleARN:!GetAtt [AutoscalingRole, Arn]ScalableDimension:ecs:service:DesiredCountServiceNamespace:ecsServiceScalingPolicy:Type:AWS::ApplicationAutoScaling::ScalingPolicyProperties:PolicyName:AStepPolicyPolicyType:StepScalingScalingTargetId:!Ref 'ServiceScalingTarget'StepScalingPolicyConfiguration:AdjustmentType:PercentChangeInCapacityCooldown:60MetricAggregationType:AverageStepAdjustments:- MetricIntervalLowerBound:0ScalingAdjustment:200ALB500sAlarmScaleUp:Type:AWS::CloudWatch::AlarmProperties:EvaluationPeriods:1Statistic:AverageThreshold:10AlarmDescription:Alarm if our ALB generates too many HTTP 500s.Period:60AlarmActions:[!Ref 'ServiceScalingPolicy']Namespace:AWS/ApplicationELBDimensions:- Name:LoadBalancerValue:!GetAtt- ECSALB- LoadBalancerFullNameComparisonOperator:GreaterThanThresholdMetricName:HTTPCode_ELB_5XX_CountEC2Role:Type:AWS::IAM::RoleProperties:AssumeRolePolicyDocument:Statement:- Effect:AllowPrincipal:Service:[ec2.amazonaws.com]Action:['sts:AssumeRole']Path:/Policies:- PolicyName:ecs-servicePolicyDocument:Statement:- Effect:AllowAction:['ecs:CreateCluster','ecs:DeregisterContainerInstance','ecs:DiscoverPollEndpoint','ecs:Poll','ecs:RegisterContainerInstance','ecs:StartTelemetrySession','ecs:Submit*','logs:CreateLogStream','logs:PutLogEvents']Resource:'*'AutoscalingRole:Type:AWS::IAM::RoleProperties:AssumeRolePolicyDocument:Statement:- Effect:AllowPrincipal:Service:[application-autoscaling.amazonaws.com]Action:['sts:AssumeRole']Path:/Policies:- PolicyName:service-autoscalingPolicyDocument:Statement:- Effect:AllowAction:['application-autoscaling:*','cloudwatch:DescribeAlarms','cloudwatch:PutMetricAlarm','ecs:DescribeServices','ecs:UpdateService']Resource:'*'EC2InstanceProfile:Type:AWS::IAM::InstanceProfileProperties:Path:/Roles:[!Ref 'EC2Role']
{"AWSTemplateFormatVersion":"2010-09-09","Parameters":{"VpcId":{"Type":"AWS::EC2::VPC::Id","Description":"Select a VPC that allows instances access to the Internet."},"SubnetId":{"Type":"List\u003cAWS::EC2::Subnet::Id\u003e","Description":"Select at two subnets in your selected VPC."}},"Resources":{"ECSCluster":{"Type":"AWS::ECS::Cluster"},"EcsSecurityGroupALBports":{"Type":"AWS::EC2::SecurityGroupIngress","Properties":{"IpProtocol":"tcp","FromPort":31000,"ToPort":61000,"SourceSecurityGroupId":"EcsSecurityGroup","GroupId":"EcsSecurityGroup"}},"ECSServiceRole":{"Type":"AWS::IAM::Role","Properties":{"AssumeRolePolicyDocument":{"Statement":[{"Effect":"Allow","Principal":{"Service":["ecs.amazonaws.com"]},"Action":["sts:AssumeRole"]}]},"Path":"/","Policies":[{"PolicyName":"ecs-service","PolicyDocument":{"Statement":[{"Action":["elasticloadbalancing:DeregisterInstancesFromLoadBalancer","elasticloadbalancing:DeregisterTargets","elasticloadbalancing:Describe*","elasticloadbalancing:RegisterInstancesWithLoadBalancer","elasticloadbalancing:RegisterTargets","ec2:Describe*","ec2:AuthorizeSecurityGroupIngress"],"Resource":"*","Effect":"Allow"}]}}]}},"AutoscalingRole":{"Type":"AWS::IAM::Role","Properties":{"AssumeRolePolicyDocument":{"Statement":[{"Effect":"Allow","Principal":{"Service":["application-autoscaling.amazonaws.com"]},"Action":["sts:AssumeRole"]}]},"Path":"/","Policies":[{"PolicyName":"service-autoscaling","PolicyDocument":{"Statement":[{"Effect":"Allow","Action":["application-autoscaling:*","cloudwatch:DescribeAlarms","cloudwatch:PutMetricAlarm","ecs:DescribeServices","ecs:UpdateService"],"Resource":"*"}]}}]}},"EcsSecurityGroupSSHinbound":{"Type":"AWS::EC2::SecurityGroupIngress","Properties":{"ToPort":0,"CidrIp":"0.0.0.0/0","GroupId":"EcsSecurityGroup","IpProtocol":"tcp","FromPort":22}},"ECSALB":{"Properties":{"Name":"ECSALB","Scheme":"internet-facing","LoadBalancerAttributes":[{"Key":"idle_timeout.timeout_seconds","Value":"30"}],"Subnets":"SubnetId","SecurityGroups":["EcsSecurityGroup"]},"Type":"AWS::ElasticLoadBalancingV2::LoadBalancer"},"ECSAutoScalingGroup":{"Type":"AWS::AutoScaling::AutoScalingGroup","Properties":{"VPCZoneIdentifier":"SubnetId","LaunchConfigurationName":"ContainerInstances","MinSize":"1","MaxSize":4,"DesiredCapacity":2},"CreationPolicy":{"ResourceSignal":{"Timeout":"PT15M"}},"UpdatePolicy":{"AutoScalingReplacingUpdate":{"WillReplace":true}}},"ServiceScalingTarget":{"Type":"AWS::ApplicationAutoScaling::ScalableTarget","Properties":{"MaxCapacity":2,"MinCapacity":1,"ResourceId":["",["service/","ECSCluster","/",["service","Name"]]],"RoleARN":["AutoscalingRole","Arn"],"ScalableDimension":"ecs:service:DesiredCount","ServiceNamespace":"ecs"}},"ServiceScalingPolicy":{"Type":"AWS::ApplicationAutoScaling::ScalingPolicy","Properties":{"PolicyType":"StepScaling","ScalingTargetId":"ServiceScalingTarget","StepScalingPolicyConfiguration":{"StepAdjustments":[{"MetricIntervalLowerBound":0,"ScalingAdjustment":200}],"AdjustmentType":"PercentChangeInCapacity","Cooldown":60,"MetricAggregationType":"Average"},"PolicyName":"AStepPolicy"}},"EC2Role":{"Type":"AWS::IAM::Role","Properties":{"AssumeRolePolicyDocument":{"Statement":[{"Effect":"Allow","Principal":{"Service":["ec2.amazonaws.com"]},"Action":["sts:AssumeRole"]}]},"Path":"/","Policies":[{"PolicyName":"ecs-service","PolicyDocument":{"Statement":[{"Action":["ecs:CreateCluster","ecs:DeregisterContainerInstance","ecs:DiscoverPollEndpoint","ecs:Poll","ecs:RegisterContainerInstance","ecs:StartTelemetrySession","ecs:Submit*","logs:CreateLogStream","logs:PutLogEvents"],"Resource":"*","Effect":"Allow"}]}}]}},"ECSTG":{"Type":"AWS::ElasticLoadBalancingV2::TargetGroup","Properties":{"HealthCheckIntervalSeconds":10,"HealthCheckProtocol":"HTTP","HealthCheckTimeoutSeconds":5,"Name":"ECSTG","Port":80,"Protocol":"HTTP","HealthCheckPath":"/","HealthyThresholdCount":2,"UnhealthyThresholdCount":2,"VpcId":"VpcId"}},"service":{"Type":"AWS::ECS::Service","Properties":{"Cluster":"ECSCluster","DesiredCount":1,"LoadBalancers":[{"ContainerName":"simple-app","ContainerPort":80,"TargetGroupArn":"ECSTG"}],"Role":"ECSServiceRole","TaskDefinition":"TaskDefinition"}},"ALB500sAlarmScaleUp":{"Properties":{"Threshold":10,"Dimensions":[{"Name":"LoadBalancer","Value":["ECSALB","LoadBalancerFullName"]}],"ComparisonOperator":"GreaterThanThreshold","MetricName":"HTTPCode_ELB_5XX_Count","EvaluationPeriods":1,"AlarmDescription":"Alarm if our ALB generates too many HTTP 500s.","Period":60,"AlarmActions":["ServiceScalingPolicy"],"Namespace":"AWS/ApplicationELB","Statistic":"Average"},"Type":"AWS::CloudWatch::Alarm"},"EC2InstanceProfile":{"Type":"AWS::IAM::InstanceProfile","Properties":{"Path":"/","Roles":["EC2Role"]}},"EcsSecurityGroup":{"Type":"AWS::EC2::SecurityGroup","Properties":{"VpcId":"VpcId","GroupDescription":"ECS Security Group"}},"EcsSecurityGroupHTTPinbound02":{"Type":"AWS::EC2::SecurityGroupIngress","Properties":{"GroupId":"EcsSecurityGroup","IpProtocol":"tcp","FromPort":80,"ToPort":0,"CidrIp":"0.0.0.0/0"}},"CloudwatchLogsGroup":{"Type":"AWS::Logs::LogGroup","Properties":{"LogGroupName":["-",["ECSLogGroup","AWS::StackName"]],"RetentionInDays":14}},"TaskDefinition":{"Type":"AWS::ECS::TaskDefinition","Properties":{"Family":["",["AWS::StackName","-ecs-demo-app"]],"ContainerDefinitions":[{"Name":"simple-app","Cpu":10,"Essential":true,"Image":"httpd:2.4","Memory":300,"LogConfiguration":{"LogDriver":"awslogs","Options":{"awslogs-group":"CloudwatchLogsGroup","awslogs-region":"AWS::Region","awslogs-stream-prefix":"ecs-demo-app"}},"MountPoints":[{"ContainerPath":"/usr/local/apache2/htdocs","SourceVolume":"my-vol"}],"PortMappings":[{"ContainerPort":80}]},{"VolumesFrom":[{"SourceContainer":"simple-app"}],"Name":"busybox","Cpu":10,"Command":["/bin/sh -c \"while true; do echo '\u003chtml\u003e \u003chead\u003e \u003ctitle\u003eAmazon ECS Sample App\u003c/title\u003e\u003c/head\u003e\u003c/html\u003e' \u003e bottom; cat top date bottom \u003e /usr/local/apache2/htdocs/index.html ; sleep 1; done\""],"Image":"busybox","Memory":200,"LogConfiguration":{"LogDriver":"awslogs","Options":{"awslogs-stream-prefix":"ecs-demo-app","awslogs-group":"CloudwatchLogsGroup","awslogs-region":"AWS::Region"}},"EntryPoint":["sh","-c"],"Essential":false}],"Volumes":[{"Name":"my-vol"}]}},"ALBListener":{"Type":"AWS::ElasticLoadBalancingV2::Listener","Properties":{"LoadBalancerArn":"ECSALB","Port":80,"Protocol":"HTTP","DefaultActions":[{"Type":"forward","TargetGroupArn":"ECSTG"}]}},"ECSALBListenerRule":{"Type":"AWS::ElasticLoadBalancingV2::ListenerRule","Properties":{"Actions":[{"Type":"forward","TargetGroupArn":"ECSTG"}],"Conditions":[{"Values":["/"],"Field":"path-pattern"}],"ListenerArn":"ALBListener","Priority":1}},"ContainerInstances":{"Type":"AWS::AutoScaling::LaunchConfiguration","Properties":{"ImageId":"ami-128731982dhash","SecurityGroups":["EcsSecurityGroup"],"InstanceType":"t2.small","IamInstanceProfile":"EC2InstanceProfile","KeyName":"my-ssh-key","UserData":{"Fn::Base64":"#!/bin/bash -xe\necho ECS_CLUSTER=${ECSCluster} \u003e\u003e /etc/ecs/ecs.config\nyum install -y aws-cfn-bootstrap\n/opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource ECSAutoScalingGroup --region ${AWS::Region}\n"}}}},"Outputs":{"ecscluster":{"Value":"ECSCluster"},"ECSALB":{"Description":"Your ALB DNS URL","Value":["",[["ECSALB","DNSName"]]]},"taskdef":{"Value":"TaskDefinition"},"ecsservice":{"Value":"service"}}}
1
2
rulesets:- CloudFormation / AWS # Rules to enforce / AWS.
Request a personalized demo
Get Started with Datadog
Ask AI
AI-generated responses may be inaccurate. Verify important info.