@aws/nx-plugin 0.62.4 → 0.63.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/py/fast-api/__snapshots__/generator.spec.ts.snap +93 -6
- package/src/py/fast-api/files/app/__name__/init.py.template +20 -5
- package/src/smithy/ts/api/__snapshots__/generator.spec.ts.snap +86 -2
- package/src/smithy/ts/api/files/handler.ts.template +14 -1
- package/src/trpc/backend/__snapshots__/generator.spec.ts.snap +219 -2
- package/src/trpc/backend/files/src/router.ts.template +23 -6
- package/src/utils/api-constructs/files/cdk/app/apis/http/__apiNameKebabCase__.ts.template +45 -0
- package/src/utils/api-constructs/files/cdk/app/apis/rest/__apiNameKebabCase__.ts.template +29 -0
package/package.json
CHANGED
|
@@ -7,11 +7,11 @@ exports[`fastapi project generator > should match snapshot > main-snapshot 1`] =
|
|
|
7
7
|
"apps/test_api/proj_test_api/init.py": "import os
|
|
8
8
|
import uuid
|
|
9
9
|
from collections.abc import Callable
|
|
10
|
+
from urllib.parse import urlparse
|
|
10
11
|
|
|
11
12
|
from aws_lambda_powertools import Logger, Metrics, Tracer
|
|
12
13
|
from aws_lambda_powertools.metrics import MetricUnit
|
|
13
14
|
from fastapi import FastAPI, Request, Response
|
|
14
|
-
from fastapi.middleware.cors import CORSMiddleware
|
|
15
15
|
from fastapi.openapi.utils import get_openapi
|
|
16
16
|
from fastapi.responses import JSONResponse
|
|
17
17
|
from fastapi.routing import APIRoute
|
|
@@ -46,10 +46,25 @@ lambda_handler = logger.inject_lambda_context(lambda_handler, clear_state=True)
|
|
|
46
46
|
lambda_handler = metrics.log_metrics(lambda_handler, capture_cold_start_metric=True)
|
|
47
47
|
|
|
48
48
|
# Add cors middleware
|
|
49
|
-
app.
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
49
|
+
@app.middleware("http")
|
|
50
|
+
async def cors_middleware(request: Request, call_next):
|
|
51
|
+
response = await call_next(request)
|
|
52
|
+
|
|
53
|
+
origin = request.headers.get("origin")
|
|
54
|
+
allowed_origins = os.environ.get('ALLOWED_ORIGINS', '').split(',') if os.environ.get('ALLOWED_ORIGINS') else []
|
|
55
|
+
|
|
56
|
+
is_localhost = origin and urlparse(origin).hostname in ['localhost', '127.0.0.1']
|
|
57
|
+
is_allowed_origin = origin and origin in allowed_origins
|
|
58
|
+
|
|
59
|
+
cors_origin = '*'
|
|
60
|
+
if allowed_origins and not is_localhost:
|
|
61
|
+
cors_origin = origin if is_allowed_origin else allowed_origins[0]
|
|
62
|
+
|
|
63
|
+
response.headers["Access-Control-Allow-Origin"] = cors_origin
|
|
64
|
+
response.headers["Access-Control-Allow-Methods"] = "*"
|
|
65
|
+
response.headers["Access-Control-Allow-Headers"] = "*"
|
|
66
|
+
|
|
67
|
+
return response
|
|
53
68
|
|
|
54
69
|
# Add exception middleware(s)
|
|
55
70
|
app.add_middleware(ExceptionMiddleware, handlers=app.exception_handlers)
|
|
@@ -311,6 +326,7 @@ export class HttpApi<
|
|
|
311
326
|
exports[`fastapi project generator > should set up shared constructs for http > test-api.ts 1`] = `
|
|
312
327
|
"import { Construct } from 'constructs';
|
|
313
328
|
import * as url from 'url';
|
|
329
|
+
import { Distribution } from 'aws-cdk-lib/aws-cloudfront';
|
|
314
330
|
import {
|
|
315
331
|
Code,
|
|
316
332
|
Runtime,
|
|
@@ -319,7 +335,7 @@ import {
|
|
|
319
335
|
Tracing,
|
|
320
336
|
} from 'aws-cdk-lib/aws-lambda';
|
|
321
337
|
import { Duration } from 'aws-cdk-lib';
|
|
322
|
-
import { CorsHttpMethod } from 'aws-cdk-lib/aws-apigatewayv2';
|
|
338
|
+
import { CorsHttpMethod, CfnApi } from 'aws-cdk-lib/aws-apigatewayv2';
|
|
323
339
|
import { HttpIamAuthorizer } from 'aws-cdk-lib/aws-apigatewayv2-authorizers';
|
|
324
340
|
import { HttpLambdaIntegration } from 'aws-cdk-lib/aws-apigatewayv2-integrations';
|
|
325
341
|
import { Grant, IGrantable } from 'aws-cdk-lib/aws-iam';
|
|
@@ -419,6 +435,48 @@ export class TestApi<
|
|
|
419
435
|
});
|
|
420
436
|
}
|
|
421
437
|
|
|
438
|
+
/**
|
|
439
|
+
* Restricts CORS to the website CloudFront distribution domains
|
|
440
|
+
*
|
|
441
|
+
* Configures the CloudFront distribution domains as the only permitted CORS origins
|
|
442
|
+
* (other than local host with default ports) in the API gateway
|
|
443
|
+
* The CORS origins are not configured within the AWS Lambda integrations since
|
|
444
|
+
* the associated header is controlled by API Gateway v2
|
|
445
|
+
*
|
|
446
|
+
* @param cloudFrontDistribution - The CloudFront distribution to grant CORS from
|
|
447
|
+
*/
|
|
448
|
+
public restrictCorsTo(
|
|
449
|
+
...websites: { cloudFrontDistribution: Distribution }[]
|
|
450
|
+
) {
|
|
451
|
+
const allowedOrigins = websites.map(
|
|
452
|
+
({ cloudFrontDistribution }) =>
|
|
453
|
+
\`https://\${cloudFrontDistribution.distributionDomainName}\`,
|
|
454
|
+
);
|
|
455
|
+
|
|
456
|
+
const cfnApi = this.api.node.defaultChild;
|
|
457
|
+
if (!(cfnApi instanceof CfnApi)) {
|
|
458
|
+
throw new Error(
|
|
459
|
+
'Unable to configure CORS: API default child is not a CfnApi instance',
|
|
460
|
+
);
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
cfnApi.corsConfiguration = {
|
|
464
|
+
allowOrigins: [
|
|
465
|
+
'http://localhost:4200',
|
|
466
|
+
'http://localhost:4300',
|
|
467
|
+
...allowedOrigins,
|
|
468
|
+
],
|
|
469
|
+
allowMethods: [CorsHttpMethod.ANY],
|
|
470
|
+
allowHeaders: [
|
|
471
|
+
'authorization',
|
|
472
|
+
'content-type',
|
|
473
|
+
'x-amz-content-sha256',
|
|
474
|
+
'x-amz-date',
|
|
475
|
+
'x-amz-security-token',
|
|
476
|
+
],
|
|
477
|
+
};
|
|
478
|
+
}
|
|
479
|
+
|
|
422
480
|
/**
|
|
423
481
|
* Grants IAM permissions to invoke any method on this API.
|
|
424
482
|
*
|
|
@@ -801,6 +859,7 @@ export class RestApi<
|
|
|
801
859
|
exports[`fastapi project generator > should set up shared constructs for rest > test-api.ts 1`] = `
|
|
802
860
|
"import { Construct } from 'constructs';
|
|
803
861
|
import * as url from 'url';
|
|
862
|
+
import { Distribution } from 'aws-cdk-lib/aws-cloudfront';
|
|
804
863
|
import {
|
|
805
864
|
Code,
|
|
806
865
|
Runtime,
|
|
@@ -921,6 +980,34 @@ export class TestApi<
|
|
|
921
980
|
});
|
|
922
981
|
}
|
|
923
982
|
|
|
983
|
+
/**
|
|
984
|
+
* Restricts CORS to the website CloudFront distribution domains
|
|
985
|
+
*
|
|
986
|
+
* Configures the CloudFront distribution domains as the only permitted CORS origins
|
|
987
|
+
* (other than local host) in the AWS Lambda integrations
|
|
988
|
+
*
|
|
989
|
+
* Note that this restriction is not applied to preflight OPTIONS
|
|
990
|
+
*
|
|
991
|
+
* @param websites - The CloudFront distribution to grant CORS from
|
|
992
|
+
*/
|
|
993
|
+
public restrictCorsTo(
|
|
994
|
+
...websites: { cloudFrontDistribution: Distribution }[]
|
|
995
|
+
) {
|
|
996
|
+
const allowedOrigins = websites
|
|
997
|
+
.map(
|
|
998
|
+
({ cloudFrontDistribution }) =>
|
|
999
|
+
\`https://\${cloudFrontDistribution.distributionDomainName}\`,
|
|
1000
|
+
)
|
|
1001
|
+
.join(',');
|
|
1002
|
+
|
|
1003
|
+
// Set ALLOWED_ORIGINS environment variable for all Lambda integrations
|
|
1004
|
+
Object.values(this.integrations).forEach((integration) => {
|
|
1005
|
+
if ('handler' in integration && integration.handler instanceof Function) {
|
|
1006
|
+
integration.handler.addEnvironment('ALLOWED_ORIGINS', allowedOrigins);
|
|
1007
|
+
}
|
|
1008
|
+
});
|
|
1009
|
+
}
|
|
1010
|
+
|
|
924
1011
|
/**
|
|
925
1012
|
* Grants IAM permissions to invoke any method on this API.
|
|
926
1013
|
*
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import uuid
|
|
3
3
|
from collections.abc import Callable
|
|
4
|
+
from urllib.parse import urlparse
|
|
4
5
|
|
|
5
6
|
from aws_lambda_powertools import Logger, Metrics, Tracer
|
|
6
7
|
from aws_lambda_powertools.metrics import MetricUnit
|
|
7
8
|
from fastapi import FastAPI, Request, Response
|
|
8
|
-
from fastapi.middleware.cors import CORSMiddleware
|
|
9
9
|
from fastapi.openapi.utils import get_openapi
|
|
10
10
|
from fastapi.responses import JSONResponse
|
|
11
11
|
from fastapi.routing import APIRoute
|
|
@@ -40,10 +40,25 @@ lambda_handler = logger.inject_lambda_context(lambda_handler, clear_state=True)
|
|
|
40
40
|
lambda_handler = metrics.log_metrics(lambda_handler, capture_cold_start_metric=True)
|
|
41
41
|
|
|
42
42
|
# Add cors middleware
|
|
43
|
-
app.
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
43
|
+
@app.middleware("http")
|
|
44
|
+
async def cors_middleware(request: Request, call_next):
|
|
45
|
+
response = await call_next(request)
|
|
46
|
+
|
|
47
|
+
origin = request.headers.get("origin")
|
|
48
|
+
allowed_origins = os.environ.get('ALLOWED_ORIGINS', '').split(',') if os.environ.get('ALLOWED_ORIGINS') else []
|
|
49
|
+
|
|
50
|
+
is_localhost = origin and urlparse(origin).hostname in ['localhost', '127.0.0.1']
|
|
51
|
+
is_allowed_origin = origin and origin in allowed_origins
|
|
52
|
+
|
|
53
|
+
cors_origin = '*'
|
|
54
|
+
if allowed_origins and not is_localhost:
|
|
55
|
+
cors_origin = origin if is_allowed_origin else allowed_origins[0]
|
|
56
|
+
|
|
57
|
+
response.headers["Access-Control-Allow-Origin"] = cors_origin
|
|
58
|
+
response.headers["Access-Control-Allow-Methods"] = "*"
|
|
59
|
+
response.headers["Access-Control-Allow-Headers"] = "*"
|
|
60
|
+
|
|
61
|
+
return response
|
|
47
62
|
|
|
48
63
|
# Add exception middleware(s)
|
|
49
64
|
app.add_middleware(ExceptionMiddleware, handlers=app.exception_handlers)
|
|
@@ -34,6 +34,7 @@ exports[`tsSmithyApiGenerator > should configure git and eslint ignores for gene
|
|
|
34
34
|
exports[`tsSmithyApiGenerator > should generate smithy ts api with Cognito auth > cognito-auth-infra.ts 1`] = `
|
|
35
35
|
"import { Construct } from 'constructs';
|
|
36
36
|
import * as url from 'url';
|
|
37
|
+
import { Distribution } from 'aws-cdk-lib/aws-cloudfront';
|
|
37
38
|
import {
|
|
38
39
|
Code,
|
|
39
40
|
Runtime,
|
|
@@ -162,6 +163,34 @@ export class TestApi<
|
|
|
162
163
|
...props,
|
|
163
164
|
});
|
|
164
165
|
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Restricts CORS to the website CloudFront distribution domains
|
|
169
|
+
*
|
|
170
|
+
* Configures the CloudFront distribution domains as the only permitted CORS origins
|
|
171
|
+
* (other than local host) in the AWS Lambda integrations
|
|
172
|
+
*
|
|
173
|
+
* Note that this restriction is not applied to preflight OPTIONS
|
|
174
|
+
*
|
|
175
|
+
* @param websites - The CloudFront distribution to grant CORS from
|
|
176
|
+
*/
|
|
177
|
+
public restrictCorsTo(
|
|
178
|
+
...websites: { cloudFrontDistribution: Distribution }[]
|
|
179
|
+
) {
|
|
180
|
+
const allowedOrigins = websites
|
|
181
|
+
.map(
|
|
182
|
+
({ cloudFrontDistribution }) =>
|
|
183
|
+
\`https://\${cloudFrontDistribution.distributionDomainName}\`,
|
|
184
|
+
)
|
|
185
|
+
.join(',');
|
|
186
|
+
|
|
187
|
+
// Set ALLOWED_ORIGINS environment variable for all Lambda integrations
|
|
188
|
+
Object.values(this.integrations).forEach((integration) => {
|
|
189
|
+
if ('handler' in integration && integration.handler instanceof Function) {
|
|
190
|
+
integration.handler.addEnvironment('ALLOWED_ORIGINS', allowedOrigins);
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
}
|
|
165
194
|
}
|
|
166
195
|
"
|
|
167
196
|
`;
|
|
@@ -169,6 +198,7 @@ export class TestApi<
|
|
|
169
198
|
exports[`tsSmithyApiGenerator > should generate smithy ts api with IAM auth > iam-auth-infra.ts 1`] = `
|
|
170
199
|
"import { Construct } from 'constructs';
|
|
171
200
|
import * as url from 'url';
|
|
201
|
+
import { Distribution } from 'aws-cdk-lib/aws-cloudfront';
|
|
172
202
|
import {
|
|
173
203
|
Code,
|
|
174
204
|
Runtime,
|
|
@@ -289,6 +319,34 @@ export class TestApi<
|
|
|
289
319
|
});
|
|
290
320
|
}
|
|
291
321
|
|
|
322
|
+
/**
|
|
323
|
+
* Restricts CORS to the website CloudFront distribution domains
|
|
324
|
+
*
|
|
325
|
+
* Configures the CloudFront distribution domains as the only permitted CORS origins
|
|
326
|
+
* (other than local host) in the AWS Lambda integrations
|
|
327
|
+
*
|
|
328
|
+
* Note that this restriction is not applied to preflight OPTIONS
|
|
329
|
+
*
|
|
330
|
+
* @param websites - The CloudFront distribution to grant CORS from
|
|
331
|
+
*/
|
|
332
|
+
public restrictCorsTo(
|
|
333
|
+
...websites: { cloudFrontDistribution: Distribution }[]
|
|
334
|
+
) {
|
|
335
|
+
const allowedOrigins = websites
|
|
336
|
+
.map(
|
|
337
|
+
({ cloudFrontDistribution }) =>
|
|
338
|
+
\`https://\${cloudFrontDistribution.distributionDomainName}\`,
|
|
339
|
+
)
|
|
340
|
+
.join(',');
|
|
341
|
+
|
|
342
|
+
// Set ALLOWED_ORIGINS environment variable for all Lambda integrations
|
|
343
|
+
Object.values(this.integrations).forEach((integration) => {
|
|
344
|
+
if ('handler' in integration && integration.handler instanceof Function) {
|
|
345
|
+
integration.handler.addEnvironment('ALLOWED_ORIGINS', allowedOrigins);
|
|
346
|
+
}
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
|
|
292
350
|
/**
|
|
293
351
|
* Grants IAM permissions to invoke any method on this API.
|
|
294
352
|
*
|
|
@@ -1110,13 +1168,26 @@ export const lambdaHandler = async (
|
|
|
1110
1168
|
return {
|
|
1111
1169
|
...apiGatewayResponse,
|
|
1112
1170
|
headers: {
|
|
1113
|
-
'Access-Control-Allow-Origin':
|
|
1171
|
+
'Access-Control-Allow-Origin': getAllowedOrigin(event),
|
|
1114
1172
|
'Access-Control-Allow-Methods': '*',
|
|
1115
1173
|
...apiGatewayResponse.headers,
|
|
1116
1174
|
},
|
|
1117
1175
|
};
|
|
1118
1176
|
};
|
|
1119
1177
|
|
|
1178
|
+
const getAllowedOrigin = (event: APIGatewayProxyEvent) => {
|
|
1179
|
+
const origin = event.headers?.origin ?? event.headers?.Origin;
|
|
1180
|
+
const allowedOrigins = process.env.ALLOWED_ORIGINS?.split(',') ?? [];
|
|
1181
|
+
const isLocalHost =
|
|
1182
|
+
origin && new Set(['localhost', '127.0.0.1']).has(new URL(origin).hostname);
|
|
1183
|
+
const isAllowedOrigin = origin && allowedOrigins.includes(origin);
|
|
1184
|
+
let corsOrigin = '*';
|
|
1185
|
+
if (allowedOrigins.length > 0 && !isLocalHost) {
|
|
1186
|
+
corsOrigin = isAllowedOrigin ? origin : allowedOrigins[0];
|
|
1187
|
+
}
|
|
1188
|
+
return corsOrigin;
|
|
1189
|
+
};
|
|
1190
|
+
|
|
1120
1191
|
export const handler = middy<APIGatewayProxyEvent, APIGatewayProxyResult>()
|
|
1121
1192
|
.use(captureLambdaHandler(tracer))
|
|
1122
1193
|
.use(injectLambdaContext(logger))
|
|
@@ -1255,13 +1326,26 @@ export const lambdaHandler = async (
|
|
|
1255
1326
|
return {
|
|
1256
1327
|
...apiGatewayResponse,
|
|
1257
1328
|
headers: {
|
|
1258
|
-
'Access-Control-Allow-Origin':
|
|
1329
|
+
'Access-Control-Allow-Origin': getAllowedOrigin(event),
|
|
1259
1330
|
'Access-Control-Allow-Methods': '*',
|
|
1260
1331
|
...apiGatewayResponse.headers,
|
|
1261
1332
|
},
|
|
1262
1333
|
};
|
|
1263
1334
|
};
|
|
1264
1335
|
|
|
1336
|
+
const getAllowedOrigin = (event: APIGatewayProxyEvent) => {
|
|
1337
|
+
const origin = event.headers?.origin ?? event.headers?.Origin;
|
|
1338
|
+
const allowedOrigins = process.env.ALLOWED_ORIGINS?.split(',') ?? [];
|
|
1339
|
+
const isLocalHost =
|
|
1340
|
+
origin && new Set(['localhost', '127.0.0.1']).has(new URL(origin).hostname);
|
|
1341
|
+
const isAllowedOrigin = origin && allowedOrigins.includes(origin);
|
|
1342
|
+
let corsOrigin = '*';
|
|
1343
|
+
if (allowedOrigins.length > 0 && !isLocalHost) {
|
|
1344
|
+
corsOrigin = isAllowedOrigin ? origin : allowedOrigins[0];
|
|
1345
|
+
}
|
|
1346
|
+
return corsOrigin;
|
|
1347
|
+
};
|
|
1348
|
+
|
|
1265
1349
|
export const handler = middy<APIGatewayProxyEvent, APIGatewayProxyResult>()
|
|
1266
1350
|
.use(captureLambdaHandler(tracer))
|
|
1267
1351
|
.use(injectLambdaContext(logger))
|
|
@@ -36,13 +36,26 @@ export const lambdaHandler = async (
|
|
|
36
36
|
return {
|
|
37
37
|
...apiGatewayResponse,
|
|
38
38
|
headers: {
|
|
39
|
-
'Access-Control-Allow-Origin':
|
|
39
|
+
'Access-Control-Allow-Origin': getAllowedOrigin(event),
|
|
40
40
|
'Access-Control-Allow-Methods': '*',
|
|
41
41
|
...apiGatewayResponse.headers,
|
|
42
42
|
},
|
|
43
43
|
};
|
|
44
44
|
};
|
|
45
45
|
|
|
46
|
+
const getAllowedOrigin = (event: APIGatewayProxyEvent) => {
|
|
47
|
+
const origin = event.headers?.origin ?? event.headers?.Origin;
|
|
48
|
+
const allowedOrigins = process.env.ALLOWED_ORIGINS?.split(',') ?? [];
|
|
49
|
+
const isLocalHost =
|
|
50
|
+
origin && new Set(['localhost', '127.0.0.1']).has(new URL(origin).hostname);
|
|
51
|
+
const isAllowedOrigin = origin && allowedOrigins.includes(origin);
|
|
52
|
+
let corsOrigin = '*';
|
|
53
|
+
if (allowedOrigins.length > 0 && !isLocalHost) {
|
|
54
|
+
corsOrigin = isAllowedOrigin ? origin : allowedOrigins[0];
|
|
55
|
+
}
|
|
56
|
+
return corsOrigin;
|
|
57
|
+
};
|
|
58
|
+
|
|
46
59
|
export const handler = middy<APIGatewayProxyEvent, APIGatewayProxyResult>()
|
|
47
60
|
.use(captureLambdaHandler(tracer))
|
|
48
61
|
.use(injectLambdaContext(logger))
|
|
@@ -347,6 +347,7 @@ exports[`trpc backend generator > should generate with cognito auth for a REST A
|
|
|
347
347
|
exports[`trpc backend generator > should generate with cognito auth for a REST API > packages/common/constructs/src/app/apis/test-api.ts 1`] = `
|
|
348
348
|
"import { Construct } from 'constructs';
|
|
349
349
|
import * as url from 'url';
|
|
350
|
+
import { Distribution } from 'aws-cdk-lib/aws-cloudfront';
|
|
350
351
|
import {
|
|
351
352
|
Code,
|
|
352
353
|
Runtime,
|
|
@@ -476,6 +477,34 @@ export class TestApi<
|
|
|
476
477
|
...props,
|
|
477
478
|
});
|
|
478
479
|
}
|
|
480
|
+
|
|
481
|
+
/**
|
|
482
|
+
* Restricts CORS to the website CloudFront distribution domains
|
|
483
|
+
*
|
|
484
|
+
* Configures the CloudFront distribution domains as the only permitted CORS origins
|
|
485
|
+
* (other than local host) in the AWS Lambda integrations
|
|
486
|
+
*
|
|
487
|
+
* Note that this restriction is not applied to preflight OPTIONS
|
|
488
|
+
*
|
|
489
|
+
* @param websites - The CloudFront distribution to grant CORS from
|
|
490
|
+
*/
|
|
491
|
+
public restrictCorsTo(
|
|
492
|
+
...websites: { cloudFrontDistribution: Distribution }[]
|
|
493
|
+
) {
|
|
494
|
+
const allowedOrigins = websites
|
|
495
|
+
.map(
|
|
496
|
+
({ cloudFrontDistribution }) =>
|
|
497
|
+
\`https://\${cloudFrontDistribution.distributionDomainName}\`,
|
|
498
|
+
)
|
|
499
|
+
.join(',');
|
|
500
|
+
|
|
501
|
+
// Set ALLOWED_ORIGINS environment variable for all Lambda integrations
|
|
502
|
+
Object.values(this.integrations).forEach((integration) => {
|
|
503
|
+
if ('handler' in integration && integration.handler instanceof Function) {
|
|
504
|
+
integration.handler.addEnvironment('ALLOWED_ORIGINS', allowedOrigins);
|
|
505
|
+
}
|
|
506
|
+
});
|
|
507
|
+
}
|
|
479
508
|
}
|
|
480
509
|
"
|
|
481
510
|
`;
|
|
@@ -511,6 +540,7 @@ exports[`trpc backend generator > should generate with cognito auth for an HTTP
|
|
|
511
540
|
exports[`trpc backend generator > should generate with cognito auth for an HTTP API > packages/common/constructs/src/app/apis/test-api.ts 1`] = `
|
|
512
541
|
"import { Construct } from 'constructs';
|
|
513
542
|
import * as url from 'url';
|
|
543
|
+
import { Distribution } from 'aws-cdk-lib/aws-cloudfront';
|
|
514
544
|
import {
|
|
515
545
|
Code,
|
|
516
546
|
Runtime,
|
|
@@ -519,7 +549,7 @@ import {
|
|
|
519
549
|
Tracing,
|
|
520
550
|
} from 'aws-cdk-lib/aws-lambda';
|
|
521
551
|
import { Duration } from 'aws-cdk-lib';
|
|
522
|
-
import { CorsHttpMethod } from 'aws-cdk-lib/aws-apigatewayv2';
|
|
552
|
+
import { CorsHttpMethod, CfnApi } from 'aws-cdk-lib/aws-apigatewayv2';
|
|
523
553
|
import { HttpUserPoolAuthorizer } from 'aws-cdk-lib/aws-apigatewayv2-authorizers';
|
|
524
554
|
import { HttpLambdaIntegration } from 'aws-cdk-lib/aws-apigatewayv2-integrations';
|
|
525
555
|
import { IUserPool, IUserPoolClient } from 'aws-cdk-lib/aws-cognito';
|
|
@@ -632,6 +662,48 @@ export class TestApi<
|
|
|
632
662
|
...props,
|
|
633
663
|
});
|
|
634
664
|
}
|
|
665
|
+
|
|
666
|
+
/**
|
|
667
|
+
* Restricts CORS to the website CloudFront distribution domains
|
|
668
|
+
*
|
|
669
|
+
* Configures the CloudFront distribution domains as the only permitted CORS origins
|
|
670
|
+
* (other than local host with default ports) in the API gateway
|
|
671
|
+
* The CORS origins are not configured within the AWS Lambda integrations since
|
|
672
|
+
* the associated header is controlled by API Gateway v2
|
|
673
|
+
*
|
|
674
|
+
* @param cloudFrontDistribution - The CloudFront distribution to grant CORS from
|
|
675
|
+
*/
|
|
676
|
+
public restrictCorsTo(
|
|
677
|
+
...websites: { cloudFrontDistribution: Distribution }[]
|
|
678
|
+
) {
|
|
679
|
+
const allowedOrigins = websites.map(
|
|
680
|
+
({ cloudFrontDistribution }) =>
|
|
681
|
+
\`https://\${cloudFrontDistribution.distributionDomainName}\`,
|
|
682
|
+
);
|
|
683
|
+
|
|
684
|
+
const cfnApi = this.api.node.defaultChild;
|
|
685
|
+
if (!(cfnApi instanceof CfnApi)) {
|
|
686
|
+
throw new Error(
|
|
687
|
+
'Unable to configure CORS: API default child is not a CfnApi instance',
|
|
688
|
+
);
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
cfnApi.corsConfiguration = {
|
|
692
|
+
allowOrigins: [
|
|
693
|
+
'http://localhost:4200',
|
|
694
|
+
'http://localhost:4300',
|
|
695
|
+
...allowedOrigins,
|
|
696
|
+
],
|
|
697
|
+
allowMethods: [CorsHttpMethod.ANY],
|
|
698
|
+
allowHeaders: [
|
|
699
|
+
'authorization',
|
|
700
|
+
'content-type',
|
|
701
|
+
'x-amz-content-sha256',
|
|
702
|
+
'x-amz-date',
|
|
703
|
+
'x-amz-security-token',
|
|
704
|
+
],
|
|
705
|
+
};
|
|
706
|
+
}
|
|
635
707
|
}
|
|
636
708
|
"
|
|
637
709
|
`;
|
|
@@ -663,6 +735,7 @@ exports[`trpc backend generator > should generate with no auth for a REST API >
|
|
|
663
735
|
exports[`trpc backend generator > should generate with no auth for a REST API > packages/common/constructs/src/app/apis/test-api.ts 1`] = `
|
|
664
736
|
"import { Construct } from 'constructs';
|
|
665
737
|
import * as url from 'url';
|
|
738
|
+
import { Distribution } from 'aws-cdk-lib/aws-cloudfront';
|
|
666
739
|
import {
|
|
667
740
|
Code,
|
|
668
741
|
Runtime,
|
|
@@ -781,6 +854,34 @@ export class TestApi<
|
|
|
781
854
|
...props,
|
|
782
855
|
});
|
|
783
856
|
}
|
|
857
|
+
|
|
858
|
+
/**
|
|
859
|
+
* Restricts CORS to the website CloudFront distribution domains
|
|
860
|
+
*
|
|
861
|
+
* Configures the CloudFront distribution domains as the only permitted CORS origins
|
|
862
|
+
* (other than local host) in the AWS Lambda integrations
|
|
863
|
+
*
|
|
864
|
+
* Note that this restriction is not applied to preflight OPTIONS
|
|
865
|
+
*
|
|
866
|
+
* @param websites - The CloudFront distribution to grant CORS from
|
|
867
|
+
*/
|
|
868
|
+
public restrictCorsTo(
|
|
869
|
+
...websites: { cloudFrontDistribution: Distribution }[]
|
|
870
|
+
) {
|
|
871
|
+
const allowedOrigins = websites
|
|
872
|
+
.map(
|
|
873
|
+
({ cloudFrontDistribution }) =>
|
|
874
|
+
\`https://\${cloudFrontDistribution.distributionDomainName}\`,
|
|
875
|
+
)
|
|
876
|
+
.join(',');
|
|
877
|
+
|
|
878
|
+
// Set ALLOWED_ORIGINS environment variable for all Lambda integrations
|
|
879
|
+
Object.values(this.integrations).forEach((integration) => {
|
|
880
|
+
if ('handler' in integration && integration.handler instanceof Function) {
|
|
881
|
+
integration.handler.addEnvironment('ALLOWED_ORIGINS', allowedOrigins);
|
|
882
|
+
}
|
|
883
|
+
});
|
|
884
|
+
}
|
|
784
885
|
}
|
|
785
886
|
"
|
|
786
887
|
`;
|
|
@@ -812,6 +913,7 @@ exports[`trpc backend generator > should generate with no auth for an HTTP API >
|
|
|
812
913
|
exports[`trpc backend generator > should generate with no auth for an HTTP API > packages/common/constructs/src/app/apis/test-api.ts 1`] = `
|
|
813
914
|
"import { Construct } from 'constructs';
|
|
814
915
|
import * as url from 'url';
|
|
916
|
+
import { Distribution } from 'aws-cdk-lib/aws-cloudfront';
|
|
815
917
|
import {
|
|
816
918
|
Code,
|
|
817
919
|
Runtime,
|
|
@@ -822,6 +924,7 @@ import {
|
|
|
822
924
|
import { Duration } from 'aws-cdk-lib';
|
|
823
925
|
import {
|
|
824
926
|
CorsHttpMethod,
|
|
927
|
+
CfnApi,
|
|
825
928
|
HttpNoneAuthorizer,
|
|
826
929
|
} from 'aws-cdk-lib/aws-apigatewayv2';
|
|
827
930
|
import { HttpLambdaIntegration } from 'aws-cdk-lib/aws-apigatewayv2-integrations';
|
|
@@ -921,6 +1024,48 @@ export class TestApi<
|
|
|
921
1024
|
...props,
|
|
922
1025
|
});
|
|
923
1026
|
}
|
|
1027
|
+
|
|
1028
|
+
/**
|
|
1029
|
+
* Restricts CORS to the website CloudFront distribution domains
|
|
1030
|
+
*
|
|
1031
|
+
* Configures the CloudFront distribution domains as the only permitted CORS origins
|
|
1032
|
+
* (other than local host with default ports) in the API gateway
|
|
1033
|
+
* The CORS origins are not configured within the AWS Lambda integrations since
|
|
1034
|
+
* the associated header is controlled by API Gateway v2
|
|
1035
|
+
*
|
|
1036
|
+
* @param cloudFrontDistribution - The CloudFront distribution to grant CORS from
|
|
1037
|
+
*/
|
|
1038
|
+
public restrictCorsTo(
|
|
1039
|
+
...websites: { cloudFrontDistribution: Distribution }[]
|
|
1040
|
+
) {
|
|
1041
|
+
const allowedOrigins = websites.map(
|
|
1042
|
+
({ cloudFrontDistribution }) =>
|
|
1043
|
+
\`https://\${cloudFrontDistribution.distributionDomainName}\`,
|
|
1044
|
+
);
|
|
1045
|
+
|
|
1046
|
+
const cfnApi = this.api.node.defaultChild;
|
|
1047
|
+
if (!(cfnApi instanceof CfnApi)) {
|
|
1048
|
+
throw new Error(
|
|
1049
|
+
'Unable to configure CORS: API default child is not a CfnApi instance',
|
|
1050
|
+
);
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
cfnApi.corsConfiguration = {
|
|
1054
|
+
allowOrigins: [
|
|
1055
|
+
'http://localhost:4200',
|
|
1056
|
+
'http://localhost:4300',
|
|
1057
|
+
...allowedOrigins,
|
|
1058
|
+
],
|
|
1059
|
+
allowMethods: [CorsHttpMethod.ANY],
|
|
1060
|
+
allowHeaders: [
|
|
1061
|
+
'authorization',
|
|
1062
|
+
'content-type',
|
|
1063
|
+
'x-amz-content-sha256',
|
|
1064
|
+
'x-amz-date',
|
|
1065
|
+
'x-amz-security-token',
|
|
1066
|
+
],
|
|
1067
|
+
};
|
|
1068
|
+
}
|
|
924
1069
|
}
|
|
925
1070
|
"
|
|
926
1071
|
`;
|
|
@@ -1065,6 +1210,7 @@ export class HttpApi<
|
|
|
1065
1210
|
exports[`trpc backend generator > should set up shared constructs for http > test-api.ts 1`] = `
|
|
1066
1211
|
"import { Construct } from 'constructs';
|
|
1067
1212
|
import * as url from 'url';
|
|
1213
|
+
import { Distribution } from 'aws-cdk-lib/aws-cloudfront';
|
|
1068
1214
|
import {
|
|
1069
1215
|
Code,
|
|
1070
1216
|
Runtime,
|
|
@@ -1073,7 +1219,7 @@ import {
|
|
|
1073
1219
|
Tracing,
|
|
1074
1220
|
} from 'aws-cdk-lib/aws-lambda';
|
|
1075
1221
|
import { Duration } from 'aws-cdk-lib';
|
|
1076
|
-
import { CorsHttpMethod } from 'aws-cdk-lib/aws-apigatewayv2';
|
|
1222
|
+
import { CorsHttpMethod, CfnApi } from 'aws-cdk-lib/aws-apigatewayv2';
|
|
1077
1223
|
import { HttpIamAuthorizer } from 'aws-cdk-lib/aws-apigatewayv2-authorizers';
|
|
1078
1224
|
import { HttpLambdaIntegration } from 'aws-cdk-lib/aws-apigatewayv2-integrations';
|
|
1079
1225
|
import { Grant, IGrantable } from 'aws-cdk-lib/aws-iam';
|
|
@@ -1174,6 +1320,48 @@ export class TestApi<
|
|
|
1174
1320
|
});
|
|
1175
1321
|
}
|
|
1176
1322
|
|
|
1323
|
+
/**
|
|
1324
|
+
* Restricts CORS to the website CloudFront distribution domains
|
|
1325
|
+
*
|
|
1326
|
+
* Configures the CloudFront distribution domains as the only permitted CORS origins
|
|
1327
|
+
* (other than local host with default ports) in the API gateway
|
|
1328
|
+
* The CORS origins are not configured within the AWS Lambda integrations since
|
|
1329
|
+
* the associated header is controlled by API Gateway v2
|
|
1330
|
+
*
|
|
1331
|
+
* @param cloudFrontDistribution - The CloudFront distribution to grant CORS from
|
|
1332
|
+
*/
|
|
1333
|
+
public restrictCorsTo(
|
|
1334
|
+
...websites: { cloudFrontDistribution: Distribution }[]
|
|
1335
|
+
) {
|
|
1336
|
+
const allowedOrigins = websites.map(
|
|
1337
|
+
({ cloudFrontDistribution }) =>
|
|
1338
|
+
\`https://\${cloudFrontDistribution.distributionDomainName}\`,
|
|
1339
|
+
);
|
|
1340
|
+
|
|
1341
|
+
const cfnApi = this.api.node.defaultChild;
|
|
1342
|
+
if (!(cfnApi instanceof CfnApi)) {
|
|
1343
|
+
throw new Error(
|
|
1344
|
+
'Unable to configure CORS: API default child is not a CfnApi instance',
|
|
1345
|
+
);
|
|
1346
|
+
}
|
|
1347
|
+
|
|
1348
|
+
cfnApi.corsConfiguration = {
|
|
1349
|
+
allowOrigins: [
|
|
1350
|
+
'http://localhost:4200',
|
|
1351
|
+
'http://localhost:4300',
|
|
1352
|
+
...allowedOrigins,
|
|
1353
|
+
],
|
|
1354
|
+
allowMethods: [CorsHttpMethod.ANY],
|
|
1355
|
+
allowHeaders: [
|
|
1356
|
+
'authorization',
|
|
1357
|
+
'content-type',
|
|
1358
|
+
'x-amz-content-sha256',
|
|
1359
|
+
'x-amz-date',
|
|
1360
|
+
'x-amz-security-token',
|
|
1361
|
+
],
|
|
1362
|
+
};
|
|
1363
|
+
}
|
|
1364
|
+
|
|
1177
1365
|
/**
|
|
1178
1366
|
* Grants IAM permissions to invoke any method on this API.
|
|
1179
1367
|
*
|
|
@@ -1627,6 +1815,7 @@ export class RestApi<
|
|
|
1627
1815
|
exports[`trpc backend generator > should set up shared constructs for rest > test-api.ts 1`] = `
|
|
1628
1816
|
"import { Construct } from 'constructs';
|
|
1629
1817
|
import * as url from 'url';
|
|
1818
|
+
import { Distribution } from 'aws-cdk-lib/aws-cloudfront';
|
|
1630
1819
|
import {
|
|
1631
1820
|
Code,
|
|
1632
1821
|
Runtime,
|
|
@@ -1748,6 +1937,34 @@ export class TestApi<
|
|
|
1748
1937
|
});
|
|
1749
1938
|
}
|
|
1750
1939
|
|
|
1940
|
+
/**
|
|
1941
|
+
* Restricts CORS to the website CloudFront distribution domains
|
|
1942
|
+
*
|
|
1943
|
+
* Configures the CloudFront distribution domains as the only permitted CORS origins
|
|
1944
|
+
* (other than local host) in the AWS Lambda integrations
|
|
1945
|
+
*
|
|
1946
|
+
* Note that this restriction is not applied to preflight OPTIONS
|
|
1947
|
+
*
|
|
1948
|
+
* @param websites - The CloudFront distribution to grant CORS from
|
|
1949
|
+
*/
|
|
1950
|
+
public restrictCorsTo(
|
|
1951
|
+
...websites: { cloudFrontDistribution: Distribution }[]
|
|
1952
|
+
) {
|
|
1953
|
+
const allowedOrigins = websites
|
|
1954
|
+
.map(
|
|
1955
|
+
({ cloudFrontDistribution }) =>
|
|
1956
|
+
\`https://\${cloudFrontDistribution.distributionDomainName}\`,
|
|
1957
|
+
)
|
|
1958
|
+
.join(',');
|
|
1959
|
+
|
|
1960
|
+
// Set ALLOWED_ORIGINS environment variable for all Lambda integrations
|
|
1961
|
+
Object.values(this.integrations).forEach((integration) => {
|
|
1962
|
+
if ('handler' in integration && integration.handler instanceof Function) {
|
|
1963
|
+
integration.handler.addEnvironment('ALLOWED_ORIGINS', allowedOrigins);
|
|
1964
|
+
}
|
|
1965
|
+
});
|
|
1966
|
+
}
|
|
1967
|
+
|
|
1751
1968
|
/**
|
|
1752
1969
|
* Grants IAM permissions to invoke any method on this API.
|
|
1753
1970
|
*
|
|
@@ -16,13 +16,30 @@ export const handler = awsLambdaRequestHandler({
|
|
|
16
16
|
router: appRouter,
|
|
17
17
|
createContext: (ctx: CreateAWSLambdaContextOptions<<%- apiGatewayEventType %>>) => ctx,
|
|
18
18
|
<%_ if (computeType === 'ServerlessApiGatewayRestApi') { _%>
|
|
19
|
-
responseMeta: () =>
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
19
|
+
responseMeta: ({ ctx }) => {
|
|
20
|
+
return {
|
|
21
|
+
headers: {
|
|
22
|
+
'Access-Control-Allow-Origin': getAllowedOrigin(ctx?.event),
|
|
23
|
+
'Access-Control-Allow-Methods': '*',
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
},
|
|
25
27
|
<%_ } _%>
|
|
26
28
|
});
|
|
27
29
|
|
|
30
|
+
<%_ if (computeType === 'ServerlessApiGatewayRestApi') { _%>
|
|
31
|
+
const getAllowedOrigin = (event: <%- apiGatewayEventType %> | undefined) => {
|
|
32
|
+
const origin = event?.headers?.origin ?? event?.headers?.Origin;
|
|
33
|
+
const allowedOrigins = process.env.ALLOWED_ORIGINS?.split(',') ?? [];
|
|
34
|
+
const isLocalHost =
|
|
35
|
+
origin && new Set(['localhost', '127.0.0.1']).has(new URL(origin).hostname);
|
|
36
|
+
const isAllowedOrigin = origin && allowedOrigins.includes(origin);
|
|
37
|
+
let corsOrigin = '*';
|
|
38
|
+
if (allowedOrigins.length > 0 && !isLocalHost) {
|
|
39
|
+
corsOrigin = isAllowedOrigin ? origin : allowedOrigins[0];
|
|
40
|
+
}
|
|
41
|
+
return corsOrigin;
|
|
42
|
+
};
|
|
43
|
+
<%_ } _%>
|
|
44
|
+
|
|
28
45
|
export type AppRouter = typeof appRouter;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Construct } from 'constructs';
|
|
2
2
|
import * as url from 'url';
|
|
3
|
+
import { Distribution } from 'aws-cdk-lib/aws-cloudfront';
|
|
3
4
|
import {
|
|
4
5
|
Code,
|
|
5
6
|
Runtime,
|
|
@@ -10,6 +11,7 @@ import {
|
|
|
10
11
|
import { Duration } from 'aws-cdk-lib';
|
|
11
12
|
import {
|
|
12
13
|
CorsHttpMethod,
|
|
14
|
+
CfnApi,
|
|
13
15
|
<%_ if (auth === 'None') { _%>
|
|
14
16
|
HttpNoneAuthorizer,
|
|
15
17
|
<%_ } _%>
|
|
@@ -168,6 +170,49 @@ export class <%= apiNameClassName %><
|
|
|
168
170
|
...props,
|
|
169
171
|
});
|
|
170
172
|
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Restricts CORS to the website CloudFront distribution domains
|
|
176
|
+
*
|
|
177
|
+
* Configures the CloudFront distribution domains as the only permitted CORS origins
|
|
178
|
+
* (other than local host with default ports) in the API gateway
|
|
179
|
+
* The CORS origins are not configured within the AWS Lambda integrations since
|
|
180
|
+
* the associated header is controlled by API Gateway v2
|
|
181
|
+
*
|
|
182
|
+
* @param cloudFrontDistribution - The CloudFront distribution to grant CORS from
|
|
183
|
+
*/
|
|
184
|
+
public restrictCorsTo(
|
|
185
|
+
...websites: { cloudFrontDistribution: Distribution }[]
|
|
186
|
+
) {
|
|
187
|
+
const allowedOrigins = websites
|
|
188
|
+
.map(
|
|
189
|
+
({ cloudFrontDistribution }) =>
|
|
190
|
+
`https://${cloudFrontDistribution.distributionDomainName}`,
|
|
191
|
+
);
|
|
192
|
+
|
|
193
|
+
const cfnApi = this.api.node.defaultChild;
|
|
194
|
+
if (!(cfnApi instanceof CfnApi)) {
|
|
195
|
+
throw new Error(
|
|
196
|
+
'Unable to configure CORS: API default child is not a CfnApi instance',
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
cfnApi.corsConfiguration = {
|
|
201
|
+
allowOrigins: [
|
|
202
|
+
'http://localhost:4200',
|
|
203
|
+
'http://localhost:4300',
|
|
204
|
+
...allowedOrigins,
|
|
205
|
+
],
|
|
206
|
+
allowMethods: [CorsHttpMethod.ANY],
|
|
207
|
+
allowHeaders: [
|
|
208
|
+
'authorization',
|
|
209
|
+
'content-type',
|
|
210
|
+
'x-amz-content-sha256',
|
|
211
|
+
'x-amz-date',
|
|
212
|
+
'x-amz-security-token',
|
|
213
|
+
],
|
|
214
|
+
};
|
|
215
|
+
}
|
|
171
216
|
<%_ if (auth === 'IAM') { _%>
|
|
172
217
|
|
|
173
218
|
/**
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Construct } from 'constructs';
|
|
2
2
|
import * as url from 'url';
|
|
3
|
+
import { Distribution } from 'aws-cdk-lib/aws-cloudfront';
|
|
3
4
|
import {
|
|
4
5
|
Code,
|
|
5
6
|
Runtime,
|
|
@@ -183,6 +184,34 @@ export class <%= apiNameClassName %><
|
|
|
183
184
|
...props,
|
|
184
185
|
});
|
|
185
186
|
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Restricts CORS to the website CloudFront distribution domains
|
|
190
|
+
*
|
|
191
|
+
* Configures the CloudFront distribution domains as the only permitted CORS origins
|
|
192
|
+
* (other than local host) in the AWS Lambda integrations
|
|
193
|
+
*
|
|
194
|
+
* Note that this restriction is not applied to preflight OPTIONS
|
|
195
|
+
*
|
|
196
|
+
* @param websites - The CloudFront distribution to grant CORS from
|
|
197
|
+
*/
|
|
198
|
+
public restrictCorsTo(
|
|
199
|
+
...websites: { cloudFrontDistribution: Distribution }[]
|
|
200
|
+
) {
|
|
201
|
+
const allowedOrigins = websites
|
|
202
|
+
.map(
|
|
203
|
+
({ cloudFrontDistribution }) =>
|
|
204
|
+
`https://${cloudFrontDistribution.distributionDomainName}`,
|
|
205
|
+
)
|
|
206
|
+
.join(',');
|
|
207
|
+
|
|
208
|
+
// Set ALLOWED_ORIGINS environment variable for all Lambda integrations
|
|
209
|
+
Object.values(this.integrations).forEach((integration) => {
|
|
210
|
+
if ('handler' in integration && integration.handler instanceof Function) {
|
|
211
|
+
integration.handler.addEnvironment('ALLOWED_ORIGINS', allowedOrigins);
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
}
|
|
186
215
|
<%_ if (auth === 'IAM') { _%>
|
|
187
216
|
|
|
188
217
|
/**
|