diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2-actions/.eslintrc.js b/packages/@aws-cdk/aws-elasticloadbalancingv2-actions/.eslintrc.js index 1a3b4ca2b6aec..2658ee8727166 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2-actions/.eslintrc.js +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2-actions/.eslintrc.js @@ -1,2 +1,3 @@ const baseConfig = require('@aws-cdk/cdk-build-tools/config/eslintrc'); +baseConfig.parserOptions.project = __dirname + '/tsconfig.json'; module.exports = baseConfig; diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2-actions/lib/cognito-action.ts b/packages/@aws-cdk/aws-elasticloadbalancingv2-actions/lib/cognito-action.ts index 699446176b151..554189cb09816 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2-actions/lib/cognito-action.ts +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2-actions/lib/cognito-action.ts @@ -72,7 +72,7 @@ export interface AuthenticateCognitoActionProps { */ export class AuthenticateCognitoAction extends elbv2.ListenerAction { - private static config(options: AuthenticateCognitoActionProps): elbv2.CfnListenerRule.AuthenticateCognitoConfigProperty { + private static config(options: AuthenticateCognitoActionProps): elbv2.CfnListener.AuthenticateCognitoConfigProperty { return { userPoolArn: options.userPool.userPoolArn, userPoolClientId: options.userPoolClient.userPoolClientId, @@ -81,7 +81,7 @@ export class AuthenticateCognitoAction extends elbv2.ListenerAction { onUnauthenticatedRequest: options.onUnauthenticatedRequest, scope: options.scope, sessionCookieName: options.sessionCookieName, - sessionTimeout: options.sessionTimeout?.toSeconds(), + sessionTimeout: options.sessionTimeout?.toSeconds().toString(), }; } @@ -90,17 +90,15 @@ export class AuthenticateCognitoAction extends elbv2.ListenerAction { */ constructor(options: AuthenticateCognitoActionProps) { super({ - action: { - type: 'authenticate-cognito', - authenticateCognitoConfig: AuthenticateCognitoAction.config(options), - }, - defaultAction: { - type: 'authenticate-cognito', - authenticateCognitoConfig: { - ...AuthenticateCognitoAction.config(options), - sessionTimeout: options.sessionTimeout?.toSeconds().toString(), - }, - }, + type: 'authenticate-cognito', + authenticateCognitoConfig: AuthenticateCognitoAction.config(options), }, options.next); + this.addRuleAction({ + type: 'authenticate-cognito', + authenticateCognitoConfig: { + ...AuthenticateCognitoAction.config(options), + sessionTimeout: options.sessionTimeout?.toSeconds(), + }, + }); } } diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2-actions/test/cognito.test.ts b/packages/@aws-cdk/aws-elasticloadbalancingv2-actions/test/cognito.test.ts index 71fab621c141c..2c5a9373a476d 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2-actions/test/cognito.test.ts +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2-actions/test/cognito.test.ts @@ -2,7 +2,6 @@ import { Template } from '@aws-cdk/assertions'; import * as cognito from '@aws-cdk/aws-cognito'; import * as ec2 from '@aws-cdk/aws-ec2'; import * as elbv2 from '@aws-cdk/aws-elasticloadbalancingv2'; -import { ApplicationProtocol, ListenerCondition } from '@aws-cdk/aws-elasticloadbalancingv2'; import { Duration, Stack } from '@aws-cdk/core'; import * as actions from '../lib'; @@ -88,12 +87,12 @@ test('Can set sessionTimeout for actions and defaultActions', () => { // WHEN const listener = lb.addListener('Listener', { - protocol: ApplicationProtocol.HTTP, + protocol: elbv2.ApplicationProtocol.HTTP, defaultAction: action, }); listener.addAction('Action2', { priority: 1, - conditions: [ListenerCondition.pathPatterns(['/action2*'])], + conditions: [elbv2.ListenerCondition.pathPatterns(['/action2*'])], action: action, }); @@ -129,7 +128,7 @@ test('Can set sessionTimeout for actions and defaultActions', () => { UserPoolArn: { 'Fn::GetAtt': ['UserPool6BA7E5F2', 'Arn'] }, UserPoolClientId: { Ref: 'Client4A7F64DF' }, UserPoolDomain: { Ref: 'Domain66AC69E0' }, - // SessionTimeout in DefaultActions is number + // SessionTimeout in Actions is number SessionTimeout: 86400, }, Order: 1, diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2-actions/test/integ.cognito.js.snapshot/cdk.out b/packages/@aws-cdk/aws-elasticloadbalancingv2-actions/test/integ.cognito.js.snapshot/cdk.out index 588d7b269d34f..b72fef144f05c 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2-actions/test/integ.cognito.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2-actions/test/integ.cognito.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"20.0.0"} \ No newline at end of file +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2-actions/test/integ.cognito.js.snapshot/integ-cognito.assets.json b/packages/@aws-cdk/aws-elasticloadbalancingv2-actions/test/integ.cognito.js.snapshot/integ-cognito.assets.json index eb440f0bb1430..43427a41c1b2d 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2-actions/test/integ.cognito.js.snapshot/integ-cognito.assets.json +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2-actions/test/integ.cognito.js.snapshot/integ-cognito.assets.json @@ -1,7 +1,7 @@ { - "version": "20.0.0", + "version": "30.1.0", "files": { - "9271c99fa7fd8d6ae26202fec69aaabba91d343b835d6cdc41a76f14fb6462d9": { + "0c2d0def6db3389453a3efadab8db4804f46dd1e84431da6a970923085b33a51": { "source": { "path": "integ-cognito.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "9271c99fa7fd8d6ae26202fec69aaabba91d343b835d6cdc41a76f14fb6462d9.json", + "objectKey": "0c2d0def6db3389453a3efadab8db4804f46dd1e84431da6a970923085b33a51.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2-actions/test/integ.cognito.js.snapshot/integ-cognito.template.json b/packages/@aws-cdk/aws-elasticloadbalancingv2-actions/test/integ.cognito.js.snapshot/integ-cognito.template.json index 1bd256812e827..8ebe942ac8060 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2-actions/test/integ.cognito.js.snapshot/integ-cognito.template.json +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2-actions/test/integ.cognito.js.snapshot/integ-cognito.template.json @@ -459,6 +459,7 @@ "DefaultActions": [ { "AuthenticateCognitoConfig": { + "SessionTimeout": "86400", "UserPoolArn": { "Fn::GetAtt": [ "UserPool6BA7E5F2", @@ -497,6 +498,55 @@ "Protocol": "HTTPS" } }, + "LBListenerAction2RuleDEE172B4": { + "Type": "AWS::ElasticLoadBalancingV2::ListenerRule", + "Properties": { + "Actions": [ + { + "AuthenticateCognitoConfig": { + "SessionTimeout": 86400, + "UserPoolArn": { + "Fn::GetAtt": [ + "UserPool6BA7E5F2", + "Arn" + ] + }, + "UserPoolClientId": { + "Ref": "Client4A7F64DF" + }, + "UserPoolDomain": { + "Ref": "Domain66AC69E0" + } + }, + "Order": 1, + "Type": "authenticate-cognito" + }, + { + "FixedResponseConfig": { + "ContentType": "text/plain", + "MessageBody": "Authenticated", + "StatusCode": "200" + }, + "Order": 2, + "Type": "fixed-response" + } + ], + "Conditions": [ + { + "Field": "path-pattern", + "PathPatternConfig": { + "Values": [ + "action2*" + ] + } + } + ], + "ListenerArn": { + "Ref": "LBListener49E825B4" + }, + "Priority": 1 + } + }, "UserPool6BA7E5F2": { "Type": "AWS::Cognito::UserPool", "Properties": { diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2-actions/test/integ.cognito.js.snapshot/integ.json b/packages/@aws-cdk/aws-elasticloadbalancingv2-actions/test/integ.cognito.js.snapshot/integ.json index f9ed1ab172e2d..e2c6ee0c8b902 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2-actions/test/integ.cognito.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2-actions/test/integ.cognito.js.snapshot/integ.json @@ -1,11 +1,12 @@ { - "version": "20.0.0", + "version": "30.1.0", "testCases": { "integ-test-cognito/DefaultTest": { "stacks": [ "integ-cognito" ], - "assertionStack": "integ-test-cognito/DefaultTest/DeployAssert" + "assertionStack": "integ-test-cognito/DefaultTest/DeployAssert", + "assertionStackName": "integtestcognitoDefaultTestDeployAssert6F2623C9" } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2-actions/test/integ.cognito.js.snapshot/integtestcognitoDefaultTestDeployAssert6F2623C9.assets.json b/packages/@aws-cdk/aws-elasticloadbalancingv2-actions/test/integ.cognito.js.snapshot/integtestcognitoDefaultTestDeployAssert6F2623C9.assets.json index dd78a08c5891d..be07bf072ac9a 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2-actions/test/integ.cognito.js.snapshot/integtestcognitoDefaultTestDeployAssert6F2623C9.assets.json +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2-actions/test/integ.cognito.js.snapshot/integtestcognitoDefaultTestDeployAssert6F2623C9.assets.json @@ -1,5 +1,5 @@ { - "version": "20.0.0", + "version": "30.1.0", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { "source": { diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2-actions/test/integ.cognito.js.snapshot/manifest.json b/packages/@aws-cdk/aws-elasticloadbalancingv2-actions/test/integ.cognito.js.snapshot/manifest.json index bfc2c9988cc6f..6754548507bfd 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2-actions/test/integ.cognito.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2-actions/test/integ.cognito.js.snapshot/manifest.json @@ -1,12 +1,6 @@ { - "version": "20.0.0", + "version": "30.1.0", "artifacts": { - "Tree": { - "type": "cdk:tree", - "properties": { - "file": "tree.json" - } - }, "integ-cognito.assets": { "type": "cdk:asset-manifest", "properties": { @@ -23,7 +17,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/9271c99fa7fd8d6ae26202fec69aaabba91d343b835d6cdc41a76f14fb6462d9.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/0c2d0def6db3389453a3efadab8db4804f46dd1e84431da6a970923085b33a51.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -195,6 +189,12 @@ "data": "LBListener49E825B4" } ], + "/integ-cognito/LB/Listener/Action2Rule/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "LBListenerAction2RuleDEE172B4" + } + ], "/integ-cognito/UserPool/Resource": [ { "type": "aws:cdk:logicalId", @@ -280,6 +280,12 @@ ] }, "displayName": "integ-test-cognito/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2-actions/test/integ.cognito.js.snapshot/tree.json b/packages/@aws-cdk/aws-elasticloadbalancingv2-actions/test/integ.cognito.js.snapshot/tree.json index b7c18103cd1e9..4a24b167bc0c6 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2-actions/test/integ.cognito.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2-actions/test/integ.cognito.js.snapshot/tree.json @@ -4,14 +4,6 @@ "id": "App", "path": "", "children": { - "Tree": { - "id": "Tree", - "path": "Tree", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" - } - }, "integ-cognito": { "id": "integ-cognito", "path": "integ-cognito", @@ -91,8 +83,8 @@ "id": "Acl", "path": "integ-cognito/Stack/PublicSubnet1/Acl", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" } }, "RouteTable": { @@ -258,8 +250,8 @@ "id": "Acl", "path": "integ-cognito/Stack/PublicSubnet2/Acl", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" } }, "RouteTable": { @@ -425,8 +417,8 @@ "id": "Acl", "path": "integ-cognito/Stack/PrivateSubnet1/Acl", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" } }, "RouteTable": { @@ -544,8 +536,8 @@ "id": "Acl", "path": "integ-cognito/Stack/PrivateSubnet2/Acl", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" } }, "RouteTable": { @@ -770,7 +762,8 @@ }, "userPoolDomain": { "Ref": "Domain66AC69E0" - } + }, + "sessionTimeout": "86400" }, "order": 1 }, @@ -800,6 +793,73 @@ "fqn": "@aws-cdk/aws-elasticloadbalancingv2.CfnListener", "version": "0.0.0" } + }, + "Action2Rule": { + "id": "Action2Rule", + "path": "integ-cognito/LB/Listener/Action2Rule", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-cognito/LB/Listener/Action2Rule/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ElasticLoadBalancingV2::ListenerRule", + "aws:cdk:cloudformation:props": { + "actions": [ + { + "type": "authenticate-cognito", + "authenticateCognitoConfig": { + "userPoolArn": { + "Fn::GetAtt": [ + "UserPool6BA7E5F2", + "Arn" + ] + }, + "userPoolClientId": { + "Ref": "Client4A7F64DF" + }, + "userPoolDomain": { + "Ref": "Domain66AC69E0" + }, + "sessionTimeout": 86400 + }, + "order": 1 + }, + { + "type": "fixed-response", + "fixedResponseConfig": { + "statusCode": "200", + "contentType": "text/plain", + "messageBody": "Authenticated" + }, + "order": 2 + } + ], + "conditions": [ + { + "field": "path-pattern", + "pathPatternConfig": { + "values": [ + "action2*" + ] + } + } + ], + "listenerArn": { + "Ref": "LBListener49E825B4" + }, + "priority": 1 + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-elasticloadbalancingv2.CfnListenerRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-elasticloadbalancingv2.ApplicationListenerRule", + "version": "0.0.0" + } } }, "constructInfo": { @@ -950,14 +1010,30 @@ "id": "DNS", "path": "integ-cognito/DNS", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.CfnOutput", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "integ-cognito/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "integ-cognito/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" } } }, "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" } }, "integ-test-cognito": { @@ -973,15 +1049,33 @@ "path": "integ-test-cognito/DefaultTest/Default", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.264" } }, "DeployAssert": { "id": "DeployAssert", "path": "integ-test-cognito/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "integ-test-cognito/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "integ-test-cognito/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } + } + }, "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" } } }, @@ -995,11 +1089,19 @@ "fqn": "@aws-cdk/integ-tests.IntegTest", "version": "0.0.0" } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.264" + } } }, "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2-actions/test/integ.cognito.ts b/packages/@aws-cdk/aws-elasticloadbalancingv2-actions/test/integ.cognito.ts index c8f3964d1f00e..8217b40b4928b 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2-actions/test/integ.cognito.ts +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2-actions/test/integ.cognito.ts @@ -1,7 +1,7 @@ import * as cognito from '@aws-cdk/aws-cognito'; import * as ec2 from '@aws-cdk/aws-ec2'; import * as elbv2 from '@aws-cdk/aws-elasticloadbalancingv2'; -import { App, CfnOutput, Stack } from '@aws-cdk/core'; +import { App, CfnOutput, Duration, Stack } from '@aws-cdk/core'; import * as integ from '@aws-cdk/integ-tests'; import { Construct } from 'constructs'; import * as actions from '../lib'; @@ -54,19 +54,25 @@ class CognitoStack extends Stack { domainPrefix: 'test-cdk-prefix', }, }); - - lb.addListener('Listener', { + const action = new actions.AuthenticateCognitoAction({ + userPool, + userPoolClient, + userPoolDomain, + sessionTimeout: Duration.days(1), + next: elbv2.ListenerAction.fixedResponse(200, { + contentType: 'text/plain', + messageBody: 'Authenticated', + }), + }); + const listener = lb.addListener('Listener', { port: 443, certificates: [certificate], - defaultAction: new actions.AuthenticateCognitoAction({ - userPool, - userPoolClient, - userPoolDomain, - next: elbv2.ListenerAction.fixedResponse(200, { - contentType: 'text/plain', - messageBody: 'Authenticated', - }), - }), + defaultAction: action, + }); + listener.addAction('Action2', { + priority: 1, + conditions: [elbv2.ListenerCondition.pathPatterns(['action2*'])], + action, }); new CfnOutput(this, 'DNS', { diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/alb/application-listener-action.ts b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/alb/application-listener-action.ts index 11b3196cc49d1..3d589eb4f86e0 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/alb/application-listener-action.ts +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/alb/application-listener-action.ts @@ -3,7 +3,7 @@ import { Construct, IConstruct } from 'constructs'; import { IApplicationListener } from './application-listener'; import { IApplicationTargetGroup } from './application-target-group'; import { CfnListener, CfnListenerRule } from '../elasticloadbalancingv2.generated'; -import { IListenerAction, ListenerActionProps } from '../shared/listener-action'; +import { IListenerAction } from '../shared/listener-action'; /** * What to do when a client makes a request to a listener @@ -39,23 +39,20 @@ export class ListenerAction implements IListenerAction { onUnauthenticatedRequest: options.onUnauthenticatedRequest, scope: options.scope, sessionCookieName: options.sessionCookieName, + sessionTimeout: options.sessionTimeout?.toSeconds().toString(), }; - return new ListenerAction({ - action: { - type: 'authenticate-oidc', - authenticateOidcConfig: { - ...config, - sessionTimeout: options.sessionTimeout?.toSeconds(), - }, - }, - defaultAction: { - type: 'authenticate-oidc', - authenticateOidcConfig: { - ...config, - sessionTimeout: options.sessionTimeout?.toSeconds().toString(), - }, - }, + const listenerAction = new ListenerAction({ + type: 'authenticate-oidc', + authenticateOidcConfig: config, }, options.next); + listenerAction.addRuleAction({ + type: 'authenticate-oidc', + authenticateOidcConfig: { + ...config, + sessionTimeout: options.sessionTimeout?.toSeconds(), + }, + }); + return listenerAction; } /** @@ -69,17 +66,13 @@ export class ListenerAction implements IListenerAction { } if (targetGroups.length === 1 && options.stickinessDuration === undefined) { // Render a "simple" action for backwards compatibility with old templates - const actionProps = { + return new TargetGroupListenerAction(targetGroups, { type: 'forward', targetGroupArn: targetGroups[0].targetGroupArn, - }; - return new TargetGroupListenerAction(targetGroups, { - action: actionProps, - defaultAction: actionProps, }); } - const actionProps = { + return new TargetGroupListenerAction(targetGroups, { type: 'forward', forwardConfig: { targetGroups: targetGroups.map(g => ({ targetGroupArn: g.targetGroupArn })), @@ -88,10 +81,6 @@ export class ListenerAction implements IListenerAction { enabled: true, } : undefined, }, - }; - return new TargetGroupListenerAction(targetGroups, { - action: actionProps, - defaultAction: actionProps, }); } @@ -105,7 +94,7 @@ export class ListenerAction implements IListenerAction { throw new Error('Need at least one targetGroup in a ListenerAction.weightedForward()'); } - const actionProps ={ + return new TargetGroupListenerAction(targetGroups.map(g => g.targetGroup), { type: 'forward', forwardConfig: { targetGroups: targetGroups.map(g => ({ targetGroupArn: g.targetGroup.targetGroupArn, weight: g.weight })), @@ -114,10 +103,6 @@ export class ListenerAction implements IListenerAction { enabled: true, } : undefined, }, - }; - return new TargetGroupListenerAction(targetGroups.map(g => g.targetGroup), { - action: actionProps, - defaultAction: actionProps, }); } @@ -127,17 +112,13 @@ export class ListenerAction implements IListenerAction { * @see https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-listeners.html#fixed-response-actions */ public static fixedResponse(statusCode: number, options: FixedResponseOptions = {}): ListenerAction { - const actionProps ={ + return new ListenerAction({ type: 'fixed-response', fixedResponseConfig: { statusCode: Tokenization.stringifyNumber(statusCode), contentType: options.contentType, messageBody: options.messageBody, }, - }; - return new ListenerAction({ - action: actionProps, - defaultAction: actionProps, }); } @@ -166,7 +147,8 @@ export class ListenerAction implements IListenerAction { if ([options.host, options.path, options.port, options.protocol, options.query].findIndex(x => x !== undefined) === -1) { throw new Error('To prevent redirect loops, set at least one of \'protocol\', \'host\', \'port\', \'path\', or \'query\'.'); } - const actionProps ={ + + return new ListenerAction({ type: 'redirect', redirectConfig: { statusCode: options.permanent ? 'HTTP_301' : 'HTTP_302', @@ -176,13 +158,16 @@ export class ListenerAction implements IListenerAction { protocol: options.protocol, query: options.query, }, - }; - return new ListenerAction({ - action: actionProps, - defaultAction: actionProps, }); } + /** + * If set, it is preferred as Action for the `ListenerRule`. + * This is necessary if `CfnListener.ActionProperty` and `CfnListenerRule.ActionProperty` + * have different structures. + */ + private _actionJson?: CfnListenerRule.ActionProperty; + /** * Create an instance of ListenerAction * @@ -190,21 +175,22 @@ export class ListenerAction implements IListenerAction { * should be created by using one of the static factory functions, * but allow overriding to make sure we allow flexibility for the future. */ - protected constructor(private readonly props: ListenerActionProps, protected readonly next?: ListenerAction) { + protected constructor(private readonly defaultActionJson: CfnListener.ActionProperty, protected readonly next?: ListenerAction) { } /** - * Render the default actions in this chain + * Render the listener rule actions in this chain */ - public renderDefaultActions(): CfnListener.ActionProperty[] { - return this.renumber([this.props.defaultAction, ...this.next?.renderDefaultActions() ?? []]); + public renderRuleActions(): CfnListenerRule.ActionProperty[] { + const actionJson = this._actionJson ?? this.defaultActionJson as CfnListenerRule.ActionProperty; + return this._renumber([actionJson, ...this.next?.renderRuleActions() ?? []]); } /** - * Render the actions in this chain + * Render the listener default actions in this chain */ - public renderActions(): CfnListenerRule.ActionProperty[] { - return this.renumber([this.props.action, ...this.next?.renderActions() ?? []]); + public renderActions(): CfnListener.ActionProperty[] { + return this._renumber([this.defaultActionJson, ...this.next?.renderActions() ?? []]); } /** @@ -214,6 +200,13 @@ export class ListenerAction implements IListenerAction { this.next?.bind(scope, listener, associatingConstruct); } + private _renumber + (actions: ActionProperty[]): ActionProperty[] { + if (actions.length < 2) { return actions; } + + return actions.map((action, i) => ({ ...action, order: i + 1 })); + } + /** * Renumber the "order" fields in the actions array. * @@ -223,11 +216,22 @@ export class ListenerAction implements IListenerAction { * Do this in `ListenerAction` instead of in `Listener` so that we give * users the opportunity to override by subclassing and overriding `renderActions`. */ - private renumber - (actions: ActionProperty[]): ActionProperty[] { - if (actions.length < 2) { return actions; } + protected renumber(actions: CfnListener.ActionProperty[]): CfnListener.ActionProperty[] { + return this._renumber(actions); + } - return actions.map((action, i) => ({ ...action, order: i + 1 })); + /** + * Sets the Action for the `ListenerRule`. + * This method is required to set a dedicated Action to a `ListenerRule` + * when the Action for the `CfnListener` and the Action for the `CfnListenerRule` + * have different structures. (e.g. `AuthenticateOidcConfig`) + * @param actionJson Action for `ListenerRule` + */ + protected addRuleAction(actionJson: CfnListenerRule.ActionProperty) { + if (this._actionJson) { + throw new Error('rule action is already set'); + } + this._actionJson = actionJson; } } @@ -469,8 +473,8 @@ export enum UnauthenticatedAction { * Listener Action that calls "registerListener" on TargetGroups */ class TargetGroupListenerAction extends ListenerAction { - constructor(private readonly targetGroups: IApplicationTargetGroup[], props: ListenerActionProps) { - super(props); + constructor(private readonly targetGroups: IApplicationTargetGroup[], defaultActionJson: CfnListener.ActionProperty) { + super(defaultActionJson); } public bind(_scope: Construct, listener: IApplicationListener, associatingConstruct?: IConstruct) { diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/alb/application-listener-rule.ts b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/alb/application-listener-rule.ts index 5c68c3d96b544..17e18083b0749 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/alb/application-listener-rule.ts +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/alb/application-listener-rule.ts @@ -235,7 +235,7 @@ export class ApplicationListenerRule extends Construct { listenerArn: props.listener.listenerArn, priority: props.priority, conditions: cdk.Lazy.any({ produce: () => this.renderConditions() }), - actions: cdk.Lazy.any({ produce: () => this.action ? this.action.renderActions() : [] }), + actions: cdk.Lazy.any({ produce: () => this.action ? this.action.renderRuleActions() : [] }), }); if (props.hostHeader) { diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/nlb/network-listener-action.ts b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/nlb/network-listener-action.ts index c4e2d337e74d6..aadbcdddaac47 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/nlb/network-listener-action.ts +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/nlb/network-listener-action.ts @@ -3,7 +3,7 @@ import { Construct } from 'constructs'; import { INetworkListener } from './network-listener'; import { INetworkTargetGroup } from './network-target-group'; import { CfnListener, CfnListenerRule } from '../elasticloadbalancingv2.generated'; -import { IListenerAction, ListenerActionProps } from '../shared/listener-action'; +import { IListenerAction } from '../shared/listener-action'; /** * What to do when a client makes a request to a listener @@ -27,17 +27,13 @@ export class NetworkListenerAction implements IListenerAction { } if (targetGroups.length === 1 && options.stickinessDuration === undefined) { // Render a "simple" action for backwards compatibility with old templates - const actionProps = { + return new TargetGroupListenerAction(targetGroups, { type: 'forward', targetGroupArn: targetGroups[0].targetGroupArn, - }; - return new TargetGroupListenerAction(targetGroups, { - action: actionProps, - defaultAction: actionProps, }); } - const actionProps = { + return new TargetGroupListenerAction(targetGroups, { type: 'forward', forwardConfig: { targetGroups: targetGroups.map(g => ({ targetGroupArn: g.targetGroupArn })), @@ -46,10 +42,6 @@ export class NetworkListenerAction implements IListenerAction { enabled: true, } : undefined, }, - }; - return new TargetGroupListenerAction(targetGroups, { - action: actionProps, - defaultAction: actionProps, }); } @@ -61,7 +53,7 @@ export class NetworkListenerAction implements IListenerAction { throw new Error('Need at least one targetGroup in a NetworkListenerAction.weightedForward()'); } - const actionProps ={ + return new TargetGroupListenerAction(targetGroups.map(g => g.targetGroup), { type: 'forward', forwardConfig: { targetGroups: targetGroups.map(g => ({ targetGroupArn: g.targetGroup.targetGroupArn, weight: g.weight })), @@ -70,13 +62,11 @@ export class NetworkListenerAction implements IListenerAction { enabled: true, } : undefined, }, - }; - return new TargetGroupListenerAction(targetGroups.map(g => g.targetGroup), { - action: actionProps, - defaultAction: actionProps, }); } + private _actionJson?: CfnListenerRule.ActionProperty; + /** * Create an instance of NetworkListenerAction * @@ -84,21 +74,22 @@ export class NetworkListenerAction implements IListenerAction { * should be created by using one of the static factory functions, * but allow overriding to make sure we allow flexibility for the future. */ - protected constructor(private readonly props: ListenerActionProps, protected readonly next?: NetworkListenerAction) { + protected constructor(private readonly defaultActionJson: CfnListener.ActionProperty, protected readonly next?: NetworkListenerAction) { } /** - * Render the default actions in this chain + * Render the listener rule actions in this chain */ - public renderDefaultActions(): CfnListener.ActionProperty[] { - return this.renumber([this.props.defaultAction, ...this.next?.renderDefaultActions() ?? []]); + public renderRuleActions(): CfnListenerRule.ActionProperty[] { + const actionJson = this._actionJson ?? this.defaultActionJson as CfnListenerRule.ActionProperty; + return this._renumber([actionJson, ...this.next?.renderRuleActions() ?? []]); } /** - * Render the actions in this chain + * Render the listener default actions in this chain */ - public renderActions(): CfnListenerRule.ActionProperty[] { - return this.renumber([this.props.action, ...this.next?.renderActions() ?? []]); + public renderActions(): CfnListener.ActionProperty[] { + return this._renumber([this.defaultActionJson, ...this.next?.renderActions() ?? []]); } /** @@ -110,6 +101,13 @@ export class NetworkListenerAction implements IListenerAction { Array.isArray(listener); } + private _renumber + (actions: ActionProperty[]): ActionProperty[] { + if (actions.length < 2) { return actions; } + + return actions.map((action, i) => ({ ...action, order: i + 1 })); + } + /** * Renumber the "order" fields in the actions array. * @@ -119,11 +117,8 @@ export class NetworkListenerAction implements IListenerAction { * Do this in `NetworkListenerAction` instead of in `Listener` so that we give * users the opportunity to override by subclassing and overriding `renderActions`. */ - private renumber - (actions: ActionProperty[]): ActionProperty[] { - if (actions.length < 2) { return actions; } - - return actions.map((action, i) => ({ ...action, order: i + 1 })); + protected renumber(actions: CfnListener.ActionProperty[]): CfnListener.ActionProperty[] { + return this._renumber(actions); } } @@ -164,8 +159,8 @@ export interface NetworkWeightedTargetGroup { * Listener Action that calls "registerListener" on TargetGroups */ class TargetGroupListenerAction extends NetworkListenerAction { - constructor(private readonly targetGroups: INetworkTargetGroup[], props: ListenerActionProps) { - super(props); + constructor(private readonly targetGroups: INetworkTargetGroup[], defaultActionJson: CfnListener.ActionProperty) { + super(defaultActionJson); } public bind(_scope: Construct, listener: INetworkListener) { diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/shared/base-listener.ts b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/shared/base-listener.ts index 68555d16f54a9..7302c9a5a6a70 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/shared/base-listener.ts +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/shared/base-listener.ts @@ -119,7 +119,7 @@ export abstract class BaseListener extends Resource implements IListener { const resource = new CfnListener(this, 'Resource', { ...additionalProps, - defaultActions: Lazy.any({ produce: () => this.defaultAction?.renderDefaultActions() ?? [] }), + defaultActions: Lazy.any({ produce: () => this.defaultAction?.renderActions() ?? [] }), }); this.listenerArn = resource.ref; diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/shared/listener-action.ts b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/shared/listener-action.ts index e126f0c9f8716..0b002fe2707a5 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/shared/listener-action.ts +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/shared/listener-action.ts @@ -5,25 +5,11 @@ import { CfnListener, CfnListenerRule } from '../elasticloadbalancingv2.generate */ export interface IListenerAction { /** - * Render the actions in this chain + * Render the listener default actions in this chain */ - renderActions(): CfnListenerRule.ActionProperty[]; + renderActions(): CfnListener.ActionProperty[]; /** - * Render the actions in this chain + * Render the listener rule actions in this chain */ - renderDefaultActions(): CfnListener.ActionProperty[]; -} - -/** - * Properties for listener actions - */ -export interface ListenerActionProps { - /** - * Property for actions - */ - readonly action: CfnListenerRule.ActionProperty - /** - * Property for Default actions - */ - readonly defaultAction: CfnListener.ActionProperty + renderRuleActions(): CfnListenerRule.ActionProperty[]; } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2/test/alb/actions.test.ts b/packages/@aws-cdk/aws-elasticloadbalancingv2/test/alb/actions.test.ts index e655e57386a7c..9d3fee5584517 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2/test/alb/actions.test.ts +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2/test/alb/actions.test.ts @@ -1,9 +1,7 @@ import { Template } from '@aws-cdk/assertions'; import * as ec2 from '@aws-cdk/aws-ec2'; import * as cdk from '@aws-cdk/core'; -import { Duration } from '@aws-cdk/core'; import * as elbv2 from '../../lib'; -import { ListenerCondition } from '../../lib'; let stack: cdk.Stack; let group1: elbv2.ApplicationTargetGroup; @@ -119,13 +117,13 @@ describe('tests', () => { issuer: 'D', tokenEndpoint: 'E', userInfoEndpoint: 'F', - sessionTimeout: Duration.days(1), + sessionTimeout: cdk.Duration.days(1), next: elbv2.ListenerAction.forward([group1]), }), }); listener.addAction('AdditionalOidcAuthenticationAction', { priority: 1, - conditions: [ListenerCondition.pathPatterns(['/page*'])], + conditions: [elbv2.ListenerCondition.pathPatterns(['/page*'])], action: elbv2.ListenerAction.authenticateOidc({ authorizationEndpoint: 'A', clientId: 'B', @@ -133,7 +131,7 @@ describe('tests', () => { issuer: 'D', tokenEndpoint: 'E', userInfoEndpoint: 'F', - sessionTimeout: Duration.days(1), + sessionTimeout: cdk.Duration.days(1), next: elbv2.ListenerAction.forward([group1]), }), }); @@ -172,7 +170,7 @@ describe('tests', () => { Issuer: 'D', TokenEndpoint: 'E', UserInfoEndpoint: 'F', - // SessionTimeout in DefaultActions is number + // SessionTimeout in Actions is number SessionTimeout: 86400, }, Order: 1,