Skip to content

Commit 1a11938

Browse files
authored
feat(elbv2): add desyncMitigationMode for elbv2 (#22730)
Add `desyncMitigationMode` property for ALB so desync mitigation mode can be set easily. see: https://docs.aws.amazon.com/elasticloadbalancing/latest/application/application-load-balancers.html#desync-mitigation-mode ---- ### All Submissions: * [x] Have you followed the guidelines in our [Contributing guide?](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) ### Adding new Unconventional Dependencies: * [ ] This PR adds new unconventional dependencies following the process described [here](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md/#adding-new-unconventional-dependencies) ### New Features * [x] Have you added the new feature to an [integration test](https://github.com/aws/aws-cdk/blob/main/INTEGRATION_TESTS.md)? * [x] Did you use `yarn integ` to deploy the infrastructure and generate the snapshot (i.e. `yarn integ` without `--dry-run`)? *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent 30602c1 commit 1a11938

13 files changed

+2137
-1
lines changed

packages/@aws-cdk/aws-elasticloadbalancingv2/README.md

+27
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,33 @@ If you do not provide any options for this method, it redirects HTTP port 80 to
204204
By default all ingress traffic will be allowed on the source port. If you want to be more selective with your
205205
ingress rules then set `open: false` and use the listener's `connections` object to selectively grant access to the listener.
206206

207+
### Load Balancer attributes
208+
209+
You can modify attributes of Application Load Balancers:
210+
211+
```ts
212+
const lb = new elbv2.ApplicationLoadBalancer(this, 'LB', {
213+
vpc,
214+
internetFacing: true,
215+
216+
// Whether HTTP/2 is enabled
217+
http2Enabled: false,
218+
219+
// The idle timeout value, in seconds
220+
idleTimeout: cdk.Duration.seconds(1000),
221+
222+
// Whether HTTP headers with header fields thatare not valid
223+
// are removed by the load balancer (true), or routed to targets
224+
dropInvalidHeaderFields: true,
225+
226+
// How the load balancer handles requests that might
227+
// pose a security risk to your application
228+
desyncMitigationMode: elbv2.DesyncMitigationMode.DEFENSIVE,
229+
});
230+
```
231+
232+
For more information, see [Load balancer attributes](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/application-load-balancers.html#load-balancer-attributes)
233+
207234
## Defining a Network Load Balancer
208235

209236
Network Load Balancers are defined in a similar way to Application Load

packages/@aws-cdk/aws-elasticloadbalancingv2/lib/alb/application-load-balancer.ts

+10-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import * as cxapi from '@aws-cdk/cx-api';
66
import { Construct } from 'constructs';
77
import { ApplicationELBMetrics } from '../elasticloadbalancingv2-canned-metrics.generated';
88
import { BaseLoadBalancer, BaseLoadBalancerLookupOptions, BaseLoadBalancerProps, ILoadBalancerV2 } from '../shared/base-load-balancer';
9-
import { IpAddressType, ApplicationProtocol } from '../shared/enums';
9+
import { IpAddressType, ApplicationProtocol, DesyncMitigationMode } from '../shared/enums';
1010
import { ApplicationListener, BaseApplicationListenerProps } from './application-listener';
1111
import { ListenerAction } from './application-listener-action';
1212

@@ -51,6 +51,14 @@ export interface ApplicationLoadBalancerProps extends BaseLoadBalancerProps {
5151
* @default false
5252
*/
5353
readonly dropInvalidHeaderFields?: boolean;
54+
55+
/**
56+
* Determines how the load balancer handles requests that
57+
* might pose a security risk to your application
58+
*
59+
* @default DesyncMitigationMode.DEFENSIVE
60+
*/
61+
readonly desyncMitigationMode?: DesyncMitigationMode;
5462
}
5563

5664
/**
@@ -109,6 +117,7 @@ export class ApplicationLoadBalancer extends BaseLoadBalancer implements IApplic
109117
if (props.http2Enabled === false) { this.setAttribute('routing.http2.enabled', 'false'); }
110118
if (props.idleTimeout !== undefined) { this.setAttribute('idle_timeout.timeout_seconds', props.idleTimeout.toSeconds().toString()); }
111119
if (props.dropInvalidHeaderFields) {this.setAttribute('routing.http.drop_invalid_header_fields.enabled', 'true'); }
120+
if (props.desyncMitigationMode !== undefined) {this.setAttribute('routing.http.desync_mitigation_mode', props.desyncMitigationMode); }
112121
}
113122

114123
/**

packages/@aws-cdk/aws-elasticloadbalancingv2/lib/shared/enums.ts

+22
Original file line numberDiff line numberDiff line change
@@ -259,3 +259,25 @@ export enum TargetGroupLoadBalancingAlgorithmType {
259259
*/
260260
LEAST_OUTSTANDING_REQUESTS = 'least_outstanding_requests',
261261
}
262+
263+
/**
264+
* How the load balancer handles requests that might pose a security risk to your application
265+
*
266+
* @see https://docs.aws.amazon.com/elasticloadbalancing/latest/application/application-load-balancers.html#desync-mitigation-mode
267+
*/
268+
export enum DesyncMitigationMode {
269+
/**
270+
* Allows all traffic
271+
*/
272+
MONITOR = 'monitor',
273+
274+
/**
275+
* Provides durable mitigation against HTTP desync while maintaining the availability of your application
276+
*/
277+
DEFENSIVE = 'defensive',
278+
279+
/**
280+
* Receives only requests that comply with RFC 7230
281+
*/
282+
STRICTEST = 'strictest',
283+
}

packages/@aws-cdk/aws-elasticloadbalancingv2/test/alb/load-balancer.test.ts

+78
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,84 @@ describe('tests', () => {
107107
});
108108
});
109109

110+
describe('Desync mitigation mode', () => {
111+
test('Defensive', () => {
112+
// GIVEN
113+
const stack = new cdk.Stack();
114+
const vpc = new ec2.Vpc(stack, 'Stack');
115+
116+
// WHEN
117+
new elbv2.ApplicationLoadBalancer(stack, 'LB', {
118+
vpc,
119+
desyncMitigationMode: elbv2.DesyncMitigationMode.DEFENSIVE,
120+
});
121+
122+
// THEN
123+
Template.fromStack(stack).hasResourceProperties('AWS::ElasticLoadBalancingV2::LoadBalancer', {
124+
LoadBalancerAttributes: [
125+
{
126+
Key: 'deletion_protection.enabled',
127+
Value: 'false',
128+
},
129+
{
130+
Key: 'routing.http.desync_mitigation_mode',
131+
Value: 'defensive',
132+
},
133+
],
134+
});
135+
});
136+
test('Monitor', () => {
137+
// GIVEN
138+
const stack = new cdk.Stack();
139+
const vpc = new ec2.Vpc(stack, 'Stack');
140+
141+
// WHEN
142+
new elbv2.ApplicationLoadBalancer(stack, 'LB', {
143+
vpc,
144+
desyncMitigationMode: elbv2.DesyncMitigationMode.MONITOR,
145+
});
146+
147+
// THEN
148+
Template.fromStack(stack).hasResourceProperties('AWS::ElasticLoadBalancingV2::LoadBalancer', {
149+
LoadBalancerAttributes: [
150+
{
151+
Key: 'deletion_protection.enabled',
152+
Value: 'false',
153+
},
154+
{
155+
Key: 'routing.http.desync_mitigation_mode',
156+
Value: 'monitor',
157+
},
158+
],
159+
});
160+
});
161+
test('Strictest', () => {
162+
// GIVEN
163+
const stack = new cdk.Stack();
164+
const vpc = new ec2.Vpc(stack, 'Stack');
165+
166+
// WHEN
167+
new elbv2.ApplicationLoadBalancer(stack, 'LB', {
168+
vpc,
169+
desyncMitigationMode: elbv2.DesyncMitigationMode.STRICTEST,
170+
});
171+
172+
// THEN
173+
Template.fromStack(stack).hasResourceProperties('AWS::ElasticLoadBalancingV2::LoadBalancer', {
174+
LoadBalancerAttributes: [
175+
{
176+
Key: 'deletion_protection.enabled',
177+
Value: 'false',
178+
},
179+
{
180+
Key: 'routing.http.desync_mitigation_mode',
181+
Value: 'strictest',
182+
},
183+
],
184+
});
185+
});
186+
});
187+
110188
test('Deletion protection false', () => {
111189
// GIVEN
112190
const stack = new cdk.Stack();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"version": "21.0.0",
3+
"files": {
4+
"21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": {
5+
"source": {
6+
"path": "Elbv2TestDefaultTestDeployAssert82DC2DEA.template.json",
7+
"packaging": "file"
8+
},
9+
"destinations": {
10+
"current_account-current_region": {
11+
"bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}",
12+
"objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json",
13+
"assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}"
14+
}
15+
}
16+
}
17+
},
18+
"dockerImages": {}
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{
2+
"Parameters": {
3+
"BootstrapVersion": {
4+
"Type": "AWS::SSM::Parameter::Value<String>",
5+
"Default": "/cdk-bootstrap/hnb659fds/version",
6+
"Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]"
7+
}
8+
},
9+
"Rules": {
10+
"CheckBootstrapVersion": {
11+
"Assertions": [
12+
{
13+
"Assert": {
14+
"Fn::Not": [
15+
{
16+
"Fn::Contains": [
17+
[
18+
"1",
19+
"2",
20+
"3",
21+
"4",
22+
"5"
23+
],
24+
{
25+
"Ref": "BootstrapVersion"
26+
}
27+
]
28+
}
29+
]
30+
},
31+
"AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI."
32+
}
33+
]
34+
}
35+
}
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"version": "21.0.0",
3+
"files": {
4+
"e0013d77550f4ad9d409277deba48d88a38a35f26ba1e36af47e988d8d2fc164": {
5+
"source": {
6+
"path": "aws-cdk-elbv2-integ.template.json",
7+
"packaging": "file"
8+
},
9+
"destinations": {
10+
"current_account-current_region": {
11+
"bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}",
12+
"objectKey": "e0013d77550f4ad9d409277deba48d88a38a35f26ba1e36af47e988d8d2fc164.json",
13+
"assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}"
14+
}
15+
}
16+
}
17+
},
18+
"dockerImages": {}
19+
}

0 commit comments

Comments
 (0)