Skip to content

Commit

Permalink
ECS: Creating special security groups for ingress, instead of adding …
Browse files Browse the repository at this point in the history
…the ingress rule to other security groups

Solves docker-archive#1783
Previously, the ECS stack included an ingress rule to allow LB to reach the tasks.
However, it added this ingress rule toe very Docker network security group, meaning other tasks on the same Docker network, possibly sensitive, were accessible externally.
We now create a new security group for port assignments for every service that has ports, and attach that security group only to that service.
This prevents other tasks in the same Docker networks are not accessible externally.
  • Loading branch information
BackSlasher committed Jan 11, 2023
1 parent bd636e0 commit 8f590ab
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 24 deletions.
18 changes: 18 additions & 0 deletions ecs/awsResources.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ func (r *awsResources) serviceSecurityGroups(service types.ServiceConfig) []stri
for net := range service.Networks {
groups = append(groups, r.securityGroups[net])
}
// TODO add the ingress secgroup
if len(service.Ports) > 0 {
groups = append(groups, r.securityGroups[serviceIngressSecGroupName(service.Name)])
}
return groups
}

Expand Down Expand Up @@ -330,6 +334,7 @@ func (b *ecsAPIService) ensureCluster(r *awsResources, project *types.Project, t

func (b *ecsAPIService) ensureNetworks(r *awsResources, project *types.Project, template *cloudformation.Template) {
if r.securityGroups == nil {
// TODO NITZ change the size hint?
r.securityGroups = make(map[string]string, len(project.Networks))
}
for name, net := range project.Networks {
Expand All @@ -353,6 +358,19 @@ func (b *ecsAPIService) ensureNetworks(r *awsResources, project *types.Project,

r.securityGroups[name] = cloudformation.Ref(securityGroup)
}

for _, service := range project.Services {
if len(service.Ports) == 0 {
continue
}
securityGroup := serviceIngressSecGroupName(service.Name)
template.Resources[securityGroup] = &ec2.SecurityGroup{
GroupDescription: fmt.Sprintf("%s Security Group for service %s ingress", project.Name, service.Name),
VpcId: r.vpc,
Tags: serviceTags(project, service),
}
r.securityGroups[securityGroup] = cloudformation.Ref(securityGroup)
}
}

func (b *ecsAPIService) ensureVolumes(r *awsResources, project *types.Project, template *cloudformation.Template) error {
Expand Down
11 changes: 7 additions & 4 deletions ecs/cloudformation.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,11 +197,10 @@ func (b *ecsAPIService) createService(project *types.Project, service types.Serv
dependsOn []string
serviceLB []ecs.Service_LoadBalancer
)
for _, port := range service.Ports {
for net := range service.Networks {
b.createIngress(service, net, port, template, resources)
}

for _, port := range service.Ports {
securityGroupName := serviceIngressSecGroupName(service.Name)
b.createIngress(service, securityGroupName, port, template, resources)
protocol := strings.ToUpper(port.Protocol)
if resources.loadBalancerType == elbv2.LoadBalancerTypeEnumApplication {
// we don't set Https as a certificate must be specified for HTTPS listeners
Expand Down Expand Up @@ -534,6 +533,10 @@ func networkResourceName(network string) string {
return fmt.Sprintf("%sNetwork", normalizeResourceName(network))
}

func serviceIngressSecGroupName(service string) string {
return fmt.Sprintf("%sServiceIngressSecurityGroup", normalizeResourceName(service))
}

func serviceResourceName(service string) string {
return fmt.Sprintf("%sService", normalizeResourceName(service))
}
Expand Down
31 changes: 21 additions & 10 deletions ecs/testdata/simple-cloudformation-conversion.golden
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,6 @@ Resources:
- Key: com.docker.compose.project
Value: TestSimpleConvert
Type: AWS::ECS::Cluster
Default80Ingress:
Properties:
CidrIp: 0.0.0.0/0
Description: simple:80/tcp on default network
FromPort: 80
GroupId:
Ref: DefaultNetwork
IpProtocol: TCP
ToPort: 80
Type: AWS::EC2::SecurityGroupIngress
DefaultNetwork:
Properties:
GroupDescription: TestSimpleConvert Security Group for default network
Expand Down Expand Up @@ -84,6 +74,7 @@ Resources:
AssignPublicIp: ENABLED
SecurityGroups:
- Ref: DefaultNetwork
- Ref: SimpleServiceIngressSecurityGroup
Subnets:
- subnet1
- subnet2
Expand Down Expand Up @@ -117,6 +108,26 @@ Resources:
NamespaceId:
Ref: CloudMap
Type: AWS::ServiceDiscovery::Service
SimpleServiceIngressSecurityGroup:
Properties:
GroupDescription: TestSimpleConvert Security Group for service simple ingress
Tags:
- Key: com.docker.compose.project
Value: TestSimpleConvert
- Key: com.docker.compose.service
Value: simple
VpcId: vpc-123
Type: AWS::EC2::SecurityGroup
SimpleServiceIngressSecurityGroup80Ingress:
Properties:
CidrIp: 0.0.0.0/0
Description: simple:80/tcp on SimpleServiceIngressSecurityGroup network
FromPort: 80
GroupId:
Ref: SimpleServiceIngressSecurityGroup
IpProtocol: TCP
ToPort: 80
Type: AWS::EC2::SecurityGroupIngress
SimpleTCP80Listener:
Properties:
DefaultActions:
Expand Down
32 changes: 22 additions & 10 deletions ecs/testdata/slightly-complex-cloudformation-conversion.golden
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,6 @@ Resources:
- Key: com.docker.compose.project
Value: TestSlightlyComplexConvert
Type: AWS::ECS::Cluster
Default80Ingress:
Properties:
CidrIp: 0.0.0.0/0
Description: entrance:80/tcp on default network
FromPort: 80
GroupId:
Ref: DefaultNetwork
IpProtocol: TCP
ToPort: 80
Type: AWS::EC2::SecurityGroupIngress
DefaultNetwork:
Properties:
GroupDescription: TestSlightlyComplexConvert Security Group for default network
Expand Down Expand Up @@ -67,6 +57,7 @@ Resources:
AssignPublicIp: ENABLED
SecurityGroups:
- Ref: DefaultNetwork
- Ref: EntranceServiceIngressSecurityGroup
Subnets:
- subnet1
- subnet2
Expand Down Expand Up @@ -100,6 +91,27 @@ Resources:
NamespaceId:
Ref: CloudMap
Type: AWS::ServiceDiscovery::Service
EntranceServiceIngressSecurityGroup:
Properties:
GroupDescription: TestSlightlyComplexConvert Security Group for service entrance
ingress
Tags:
- Key: com.docker.compose.project
Value: TestSlightlyComplexConvert
- Key: com.docker.compose.service
Value: entrance
VpcId: vpc-123
Type: AWS::EC2::SecurityGroup
EntranceServiceIngressSecurityGroup80Ingress:
Properties:
CidrIp: 0.0.0.0/0
Description: entrance:80/tcp on EntranceServiceIngressSecurityGroup network
FromPort: 80
GroupId:
Ref: EntranceServiceIngressSecurityGroup
IpProtocol: TCP
ToPort: 80
Type: AWS::EC2::SecurityGroupIngress
EntranceTCP80Listener:
Properties:
DefaultActions:
Expand Down

0 comments on commit 8f590ab

Please sign in to comment.