Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions apis/elbv2/v1beta1/ingressclassparams_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,10 @@ type IngressClassParamsSpec struct {
// WAFv2ACLArn specifies ARN for the Amazon WAFv2 web ACL.
// +optional
WAFv2ACLArn string `json:"wafv2AclArn"`

// WAFv2ACLName specifies name of the Amazon WAFv2 web ACL.
// +optional
WAFv2ACLName string `json:"wafv2AclName"`
}

// +kubebuilder:object:root=true
Expand Down
3 changes: 3 additions & 0 deletions config/crd/bases/elbv2.k8s.aws_ingressclassparams.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,9 @@ spec:
wafv2AclArn:
description: WAFv2ACLArn specifies ARN for the Amazon WAFv2 web ACL.
type: string
wafv2AclName:
description: WAFv2ACLName specifies name of the Amazon WAFv2 web ACL.
type: string
type: object
x-kubernetes-validations:
- message: cannot specify both 'prefixListsIDs' and 'PrefixListsIDs' fields
Expand Down
2 changes: 1 addition & 1 deletion controllers/ingress/group_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ func NewGroupReconciler(cloud services.Cloud, k8sClient client.Client, eventReco
referenceIndexer := ingress.NewDefaultReferenceIndexer(enhancedBackendBuilder, authConfigBuilder, logger)
trackingProvider := tracking.NewDefaultProvider(ingressTagPrefix, controllerConfig.ClusterName)
modelBuilder := ingress.NewDefaultModelBuilder(k8sClient, eventRecorder,
cloud.EC2(), cloud.ELBV2(), cloud.ACM(),
cloud.EC2(), cloud.ELBV2(), cloud.WAFv2(), cloud.ACM(),
annotationParser, subnetsResolver,
authConfigBuilder, enhancedBackendBuilder, trackingProvider, elbv2TaggingManager, controllerConfig.FeatureGates,
cloud.VpcID(), controllerConfig.ClusterName, controllerConfig.DefaultTags, controllerConfig.ExternalManagedTags,
Expand Down
19 changes: 18 additions & 1 deletion docs/guide/ingress/annotations.md
Original file line number Diff line number Diff line change
Expand Up @@ -1041,7 +1041,24 @@ Load balancer capacity unit reservation can be configured via following annotati
- disable WAFV2
```alb.ingress.kubernetes.io/wafv2-acl-arn: none
```
- <a name="wafv2-acl-name">`alb.ingress.kubernetes.io/wafv2-acl-name`</a> specifies Name of the Amazon WAFv2 web ACL.
!!!warning ""
Only Regional WAFv2 is supported.
!!!note ""
When this annotation is absent or empty, the controller will keep LoadBalancer WAFv2 settings unchanged.
To disable WAFv2, explicitly set the annotation value to 'none'.
!!!example
- enable WAFv2
```alb.ingress.kubernetes.io/wafv2-acl-name: web-acl-name-1
```
- disable WAFV2
```alb.ingress.kubernetes.io/wafv2-acl-name: none
```
- <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.
!!!note ""
Expand Down
18 changes: 17 additions & 1 deletion docs/guide/ingress/ingress_class.md
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,15 @@ You can use IngressClassParams to enforce settings for a set of Ingresses.
- key: routing.http.response.server.enabled
value: "false"
```
- with wafv2AclName
```
apiVersion: elbv2.k8s.aws/v1beta1
kind: IngressClassParams
metadata:
name: class2048-config
spec:
wafv2AclName: "web-acl-name-1"
```

### IngressClassParams specification

Expand Down Expand Up @@ -384,4 +393,11 @@ Cluster administrators can use `Listeners` field to specify the [Listener Attrib

Cluster administrators can use the optional `wafv2AclArn` field to specify ARN for the Amazon WAFv2 web ACL.
Only Regional WAFv2 is supported.
When this annotation is absent or empty, the controller will keep LoadBalancer WAFv2 settings unchanged. To disable WAFv2, explicitly set the annotation value to 'none'.
When this param is absent or empty, the controller will keep LoadBalancer WAFv2 settings unchanged. To disable WAFv2, explicitly set the annotation value to 'none'.

#### spec.wafv2AclName

Cluster administrators can use the optional `wafv2AclName` field to specify name of the Amazon WAFv2 web ACL.
Only Regional WAFv2 is supported.
When this param is absent or empty, the controller will keep LoadBalancer WAFv2 settings unchanged. To disable WAFv2, explicitly set the param value to 'none'.
If the field is specified, LBC will ignore the 'alb.ingress.kubernetes.io/wafv2-acl-name' annotation.
3 changes: 3 additions & 0 deletions helm/aws-load-balancer-controller/crds/crds.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,9 @@ spec:
wafv2AclArn:
description: WAFv2ACLArn specifies ARN for the Amazon WAFv2 web ACL.
type: string
wafv2AclName:
description: WAFv2ACLName specifies name of the Amazon WAFv2 web ACL.
type: string
type: object
x-kubernetes-validations:
- message: cannot specify both 'prefixListsIDs' and 'PrefixListsIDs' fields
Expand Down
1 change: 1 addition & 0 deletions pkg/annotations/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const (
IngressSuffixCustomerOwnedIPv4Pool = "customer-owned-ipv4-pool"
IngressSuffixLoadBalancerAttributes = "load-balancer-attributes"
IngressSuffixWAFv2ACLARN = "wafv2-acl-arn"
IngressSuffixWAFv2ACLName = "wafv2-acl-name"
IngressSuffixWAFACLID = "waf-acl-id"
IngressSuffixWebACLID = "web-acl-id" // deprecated, use "waf-acl-id" instead.
IngressSuffixShieldAdvancedProtection = "shield-advanced-protection"
Expand Down
9 changes: 9 additions & 0 deletions pkg/aws/services/wafv2.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ type WAFv2 interface {
AssociateWebACLWithContext(context.Context, *wafv2.AssociateWebACLInput) (*wafv2.AssociateWebACLOutput, error)
DisassociateWebACLWithContext(ctx context.Context, req *wafv2.DisassociateWebACLInput) (*wafv2.DisassociateWebACLOutput, error)
GetWebACLForResourceWithContext(ctx context.Context, req *wafv2.GetWebACLForResourceInput) (*wafv2.GetWebACLForResourceOutput, error)
GetWebACLWithContext(ctx context.Context, req *wafv2.GetWebACLInput) (*wafv2.GetWebACLOutput, error)
}

// NewWAFv2 constructs new WAFv2 implementation.
Expand Down Expand Up @@ -46,3 +47,11 @@ func (c *wafv2Client) GetWebACLForResourceWithContext(ctx context.Context, req *
}
return client.GetWebACLForResource(ctx, req)
}

func (c *wafv2Client) GetWebACLWithContext(ctx context.Context, req *wafv2.GetWebACLInput) (*wafv2.GetWebACLOutput, error) {
client, err := c.awsClientsProvider.GetWAFv2Client(ctx, "GetWebACL")
if err != nil {
return nil, err
}
return client.GetWebACL(ctx, req)
}
15 changes: 15 additions & 0 deletions pkg/aws/services/wafv2_mocks.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

61 changes: 49 additions & 12 deletions pkg/ingress/model_build_load_balancer_addons.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,26 +32,63 @@ func (t *defaultModelBuildTask) buildLoadBalancerAddOns(ctx context.Context, lbA
return nil
}

func (t *defaultModelBuildTask) buildWAFv2WebACLAssociation(_ context.Context, lbARN core.StringToken) (*wafv2model.WebACLAssociation, error) {
func (t *defaultModelBuildTask) buildWAFv2WebACLAssociation(ctx context.Context, lbARN core.StringToken) (*wafv2model.WebACLAssociation, error) {
explicitWebACLARNs := sets.NewString()
explicitWebACLNames := sets.NewString()

for _, member := range t.ingGroup.Members {
rawWebACLARN := ""
_ = t.annotationParser.ParseStringAnnotation(annotations.IngressSuffixWAFv2ACLARN, &rawWebACLARN, member.Ing.Annotations)
if rawWebACLARN != "" {
if member.IngClassConfig.IngClassParams != nil && member.IngClassConfig.IngClassParams.Spec.WAFv2ACLName != "" {
rawWebACLName := member.IngClassConfig.IngClassParams.Spec.WAFv2ACLName
explicitWebACLNames.Insert(rawWebACLName)
continue
}
rawWebACLName := ""
_ = t.annotationParser.ParseStringAnnotation(annotations.IngressSuffixWAFv2ACLName, &rawWebACLName, member.Ing.Annotations)
if rawWebACLName != "" {
explicitWebACLNames.Insert(rawWebACLName)
}
}

webACLARN := ""

if len(explicitWebACLNames) == 0 {
for _, member := range t.ingGroup.Members {
if member.IngClassConfig.IngClassParams != nil && member.IngClassConfig.IngClassParams.Spec.WAFv2ACLArn != "" {
webACLARN = member.IngClassConfig.IngClassParams.Spec.WAFv2ACLArn
explicitWebACLARNs.Insert(webACLARN)
continue
}

rawWebACLARN := ""
if exists := t.annotationParser.ParseStringAnnotation(annotations.IngressSuffixWAFv2ACLARN, &rawWebACLARN, member.Ing.Annotations); !exists {
continue
}
explicitWebACLARNs.Insert(rawWebACLARN)
}
params := member.IngClassConfig.IngClassParams
if params != nil && params.Spec.WAFv2ACLArn != "" {
explicitWebACLARNs.Insert(params.Spec.WAFv2ACLArn)
if len(explicitWebACLARNs) == 0 {
return nil, nil
}
if len(explicitWebACLARNs) > 1 {
return nil, errors.Errorf("conflicting WAFv2 WebACL ARNs: %v", explicitWebACLARNs.List())
}
webACLARN, _ = explicitWebACLARNs.PopAny()
}
if len(explicitWebACLARNs) == 0 {
return nil, nil

if len(explicitWebACLNames) > 1 {
return nil, errors.Errorf("conflicting WAFv2 WebACL names: %v", explicitWebACLNames.List())
}
if len(explicitWebACLARNs) > 1 {
return nil, errors.Errorf("conflicting WAFv2 WebACL ARNs: %v", explicitWebACLARNs.List())

if len(explicitWebACLNames) == 1 {
rawWebACLName, _ := explicitWebACLNames.PopAny()
if rawWebACLName != "none" {
var err error
webACLARN, err = t.webACLNameToArnMapper.getArnByName(ctx, rawWebACLName)
if err != nil {
return nil, errors.Errorf("couldn't find WAFv2 WebACL with name: %v", rawWebACLName)
}
}
}
webACLARN, _ := explicitWebACLARNs.PopAny()

switch webACLARN {
case wafv2ACLARNNone:
association := wafv2model.NewWebACLAssociation(t.stack, resourceIDLoadBalancer, wafv2model.WebACLAssociationSpec{
Expand Down
Loading