Skip to content

Commit 1e57960

Browse files
committed
inboud_security_groups
Add referencing existing security groups for inbound traffic Add referencing existing security groups for inbound traffic
1 parent 9e2cbe7 commit 1e57960

File tree

6 files changed

+213
-4
lines changed

6 files changed

+213
-4
lines changed

docs/guide/ingress/annotations.md

+18
Original file line numberDiff line numberDiff line change
@@ -530,6 +530,24 @@ Access control for LoadBalancer can be controlled with following annotations:
530530
```
531531
alb.ingress.kubernetes.io/inbound-cidrs: 10.0.0.0/24
532532
```
533+
- <a name="inbound-security-groups">`alb.ingress.kubernetes.io/inbound-security-groups`</a> specifies the SecurtityGroups that are allowed to access LoadBalancer.
534+
535+
!!!note "Merge Behavior"
536+
`inbound-security-groups` is merged across all Ingresses in IngressGroup, but is exclusive per listen-port.
537+
538+
- the `inbound-security-groups` will only impact the ports defined for that Ingress.
539+
- if same listen-port is defined by multiple Ingress within IngressGroup, `inbound-security-groups` should only be defined on one of the Ingress.
540+
541+
!!!warning ""
542+
this annotation will be ignored if `alb.ingress.kubernetes.io/security-groups` is specified.
543+
544+
!!!tip ""
545+
Both name or ID of securityGroups are supported. Name matches a `Name` tag, not the `groupName` attribute.
546+
547+
!!!example
548+
```
549+
alb.ingress.kubernetes.io/inbound-security-groups: sg-xxxx, nameOfSg1, nameOfSg2
550+
```
533551

534552
- <a name="security-group-prefix-lists">`alb.ingress.kubernetes.io/security-group-prefix-lists`</a> specifies the managed prefix lists that are allowed to access LoadBalancer.
535553

pkg/annotations/constants.go

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ const (
2323
IngressSuffixListenPorts = "listen-ports"
2424
IngressSuffixSSLRedirect = "ssl-redirect"
2525
IngressSuffixInboundCIDRs = "inbound-cidrs"
26+
IngressSuffixInboundSecurityGroups = "inbound-security-groups"
2627
IngressSuffixCertificateARN = "certificate-arn"
2728
IngressSuffixSSLPolicy = "ssl-policy"
2829
IngressSuffixTargetType = "target-type"

pkg/ingress/model_build_listener.go

+27-4
Original file line numberDiff line numberDiff line change
@@ -107,17 +107,25 @@ type listenPortConfig struct {
107107
sslPolicy *string
108108
tlsCerts []string
109109
mutualAuthentication *elbv2model.MutualAuthenticationAttributes
110+
securityGroupIDs []string
110111
}
111112

112113
func (t *defaultModelBuildTask) computeIngressListenPortConfigByPort(ctx context.Context, ing *ClassifiedIngress) (map[int64]listenPortConfig, error) {
113114
explicitTLSCertARNs := t.computeIngressExplicitTLSCertARNs(ctx, ing)
114115
explicitSSLPolicy := t.computeIngressExplicitSSLPolicy(ctx, ing)
115116
var prefixListIDs []string
116117
t.annotationParser.ParseStringSliceAnnotation(annotations.IngressSuffixSecurityGroupPrefixLists, &prefixListIDs, ing.Ing.Annotations)
118+
119+
securityGroupIDs, err := t.computeIngressExplicitSecurityGroupIDs(ctx, ing)
120+
if err != nil {
121+
return nil, err
122+
}
123+
117124
inboundCIDRv4s, inboundCIDRV6s, err := t.computeIngressExplicitInboundCIDRs(ctx, ing)
118125
if err != nil {
119126
return nil, err
120127
}
128+
121129
mutualAuthenticationAttributes, err := t.computeIngressMutualAuthentication(ctx, ing)
122130
if err != nil {
123131
return nil, err
@@ -146,10 +154,11 @@ func (t *defaultModelBuildTask) computeIngressListenPortConfigByPort(ctx context
146154
listenPortConfigByPort := make(map[int64]listenPortConfig, len(listenPorts))
147155
for port, protocol := range listenPorts {
148156
cfg := listenPortConfig{
149-
protocol: protocol,
150-
inboundCIDRv4s: inboundCIDRv4s,
151-
inboundCIDRv6s: inboundCIDRV6s,
152-
prefixLists: prefixListIDs,
157+
protocol: protocol,
158+
inboundCIDRv4s: inboundCIDRv4s,
159+
inboundCIDRv6s: inboundCIDRV6s,
160+
prefixLists: prefixListIDs,
161+
securityGroupIDs: securityGroupIDs,
153162
}
154163
if protocol == elbv2model.ProtocolHTTPS {
155164
if len(explicitTLSCertARNs) == 0 {
@@ -225,6 +234,20 @@ func (t *defaultModelBuildTask) computeIngressListenPorts(_ context.Context, ing
225234
return portAndProtocols, nil
226235
}
227236

237+
func (t *defaultModelBuildTask) computeIngressExplicitSecurityGroupIDs(ctx context.Context, ing *ClassifiedIngress) ([]string, error) {
238+
var rawSecurityGroups []string
239+
if exists := t.annotationParser.ParseStringSliceAnnotation(annotations.IngressSuffixInboundSecurityGroups, &rawSecurityGroups, ing.Ing.Annotations); !exists {
240+
return nil, nil
241+
}
242+
243+
securityGroupIDs, err := t.sgResolver.ResolveViaNameOrID(ctx, rawSecurityGroups)
244+
if err != nil {
245+
return nil, fmt.Errorf("invalid %v settings on Ingress: %v: %w", annotations.IngressSuffixInboundSecurityGroups, k8s.NamespacedName(ing.Ing), err)
246+
}
247+
248+
return securityGroupIDs, nil
249+
}
250+
228251
func (t *defaultModelBuildTask) computeIngressExplicitInboundCIDRs(_ context.Context, ing *ClassifiedIngress) ([]string, []string, error) {
229252
var rawInboundCIDRs []string
230253
fromIngressClassParams := false

pkg/ingress/model_build_managed_sg.go

+12
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,18 @@ func (t *defaultModelBuildTask) buildManagedSecurityGroupIngressPermissions(_ co
109109
},
110110
})
111111
}
112+
for _, sgID := range cfg.securityGroupIDs {
113+
permissions = append(permissions, ec2model.IPPermission{
114+
IPProtocol: "tcp",
115+
FromPort: awssdk.Int64(port),
116+
ToPort: awssdk.Int64(port),
117+
UserIDGroupPairs: []ec2model.UserIDGroupPair{
118+
{
119+
GroupID: sgID,
120+
},
121+
},
122+
})
123+
}
112124
}
113125
return permissions
114126
}

pkg/ingress/model_builder.go

+15
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,9 @@ func (t *defaultModelBuildTask) mergeListenPortConfigs(_ context.Context, listen
310310
var mergedMtlsAttributesProvider *types.NamespacedName
311311
var mergedMtlsAttributes *elbv2model.MutualAuthenticationAttributes
312312

313+
var mergedSecurityGroupProvider *types.NamespacedName
314+
mergedSecurityGroups := sets.NewString()
315+
313316
for _, cfg := range listenPortConfigs {
314317
if mergedProtocolProvider == nil {
315318
mergedProtocolProvider = &cfg.ingKey
@@ -343,6 +346,17 @@ func (t *defaultModelBuildTask) mergeListenPortConfigs(_ context.Context, listen
343346
}
344347
}
345348

349+
if len(cfg.listenPortConfig.securityGroupIDs) != 0 {
350+
cfgSecurityGroups := sets.NewString(cfg.listenPortConfig.securityGroupIDs...)
351+
if mergedSecurityGroupProvider == nil {
352+
mergedSecurityGroupProvider = &cfg.ingKey
353+
mergedSecurityGroups = cfgSecurityGroups
354+
} else if !mergedSecurityGroups.Equal(cfgSecurityGroups) {
355+
return listenPortConfig{}, errors.Errorf("conflicting security groups, %v: %v | %v: %v",
356+
*mergedSecurityGroupProvider, mergedSecurityGroups.List(), cfg.ingKey, cfgSecurityGroups.List())
357+
}
358+
}
359+
346360
if cfg.listenPortConfig.sslPolicy != nil {
347361
if mergedSSLPolicyProvider == nil {
348362
mergedSSLPolicyProvider = &cfg.ingKey
@@ -389,6 +403,7 @@ func (t *defaultModelBuildTask) mergeListenPortConfigs(_ context.Context, listen
389403
sslPolicy: mergedSSLPolicy,
390404
tlsCerts: mergedTLSCerts,
391405
mutualAuthentication: mergedMtlsAttributes,
406+
securityGroupIDs: mergedSecurityGroups.List(),
392407
}, nil
393408
}
394409

pkg/ingress/model_builder_test.go

+140
Original file line numberDiff line numberDiff line change
@@ -3628,6 +3628,146 @@ func Test_defaultModelBuilder_Build(t *testing.T) {
36283628
}
36293629
}
36303630
}
3631+
}`,
3632+
},
3633+
{
3634+
name: "Ingress - ingress mixed inbound ip address & security groups",
3635+
env: env{
3636+
svcs: []*corev1.Service{ns_1_svc_1, ns_1_svc_2, ns_1_svc_3},
3637+
},
3638+
fields: fields{
3639+
resolveViaDiscoveryCalls: []resolveViaDiscoveryCall{resolveViaDiscoveryCallForInternalLB},
3640+
listLoadBalancersCalls: []listLoadBalancersCall{listLoadBalancerCallForEmptyLB},
3641+
describeSecurityGroupsResult: []describeSecurityGroupsResult{
3642+
{
3643+
securityGroups: []*ec2sdk.SecurityGroup{
3644+
{
3645+
GroupId: awssdk.String("sg-903004f8"),
3646+
},
3647+
{
3648+
GroupId: awssdk.String("sg-903004f1"),
3649+
},
3650+
},
3651+
},
3652+
},
3653+
enableBackendSG: true,
3654+
},
3655+
args: args{
3656+
ingGroup: Group{
3657+
ID: GroupID{Namespace: "ns-1", Name: "ing-1"},
3658+
Members: []ClassifiedIngress{
3659+
{
3660+
Ing: &networking.Ingress{
3661+
ObjectMeta: metav1.ObjectMeta{
3662+
Namespace: "ns-1",
3663+
Name: "ing-1",
3664+
Annotations: map[string]string{
3665+
"alb.ingress.kubernetes.io/inbound-cidrs": "20.45.16.0/26",
3666+
"alb.ingress.kubernetes.io/inbound-security-groups": "sg-903004f8, sg-903004f1",
3667+
},
3668+
},
3669+
Spec: networking.IngressSpec{
3670+
Rules: []networking.IngressRule{
3671+
{
3672+
Host: "app-1.example.com",
3673+
IngressRuleValue: networking.IngressRuleValue{
3674+
HTTP: &networking.HTTPIngressRuleValue{
3675+
Paths: []networking.HTTPIngressPath{
3676+
{
3677+
Path: "/svc-1",
3678+
Backend: networking.IngressBackend{
3679+
Service: &networking.IngressServiceBackend{
3680+
Name: ns_1_svc_1.Name,
3681+
Port: networking.ServiceBackendPort{
3682+
Name: "http",
3683+
},
3684+
},
3685+
},
3686+
},
3687+
{
3688+
Path: "/svc-2",
3689+
Backend: networking.IngressBackend{
3690+
Service: &networking.IngressServiceBackend{
3691+
Name: ns_1_svc_2.Name,
3692+
Port: networking.ServiceBackendPort{
3693+
Name: "http",
3694+
},
3695+
},
3696+
},
3697+
},
3698+
},
3699+
},
3700+
},
3701+
},
3702+
{
3703+
Host: "app-2.example.com",
3704+
IngressRuleValue: networking.IngressRuleValue{
3705+
HTTP: &networking.HTTPIngressRuleValue{
3706+
Paths: []networking.HTTPIngressPath{
3707+
{
3708+
Path: "/svc-3",
3709+
Backend: networking.IngressBackend{
3710+
Service: &networking.IngressServiceBackend{
3711+
Name: ns_1_svc_3.Name,
3712+
Port: networking.ServiceBackendPort{
3713+
Name: "https",
3714+
},
3715+
},
3716+
},
3717+
},
3718+
},
3719+
},
3720+
},
3721+
},
3722+
},
3723+
},
3724+
},
3725+
},
3726+
},
3727+
},
3728+
},
3729+
wantStackPatch: `
3730+
{
3731+
"resources": {
3732+
"AWS::EC2::SecurityGroup": {
3733+
"ManagedLBSecurityGroup": {
3734+
"spec": {
3735+
"ingress": [
3736+
{
3737+
"fromPort": 80,
3738+
"ipProtocol": "tcp",
3739+
"ipRanges": [
3740+
{
3741+
"cidrIP": "20.45.16.0/26"
3742+
}
3743+
],
3744+
"toPort": 80
3745+
},
3746+
{
3747+
"fromPort": 80,
3748+
"ipProtocol": "tcp",
3749+
"toPort": 80,
3750+
"userIDGroupPairs": [
3751+
{
3752+
"groupID": "sg-903004f1"
3753+
}
3754+
]
3755+
},
3756+
{
3757+
"fromPort": 80,
3758+
"ipProtocol": "tcp",
3759+
"toPort": 80,
3760+
"userIDGroupPairs": [
3761+
{
3762+
"groupID": "sg-903004f8"
3763+
}
3764+
]
3765+
}
3766+
]
3767+
}
3768+
}
3769+
}
3770+
}
36313771
}`,
36323772
},
36333773
}

0 commit comments

Comments
 (0)