in pkg/providers/v1/aws.go [4700:4820]
func (c *Cloud) updateInstanceSecurityGroupsForLoadBalancer(lb *elb.LoadBalancerDescription, instances map[InstanceID]*ec2.Instance, annotations map[string]string) error {
if c.cfg.Global.DisableSecurityGroupIngress {
return nil
}
// Determine the load balancer security group id
lbSecurityGroupIDs := aws.StringValueSlice(lb.SecurityGroups)
if len(lbSecurityGroupIDs) == 0 {
return fmt.Errorf("could not determine security group for load balancer: %s", aws.StringValue(lb.LoadBalancerName))
}
c.sortELBSecurityGroupList(lbSecurityGroupIDs, annotations)
loadBalancerSecurityGroupID := lbSecurityGroupIDs[0]
// Get the actual list of groups that allow ingress from the load-balancer
var actualGroups []*ec2.SecurityGroup
{
describeRequest := &ec2.DescribeSecurityGroupsInput{}
describeRequest.Filters = []*ec2.Filter{
newEc2Filter("ip-permission.group-id", loadBalancerSecurityGroupID),
}
response, err := c.ec2.DescribeSecurityGroups(describeRequest)
if err != nil {
return fmt.Errorf("error querying security groups for ELB: %q", err)
}
for _, sg := range response {
if !c.tagging.hasClusterTag(sg.Tags) {
continue
}
actualGroups = append(actualGroups, sg)
}
}
taggedSecurityGroups, err := c.getTaggedSecurityGroups()
if err != nil {
return fmt.Errorf("error querying for tagged security groups: %q", err)
}
// Open the firewall from the load balancer to the instance
// We don't actually have a trivial way to know in advance which security group the instance is in
// (it is probably the node security group, but we don't easily have that).
// However, we _do_ have the list of security groups on the instance records.
// Map containing the changes we want to make; true to add, false to remove
instanceSecurityGroupIds := map[string]bool{}
// Scan instances for groups we want open
for _, instance := range instances {
securityGroup, err := findSecurityGroupForInstance(instance, taggedSecurityGroups)
if err != nil {
return err
}
if securityGroup == nil {
klog.Warning("Ignoring instance without security group: ", aws.StringValue(instance.InstanceId))
continue
}
id := aws.StringValue(securityGroup.GroupId)
if id == "" {
klog.Warningf("found security group without id: %v", securityGroup)
continue
}
instanceSecurityGroupIds[id] = true
}
// Compare to actual groups
for _, actualGroup := range actualGroups {
actualGroupID := aws.StringValue(actualGroup.GroupId)
if actualGroupID == "" {
klog.Warning("Ignoring group without ID: ", actualGroup)
continue
}
adding, found := instanceSecurityGroupIds[actualGroupID]
if found && adding {
// We don't need to make a change; the permission is already in place
delete(instanceSecurityGroupIds, actualGroupID)
} else {
// This group is not needed by allInstances; delete it
instanceSecurityGroupIds[actualGroupID] = false
}
}
for instanceSecurityGroupID, add := range instanceSecurityGroupIds {
if add {
klog.V(2).Infof("Adding rule for traffic from the load balancer (%s) to instances (%s)", loadBalancerSecurityGroupID, instanceSecurityGroupID)
} else {
klog.V(2).Infof("Removing rule for traffic from the load balancer (%s) to instance (%s)", loadBalancerSecurityGroupID, instanceSecurityGroupID)
}
sourceGroupID := &ec2.UserIdGroupPair{}
sourceGroupID.GroupId = &loadBalancerSecurityGroupID
allProtocols := "-1"
permission := &ec2.IpPermission{}
permission.IpProtocol = &allProtocols
permission.UserIdGroupPairs = []*ec2.UserIdGroupPair{sourceGroupID}
permissions := []*ec2.IpPermission{permission}
if add {
changed, err := c.addSecurityGroupIngress(instanceSecurityGroupID, permissions)
if err != nil {
return err
}
if !changed {
klog.Warning("Allowing ingress was not needed; concurrent change? groupId=", instanceSecurityGroupID)
}
} else {
changed, err := c.removeSecurityGroupIngress(instanceSecurityGroupID, permissions)
if err != nil {
return err
}
if !changed {
klog.Warning("Revoking ingress was not needed; concurrent change? groupId=", instanceSecurityGroupID)
}
}
}
return nil
}