From 0b2bf0d2f680f6e33baa38126a3a34cb3cbbecff Mon Sep 17 00:00:00 2001 From: Wagner Mattei Date: Wed, 23 Apr 2025 15:52:56 -0300 Subject: [PATCH 1/3] chore(elasticloadbalancingv2): Add validation on application listeners for certificates on HTTP protocol --- .../lib/alb/application-listener.ts | 4 ++++ .../test/alb/listener.test.ts | 17 +++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/alb/application-listener.ts b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/alb/application-listener.ts index 30a180d5a948d..300dc8fa737b4 100644 --- a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/alb/application-listener.ts +++ b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/alb/application-listener.ts @@ -263,6 +263,10 @@ export class ApplicationListener extends BaseListener implements IApplicationLis throw new ValidationError('At least one of \'port\' or \'protocol\' is required', scope); } + if (protocol === ApplicationProtocol.HTTP && props.certificates?.length) { + throw new ValidationError('A certificate cannot be specified for HTTP listeners', scope); + } + validateMutualAuthentication(scope, props.mutualAuthentication); let advertiseTrustStoreCaNames: string | undefined; diff --git a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/test/alb/listener.test.ts b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/test/alb/listener.test.ts index 1a50aea159256..80a01d0306ad0 100644 --- a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/test/alb/listener.test.ts +++ b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/test/alb/listener.test.ts @@ -257,6 +257,23 @@ describe('tests', () => { }); }); + test('HTTP listener requires no certificate', () => { + // GIVEN + const stack = new cdk.Stack(); + const vpc = new ec2.Vpc(stack, 'Stack'); + const lb = new elbv2.ApplicationLoadBalancer(stack, 'LB', { vpc }); + + // WHEN + const listener = lb.addListener('Listener', { + port: 80, + defaultTargetGroups: [new elbv2.ApplicationTargetGroup(stack, 'Group', { vpc, port: 80 })], + }); + + // THEN + const errors = listener.node.validate(); + expect(errors).toEqual(['A certificate cannot be specified for HTTP listeners']); + }); + test('Can configure targetType on TargetGroups', () => { // GIVEN const stack = new cdk.Stack(); From 94c56c101a04d0000fe655b911fee6da9c1b5060 Mon Sep 17 00:00:00 2001 From: Wagner Mattei Date: Wed, 23 Apr 2025 17:24:37 -0300 Subject: [PATCH 2/3] chore(elasticloadbalancingv2): Fix test case and changed error message --- .../lib/alb/application-listener.ts | 2 +- .../test/alb/listener.test.ts | 11 ++++------- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/alb/application-listener.ts b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/alb/application-listener.ts index 300dc8fa737b4..9d6c86947ecb2 100644 --- a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/alb/application-listener.ts +++ b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/alb/application-listener.ts @@ -264,7 +264,7 @@ export class ApplicationListener extends BaseListener implements IApplicationLis } if (protocol === ApplicationProtocol.HTTP && props.certificates?.length) { - throw new ValidationError('A certificate cannot be specified for HTTP listeners', scope); + throw new ValidationError('certificates cannot be specified for HTTP listeners', scope); } validateMutualAuthentication(scope, props.mutualAuthentication); diff --git a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/test/alb/listener.test.ts b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/test/alb/listener.test.ts index 80a01d0306ad0..70cb7896b0a78 100644 --- a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/test/alb/listener.test.ts +++ b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/test/alb/listener.test.ts @@ -257,21 +257,18 @@ describe('tests', () => { }); }); - test('HTTP listener requires no certificate', () => { + test('HTTP listener cannot have a certificate', () => { // GIVEN const stack = new cdk.Stack(); const vpc = new ec2.Vpc(stack, 'Stack'); const lb = new elbv2.ApplicationLoadBalancer(stack, 'LB', { vpc }); // WHEN - const listener = lb.addListener('Listener', { + expect(() => lb.addListener('Listener', { port: 80, + certificates: [elbv2.ListenerCertificate.fromArn('cert1')], defaultTargetGroups: [new elbv2.ApplicationTargetGroup(stack, 'Group', { vpc, port: 80 })], - }); - - // THEN - const errors = listener.node.validate(); - expect(errors).toEqual(['A certificate cannot be specified for HTTP listeners']); + })).toThrow(/certificates cannot be specified for HTTP listeners/); }); test('Can configure targetType on TargetGroups', () => { From 249d83b1734ccc2010da41a654ad790de7a4d3fe Mon Sep 17 00:00:00 2001 From: Wagner Mattei Date: Tue, 13 May 2025 21:57:01 -0300 Subject: [PATCH 3/3] Adding warning annotations instead of throwing an error --- .../lib/alb/application-listener.ts | 10 +++++----- .../test/alb/listener.test.ts | 9 +++++---- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/alb/application-listener.ts b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/alb/application-listener.ts index 9d6c86947ecb2..b300618b7251b 100644 --- a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/alb/application-listener.ts +++ b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/alb/application-listener.ts @@ -8,7 +8,7 @@ import { ListenerCondition } from './conditions'; import { ITrustStore } from './trust-store'; import * as ec2 from '../../../aws-ec2'; import * as cxschema from '../../../cloud-assembly-schema'; -import { Duration, FeatureFlags, Lazy, Resource, Token } from '../../../core'; +import { Annotations, Duration, FeatureFlags, Lazy, Resource, Token } from '../../../core'; import { ValidationError } from '../../../core/lib/errors'; import { addConstructMetadata, MethodMetadata } from '../../../core/lib/metadata-resource'; import * as cxapi from '../../../cx-api'; @@ -263,10 +263,6 @@ export class ApplicationListener extends BaseListener implements IApplicationLis throw new ValidationError('At least one of \'port\' or \'protocol\' is required', scope); } - if (protocol === ApplicationProtocol.HTTP && props.certificates?.length) { - throw new ValidationError('certificates cannot be specified for HTTP listeners', scope); - } - validateMutualAuthentication(scope, props.mutualAuthentication); let advertiseTrustStoreCaNames: string | undefined; @@ -290,6 +286,10 @@ export class ApplicationListener extends BaseListener implements IApplicationLis // Enhanced CDK Analytics Telemetry addConstructMetadata(this, props); + if (protocol === ApplicationProtocol.HTTP && props.certificates?.length) { + Annotations.of(this).addWarningV2('@aws-cdk/aws-elasticloadbalancingv2:httpListenerWithCertificates', 'Certificates cannot be specified for HTTP listeners. Use HTTPS instead.'); + } + this.loadBalancer = props.loadBalancer; this.protocol = protocol; this.port = port; diff --git a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/test/alb/listener.test.ts b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/test/alb/listener.test.ts index 70cb7896b0a78..9e488f64a94c2 100644 --- a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/test/alb/listener.test.ts +++ b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/test/alb/listener.test.ts @@ -1,6 +1,6 @@ import { describeDeprecated, testDeprecated } from '@aws-cdk/cdk-build-tools'; import * as constructs from 'constructs'; -import { Match, Template } from '../../../assertions'; +import { Annotations, Match, Template } from '../../../assertions'; import * as acm from '../../../aws-certificatemanager'; import { Metric } from '../../../aws-cloudwatch'; import * as ec2 from '../../../aws-ec2'; @@ -263,12 +263,13 @@ describe('tests', () => { const vpc = new ec2.Vpc(stack, 'Stack'); const lb = new elbv2.ApplicationLoadBalancer(stack, 'LB', { vpc }); - // WHEN - expect(() => lb.addListener('Listener', { + const listener = lb.addListener('Listener', { port: 80, certificates: [elbv2.ListenerCertificate.fromArn('cert1')], defaultTargetGroups: [new elbv2.ApplicationTargetGroup(stack, 'Group', { vpc, port: 80 })], - })).toThrow(/certificates cannot be specified for HTTP listeners/); + }); + + Annotations.fromStack(stack).hasWarning('/'+listener.node.path, Match.stringLikeRegexp('Certificates cannot be specified for HTTP listeners. Use HTTPS instead.')); }); test('Can configure targetType on TargetGroups', () => {