Skip to content

Commit 5819016

Browse files
authored
Merge pull request #991 from csnitker/master
IPv6 Support in Inbound CIDR Annotation
2 parents fc9f774 + 443f07d commit 5819016

File tree

4 files changed

+146
-24
lines changed

4 files changed

+146
-24
lines changed

internal/alb/sg/association.go

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,11 @@ type associationController struct {
6262
}
6363

6464
type associationConfig struct {
65-
LbPorts []int64
66-
LbInboundCIDRs []string
67-
LbExternalSGs []string
68-
AdditionalTags map[string]string
65+
LbPorts []int64
66+
LbInboundCIDRs []string
67+
LbInboundV6CIDRs []string
68+
LbExternalSGs []string
69+
AdditionalTags map[string]string
6970
}
7071

7172
func (c *associationController) Reconcile(ctx context.Context, ingress *extensions.Ingress, lbInstance *elbv2.LoadBalancer, tgGroup tg.TargetGroupGroup) error {
@@ -144,12 +145,31 @@ func (c *associationController) reconcileLbSG(ctx context.Context, ingressKey ty
144145
Description: aws.String(fmt.Sprintf("Allow ingress on port %v from %v", port, cidr)),
145146
})
146147
}
148+
149+
ipv6Ranges := make([]*ec2.Ipv6Range, 0, len(cfg.LbInboundV6CIDRs))
150+
for _, cidr := range cfg.LbInboundV6CIDRs {
151+
ipv6Ranges = append(ipv6Ranges, &ec2.Ipv6Range{
152+
CidrIpv6: aws.String(cidr),
153+
Description: aws.String(fmt.Sprintf("Allow ingress on port %v from %v", port, cidr)),
154+
})
155+
}
156+
157+
if len(ipv6Ranges) > 0 {
158+
inboundPermissions = append(inboundPermissions, &ec2.IpPermission{
159+
IpProtocol: aws.String("tcp"),
160+
FromPort: aws.Int64(port),
161+
ToPort: aws.Int64(port),
162+
Ipv6Ranges: ipv6Ranges,
163+
})
164+
}
165+
147166
permission := &ec2.IpPermission{
148167
IpProtocol: aws.String("tcp"),
149168
FromPort: aws.Int64(port),
150169
ToPort: aws.Int64(port),
151170
IpRanges: ipRanges,
152171
}
172+
153173
inboundPermissions = append(inboundPermissions, permission)
154174
}
155175
if err := c.sgController.Reconcile(ctx, sgInstance, inboundPermissions, sgTags); err != nil {
@@ -255,10 +275,11 @@ func (c *associationController) buildAssociationConfig(ctx context.Context, ingr
255275
return associationConfig{}, err
256276
}
257277
return associationConfig{
258-
LbPorts: lbPorts,
259-
LbInboundCIDRs: ingressAnnos.LoadBalancer.InboundCidrs,
260-
LbExternalSGs: lbExternalSGs,
261-
AdditionalTags: ingressAnnos.Tags.LoadBalancer,
278+
LbPorts: lbPorts,
279+
LbInboundCIDRs: ingressAnnos.LoadBalancer.InboundCidrs,
280+
LbInboundV6CIDRs: ingressAnnos.LoadBalancer.InboundV6CIDRs,
281+
LbExternalSGs: lbExternalSGs,
282+
AdditionalTags: ingressAnnos.Tags.LoadBalancer,
262283
}, nil
263284
}
264285

internal/alb/sg/security_group.go

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,12 @@ func ipPermissionEquals(source *ec2.IpPermission, target *ec2.IpPermission) bool
105105
if len(diffIPRanges(target.IpRanges, source.IpRanges)) != 0 {
106106
return false
107107
}
108+
if len(diffIPv6Ranges(source.Ipv6Ranges, target.Ipv6Ranges)) != 0 {
109+
return false
110+
}
111+
if len(diffIPv6Ranges(target.Ipv6Ranges, source.Ipv6Ranges)) != 0 {
112+
return false
113+
}
108114
if len(diffUserIDGroupPairs(source.UserIdGroupPairs, target.UserIdGroupPairs)) != 0 {
109115
return false
110116
}
@@ -115,12 +121,29 @@ func ipPermissionEquals(source *ec2.IpPermission, target *ec2.IpPermission) bool
115121
return true
116122
}
117123

124+
// diffIPv6Ranges calculates set_difference as source - target
125+
func diffIPv6Ranges(source []*ec2.Ipv6Range, target []*ec2.Ipv6Range) (diffs []*ec2.Ipv6Range) {
126+
for _, sRange := range source {
127+
containsInTarget := false
128+
for _, tRange := range target {
129+
if ipRangeEquals(sRange.CidrIpv6, tRange.CidrIpv6) {
130+
containsInTarget = true
131+
break
132+
}
133+
}
134+
if !containsInTarget {
135+
diffs = append(diffs, sRange)
136+
}
137+
}
138+
return diffs
139+
}
140+
118141
// diffIPRanges calculates set_difference as source - target
119142
func diffIPRanges(source []*ec2.IpRange, target []*ec2.IpRange) (diffs []*ec2.IpRange) {
120143
for _, sRange := range source {
121144
containsInTarget := false
122145
for _, tRange := range target {
123-
if ipRangeEquals(sRange, tRange) {
146+
if ipRangeEquals(sRange.CidrIp, tRange.CidrIp) {
124147
containsInTarget = true
125148
break
126149
}
@@ -133,8 +156,8 @@ func diffIPRanges(source []*ec2.IpRange, target []*ec2.IpRange) (diffs []*ec2.Ip
133156
}
134157

135158
// ipRangeEquals test whether two IPRange instance are equals
136-
func ipRangeEquals(source *ec2.IpRange, target *ec2.IpRange) bool {
137-
return aws.StringValue(source.CidrIp) == aws.StringValue(target.CidrIp)
159+
func ipRangeEquals(source *string, target *string) bool {
160+
return aws.StringValue(source) == aws.StringValue(target)
138161
}
139162

140163
// diffUserIDGroupPairs calculates set_difference as source - target

internal/alb/sg/security_group_test.go

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,11 @@ func TestDiffIPPermissions(t *testing.T) {
390390
CidrIp: aws.String("192.168.1.1/32"),
391391
},
392392
},
393+
Ipv6Ranges: []*ec2.Ipv6Range{
394+
{
395+
CidrIpv6: aws.String("::/0"),
396+
},
397+
},
393398
UserIdGroupPairs: []*ec2.UserIdGroupPair{
394399
{
395400
GroupId: aws.String("groupA"),
@@ -398,6 +403,69 @@ func TestDiffIPPermissions(t *testing.T) {
398403
},
399404
},
400405
target: []*ec2.IpPermission{},
406+
expectedDiffs: []*ec2.IpPermission{
407+
{
408+
IpProtocol: aws.String("tcp"),
409+
FromPort: aws.Int64(80),
410+
ToPort: aws.Int64(81),
411+
IpRanges: []*ec2.IpRange{
412+
{
413+
CidrIp: aws.String("192.168.1.1/32"),
414+
},
415+
},
416+
Ipv6Ranges: []*ec2.Ipv6Range{
417+
{
418+
CidrIpv6: aws.String("::/0"),
419+
},
420+
},
421+
UserIdGroupPairs: []*ec2.UserIdGroupPair{
422+
{
423+
GroupId: aws.String("groupA"),
424+
},
425+
},
426+
},
427+
},
428+
},
429+
{
430+
source: []*ec2.IpPermission{
431+
{
432+
IpProtocol: aws.String("tcp"),
433+
FromPort: aws.Int64(80),
434+
ToPort: aws.Int64(81),
435+
IpRanges: []*ec2.IpRange{
436+
{
437+
CidrIp: aws.String("192.168.1.1/32"),
438+
},
439+
},
440+
UserIdGroupPairs: []*ec2.UserIdGroupPair{
441+
{
442+
GroupId: aws.String("groupA"),
443+
},
444+
},
445+
},
446+
},
447+
target: []*ec2.IpPermission{
448+
{
449+
IpProtocol: aws.String("tcp"),
450+
FromPort: aws.Int64(80),
451+
ToPort: aws.Int64(81),
452+
IpRanges: []*ec2.IpRange{
453+
{
454+
CidrIp: aws.String("192.168.1.1/32"),
455+
},
456+
},
457+
Ipv6Ranges: []*ec2.Ipv6Range{
458+
{
459+
CidrIpv6: aws.String("::/0"),
460+
},
461+
},
462+
UserIdGroupPairs: []*ec2.UserIdGroupPair{
463+
{
464+
GroupId: aws.String("groupA"),
465+
},
466+
},
467+
},
468+
},
401469
expectedDiffs: []*ec2.IpPermission{
402470
{
403471
IpProtocol: aws.String("tcp"),

internal/ingress/annotations/loadbalancer/main.go

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ type Config struct {
4242
WebACLId *string
4343

4444
InboundCidrs []string
45+
InboundV6CIDRs []string
4546
Ports []PortData
4647
SecurityGroups []string
4748
Subnets []string
@@ -102,7 +103,7 @@ func (lb loadBalancer) Parse(ing parser.AnnotationInterface) (interface{}, error
102103
securityGroups := parser.GetStringSliceAnnotation("security-groups", ing)
103104
subnets := parser.GetStringSliceAnnotation("subnets", ing)
104105

105-
cidrs, err := parseCidrs(ing)
106+
v4CIDRs, v6CIDRs, err := parseCidrs(ing)
106107
if err != nil {
107108
return nil, err
108109
}
@@ -112,9 +113,10 @@ func (lb loadBalancer) Parse(ing parser.AnnotationInterface) (interface{}, error
112113
Scheme: scheme,
113114
IPAddressType: ipAddressType,
114115

115-
Attributes: attributes,
116-
InboundCidrs: cidrs,
117-
Ports: ports,
116+
Attributes: attributes,
117+
InboundCidrs: v4CIDRs,
118+
InboundV6CIDRs: v6CIDRs,
119+
Ports: ports,
118120

119121
Subnets: subnets,
120122
SecurityGroups: securityGroups,
@@ -203,7 +205,7 @@ func parsePorts(ing parser.AnnotationInterface) ([]PortData, error) {
203205
return lps, nil
204206
}
205207

206-
func parseCidrs(ing parser.AnnotationInterface) (out []string, err error) {
208+
func parseCidrs(ing parser.AnnotationInterface) (v4CIDRs, v6CIDRs []string, err error) {
207209
cidrConfig := parser.GetStringSliceAnnotation("security-group-inbound-cidrs", ing)
208210
if len(cidrConfig) != 0 {
209211
glog.Warningf("`security-group-inbound-cidrs` annotation is deprecated, use `inbound-cidrs` instead")
@@ -212,20 +214,28 @@ func parseCidrs(ing parser.AnnotationInterface) (out []string, err error) {
212214
}
213215

214216
for _, inboundCidr := range cidrConfig {
215-
ip, _, err := net.ParseCIDR(inboundCidr)
217+
_, _, err := net.ParseCIDR(inboundCidr)
216218
if err != nil {
217-
return out, err
219+
return v4CIDRs, v6CIDRs, err
218220
}
219221

220-
if ip.To4() == nil {
221-
return out, fmt.Errorf("CIDR must use an IPv4 address: %v", inboundCidr)
222+
if strings.Contains(inboundCidr, ":") {
223+
v6CIDRs = append(v6CIDRs, inboundCidr)
224+
} else {
225+
v4CIDRs = append(v4CIDRs, inboundCidr)
222226
}
223-
out = append(out, inboundCidr)
224227
}
225-
if len(out) == 0 {
226-
out = append(out, "0.0.0.0/0")
228+
229+
if len(v4CIDRs) == 0 && len(v6CIDRs) == 0 {
230+
v4CIDRs = append(v4CIDRs, "0.0.0.0/0")
231+
232+
addrType, _ := parser.GetStringAnnotation("ip-address-type", ing)
233+
if addrType != nil && *addrType == elbv2.IpAddressTypeDualstack {
234+
v6CIDRs = append(v6CIDRs, "::/0")
235+
}
227236
}
228-
return out, nil
237+
238+
return v4CIDRs, v6CIDRs, nil
229239
}
230240

231241
func Dummy() *Config {

0 commit comments

Comments
 (0)