Skip to content

Commit e708278

Browse files
committed
keep LB addons' settings unchanged unless explicitly specified
1 parent e5d625f commit e708278

File tree

6 files changed

+106
-99
lines changed

6 files changed

+106
-99
lines changed

docs/guide/ingress/annotations.md

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -907,35 +907,53 @@ In addition, you can use annotations to specify additional tags
907907

908908
## Addons
909909

910-
!!!note
911-
If waf-acl-arn is specified via the ingress annotations, the controller will make sure the waf-acl is associated to the provisioned ALB with the ingress.
912-
If there is not such annotation, the controller will make sure no waf-acl is associated, so it may remove the existing waf-acl on the ALB provisioned.
913-
If users do not want the controller to manage the waf-acl on the ALBs, they can disable the feature by setting controller command line flags `--enable-waf=false` or `--enable-wafv2=false`
914-
915-
- <a name="waf-acl-id">`alb.ingress.kubernetes.io/waf-acl-id`</a> specifies the identifier for the Amazon WAF web ACL.
910+
- <a name="waf-acl-id">`alb.ingress.kubernetes.io/waf-acl-id`</a> specifies the identifier for the Amazon WAF Classic web ACL.
916911

917912
!!!warning ""
918-
Only Regional WAF is supported.
913+
Only Regional WAF Classic is supported.
914+
915+
!!!note ""
916+
When this annotation is absent or empty, the controller will keep LoadBalancer WAF Classic settings unchanged.
917+
To disable WAF Classic, explicitly set the annotation value to 'none'.
919918

920919
!!!example
921-
```alb.ingress.kubernetes.io/waf-acl-id: 499e8b99-6671-4614-a86d-adb1810b7fbe
922-
```
920+
- enable WAF Classic
921+
```alb.ingress.kubernetes.io/waf-acl-id: 499e8b99-6671-4614-a86d-adb1810b7fbe
922+
```
923+
- disable WAF Classic
924+
```alb.ingress.kubernetes.io/waf-acl-id: none
925+
```
923926

924927
- <a name="wafv2-acl-arn">`alb.ingress.kubernetes.io/wafv2-acl-arn`</a> specifies ARN for the Amazon WAFv2 web ACL.
925928

926929
!!!warning ""
927930
Only Regional WAFv2 is supported.
928931

932+
!!!note ""
933+
When this annotation is absent or empty, the controller will keep LoadBalancer WAFv2 settings unchanged.
934+
To disable WAFv2, explicitly set the annotation value to 'none'.
935+
929936
!!!tip ""
930937
To get the WAFv2 Web ACL ARN from the Console, click the gear icon in the upper right and enable the ARN column.
931938

932939
!!!example
933-
```alb.ingress.kubernetes.io/wafv2-acl-arn: arn:aws:wafv2:us-west-2:xxxxx:regional/webacl/xxxxxxx/3ab78708-85b0-49d3-b4e1-7a9615a6613b
934-
```
935-
940+
- enable WAFv2
941+
```alb.ingress.kubernetes.io/wafv2-acl-arn: arn:aws:wafv2:us-west-2:xxxxx:regional/webacl/xxxxxxx/3ab78708-85b0-49d3-b4e1-7a9615a6613b
942+
```
943+
- disable WAFV2
944+
```alb.ingress.kubernetes.io/wafv2-acl-arn: none
945+
```
946+
936947
- <a name="shield-advanced-protection">`alb.ingress.kubernetes.io/shield-advanced-protection`</a> turns on / off the AWS Shield Advanced protection for the load balancer.
937948

938-
!!!example
939-
```alb.ingress.kubernetes.io/shield-advanced-protection: 'true'
940-
```
949+
!!!note ""
950+
When this annotation is absent, the controller will keep LoadBalancer shield protection settings unchanged.
951+
To disable shield protection, explicitly set the annotation value to 'false'.
941952

953+
!!!example
954+
- enable shield protection
955+
```alb.ingress.kubernetes.io/shield-advanced-protection: 'true'
956+
```
957+
- disable shield protection
958+
```alb.ingress.kubernetes.io/shield-advanced-protection: 'false'
959+
```

pkg/deploy/shield/protection_synthesizer.go

Lines changed: 12 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ package shield
22

33
import (
44
"context"
5+
"fmt"
56
"github.com/go-logr/logr"
67
"github.com/pkg/errors"
78
"k8s.io/apimachinery/pkg/util/sets"
89
"sigs.k8s.io/aws-load-balancer-controller/pkg/model/core"
9-
elbv2model "sigs.k8s.io/aws-load-balancer-controller/pkg/model/elbv2"
1010
shieldmodel "sigs.k8s.io/aws-load-balancer-controller/pkg/model/shield"
1111
)
1212

@@ -32,25 +32,18 @@ type protectionSynthesizer struct {
3232

3333
func (s *protectionSynthesizer) Synthesize(ctx context.Context) error {
3434
var resProtections []*shieldmodel.Protection
35-
s.stack.ListResources(&resProtections)
35+
if err := s.stack.ListResources(&resProtections); err != nil {
36+
return fmt.Errorf("[should never happen] failed to list resources: %w", err)
37+
}
38+
if len(resProtections) == 0 {
39+
return nil
40+
}
3641
resProtectionsByResARN, err := mapResProtectionByResourceARN(resProtections)
3742
if err != nil {
3843
return err
3944
}
40-
41-
var resLBs []*elbv2model.LoadBalancer
42-
s.stack.ListResources(&resLBs)
43-
for _, resLB := range resLBs {
44-
// shield protection can only be associated with ALB for now.
45-
if resLB.Spec.Type != elbv2model.LoadBalancerTypeApplication {
46-
continue
47-
}
48-
lbARN, err := resLB.LoadBalancerARN().Resolve(ctx)
49-
if err != nil {
50-
return err
51-
}
52-
resProtections := resProtectionsByResARN[lbARN]
53-
if err := s.synthesizeProtectionsOnLB(ctx, lbARN, resProtections); err != nil {
45+
for resARN, protections := range resProtectionsByResARN {
46+
if err := s.synthesizeProtectionsOnLB(ctx, resARN, protections); err != nil {
5447
return err
5548
}
5649
}
@@ -63,15 +56,10 @@ func (s *protectionSynthesizer) PostSynthesize(ctx context.Context) error {
6356
}
6457

6558
func (s *protectionSynthesizer) synthesizeProtectionsOnLB(ctx context.Context, lbARN string, resProtections []*shieldmodel.Protection) error {
66-
if len(resProtections) > 1 {
67-
return errors.Errorf("[should never happen] multiple shield protection desired on LoadBalancer: %v", lbARN)
59+
if len(resProtections) != 1 {
60+
return errors.Errorf("[should never happen] should be exactly one shield protection desired on LoadBalancer: %v", lbARN)
6861
}
69-
70-
enableProtection := false
71-
if len(resProtections) == 1 {
72-
enableProtection = true
73-
}
74-
62+
enableProtection := resProtections[0].Spec.Enabled
7563
protectionInfo, err := s.protectionManager.GetProtection(ctx, lbARN)
7664
if err != nil {
7765
return err

pkg/deploy/wafregional/web_acl_association_synthesizer.go

Lines changed: 15 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ package wafregional
22

33
import (
44
"context"
5+
"fmt"
56
"github.com/go-logr/logr"
67
"github.com/pkg/errors"
78
"sigs.k8s.io/aws-load-balancer-controller/pkg/model/core"
8-
elbv2model "sigs.k8s.io/aws-load-balancer-controller/pkg/model/elbv2"
99
wafregionalmodel "sigs.k8s.io/aws-load-balancer-controller/pkg/model/wafregional"
1010
)
1111

@@ -26,25 +26,18 @@ type webACLAssociationSynthesizer struct {
2626

2727
func (s *webACLAssociationSynthesizer) Synthesize(ctx context.Context) error {
2828
var resAssociations []*wafregionalmodel.WebACLAssociation
29-
s.stack.ListResources(&resAssociations)
29+
if err := s.stack.ListResources(&resAssociations); err != nil {
30+
return fmt.Errorf("[should never happen] failed to list resources: %w", err)
31+
}
32+
if len(resAssociations) == 0 {
33+
return nil
34+
}
3035
resAssociationsByResARN, err := mapResWebACLAssociationByResourceARN(resAssociations)
3136
if err != nil {
3237
return err
3338
}
34-
35-
var resLBs []*elbv2model.LoadBalancer
36-
s.stack.ListResources(&resLBs)
37-
for _, resLB := range resLBs {
38-
// wafRegional WebACL can only be associated with ALB for now.
39-
if resLB.Spec.Type != elbv2model.LoadBalancerTypeApplication {
40-
continue
41-
}
42-
lbARN, err := resLB.LoadBalancerARN().Resolve(ctx)
43-
if err != nil {
44-
return err
45-
}
46-
resAssociations := resAssociationsByResARN[lbARN]
47-
if err := s.synthesizeWebACLAssociationsOnLB(ctx, lbARN, resAssociations); err != nil {
39+
for resARN, webACLAssociations := range resAssociationsByResARN {
40+
if err := s.synthesizeWebACLAssociationsOnLB(ctx, resARN, webACLAssociations); err != nil {
4841
return err
4942
}
5043
}
@@ -57,30 +50,26 @@ func (s *webACLAssociationSynthesizer) PostSynthesize(ctx context.Context) error
5750
}
5851

5952
func (s *webACLAssociationSynthesizer) synthesizeWebACLAssociationsOnLB(ctx context.Context, lbARN string, resAssociations []*wafregionalmodel.WebACLAssociation) error {
60-
if len(resAssociations) > 1 {
61-
return errors.Errorf("[should never happen] multiple WAFRegional webACL desired on LoadBalancer: %v", lbARN)
62-
}
63-
64-
var desiredWebACLID string
65-
if len(resAssociations) == 1 {
66-
desiredWebACLID = resAssociations[0].Spec.WebACLID
53+
if len(resAssociations) != 1 {
54+
return errors.Errorf("[should never happen] should be exactly one WAFRegional webACL desired on LoadBalancer: %v", lbARN)
6755
}
56+
desiredWebACLID := resAssociations[0].Spec.WebACLID
6857
currentWebACLID, err := s.associationManager.GetAssociatedWebACL(ctx, lbARN)
6958
if err != nil {
7059
return err
7160
}
7261
switch {
7362
case desiredWebACLID == "" && currentWebACLID != "":
7463
if err := s.associationManager.DisassociateWebACL(ctx, lbARN); err != nil {
75-
return errors.Wrap(err, "failed to delete WAFv2 WAFRegional association on LoadBalancer")
64+
return errors.Wrap(err, "failed to delete WAFRegional association on LoadBalancer")
7665
}
7766
case desiredWebACLID != "" && currentWebACLID == "":
7867
if err := s.associationManager.AssociateWebACL(ctx, lbARN, desiredWebACLID); err != nil {
79-
return errors.Wrap(err, "failed to create WAFv2 WAFRegional association on LoadBalancer")
68+
return errors.Wrap(err, "failed to create WAFRegional association on LoadBalancer")
8069
}
8170
case desiredWebACLID != "" && currentWebACLID != "" && desiredWebACLID != currentWebACLID:
8271
if err := s.associationManager.AssociateWebACL(ctx, lbARN, desiredWebACLID); err != nil {
83-
return errors.Wrap(err, "failed to update WAFv2 WAFRegional association on LoadBalancer")
72+
return errors.Wrap(err, "failed to update WAFRegional association on LoadBalancer")
8473
}
8574
}
8675
return nil

pkg/deploy/wafv2/web_acl_association_synthesizer.go

Lines changed: 12 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ package wafv2
22

33
import (
44
"context"
5+
"fmt"
56
"github.com/go-logr/logr"
67
"github.com/pkg/errors"
78
"sigs.k8s.io/aws-load-balancer-controller/pkg/model/core"
8-
elbv2model "sigs.k8s.io/aws-load-balancer-controller/pkg/model/elbv2"
99
wafv2model "sigs.k8s.io/aws-load-balancer-controller/pkg/model/wafv2"
1010
)
1111

@@ -26,25 +26,18 @@ type webACLAssociationSynthesizer struct {
2626

2727
func (s *webACLAssociationSynthesizer) Synthesize(ctx context.Context) error {
2828
var resAssociations []*wafv2model.WebACLAssociation
29-
s.stack.ListResources(&resAssociations)
29+
if err := s.stack.ListResources(&resAssociations); err != nil {
30+
return fmt.Errorf("[should never happen] failed to list resources: %w", err)
31+
}
32+
if len(resAssociations) == 0 {
33+
return nil
34+
}
3035
resAssociationsByResARN, err := mapResWebACLAssociationByResourceARN(resAssociations)
3136
if err != nil {
3237
return err
3338
}
34-
35-
var resLBs []*elbv2model.LoadBalancer
36-
s.stack.ListResources(&resLBs)
37-
for _, resLB := range resLBs {
38-
// wafv2 WebACL can only be associated with ALB for now.
39-
if resLB.Spec.Type != elbv2model.LoadBalancerTypeApplication {
40-
continue
41-
}
42-
lbARN, err := resLB.LoadBalancerARN().Resolve(ctx)
43-
if err != nil {
44-
return err
45-
}
46-
resAssociations := resAssociationsByResARN[lbARN]
47-
if err := s.synthesizeWebACLAssociationsOnLB(ctx, lbARN, resAssociations); err != nil {
39+
for resARN, webACLAssociations := range resAssociationsByResARN {
40+
if err := s.synthesizeWebACLAssociationsOnLB(ctx, resARN, webACLAssociations); err != nil {
4841
return err
4942
}
5043
}
@@ -57,14 +50,10 @@ func (s *webACLAssociationSynthesizer) PostSynthesize(ctx context.Context) error
5750
}
5851

5952
func (s *webACLAssociationSynthesizer) synthesizeWebACLAssociationsOnLB(ctx context.Context, lbARN string, resAssociations []*wafv2model.WebACLAssociation) error {
60-
if len(resAssociations) > 1 {
61-
return errors.Errorf("[should never happen] multiple WAFv2 webACL desired on LoadBalancer: %v", lbARN)
62-
}
63-
64-
var desiredWebACLARN string
65-
if len(resAssociations) == 1 {
66-
desiredWebACLARN = resAssociations[0].Spec.WebACLARN
53+
if len(resAssociations) != 1 {
54+
return errors.Errorf("[should never happen] should be exactly one WAFv2 webACL association on LoadBalancer: %v", lbARN)
6755
}
56+
desiredWebACLARN := resAssociations[0].Spec.WebACLARN
6857
currentWebACLARN, err := s.associationManager.GetAssociatedWebACL(ctx, lbARN)
6958
if err != nil {
7059
return err

pkg/ingress/model_build_load_balancer_addons.go

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,13 @@ import (
1111
wafv2model "sigs.k8s.io/aws-load-balancer-controller/pkg/model/wafv2"
1212
)
1313

14+
const (
15+
// sentinel annotation value to disable wafv2 ACL on resources.
16+
wafv2ACLARNNone = "none"
17+
// sentinel annotation value to disable wafRegional on resources.
18+
webACLIDNone = "none"
19+
)
20+
1421
func (t *defaultModelBuildTask) buildLoadBalancerAddOns(ctx context.Context, lbARN core.StringToken) error {
1522
if _, err := t.buildWAFv2WebACLAssociation(ctx, lbARN); err != nil {
1623
return err
@@ -39,14 +46,22 @@ func (t *defaultModelBuildTask) buildWAFv2WebACLAssociation(_ context.Context, l
3946
return nil, errors.Errorf("conflicting WAFv2 WebACL ARNs: %v", explicitWebACLARNs.List())
4047
}
4148
webACLARN, _ := explicitWebACLARNs.PopAny()
42-
if webACLARN != "" {
49+
switch webACLARN {
50+
case "":
51+
return nil, nil
52+
case wafv2ACLARNNone:
53+
association := wafv2model.NewWebACLAssociation(t.stack, resourceIDLoadBalancer, wafv2model.WebACLAssociationSpec{
54+
WebACLARN: "",
55+
ResourceARN: lbARN,
56+
})
57+
return association, nil
58+
default:
4359
association := wafv2model.NewWebACLAssociation(t.stack, resourceIDLoadBalancer, wafv2model.WebACLAssociationSpec{
4460
WebACLARN: webACLARN,
4561
ResourceARN: lbARN,
4662
})
4763
return association, nil
4864
}
49-
return nil, nil
5065
}
5166

5267
func (t *defaultModelBuildTask) buildWAFRegionalWebACLAssociation(_ context.Context, lbARN core.StringToken) (*wafregionalmodel.WebACLAssociation, error) {
@@ -66,14 +81,22 @@ func (t *defaultModelBuildTask) buildWAFRegionalWebACLAssociation(_ context.Cont
6681
return nil, errors.Errorf("conflicting WAFRegional WebACL IDs: %v", explicitWebACLIDs.List())
6782
}
6883
webACLID, _ := explicitWebACLIDs.PopAny()
69-
if webACLID != "" {
84+
switch webACLID {
85+
case "":
86+
return nil, nil
87+
case webACLIDNone:
88+
association := wafregionalmodel.NewWebACLAssociation(t.stack, resourceIDLoadBalancer, wafregionalmodel.WebACLAssociationSpec{
89+
WebACLID: "",
90+
ResourceARN: lbARN,
91+
})
92+
return association, nil
93+
default:
7094
association := wafregionalmodel.NewWebACLAssociation(t.stack, resourceIDLoadBalancer, wafregionalmodel.WebACLAssociationSpec{
7195
WebACLID: webACLID,
7296
ResourceARN: lbARN,
7397
})
7498
return association, nil
7599
}
76-
return nil, nil
77100
}
78101

79102
func (t *defaultModelBuildTask) buildShieldProtection(_ context.Context, lbARN core.StringToken) (*shieldmodel.Protection, error) {
@@ -94,11 +117,10 @@ func (t *defaultModelBuildTask) buildShieldProtection(_ context.Context, lbARN c
94117
if len(explicitEnableProtections) > 1 {
95118
return nil, errors.New("conflicting enable shield advanced protection")
96119
}
97-
if _, enableProtection := explicitEnableProtections[true]; enableProtection {
98-
protection := shieldmodel.NewProtection(t.stack, resourceIDLoadBalancer, shieldmodel.ProtectionSpec{
99-
ResourceARN: lbARN,
100-
})
101-
return protection, nil
102-
}
103-
return nil, nil
120+
_, enableProtection := explicitEnableProtections[true]
121+
protection := shieldmodel.NewProtection(t.stack, resourceIDLoadBalancer, shieldmodel.ProtectionSpec{
122+
Enabled: enableProtection,
123+
ResourceARN: lbARN,
124+
})
125+
return protection, nil
104126
}

pkg/model/shield/protection.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,6 @@ func (p *Protection) registerDependencies(stack core.Stack) {
2929

3030
// ProtectionSpec defines the desired state of Protection.
3131
type ProtectionSpec struct {
32+
Enabled bool `json:"enabled"`
3233
ResourceARN core.StringToken `json:"resourceARN"`
3334
}

0 commit comments

Comments
 (0)