From 3ee305d6e5431e7767779291a9ed907c5923945a Mon Sep 17 00:00:00 2001 From: tmokmss Date: Fri, 8 Oct 2021 19:24:43 +0900 Subject: [PATCH 1/8] add grantManagementApiAccess method --- .../aws-apigatewayv2/lib/websocket/api.ts | 23 ++++++++++++++++++ .../test/websocket/api.test.ts | 24 ++++++++++++++++++- 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-apigatewayv2/lib/websocket/api.ts b/packages/@aws-cdk/aws-apigatewayv2/lib/websocket/api.ts index f2f2653c94ee6..88c19f26146b5 100644 --- a/packages/@aws-cdk/aws-apigatewayv2/lib/websocket/api.ts +++ b/packages/@aws-cdk/aws-apigatewayv2/lib/websocket/api.ts @@ -1,3 +1,5 @@ +import { Grant, IGrantable } from '@aws-cdk/aws-iam'; +import { Stack } from '@aws-cdk/core'; import { Construct } from 'constructs'; import { CfnApi } from '../apigatewayv2.generated'; import { IApi } from '../common/api'; @@ -67,12 +69,15 @@ export interface WebSocketApiProps { export class WebSocketApi extends ApiBase implements IWebSocketApi { public readonly apiId: string; public readonly apiEndpoint: string; + public readonly apiArn: string; /** * A human friendly name for this WebSocket API. Note that this is different from `webSocketApiId`. */ public readonly webSocketApiName?: string; + private readonly connectRoute?: WebSocketRoute; + constructor(scope: Construct, id: string, props?: WebSocketApiProps) { super(scope, id); @@ -86,6 +91,10 @@ export class WebSocketApi extends ApiBase implements IWebSocketApi { }); this.apiId = resource.ref; this.apiEndpoint = resource.attrApiEndpoint; + this.apiArn = Stack.of(this).formatArn({ + service: 'execute-api', + resource: this.apiId, + }); if (props?.connectRouteOptions) { this.addRoute('$connect', props.connectRouteOptions); @@ -127,4 +136,18 @@ export class WebSocketApi extends ApiBase implements IWebSocketApi { ...options, }); } + + /** + * Grant access to the API Gateway management API for this WebSocket API to an IAM + * principal (Role/Group/User). + * + * @param identity The principal + */ + public grantManagementApiAccess(identity: IGrantable): Grant { + return Grant.addToPrincipal({ + grantee: identity, + actions: ['execute-api:ManageConnections'], + resourceArns: [`${this.apiArn}/*`], + }); + } } diff --git a/packages/@aws-cdk/aws-apigatewayv2/test/websocket/api.test.ts b/packages/@aws-cdk/aws-apigatewayv2/test/websocket/api.test.ts index 959555a5c2b7a..5b051e24e54fb 100644 --- a/packages/@aws-cdk/aws-apigatewayv2/test/websocket/api.test.ts +++ b/packages/@aws-cdk/aws-apigatewayv2/test/websocket/api.test.ts @@ -1,4 +1,5 @@ -import { Template } from '@aws-cdk/assertions'; +import { Match, Template } from '@aws-cdk/assertions'; +import { User } from '@aws-cdk/aws-iam'; import { Stack } from '@aws-cdk/core'; import { IWebSocketRouteIntegration, WebSocketApi, WebSocketIntegrationType, @@ -80,6 +81,27 @@ describe('WebSocketApi', () => { RouteKey: '$default', }); }); + + test('grantManagementApiAccess: adds an IAM policy to the principal', () => { + // GIVEN + const stack = new Stack(); + const api = new WebSocketApi(stack, 'api'); + const principal = new User(stack, 'user'); + + // WHEN + api.grantManagementApiAccess(principal); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: Match.arrayWith([{ + Action: 'execute-api:ManageConnections', + Effect: 'Allow', + Resource: stack.resolve(`${api.apiArn}/*`), + }]), + }, + }); + }); }); class DummyIntegration implements IWebSocketRouteIntegration { From e57b89df7ebc11080437ff57d5ca5b771cf36326 Mon Sep 17 00:00:00 2001 From: tmokmss Date: Fri, 8 Oct 2021 23:12:20 +0900 Subject: [PATCH 2/8] fix --- packages/@aws-cdk/aws-apigatewayv2/lib/websocket/api.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/@aws-cdk/aws-apigatewayv2/lib/websocket/api.ts b/packages/@aws-cdk/aws-apigatewayv2/lib/websocket/api.ts index 88c19f26146b5..20cd28df671b3 100644 --- a/packages/@aws-cdk/aws-apigatewayv2/lib/websocket/api.ts +++ b/packages/@aws-cdk/aws-apigatewayv2/lib/websocket/api.ts @@ -76,8 +76,6 @@ export class WebSocketApi extends ApiBase implements IWebSocketApi { */ public readonly webSocketApiName?: string; - private readonly connectRoute?: WebSocketRoute; - constructor(scope: Construct, id: string, props?: WebSocketApiProps) { super(scope, id); From 02e3b4f47d7cdf10f35f002e72f768879c4191a9 Mon Sep 17 00:00:00 2001 From: tmokmss Date: Fri, 8 Oct 2021 23:44:29 +0900 Subject: [PATCH 3/8] fix --- .../aws-apigatewayv2/lib/websocket/api.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/packages/@aws-cdk/aws-apigatewayv2/lib/websocket/api.ts b/packages/@aws-cdk/aws-apigatewayv2/lib/websocket/api.ts index 20cd28df671b3..67bbbabdced54 100644 --- a/packages/@aws-cdk/aws-apigatewayv2/lib/websocket/api.ts +++ b/packages/@aws-cdk/aws-apigatewayv2/lib/websocket/api.ts @@ -67,8 +67,25 @@ export interface WebSocketApiProps { * @resource AWS::ApiGatewayV2::Api */ export class WebSocketApi extends ApiBase implements IWebSocketApi { + /** + * The ID of the WebSocket API. + * + * @attribute + */ public readonly apiId: string; + + /** + * The Endpoint of the WebSocket API. + * + * @attribute + */ public readonly apiEndpoint: string; + + /** + * The ARN of the WebSocket API. + * + * @attribute + */ public readonly apiArn: string; /** From b3b67e3d64ea9e2150ffadfd2be77441e437f1e5 Mon Sep 17 00:00:00 2001 From: tmokmss Date: Sat, 9 Oct 2021 10:43:12 +0900 Subject: [PATCH 4/8] add stage support --- .../aws-apigatewayv2/lib/websocket/api.ts | 24 +++++----------- .../aws-apigatewayv2/lib/websocket/stage.ts | 15 ++++++++++ .../test/websocket/stage.test.ts | 28 ++++++++++++++++++- 3 files changed, 49 insertions(+), 18 deletions(-) diff --git a/packages/@aws-cdk/aws-apigatewayv2/lib/websocket/api.ts b/packages/@aws-cdk/aws-apigatewayv2/lib/websocket/api.ts index 67bbbabdced54..b0cba2f3910dc 100644 --- a/packages/@aws-cdk/aws-apigatewayv2/lib/websocket/api.ts +++ b/packages/@aws-cdk/aws-apigatewayv2/lib/websocket/api.ts @@ -11,6 +11,13 @@ import { WebSocketRoute, WebSocketRouteOptions } from './route'; * Represents a WebSocket API */ export interface IWebSocketApi extends IApi { + /** + * The ARN of the WebSocket API. + * + * @attribute + */ + readonly apiArn: string; + /** * Add a websocket integration * @internal @@ -67,25 +74,8 @@ export interface WebSocketApiProps { * @resource AWS::ApiGatewayV2::Api */ export class WebSocketApi extends ApiBase implements IWebSocketApi { - /** - * The ID of the WebSocket API. - * - * @attribute - */ public readonly apiId: string; - - /** - * The Endpoint of the WebSocket API. - * - * @attribute - */ public readonly apiEndpoint: string; - - /** - * The ARN of the WebSocket API. - * - * @attribute - */ public readonly apiArn: string; /** diff --git a/packages/@aws-cdk/aws-apigatewayv2/lib/websocket/stage.ts b/packages/@aws-cdk/aws-apigatewayv2/lib/websocket/stage.ts index f6bc91909dcba..d4825270ee7c0 100644 --- a/packages/@aws-cdk/aws-apigatewayv2/lib/websocket/stage.ts +++ b/packages/@aws-cdk/aws-apigatewayv2/lib/websocket/stage.ts @@ -1,3 +1,4 @@ +import { Grant, IGrantable } from '@aws-cdk/aws-iam'; import { Stack } from '@aws-cdk/core'; import { Construct } from 'constructs'; import { CfnStage } from '../apigatewayv2.generated'; @@ -114,4 +115,18 @@ export class WebSocketStage extends StageBase implements IWebSocketStage { const urlPath = this.stageName; return `https://${this.api.apiId}.execute-api.${s.region}.${s.urlSuffix}/${urlPath}`; } + + /** + * Grant access to the API Gateway management API for this WebSocket API Stage to an IAM + * principal (Role/Group/User). + * + * @param identity The principal + */ + public grantManagementApiAccess(identity: IGrantable): Grant { + return Grant.addToPrincipal({ + grantee: identity, + actions: ['execute-api:ManageConnections'], + resourceArns: [`${this.api.apiArn}/${this.stageName}/POST/@connections`], + }); + } } diff --git a/packages/@aws-cdk/aws-apigatewayv2/test/websocket/stage.test.ts b/packages/@aws-cdk/aws-apigatewayv2/test/websocket/stage.test.ts index d942eb6dc7a4e..b3eab6c950126 100644 --- a/packages/@aws-cdk/aws-apigatewayv2/test/websocket/stage.test.ts +++ b/packages/@aws-cdk/aws-apigatewayv2/test/websocket/stage.test.ts @@ -1,4 +1,5 @@ -import { Template } from '@aws-cdk/assertions'; +import { Match, Template } from '@aws-cdk/assertions'; +import { User } from '@aws-cdk/aws-iam'; import { Stack } from '@aws-cdk/core'; import { WebSocketApi, WebSocketStage } from '../../lib'; @@ -59,4 +60,29 @@ describe('WebSocketStage', () => { expect(defaultStage.callbackUrl.endsWith('/dev')).toBe(true); expect(defaultStage.callbackUrl.startsWith('https://')).toBe(true); }); + + test('grantManagementApiAccess: adds an IAM policy to the principal', () => { + // GIVEN + const stack = new Stack(); + const api = new WebSocketApi(stack, 'Api'); + const defaultStage = new WebSocketStage(stack, 'Stage', { + webSocketApi: api, + stageName: 'dev', + }); + const principal = new User(stack, 'User'); + + // WHEN + defaultStage.grantManagementApiAccess(principal); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: Match.arrayWith([{ + Action: 'execute-api:ManageConnections', + Effect: 'Allow', + Resource: stack.resolve(`${api.apiArn}/${defaultStage.stageName}/POST/@connections`), + }]), + }, + }); + }); }); From bc0ee0e077e6915bb4373c19f67072e316db5f1e Mon Sep 17 00:00:00 2001 From: tmokmss Date: Sat, 9 Oct 2021 14:48:09 +0900 Subject: [PATCH 5/8] fix the resource should be apiArn/stage-name/POST/@connections/{connectionId} adding /* suffix --- packages/@aws-cdk/aws-apigatewayv2/lib/websocket/stage.ts | 2 +- packages/@aws-cdk/aws-apigatewayv2/test/websocket/stage.test.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/@aws-cdk/aws-apigatewayv2/lib/websocket/stage.ts b/packages/@aws-cdk/aws-apigatewayv2/lib/websocket/stage.ts index d4825270ee7c0..3c20d458e0247 100644 --- a/packages/@aws-cdk/aws-apigatewayv2/lib/websocket/stage.ts +++ b/packages/@aws-cdk/aws-apigatewayv2/lib/websocket/stage.ts @@ -126,7 +126,7 @@ export class WebSocketStage extends StageBase implements IWebSocketStage { return Grant.addToPrincipal({ grantee: identity, actions: ['execute-api:ManageConnections'], - resourceArns: [`${this.api.apiArn}/${this.stageName}/POST/@connections`], + resourceArns: [`${this.api.apiArn}/${this.stageName}/POST/@connections/*`], }); } } diff --git a/packages/@aws-cdk/aws-apigatewayv2/test/websocket/stage.test.ts b/packages/@aws-cdk/aws-apigatewayv2/test/websocket/stage.test.ts index b3eab6c950126..7af7df04c6786 100644 --- a/packages/@aws-cdk/aws-apigatewayv2/test/websocket/stage.test.ts +++ b/packages/@aws-cdk/aws-apigatewayv2/test/websocket/stage.test.ts @@ -80,7 +80,7 @@ describe('WebSocketStage', () => { Statement: Match.arrayWith([{ Action: 'execute-api:ManageConnections', Effect: 'Allow', - Resource: stack.resolve(`${api.apiArn}/${defaultStage.stageName}/POST/@connections`), + Resource: stack.resolve(`${api.apiArn}/${defaultStage.stageName}/POST/@connections/*`), }]), }, }); From 7085f48313969013e9d431cc0b848076ae2c222d Mon Sep 17 00:00:00 2001 From: tmokmss Date: Fri, 29 Oct 2021 00:42:44 +0900 Subject: [PATCH 6/8] fix --- packages/@aws-cdk/aws-apigatewayv2/README.md | 43 +++++++++++++----- .../aws-apigatewayv2/lib/websocket/api.ts | 21 +++------ .../aws-apigatewayv2/lib/websocket/stage.ts | 7 ++- .../test/websocket/api.test.ts | 41 +++++++++-------- .../test/websocket/stage.test.ts | 45 ++++++++++--------- 5 files changed, 93 insertions(+), 64 deletions(-) diff --git a/packages/@aws-cdk/aws-apigatewayv2/README.md b/packages/@aws-cdk/aws-apigatewayv2/README.md index cf0a2ab0552c7..1abe466b15af7 100644 --- a/packages/@aws-cdk/aws-apigatewayv2/README.md +++ b/packages/@aws-cdk/aws-apigatewayv2/README.md @@ -28,17 +28,20 @@ Higher level constructs for Websocket APIs | ![Experimental](https://img.shields ## Table of Contents -- [Introduction](#introduction) -- [HTTP API](#http-api) - - [Defining HTTP APIs](#defining-http-apis) - - [Cross Origin Resource Sharing (CORS)](#cross-origin-resource-sharing-cors) - - [Publishing HTTP APIs](#publishing-http-apis) - - [Custom Domain](#custom-domain) - - [Managing access](#managing-access) - - [Metrics](#metrics) - - [VPC Link](#vpc-link) - - [Private Integration](#private-integration) -- [WebSocket API](#websocket-api) +- [AWS::APIGatewayv2 Construct Library](#awsapigatewayv2-construct-library) + - [Table of Contents](#table-of-contents) + - [Introduction](#introduction) + - [HTTP API](#http-api) + - [Defining HTTP APIs](#defining-http-apis) + - [Cross Origin Resource Sharing (CORS)](#cross-origin-resource-sharing-cors) + - [Publishing HTTP APIs](#publishing-http-apis) + - [Custom Domain](#custom-domain) + - [Managing access](#managing-access) + - [Metrics](#metrics) + - [VPC Link](#vpc-link) + - [Private Integration](#private-integration) + - [WebSocket API](#websocket-api) + - [Manage Connections Permission](#manage-connections-permission) ## Introduction @@ -336,3 +339,21 @@ webSocketApi.addRoute('sendmessage', { }), }); ``` + +### Manage Connections Permission + +Grant permission to use API Gateway Management API of a WebSocket API by calling the `grantManageConnections` API. + +```ts +const lambda = new lambda.Function(this, 'lambda', { /* ... */ }); + +const webSocketApi = new WebSocketApi(stack, 'mywsapi'); +const stage = new WebSocketStage(stack, 'mystage', { + webSocketApi, + stageName: 'dev', +}); +// per stage permission +stage.grantManageConnections(lambda); +// for all the stages permission +webSocketApi.grantManageConnections(lambda); +``` diff --git a/packages/@aws-cdk/aws-apigatewayv2/lib/websocket/api.ts b/packages/@aws-cdk/aws-apigatewayv2/lib/websocket/api.ts index b0cba2f3910dc..ad7bda8628848 100644 --- a/packages/@aws-cdk/aws-apigatewayv2/lib/websocket/api.ts +++ b/packages/@aws-cdk/aws-apigatewayv2/lib/websocket/api.ts @@ -11,13 +11,6 @@ import { WebSocketRoute, WebSocketRouteOptions } from './route'; * Represents a WebSocket API */ export interface IWebSocketApi extends IApi { - /** - * The ARN of the WebSocket API. - * - * @attribute - */ - readonly apiArn: string; - /** * Add a websocket integration * @internal @@ -76,7 +69,6 @@ export interface WebSocketApiProps { export class WebSocketApi extends ApiBase implements IWebSocketApi { public readonly apiId: string; public readonly apiEndpoint: string; - public readonly apiArn: string; /** * A human friendly name for this WebSocket API. Note that this is different from `webSocketApiId`. @@ -96,10 +88,6 @@ export class WebSocketApi extends ApiBase implements IWebSocketApi { }); this.apiId = resource.ref; this.apiEndpoint = resource.attrApiEndpoint; - this.apiArn = Stack.of(this).formatArn({ - service: 'execute-api', - resource: this.apiId, - }); if (props?.connectRouteOptions) { this.addRoute('$connect', props.connectRouteOptions); @@ -148,11 +136,16 @@ export class WebSocketApi extends ApiBase implements IWebSocketApi { * * @param identity The principal */ - public grantManagementApiAccess(identity: IGrantable): Grant { + public grantManageConnections(identity: IGrantable): Grant { + const arn = Stack.of(this).formatArn({ + service: 'execute-api', + resource: this.apiId, + }); + return Grant.addToPrincipal({ grantee: identity, actions: ['execute-api:ManageConnections'], - resourceArns: [`${this.apiArn}/*`], + resourceArns: [`${arn}/*/POST/@connections/*`], }); } } diff --git a/packages/@aws-cdk/aws-apigatewayv2/lib/websocket/stage.ts b/packages/@aws-cdk/aws-apigatewayv2/lib/websocket/stage.ts index 3c20d458e0247..6d5cc8527fef0 100644 --- a/packages/@aws-cdk/aws-apigatewayv2/lib/websocket/stage.ts +++ b/packages/@aws-cdk/aws-apigatewayv2/lib/websocket/stage.ts @@ -123,10 +123,15 @@ export class WebSocketStage extends StageBase implements IWebSocketStage { * @param identity The principal */ public grantManagementApiAccess(identity: IGrantable): Grant { + const arn = Stack.of(this.api).formatArn({ + service: 'execute-api', + resource: this.api.apiId, + }); + return Grant.addToPrincipal({ grantee: identity, actions: ['execute-api:ManageConnections'], - resourceArns: [`${this.api.apiArn}/${this.stageName}/POST/@connections/*`], + resourceArns: [`${arn}/${this.stageName}/POST/@connections/*`], }); } } diff --git a/packages/@aws-cdk/aws-apigatewayv2/test/websocket/api.test.ts b/packages/@aws-cdk/aws-apigatewayv2/test/websocket/api.test.ts index 5b051e24e54fb..dec3195da93ce 100644 --- a/packages/@aws-cdk/aws-apigatewayv2/test/websocket/api.test.ts +++ b/packages/@aws-cdk/aws-apigatewayv2/test/websocket/api.test.ts @@ -82,24 +82,29 @@ describe('WebSocketApi', () => { }); }); - test('grantManagementApiAccess: adds an IAM policy to the principal', () => { - // GIVEN - const stack = new Stack(); - const api = new WebSocketApi(stack, 'api'); - const principal = new User(stack, 'user'); - - // WHEN - api.grantManagementApiAccess(principal); - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { - PolicyDocument: { - Statement: Match.arrayWith([{ - Action: 'execute-api:ManageConnections', - Effect: 'Allow', - Resource: stack.resolve(`${api.apiArn}/*`), - }]), - }, + describe('grantManageConnections', () => { + test('adds an IAM policy to the principal', () => { + // GIVEN + const stack = new Stack(); + const api = new WebSocketApi(stack, 'api'); + const principal = new User(stack, 'user'); + + // WHEN + api.grantManageConnections(principal); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: Match.arrayWith([{ + Action: 'execute-api:ManageConnections', + Effect: 'Allow', + Resource: stack.resolve(`${Stack.of(api).formatArn({ + service: 'execute-api', + resource: api.apiId, + })}/*/POST/@connections/*`), + }]), + }, + }); }); }); }); diff --git a/packages/@aws-cdk/aws-apigatewayv2/test/websocket/stage.test.ts b/packages/@aws-cdk/aws-apigatewayv2/test/websocket/stage.test.ts index 7af7df04c6786..1f5b7cb9f0a51 100644 --- a/packages/@aws-cdk/aws-apigatewayv2/test/websocket/stage.test.ts +++ b/packages/@aws-cdk/aws-apigatewayv2/test/websocket/stage.test.ts @@ -61,28 +61,33 @@ describe('WebSocketStage', () => { expect(defaultStage.callbackUrl.startsWith('https://')).toBe(true); }); - test('grantManagementApiAccess: adds an IAM policy to the principal', () => { - // GIVEN - const stack = new Stack(); - const api = new WebSocketApi(stack, 'Api'); - const defaultStage = new WebSocketStage(stack, 'Stage', { - webSocketApi: api, - stageName: 'dev', - }); - const principal = new User(stack, 'User'); + describe('grantManageConnections', () => { + test('adds an IAM policy to the principal', () => { + // GIVEN + const stack = new Stack(); + const api = new WebSocketApi(stack, 'Api'); + const defaultStage = new WebSocketStage(stack, 'Stage', { + webSocketApi: api, + stageName: 'dev', + }); + const principal = new User(stack, 'User'); - // WHEN - defaultStage.grantManagementApiAccess(principal); + // WHEN + defaultStage.grantManagementApiAccess(principal); - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { - PolicyDocument: { - Statement: Match.arrayWith([{ - Action: 'execute-api:ManageConnections', - Effect: 'Allow', - Resource: stack.resolve(`${api.apiArn}/${defaultStage.stageName}/POST/@connections/*`), - }]), - }, + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: Match.arrayWith([{ + Action: 'execute-api:ManageConnections', + Effect: 'Allow', + Resource: stack.resolve(`${Stack.of(api).formatArn({ + service: 'execute-api', + resource: api.apiId, + })}/${defaultStage.stageName}/POST/@connections/*`), + }]), + }, + }); }); }); }); From adbb0f423f6919421c1354d8a0a064948b49a5d4 Mon Sep 17 00:00:00 2001 From: tmokmss Date: Fri, 29 Oct 2021 01:14:26 +0900 Subject: [PATCH 7/8] Update README.md --- packages/@aws-cdk/aws-apigatewayv2/README.md | 26 +++++++++----------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/packages/@aws-cdk/aws-apigatewayv2/README.md b/packages/@aws-cdk/aws-apigatewayv2/README.md index 1abe466b15af7..85ca73bbb6ccf 100644 --- a/packages/@aws-cdk/aws-apigatewayv2/README.md +++ b/packages/@aws-cdk/aws-apigatewayv2/README.md @@ -28,20 +28,18 @@ Higher level constructs for Websocket APIs | ![Experimental](https://img.shields ## Table of Contents -- [AWS::APIGatewayv2 Construct Library](#awsapigatewayv2-construct-library) - - [Table of Contents](#table-of-contents) - - [Introduction](#introduction) - - [HTTP API](#http-api) - - [Defining HTTP APIs](#defining-http-apis) - - [Cross Origin Resource Sharing (CORS)](#cross-origin-resource-sharing-cors) - - [Publishing HTTP APIs](#publishing-http-apis) - - [Custom Domain](#custom-domain) - - [Managing access](#managing-access) - - [Metrics](#metrics) - - [VPC Link](#vpc-link) - - [Private Integration](#private-integration) - - [WebSocket API](#websocket-api) - - [Manage Connections Permission](#manage-connections-permission) +- [Introduction](#introduction) +- [HTTP API](#http-api) + - [Defining HTTP APIs](#defining-http-apis) + - [Cross Origin Resource Sharing (CORS)](#cross-origin-resource-sharing-cors) + - [Publishing HTTP APIs](#publishing-http-apis) + - [Custom Domain](#custom-domain) + - [Managing access](#managing-access) + - [Metrics](#metrics) + - [VPC Link](#vpc-link) + - [Private Integration](#private-integration) +- [WebSocket API](#websocket-api) + - [Manage Connections Permission](#manage-connections-permission) ## Introduction From c6fb742b444a5f246c8c27ab77f3e423730ea510 Mon Sep 17 00:00:00 2001 From: tmokmss Date: Fri, 29 Oct 2021 22:49:34 +0900 Subject: [PATCH 8/8] fix --- packages/@aws-cdk/aws-apigatewayv2/README.md | 1 + .../test/websocket/api.test.ts | 25 ++++++++++++++++--- .../test/websocket/stage.test.ts | 25 ++++++++++++++++--- 3 files changed, 43 insertions(+), 8 deletions(-) diff --git a/packages/@aws-cdk/aws-apigatewayv2/README.md b/packages/@aws-cdk/aws-apigatewayv2/README.md index 85ca73bbb6ccf..229b151dc2037 100644 --- a/packages/@aws-cdk/aws-apigatewayv2/README.md +++ b/packages/@aws-cdk/aws-apigatewayv2/README.md @@ -341,6 +341,7 @@ webSocketApi.addRoute('sendmessage', { ### Manage Connections Permission Grant permission to use API Gateway Management API of a WebSocket API by calling the `grantManageConnections` API. +You can use Management API to send a callback message to a connected client, get connection information, or disconnect the client. Learn more at [Use @connections commands in your backend service](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-how-to-call-websocket-api-connections.html). ```ts const lambda = new lambda.Function(this, 'lambda', { /* ... */ }); diff --git a/packages/@aws-cdk/aws-apigatewayv2/test/websocket/api.test.ts b/packages/@aws-cdk/aws-apigatewayv2/test/websocket/api.test.ts index dec3195da93ce..24337a3f7c3f2 100644 --- a/packages/@aws-cdk/aws-apigatewayv2/test/websocket/api.test.ts +++ b/packages/@aws-cdk/aws-apigatewayv2/test/websocket/api.test.ts @@ -98,10 +98,27 @@ describe('WebSocketApi', () => { Statement: Match.arrayWith([{ Action: 'execute-api:ManageConnections', Effect: 'Allow', - Resource: stack.resolve(`${Stack.of(api).formatArn({ - service: 'execute-api', - resource: api.apiId, - })}/*/POST/@connections/*`), + Resource: { + 'Fn::Join': ['', [ + 'arn:', + { + Ref: 'AWS::Partition', + }, + ':execute-api:', + { + Ref: 'AWS::Region', + }, + ':', + { + Ref: 'AWS::AccountId', + }, + ':', + { + Ref: 'apiC8550315', + }, + '/*/POST/@connections/*', + ]], + }, }]), }, }); diff --git a/packages/@aws-cdk/aws-apigatewayv2/test/websocket/stage.test.ts b/packages/@aws-cdk/aws-apigatewayv2/test/websocket/stage.test.ts index 1f5b7cb9f0a51..b873f7fa74efa 100644 --- a/packages/@aws-cdk/aws-apigatewayv2/test/websocket/stage.test.ts +++ b/packages/@aws-cdk/aws-apigatewayv2/test/websocket/stage.test.ts @@ -81,10 +81,27 @@ describe('WebSocketStage', () => { Statement: Match.arrayWith([{ Action: 'execute-api:ManageConnections', Effect: 'Allow', - Resource: stack.resolve(`${Stack.of(api).formatArn({ - service: 'execute-api', - resource: api.apiId, - })}/${defaultStage.stageName}/POST/@connections/*`), + Resource: { + 'Fn::Join': ['', [ + 'arn:', + { + Ref: 'AWS::Partition', + }, + ':execute-api:', + { + Ref: 'AWS::Region', + }, + ':', + { + Ref: 'AWS::AccountId', + }, + ':', + { + Ref: 'ApiF70053CD', + }, + `/${defaultStage.stageName}/POST/@connections/*`, + ]], + }, }]), }, });