@gradientedge/cdk-utils 8.113.0 → 8.115.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/dist/src/lib/construct/api-to-any-target/index.d.ts +3 -0
- package/dist/src/lib/construct/api-to-any-target/index.js +19 -0
- package/dist/src/lib/construct/api-to-any-target/main.d.ts +48 -0
- package/dist/src/lib/construct/api-to-any-target/main.js +159 -0
- package/dist/src/lib/construct/api-to-any-target/target.d.ts +23 -0
- package/dist/src/lib/construct/api-to-any-target/target.js +18 -0
- package/dist/src/lib/construct/api-to-any-target/types.d.ts +57 -0
- package/dist/src/lib/construct/api-to-any-target/types.js +2 -0
- package/dist/src/lib/construct/index.d.ts +1 -0
- package/dist/src/lib/construct/index.js +1 -0
- package/dist/src/lib/construct/site-with-ecs-backend/main.d.ts +3 -2
- package/dist/src/lib/construct/site-with-ecs-backend/main.js +17 -13
- package/dist/src/lib/services/aws/api-gateway/main.d.ts +3 -1
- package/package.json +17 -17
- package/src/lib/construct/api-to-any-target/index.ts +3 -0
- package/src/lib/construct/api-to-any-target/main.ts +225 -0
- package/src/lib/construct/api-to-any-target/target.ts +29 -0
- package/src/lib/construct/api-to-any-target/types.ts +66 -0
- package/src/lib/construct/index.ts +1 -0
- package/src/lib/construct/site-with-ecs-backend/main.ts +17 -13
- package/src/lib/services/aws/api-gateway/main.ts +1 -1
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./main"), exports);
|
|
18
|
+
__exportStar(require("./target"), exports);
|
|
19
|
+
__exportStar(require("./types"), exports);
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { Resource } from 'aws-cdk-lib/aws-apigateway';
|
|
2
|
+
import { ISecret } from 'aws-cdk-lib/aws-secretsmanager';
|
|
3
|
+
import { Construct } from 'constructs';
|
|
4
|
+
import { CommonConstruct } from '../../common';
|
|
5
|
+
import { ApiToAnyTargetProps, ApiToAnyTargetRestApiResource, ApiToAnyTargetRestApiType } from './types';
|
|
6
|
+
/**
|
|
7
|
+
* @classdesc Provides a construct to create and deploy a shallow API Gateway
|
|
8
|
+
* @example
|
|
9
|
+
* import { ApiToAnyTarget, ApiToAnyTargetProps } '@gradientedge/cdk-utils'
|
|
10
|
+
* import { Construct } from 'constructs'
|
|
11
|
+
*
|
|
12
|
+
* class CustomConstruct extends ApiToAnyTarget {
|
|
13
|
+
* constructor(parent: Construct, id: string, props: ApiToAnyTargetProps) {
|
|
14
|
+
* super(parent, id, props)
|
|
15
|
+
* this.props = props
|
|
16
|
+
* this.id = id
|
|
17
|
+
* this.initResources()
|
|
18
|
+
* }
|
|
19
|
+
* }
|
|
20
|
+
*/
|
|
21
|
+
export declare class ApiToAnyTarget extends CommonConstruct {
|
|
22
|
+
props: ApiToAnyTargetProps;
|
|
23
|
+
id: string;
|
|
24
|
+
applicationSecrets: ISecret[];
|
|
25
|
+
apiToAnyTargetRestApi: ApiToAnyTargetRestApiType;
|
|
26
|
+
apiResource: string;
|
|
27
|
+
constructor(parent: Construct, id: string, props: ApiToAnyTargetProps);
|
|
28
|
+
protected initResources(): void;
|
|
29
|
+
/**
|
|
30
|
+
* @summary Method to resolve secrets from SecretsManager
|
|
31
|
+
* - To be implemented in the overriding method in the implementation class
|
|
32
|
+
*/
|
|
33
|
+
protected resolveSecrets(): void;
|
|
34
|
+
/**
|
|
35
|
+
* @summary Method to resolve a hosted zone based on domain attributes
|
|
36
|
+
*/
|
|
37
|
+
protected resolveHostedZone(): void;
|
|
38
|
+
/**
|
|
39
|
+
* @summary Method to resolve a certificate based on attributes
|
|
40
|
+
*/
|
|
41
|
+
protected resolveCertificate(): void;
|
|
42
|
+
protected createApiToAnyTargetRestApiLogGroup(): void;
|
|
43
|
+
protected createApiToAnyTargetRestApi(): void;
|
|
44
|
+
protected createApiToAnyTargetResource(apiResourceProps: ApiToAnyTargetRestApiResource): Resource | undefined;
|
|
45
|
+
protected createApiDomain(): void;
|
|
46
|
+
protected createApiBasePathMapping(): void;
|
|
47
|
+
protected createApiRouteAssets(): void;
|
|
48
|
+
}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ApiToAnyTarget = void 0;
|
|
4
|
+
const aws_cdk_lib_1 = require("aws-cdk-lib");
|
|
5
|
+
const aws_apigateway_1 = require("aws-cdk-lib/aws-apigateway");
|
|
6
|
+
const common_1 = require("../../common");
|
|
7
|
+
const target_1 = require("./target");
|
|
8
|
+
/**
|
|
9
|
+
* @classdesc Provides a construct to create and deploy a shallow API Gateway
|
|
10
|
+
* @example
|
|
11
|
+
* import { ApiToAnyTarget, ApiToAnyTargetProps } '@gradientedge/cdk-utils'
|
|
12
|
+
* import { Construct } from 'constructs'
|
|
13
|
+
*
|
|
14
|
+
* class CustomConstruct extends ApiToAnyTarget {
|
|
15
|
+
* constructor(parent: Construct, id: string, props: ApiToAnyTargetProps) {
|
|
16
|
+
* super(parent, id, props)
|
|
17
|
+
* this.props = props
|
|
18
|
+
* this.id = id
|
|
19
|
+
* this.initResources()
|
|
20
|
+
* }
|
|
21
|
+
* }
|
|
22
|
+
*/
|
|
23
|
+
class ApiToAnyTarget extends common_1.CommonConstruct {
|
|
24
|
+
props;
|
|
25
|
+
id;
|
|
26
|
+
/* application related resources */
|
|
27
|
+
applicationSecrets;
|
|
28
|
+
/* rest restApi related resources */
|
|
29
|
+
apiToAnyTargetRestApi;
|
|
30
|
+
apiResource;
|
|
31
|
+
constructor(parent, id, props) {
|
|
32
|
+
super(parent, id, props);
|
|
33
|
+
this.props = props;
|
|
34
|
+
this.id = id;
|
|
35
|
+
this.apiToAnyTargetRestApi = new target_1.ApiToAnyTargetRestApi();
|
|
36
|
+
}
|
|
37
|
+
initResources() {
|
|
38
|
+
/* application related resources */
|
|
39
|
+
this.resolveSecrets();
|
|
40
|
+
/* core resources */
|
|
41
|
+
this.resolveHostedZone();
|
|
42
|
+
this.resolveCertificate();
|
|
43
|
+
/* restApi related resources */
|
|
44
|
+
this.createApiToAnyTargetRestApiLogGroup();
|
|
45
|
+
this.createApiToAnyTargetRestApi();
|
|
46
|
+
this.createApiDomain();
|
|
47
|
+
this.createApiBasePathMapping();
|
|
48
|
+
this.createApiRouteAssets();
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* @summary Method to resolve secrets from SecretsManager
|
|
52
|
+
* - To be implemented in the overriding method in the implementation class
|
|
53
|
+
*/
|
|
54
|
+
resolveSecrets() {
|
|
55
|
+
this.applicationSecrets = [];
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* @summary Method to resolve a hosted zone based on domain attributes
|
|
59
|
+
*/
|
|
60
|
+
resolveHostedZone() {
|
|
61
|
+
this.apiToAnyTargetRestApi.hostedZone = this.route53Manager.withHostedZoneFromFullyQualifiedDomainName(`${this.id}-hosted-zone`, this, this.props.useExistingHostedZone);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* @summary Method to resolve a certificate based on attributes
|
|
65
|
+
*/
|
|
66
|
+
resolveCertificate() {
|
|
67
|
+
if (this.props.api.useExisting)
|
|
68
|
+
return;
|
|
69
|
+
if (this.props.api.certificate.useExistingCertificate &&
|
|
70
|
+
this.props.api.certificate.certificateSsmName &&
|
|
71
|
+
this.props.api.certificate.certificateRegion) {
|
|
72
|
+
this.props.api.certificate.certificateArn = this.ssmManager.readStringParameterFromRegion(`${this.id}-certificate-param`, this, this.props.api.certificate.certificateSsmName, this.props.api.certificate.certificateRegion);
|
|
73
|
+
}
|
|
74
|
+
this.apiToAnyTargetRestApi.certificate = this.acmManager.resolveCertificate(`${this.id}-certificate`, this, this.props.api.certificate);
|
|
75
|
+
}
|
|
76
|
+
createApiToAnyTargetRestApiLogGroup() {
|
|
77
|
+
this.apiToAnyTargetRestApi.accessLogGroup = this.logManager.createLogGroup(`${this.id}-rest-api-access-log`, this, {
|
|
78
|
+
logGroupName: `/custom/api/${this.id}-rest-api-access`,
|
|
79
|
+
removalPolicy: aws_cdk_lib_1.RemovalPolicy.DESTROY,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
createApiToAnyTargetRestApi() {
|
|
83
|
+
if (this.props.api.useExisting && this.props.api.importedRestApiRef) {
|
|
84
|
+
this.apiToAnyTargetRestApi.api = aws_apigateway_1.RestApi.fromRestApiId(this, `${this.id}-rest-api`, aws_cdk_lib_1.Fn.importValue(this.props.api.importedRestApiRef));
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
this.apiToAnyTargetRestApi.api = new aws_apigateway_1.RestApi(this, `${this.id}-rest-api`, {
|
|
88
|
+
...{
|
|
89
|
+
cloudWatchRole: this.props.api.restApi?.cloudWatchRole ?? true,
|
|
90
|
+
defaultCorsPreflightOptions: {
|
|
91
|
+
allowHeaders: aws_apigateway_1.Cors.DEFAULT_HEADERS,
|
|
92
|
+
allowMethods: aws_apigateway_1.Cors.ALL_METHODS,
|
|
93
|
+
allowOrigins: aws_apigateway_1.Cors.ALL_ORIGINS,
|
|
94
|
+
},
|
|
95
|
+
defaultIntegration: this.apiToAnyTargetRestApi.integration,
|
|
96
|
+
defaultMethodOptions: {
|
|
97
|
+
methodResponses: [this.apiToAnyTargetRestApi.methodResponse, this.apiToAnyTargetRestApi.methodErrorResponse],
|
|
98
|
+
},
|
|
99
|
+
deploy: this.props.api.restApi?.deploy ?? true,
|
|
100
|
+
deployOptions: {
|
|
101
|
+
accessLogDestination: new aws_apigateway_1.LogGroupLogDestination(this.apiToAnyTargetRestApi.accessLogGroup),
|
|
102
|
+
accessLogFormat: aws_apigateway_1.AccessLogFormat.jsonWithStandardFields(),
|
|
103
|
+
dataTraceEnabled: this.props.api.restApi?.deployOptions?.dataTraceEnabled,
|
|
104
|
+
description: `${this.id} - ${this.props.stage} stage`,
|
|
105
|
+
loggingLevel: aws_apigateway_1.MethodLoggingLevel.INFO,
|
|
106
|
+
metricsEnabled: true,
|
|
107
|
+
stageName: this.props.stage,
|
|
108
|
+
tracingEnabled: this.props.api.restApi?.deployOptions?.tracingEnabled,
|
|
109
|
+
},
|
|
110
|
+
endpointConfiguration: {
|
|
111
|
+
types: [this.isProductionStage() ? aws_apigateway_1.EndpointType.EDGE : aws_apigateway_1.EndpointType.REGIONAL],
|
|
112
|
+
},
|
|
113
|
+
restApiName: `${this.id}-rest-api-${this.props.stage}`,
|
|
114
|
+
},
|
|
115
|
+
...this.props.api.restApi,
|
|
116
|
+
});
|
|
117
|
+
this.addCfnOutput(`${this.id}-restApiId`, this.apiToAnyTargetRestApi.api.restApiId);
|
|
118
|
+
this.addCfnOutput(`${this.id}-restApiRootResourceId`, this.apiToAnyTargetRestApi.api.root.resourceId);
|
|
119
|
+
}
|
|
120
|
+
createApiToAnyTargetResource(apiResourceProps) {
|
|
121
|
+
if (!this.props.api.withResource)
|
|
122
|
+
return;
|
|
123
|
+
let rootResource;
|
|
124
|
+
if (this.props.api.withResource && this.props.api.importedRestApiRootResourceRef) {
|
|
125
|
+
rootResource = aws_apigateway_1.Resource.fromResourceAttributes(this, `${this.id}-root-resource-for-${apiResourceProps.path}`, {
|
|
126
|
+
path: '/',
|
|
127
|
+
resourceId: aws_cdk_lib_1.Fn.importValue(this.props.api.importedRestApiRootResourceRef),
|
|
128
|
+
restApi: this.apiToAnyTargetRestApi.api,
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
rootResource = this.apiToAnyTargetRestApi.api.root;
|
|
133
|
+
}
|
|
134
|
+
return this.apiManager.createApiResource(`${this.id}-resource-${apiResourceProps.path}}`, this, apiResourceProps.parent ?? rootResource, apiResourceProps.path, apiResourceProps.integration, apiResourceProps.addProxy, apiResourceProps.authorizer, apiResourceProps.allowedOrigins, apiResourceProps.allowedMethods, apiResourceProps.allowedHeaders, apiResourceProps.methodRequestParameters, apiResourceProps.proxyIntegration);
|
|
135
|
+
}
|
|
136
|
+
createApiDomain() {
|
|
137
|
+
if (this.props.api.useExisting)
|
|
138
|
+
return;
|
|
139
|
+
this.apiToAnyTargetRestApi.domain = this.apiManager.createApiDomain(`${this.id}-api-domain`, this, this.isProductionStage() || this.props.skipStageForARecords
|
|
140
|
+
? `${this.props.apiSubDomain}.${this.fullyQualifiedDomainName}`
|
|
141
|
+
: `${this.props.apiSubDomain}-${this.props.stage}.${this.fullyQualifiedDomainName}`, this.apiToAnyTargetRestApi.certificate);
|
|
142
|
+
}
|
|
143
|
+
createApiBasePathMapping() {
|
|
144
|
+
if (this.props.api.useExisting)
|
|
145
|
+
return;
|
|
146
|
+
new aws_apigateway_1.BasePathMapping(this, `${this.id}-base-bath-mapping`, {
|
|
147
|
+
basePath: '',
|
|
148
|
+
domainName: this.apiToAnyTargetRestApi.domain,
|
|
149
|
+
restApi: this.apiToAnyTargetRestApi.api,
|
|
150
|
+
stage: this.apiToAnyTargetRestApi.api.deploymentStage,
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
createApiRouteAssets() {
|
|
154
|
+
if (this.props.api.useExisting)
|
|
155
|
+
return;
|
|
156
|
+
this.route53Manager.createApiGatewayARecord(`${this.id}-custom-domain-a-record`, this, this.props.apiSubDomain, this.apiToAnyTargetRestApi.domain, this.apiToAnyTargetRestApi.hostedZone, this.props.skipStageForARecords);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
exports.ApiToAnyTarget = ApiToAnyTarget;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { IRestApi, IAuthorizer, BasePathMapping, DomainName, Integration, Method, MethodResponse, Resource } from 'aws-cdk-lib/aws-apigateway';
|
|
2
|
+
import { ICertificate } from 'aws-cdk-lib/aws-certificatemanager';
|
|
3
|
+
import { LogGroup } from 'aws-cdk-lib/aws-logs';
|
|
4
|
+
import { IHostedZone } from 'aws-cdk-lib/aws-route53';
|
|
5
|
+
import { ApiToAnyTargetRestApiType } from './types';
|
|
6
|
+
export declare class ApiToAnyTargetRestApi implements ApiToAnyTargetRestApiType {
|
|
7
|
+
accessLogGroup: LogGroup;
|
|
8
|
+
api: IRestApi;
|
|
9
|
+
authoriser?: IAuthorizer;
|
|
10
|
+
basePathMappings: BasePathMapping[];
|
|
11
|
+
certificate: ICertificate;
|
|
12
|
+
domain: DomainName;
|
|
13
|
+
hostedZone: IHostedZone;
|
|
14
|
+
integration: Integration;
|
|
15
|
+
method: {
|
|
16
|
+
[httpMethod: string]: Method;
|
|
17
|
+
};
|
|
18
|
+
methodErrorResponse: MethodResponse;
|
|
19
|
+
methodResponse: MethodResponse;
|
|
20
|
+
resource: {
|
|
21
|
+
[path: string]: Resource;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ApiToAnyTargetRestApi = void 0;
|
|
4
|
+
class ApiToAnyTargetRestApi {
|
|
5
|
+
accessLogGroup;
|
|
6
|
+
api;
|
|
7
|
+
authoriser;
|
|
8
|
+
basePathMappings;
|
|
9
|
+
certificate;
|
|
10
|
+
domain;
|
|
11
|
+
hostedZone;
|
|
12
|
+
integration;
|
|
13
|
+
method;
|
|
14
|
+
methodErrorResponse;
|
|
15
|
+
methodResponse;
|
|
16
|
+
resource;
|
|
17
|
+
}
|
|
18
|
+
exports.ApiToAnyTargetRestApi = ApiToAnyTargetRestApi;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { BasePathMapping, DomainName, IAuthorizer, IResource, IRestApi, Integration, Method, MethodResponse, Resource, RestApiProps } from 'aws-cdk-lib/aws-apigateway';
|
|
2
|
+
import { ICertificate } from 'aws-cdk-lib/aws-certificatemanager';
|
|
3
|
+
import { LogGroup } from 'aws-cdk-lib/aws-logs';
|
|
4
|
+
import { IHostedZone } from 'aws-cdk-lib/aws-route53';
|
|
5
|
+
import { CommonStackProps } from '../../common';
|
|
6
|
+
import { AcmProps } from '../../services';
|
|
7
|
+
export interface ApiToAnyTargetRestApiType {
|
|
8
|
+
accessLogGroup: LogGroup;
|
|
9
|
+
api: IRestApi;
|
|
10
|
+
authoriser?: IAuthorizer;
|
|
11
|
+
basePathMappings: BasePathMapping[];
|
|
12
|
+
certificate: ICertificate;
|
|
13
|
+
domain: DomainName;
|
|
14
|
+
hostedZone: IHostedZone;
|
|
15
|
+
integration: Integration;
|
|
16
|
+
method: {
|
|
17
|
+
[httpMethod: string]: Method;
|
|
18
|
+
};
|
|
19
|
+
methodErrorResponse: MethodResponse;
|
|
20
|
+
methodResponse: MethodResponse;
|
|
21
|
+
resource: {
|
|
22
|
+
[path: string]: Resource;
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
export interface ApiToAnyTargetRestApiResource {
|
|
26
|
+
addProxy: boolean;
|
|
27
|
+
authorizer?: IAuthorizer;
|
|
28
|
+
allowedOrigins?: string[];
|
|
29
|
+
allowedMethods?: string[];
|
|
30
|
+
allowedHeaders?: string[];
|
|
31
|
+
integration: Integration;
|
|
32
|
+
methodRequestParameters?: {
|
|
33
|
+
[param: string]: boolean;
|
|
34
|
+
};
|
|
35
|
+
path: string;
|
|
36
|
+
parent?: IResource;
|
|
37
|
+
proxyIntegration?: Integration;
|
|
38
|
+
}
|
|
39
|
+
export interface ApiToAnyTargetRestApiProps {
|
|
40
|
+
certificate: AcmProps;
|
|
41
|
+
importedRestApiRef?: string;
|
|
42
|
+
importedRestApiRootResourceRef?: string;
|
|
43
|
+
methodErrorResponse: MethodResponse;
|
|
44
|
+
methodResponse: MethodResponse;
|
|
45
|
+
restApi: RestApiProps;
|
|
46
|
+
useExisting: boolean;
|
|
47
|
+
withResource?: boolean;
|
|
48
|
+
}
|
|
49
|
+
export interface ApiToAnyTargetProps extends CommonStackProps {
|
|
50
|
+
api: ApiToAnyTargetRestApiProps;
|
|
51
|
+
apiRootPaths?: string[];
|
|
52
|
+
apiSubDomain: string;
|
|
53
|
+
logLevel: string;
|
|
54
|
+
nodeEnv: string;
|
|
55
|
+
timezone: string;
|
|
56
|
+
useExistingHostedZone: boolean;
|
|
57
|
+
}
|
|
@@ -14,6 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./api-to-any-target"), exports);
|
|
17
18
|
__exportStar(require("./api-to-eventbridge-target"), exports);
|
|
18
19
|
__exportStar(require("./api-to-eventbridge-target-with-sns"), exports);
|
|
19
20
|
__exportStar(require("./api-to-lambda-target"), exports);
|
|
@@ -12,7 +12,7 @@ import * as s3 from 'aws-cdk-lib/aws-s3';
|
|
|
12
12
|
import * as efs from 'aws-cdk-lib/aws-efs';
|
|
13
13
|
import { Construct } from 'constructs';
|
|
14
14
|
import { CommonConstruct } from '../../common';
|
|
15
|
-
import { SiteWithEcsBackendProps, SiteResponseHeadersPolicyProps } from './types';
|
|
15
|
+
import { SiteWithEcsBackendProps, SiteResponseHeadersPolicyProps, SiteCachePolicyProps } from './types';
|
|
16
16
|
/**
|
|
17
17
|
* @classdesc Provides a construct to create and deploy a site hosted with an clustered ECS/ELB backend
|
|
18
18
|
* @example
|
|
@@ -126,7 +126,8 @@ export declare class SiteWithEcsBackend extends CommonConstruct {
|
|
|
126
126
|
* Method to create log bucket for site distribution
|
|
127
127
|
*/
|
|
128
128
|
protected createSiteLogBucket(): void;
|
|
129
|
-
protected
|
|
129
|
+
protected createSiteCachePolicy(id: string, siteCachePolicy: SiteCachePolicyProps): cdk.aws_cloudfront.CachePolicy;
|
|
130
|
+
protected createSiteOriginCachePolicy(): void;
|
|
130
131
|
protected createSiteOriginRequestPolicy(): void;
|
|
131
132
|
protected createResponseHeaderPolicy(props: SiteResponseHeadersPolicyProps): cdk.aws_cloudfront.ResponseHeadersPolicy | undefined;
|
|
132
133
|
protected createSiteOriginResponseHeadersPolicy(): void;
|
|
@@ -104,7 +104,7 @@ class SiteWithEcsBackend extends common_1.CommonConstruct {
|
|
|
104
104
|
this.createEcsBuildArgs();
|
|
105
105
|
this.createEcsContainerImage();
|
|
106
106
|
this.createEcsService();
|
|
107
|
-
this.
|
|
107
|
+
this.createSiteOriginCachePolicy();
|
|
108
108
|
this.createSiteOriginRequestPolicy();
|
|
109
109
|
this.createSiteOriginResponseHeadersPolicy();
|
|
110
110
|
this.createSiteOrigin();
|
|
@@ -347,20 +347,23 @@ class SiteWithEcsBackend extends common_1.CommonConstruct {
|
|
|
347
347
|
createSiteLogBucket() {
|
|
348
348
|
this.siteLogBucket = this.s3Manager.createS3Bucket(`${this.id}-site-logs`, this, this.props.siteLogBucket);
|
|
349
349
|
}
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
this.siteCachePolicy = new cloudfront.CachePolicy(this, `${this.id}-site-cache-policy`, {
|
|
354
|
-
cachePolicyName: `${this.id}-site-cache-policy`,
|
|
350
|
+
createSiteCachePolicy(id, siteCachePolicy) {
|
|
351
|
+
return new cloudfront.CachePolicy(this, `${id}`, {
|
|
352
|
+
cachePolicyName: `${this.id}-${siteCachePolicy.cachePolicyName}`,
|
|
355
353
|
comment: `Policy for ${this.id}-distribution - ${this.props.stage} stage`,
|
|
356
|
-
defaultTtl: cdk.Duration.seconds(
|
|
357
|
-
minTtl: cdk.Duration.seconds(
|
|
358
|
-
maxTtl: cdk.Duration.seconds(
|
|
359
|
-
enableAcceptEncodingGzip:
|
|
360
|
-
queryStringBehavior:
|
|
361
|
-
headerBehavior:
|
|
362
|
-
cookieBehavior:
|
|
354
|
+
defaultTtl: cdk.Duration.seconds(siteCachePolicy.defaultTtlInSeconds),
|
|
355
|
+
minTtl: cdk.Duration.seconds(siteCachePolicy.minTtlInSeconds),
|
|
356
|
+
maxTtl: cdk.Duration.seconds(siteCachePolicy.maxTtlInSeconds),
|
|
357
|
+
enableAcceptEncodingGzip: siteCachePolicy.enableAcceptEncodingGzip,
|
|
358
|
+
queryStringBehavior: siteCachePolicy.queryStringBehavior,
|
|
359
|
+
headerBehavior: siteCachePolicy.headerBehavior,
|
|
360
|
+
cookieBehavior: siteCachePolicy.cookieBehavior,
|
|
363
361
|
});
|
|
362
|
+
}
|
|
363
|
+
createSiteOriginCachePolicy() {
|
|
364
|
+
if (!this.props.siteCachePolicy)
|
|
365
|
+
return;
|
|
366
|
+
this.siteCachePolicy = this.createSiteCachePolicy(`${this.id}-site-cache-policy`, this.props.siteCachePolicy);
|
|
364
367
|
_.assign(this.props.siteDistribution.defaultBehavior, {
|
|
365
368
|
cachePolicy: this.siteCachePolicy,
|
|
366
369
|
});
|
|
@@ -387,6 +390,7 @@ class SiteWithEcsBackend extends common_1.CommonConstruct {
|
|
|
387
390
|
comment: `Response Header Policy for ${props.type} for ${this.id}-distribution - ${this.props.stage} stage`,
|
|
388
391
|
responseHeadersPolicyName: `${this.id}-${props.type}-response`,
|
|
389
392
|
securityHeadersBehavior: {
|
|
393
|
+
...props.securityHeadersBehavior,
|
|
390
394
|
strictTransportSecurity: {
|
|
391
395
|
...props.securityHeadersBehavior?.strictTransportSecurity,
|
|
392
396
|
accessControlMaxAge: cdk.Duration.seconds(props.securityHeadersBehavior?.strictTransportSecurity?.accessControlMaxAgeInSeconds),
|
|
@@ -52,7 +52,9 @@ export declare class ApiManager {
|
|
|
52
52
|
* @param methodRequestParameters
|
|
53
53
|
* @param proxyIntegration
|
|
54
54
|
*/
|
|
55
|
-
createApiResource(id: string, scope: CommonConstruct, parent: apig.IResource, path: string, integration: apig.Integration, addProxy: boolean, authorizer?: apig.IAuthorizer, allowedOrigins?: string[], allowedMethods?: string[], allowedHeaders?: string[], methodRequestParameters?:
|
|
55
|
+
createApiResource(id: string, scope: CommonConstruct, parent: apig.IResource, path: string, integration: apig.Integration, addProxy: boolean, authorizer?: apig.IAuthorizer, allowedOrigins?: string[], allowedMethods?: string[], allowedHeaders?: string[], methodRequestParameters?: {
|
|
56
|
+
[param: string]: boolean;
|
|
57
|
+
}, proxyIntegration?: apig.Integration): apig.Resource;
|
|
56
58
|
/**
|
|
57
59
|
* @summary Method to create an api deployment
|
|
58
60
|
* @param id
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gradientedge/cdk-utils",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.115.0",
|
|
4
4
|
"description": "Utilities for AWS CDK provisioning",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"engines": {
|
|
@@ -46,14 +46,14 @@
|
|
|
46
46
|
}
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@aws-sdk/client-secrets-manager": "^3.
|
|
50
|
-
"@aws-sdk/credential-providers": "^3.
|
|
51
|
-
"@aws-sdk/types": "^3.
|
|
52
|
-
"@types/lodash": "^4.14.
|
|
53
|
-
"@types/node": "^20.
|
|
49
|
+
"@aws-sdk/client-secrets-manager": "^3.395.0",
|
|
50
|
+
"@aws-sdk/credential-providers": "^3.395.0",
|
|
51
|
+
"@aws-sdk/types": "^3.391.0",
|
|
52
|
+
"@types/lodash": "^4.14.197",
|
|
53
|
+
"@types/node": "^20.5.1",
|
|
54
54
|
"@types/uuid": "^9.0.2",
|
|
55
55
|
"app-root-path": "^3.1.0",
|
|
56
|
-
"aws-cdk-lib": "^2.
|
|
56
|
+
"aws-cdk-lib": "^2.92.0",
|
|
57
57
|
"constructs": "^10.2.69",
|
|
58
58
|
"lodash": "^4.17.21",
|
|
59
59
|
"moment": "^2.29.4",
|
|
@@ -63,22 +63,22 @@
|
|
|
63
63
|
"uuid": "^9.0.0"
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|
|
66
|
-
"@babel/core": "^7.22.
|
|
67
|
-
"@babel/eslint-parser": "^7.22.
|
|
66
|
+
"@babel/core": "^7.22.10",
|
|
67
|
+
"@babel/eslint-parser": "^7.22.10",
|
|
68
68
|
"@babel/plugin-proposal-class-properties": "^7.18.6",
|
|
69
69
|
"@types/jest": "^29.5.3",
|
|
70
|
-
"@typescript-eslint/eslint-plugin": "^6.
|
|
71
|
-
"@typescript-eslint/parser": "^6.
|
|
72
|
-
"aws-cdk": "^2.
|
|
70
|
+
"@typescript-eslint/eslint-plugin": "^6.4.0",
|
|
71
|
+
"@typescript-eslint/parser": "^6.4.0",
|
|
72
|
+
"aws-cdk": "^2.92.0",
|
|
73
73
|
"better-docs": "^2.7.2",
|
|
74
74
|
"codecov": "^3.8.3",
|
|
75
75
|
"commitizen": "^4.3.0",
|
|
76
76
|
"docdash": "^2.0.1",
|
|
77
77
|
"dotenv": "^16.3.1",
|
|
78
|
-
"eslint": "^8.
|
|
78
|
+
"eslint": "^8.47.0",
|
|
79
79
|
"eslint-config-prettier": "^9.0.0",
|
|
80
|
-
"eslint-plugin-import": "^2.28.
|
|
81
|
-
"eslint-plugin-jsdoc": "^46.
|
|
80
|
+
"eslint-plugin-import": "^2.28.1",
|
|
81
|
+
"eslint-plugin-jsdoc": "^46.5.0",
|
|
82
82
|
"husky": "^8.0.3",
|
|
83
83
|
"jest": "^29.6.2",
|
|
84
84
|
"jest-extended": "^4.0.1",
|
|
@@ -88,10 +88,10 @@
|
|
|
88
88
|
"jsdoc-mermaid": "^1.0.0",
|
|
89
89
|
"jsdoc-plugin-typescript": "^2.2.1",
|
|
90
90
|
"jsdoc-to-markdown": "^8.0.0",
|
|
91
|
-
"prettier": "^3.0.
|
|
91
|
+
"prettier": "^3.0.2",
|
|
92
92
|
"prettier-plugin-organize-imports": "^3.2.3",
|
|
93
93
|
"rimraf": "^5.0.1",
|
|
94
|
-
"semantic-release": "^21.0.
|
|
94
|
+
"semantic-release": "^21.0.9",
|
|
95
95
|
"taffydb": "^2.7.3",
|
|
96
96
|
"ts-jest": "^29.1.1",
|
|
97
97
|
"ts-node": "^10.9.1",
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import { Fn, RemovalPolicy } from 'aws-cdk-lib'
|
|
2
|
+
import {
|
|
3
|
+
AccessLogFormat,
|
|
4
|
+
BasePathMapping,
|
|
5
|
+
Cors,
|
|
6
|
+
EndpointType,
|
|
7
|
+
LogGroupLogDestination,
|
|
8
|
+
MethodLoggingLevel,
|
|
9
|
+
Resource,
|
|
10
|
+
RestApi,
|
|
11
|
+
} from 'aws-cdk-lib/aws-apigateway'
|
|
12
|
+
import { ISecret } from 'aws-cdk-lib/aws-secretsmanager'
|
|
13
|
+
import { Construct } from 'constructs'
|
|
14
|
+
import { CommonConstruct } from '../../common'
|
|
15
|
+
import { ApiToAnyTargetProps, ApiToAnyTargetRestApiResource, ApiToAnyTargetRestApiType } from './types'
|
|
16
|
+
import { ApiToAnyTargetRestApi } from './target'
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @classdesc Provides a construct to create and deploy a shallow API Gateway
|
|
20
|
+
* @example
|
|
21
|
+
* import { ApiToAnyTarget, ApiToAnyTargetProps } '@gradientedge/cdk-utils'
|
|
22
|
+
* import { Construct } from 'constructs'
|
|
23
|
+
*
|
|
24
|
+
* class CustomConstruct extends ApiToAnyTarget {
|
|
25
|
+
* constructor(parent: Construct, id: string, props: ApiToAnyTargetProps) {
|
|
26
|
+
* super(parent, id, props)
|
|
27
|
+
* this.props = props
|
|
28
|
+
* this.id = id
|
|
29
|
+
* this.initResources()
|
|
30
|
+
* }
|
|
31
|
+
* }
|
|
32
|
+
*/
|
|
33
|
+
export class ApiToAnyTarget extends CommonConstruct {
|
|
34
|
+
props: ApiToAnyTargetProps
|
|
35
|
+
id: string
|
|
36
|
+
|
|
37
|
+
/* application related resources */
|
|
38
|
+
applicationSecrets: ISecret[]
|
|
39
|
+
|
|
40
|
+
/* rest restApi related resources */
|
|
41
|
+
apiToAnyTargetRestApi: ApiToAnyTargetRestApiType
|
|
42
|
+
apiResource: string
|
|
43
|
+
|
|
44
|
+
constructor(parent: Construct, id: string, props: ApiToAnyTargetProps) {
|
|
45
|
+
super(parent, id, props)
|
|
46
|
+
this.props = props
|
|
47
|
+
this.id = id
|
|
48
|
+
|
|
49
|
+
this.apiToAnyTargetRestApi = new ApiToAnyTargetRestApi()
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
protected initResources() {
|
|
53
|
+
/* application related resources */
|
|
54
|
+
this.resolveSecrets()
|
|
55
|
+
|
|
56
|
+
/* core resources */
|
|
57
|
+
this.resolveHostedZone()
|
|
58
|
+
this.resolveCertificate()
|
|
59
|
+
|
|
60
|
+
/* restApi related resources */
|
|
61
|
+
this.createApiToAnyTargetRestApiLogGroup()
|
|
62
|
+
this.createApiToAnyTargetRestApi()
|
|
63
|
+
this.createApiDomain()
|
|
64
|
+
this.createApiBasePathMapping()
|
|
65
|
+
this.createApiRouteAssets()
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* @summary Method to resolve secrets from SecretsManager
|
|
70
|
+
* - To be implemented in the overriding method in the implementation class
|
|
71
|
+
*/
|
|
72
|
+
protected resolveSecrets() {
|
|
73
|
+
this.applicationSecrets = []
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* @summary Method to resolve a hosted zone based on domain attributes
|
|
78
|
+
*/
|
|
79
|
+
protected resolveHostedZone() {
|
|
80
|
+
this.apiToAnyTargetRestApi.hostedZone = this.route53Manager.withHostedZoneFromFullyQualifiedDomainName(
|
|
81
|
+
`${this.id}-hosted-zone`,
|
|
82
|
+
this,
|
|
83
|
+
this.props.useExistingHostedZone
|
|
84
|
+
)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* @summary Method to resolve a certificate based on attributes
|
|
89
|
+
*/
|
|
90
|
+
protected resolveCertificate() {
|
|
91
|
+
if (this.props.api.useExisting) return
|
|
92
|
+
if (
|
|
93
|
+
this.props.api.certificate.useExistingCertificate &&
|
|
94
|
+
this.props.api.certificate.certificateSsmName &&
|
|
95
|
+
this.props.api.certificate.certificateRegion
|
|
96
|
+
) {
|
|
97
|
+
this.props.api.certificate.certificateArn = this.ssmManager.readStringParameterFromRegion(
|
|
98
|
+
`${this.id}-certificate-param`,
|
|
99
|
+
this,
|
|
100
|
+
this.props.api.certificate.certificateSsmName,
|
|
101
|
+
this.props.api.certificate.certificateRegion
|
|
102
|
+
)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
this.apiToAnyTargetRestApi.certificate = this.acmManager.resolveCertificate(
|
|
106
|
+
`${this.id}-certificate`,
|
|
107
|
+
this,
|
|
108
|
+
this.props.api.certificate
|
|
109
|
+
)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
protected createApiToAnyTargetRestApiLogGroup() {
|
|
113
|
+
this.apiToAnyTargetRestApi.accessLogGroup = this.logManager.createLogGroup(`${this.id}-rest-api-access-log`, this, {
|
|
114
|
+
logGroupName: `/custom/api/${this.id}-rest-api-access`,
|
|
115
|
+
removalPolicy: RemovalPolicy.DESTROY,
|
|
116
|
+
})
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
protected createApiToAnyTargetRestApi() {
|
|
120
|
+
if (this.props.api.useExisting && this.props.api.importedRestApiRef) {
|
|
121
|
+
this.apiToAnyTargetRestApi.api = RestApi.fromRestApiId(
|
|
122
|
+
this,
|
|
123
|
+
`${this.id}-rest-api`,
|
|
124
|
+
Fn.importValue(this.props.api.importedRestApiRef)
|
|
125
|
+
)
|
|
126
|
+
return
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
this.apiToAnyTargetRestApi.api = new RestApi(this, `${this.id}-rest-api`, {
|
|
130
|
+
...{
|
|
131
|
+
cloudWatchRole: this.props.api.restApi?.cloudWatchRole ?? true,
|
|
132
|
+
defaultCorsPreflightOptions: {
|
|
133
|
+
allowHeaders: Cors.DEFAULT_HEADERS,
|
|
134
|
+
allowMethods: Cors.ALL_METHODS,
|
|
135
|
+
allowOrigins: Cors.ALL_ORIGINS,
|
|
136
|
+
},
|
|
137
|
+
defaultIntegration: this.apiToAnyTargetRestApi.integration,
|
|
138
|
+
defaultMethodOptions: {
|
|
139
|
+
methodResponses: [this.apiToAnyTargetRestApi.methodResponse, this.apiToAnyTargetRestApi.methodErrorResponse],
|
|
140
|
+
},
|
|
141
|
+
deploy: this.props.api.restApi?.deploy ?? true,
|
|
142
|
+
deployOptions: {
|
|
143
|
+
accessLogDestination: new LogGroupLogDestination(this.apiToAnyTargetRestApi.accessLogGroup),
|
|
144
|
+
accessLogFormat: AccessLogFormat.jsonWithStandardFields(),
|
|
145
|
+
dataTraceEnabled: this.props.api.restApi?.deployOptions?.dataTraceEnabled,
|
|
146
|
+
description: `${this.id} - ${this.props.stage} stage`,
|
|
147
|
+
loggingLevel: MethodLoggingLevel.INFO,
|
|
148
|
+
metricsEnabled: true,
|
|
149
|
+
stageName: this.props.stage,
|
|
150
|
+
tracingEnabled: this.props.api.restApi?.deployOptions?.tracingEnabled,
|
|
151
|
+
},
|
|
152
|
+
endpointConfiguration: {
|
|
153
|
+
types: [this.isProductionStage() ? EndpointType.EDGE : EndpointType.REGIONAL],
|
|
154
|
+
},
|
|
155
|
+
restApiName: `${this.id}-rest-api-${this.props.stage}`,
|
|
156
|
+
},
|
|
157
|
+
...this.props.api.restApi,
|
|
158
|
+
})
|
|
159
|
+
this.addCfnOutput(`${this.id}-restApiId`, this.apiToAnyTargetRestApi.api.restApiId)
|
|
160
|
+
this.addCfnOutput(`${this.id}-restApiRootResourceId`, this.apiToAnyTargetRestApi.api.root.resourceId)
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
protected createApiToAnyTargetResource(apiResourceProps: ApiToAnyTargetRestApiResource) {
|
|
164
|
+
if (!this.props.api.withResource) return
|
|
165
|
+
let rootResource
|
|
166
|
+
if (this.props.api.withResource && this.props.api.importedRestApiRootResourceRef) {
|
|
167
|
+
rootResource = Resource.fromResourceAttributes(this, `${this.id}-root-resource-for-${apiResourceProps.path}`, {
|
|
168
|
+
path: '/',
|
|
169
|
+
resourceId: Fn.importValue(this.props.api.importedRestApiRootResourceRef),
|
|
170
|
+
restApi: this.apiToAnyTargetRestApi.api,
|
|
171
|
+
})
|
|
172
|
+
} else {
|
|
173
|
+
rootResource = this.apiToAnyTargetRestApi.api.root
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
return this.apiManager.createApiResource(
|
|
177
|
+
`${this.id}-resource-${apiResourceProps.path}}`,
|
|
178
|
+
this,
|
|
179
|
+
apiResourceProps.parent ?? rootResource,
|
|
180
|
+
apiResourceProps.path,
|
|
181
|
+
apiResourceProps.integration,
|
|
182
|
+
apiResourceProps.addProxy,
|
|
183
|
+
apiResourceProps.authorizer,
|
|
184
|
+
apiResourceProps.allowedOrigins,
|
|
185
|
+
apiResourceProps.allowedMethods,
|
|
186
|
+
apiResourceProps.allowedHeaders,
|
|
187
|
+
apiResourceProps.methodRequestParameters,
|
|
188
|
+
apiResourceProps.proxyIntegration
|
|
189
|
+
)
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
protected createApiDomain() {
|
|
193
|
+
if (this.props.api.useExisting) return
|
|
194
|
+
this.apiToAnyTargetRestApi.domain = this.apiManager.createApiDomain(
|
|
195
|
+
`${this.id}-api-domain`,
|
|
196
|
+
this,
|
|
197
|
+
this.isProductionStage() || this.props.skipStageForARecords
|
|
198
|
+
? `${this.props.apiSubDomain}.${this.fullyQualifiedDomainName}`
|
|
199
|
+
: `${this.props.apiSubDomain}-${this.props.stage}.${this.fullyQualifiedDomainName}`,
|
|
200
|
+
this.apiToAnyTargetRestApi.certificate
|
|
201
|
+
)
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
protected createApiBasePathMapping() {
|
|
205
|
+
if (this.props.api.useExisting) return
|
|
206
|
+
new BasePathMapping(this, `${this.id}-base-bath-mapping`, {
|
|
207
|
+
basePath: '',
|
|
208
|
+
domainName: this.apiToAnyTargetRestApi.domain,
|
|
209
|
+
restApi: this.apiToAnyTargetRestApi.api,
|
|
210
|
+
stage: this.apiToAnyTargetRestApi.api.deploymentStage,
|
|
211
|
+
})
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
protected createApiRouteAssets() {
|
|
215
|
+
if (this.props.api.useExisting) return
|
|
216
|
+
this.route53Manager.createApiGatewayARecord(
|
|
217
|
+
`${this.id}-custom-domain-a-record`,
|
|
218
|
+
this,
|
|
219
|
+
this.props.apiSubDomain,
|
|
220
|
+
this.apiToAnyTargetRestApi.domain,
|
|
221
|
+
this.apiToAnyTargetRestApi.hostedZone,
|
|
222
|
+
this.props.skipStageForARecords
|
|
223
|
+
)
|
|
224
|
+
}
|
|
225
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import {
|
|
2
|
+
IRestApi,
|
|
3
|
+
IAuthorizer,
|
|
4
|
+
BasePathMapping,
|
|
5
|
+
DomainName,
|
|
6
|
+
Integration,
|
|
7
|
+
Method,
|
|
8
|
+
MethodResponse,
|
|
9
|
+
Resource,
|
|
10
|
+
} from 'aws-cdk-lib/aws-apigateway'
|
|
11
|
+
import { ICertificate } from 'aws-cdk-lib/aws-certificatemanager'
|
|
12
|
+
import { LogGroup } from 'aws-cdk-lib/aws-logs'
|
|
13
|
+
import { IHostedZone } from 'aws-cdk-lib/aws-route53'
|
|
14
|
+
import { ApiToAnyTargetRestApiType } from './types'
|
|
15
|
+
|
|
16
|
+
export class ApiToAnyTargetRestApi implements ApiToAnyTargetRestApiType {
|
|
17
|
+
accessLogGroup: LogGroup
|
|
18
|
+
api: IRestApi
|
|
19
|
+
authoriser?: IAuthorizer
|
|
20
|
+
basePathMappings: BasePathMapping[]
|
|
21
|
+
certificate: ICertificate
|
|
22
|
+
domain: DomainName
|
|
23
|
+
hostedZone: IHostedZone
|
|
24
|
+
integration: Integration
|
|
25
|
+
method: { [httpMethod: string]: Method }
|
|
26
|
+
methodErrorResponse: MethodResponse
|
|
27
|
+
methodResponse: MethodResponse
|
|
28
|
+
resource: { [path: string]: Resource }
|
|
29
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BasePathMapping,
|
|
3
|
+
DomainName,
|
|
4
|
+
IAuthorizer,
|
|
5
|
+
IResource,
|
|
6
|
+
IRestApi,
|
|
7
|
+
Integration,
|
|
8
|
+
Method,
|
|
9
|
+
MethodResponse,
|
|
10
|
+
Resource,
|
|
11
|
+
RestApiProps,
|
|
12
|
+
} from 'aws-cdk-lib/aws-apigateway'
|
|
13
|
+
import { ICertificate } from 'aws-cdk-lib/aws-certificatemanager'
|
|
14
|
+
import { LogGroup } from 'aws-cdk-lib/aws-logs'
|
|
15
|
+
import { IHostedZone } from 'aws-cdk-lib/aws-route53'
|
|
16
|
+
import { CommonStackProps } from '../../common'
|
|
17
|
+
import { AcmProps } from '../../services'
|
|
18
|
+
|
|
19
|
+
export interface ApiToAnyTargetRestApiType {
|
|
20
|
+
accessLogGroup: LogGroup
|
|
21
|
+
api: IRestApi
|
|
22
|
+
authoriser?: IAuthorizer
|
|
23
|
+
basePathMappings: BasePathMapping[]
|
|
24
|
+
certificate: ICertificate
|
|
25
|
+
domain: DomainName
|
|
26
|
+
hostedZone: IHostedZone
|
|
27
|
+
integration: Integration
|
|
28
|
+
method: { [httpMethod: string]: Method }
|
|
29
|
+
methodErrorResponse: MethodResponse
|
|
30
|
+
methodResponse: MethodResponse
|
|
31
|
+
resource: { [path: string]: Resource }
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface ApiToAnyTargetRestApiResource {
|
|
35
|
+
addProxy: boolean
|
|
36
|
+
authorizer?: IAuthorizer
|
|
37
|
+
allowedOrigins?: string[]
|
|
38
|
+
allowedMethods?: string[]
|
|
39
|
+
allowedHeaders?: string[]
|
|
40
|
+
integration: Integration
|
|
41
|
+
methodRequestParameters?: { [param: string]: boolean }
|
|
42
|
+
path: string
|
|
43
|
+
parent?: IResource
|
|
44
|
+
proxyIntegration?: Integration
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface ApiToAnyTargetRestApiProps {
|
|
48
|
+
certificate: AcmProps
|
|
49
|
+
importedRestApiRef?: string
|
|
50
|
+
importedRestApiRootResourceRef?: string
|
|
51
|
+
methodErrorResponse: MethodResponse
|
|
52
|
+
methodResponse: MethodResponse
|
|
53
|
+
restApi: RestApiProps
|
|
54
|
+
useExisting: boolean
|
|
55
|
+
withResource?: boolean
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface ApiToAnyTargetProps extends CommonStackProps {
|
|
59
|
+
api: ApiToAnyTargetRestApiProps
|
|
60
|
+
apiRootPaths?: string[]
|
|
61
|
+
apiSubDomain: string
|
|
62
|
+
logLevel: string
|
|
63
|
+
nodeEnv: string
|
|
64
|
+
timezone: string
|
|
65
|
+
useExistingHostedZone: boolean
|
|
66
|
+
}
|
|
@@ -14,7 +14,7 @@ import * as s3 from 'aws-cdk-lib/aws-s3'
|
|
|
14
14
|
import * as efs from 'aws-cdk-lib/aws-efs'
|
|
15
15
|
import { Construct } from 'constructs'
|
|
16
16
|
import { CommonConstruct } from '../../common'
|
|
17
|
-
import { SiteWithEcsBackendProps, SiteResponseHeadersPolicyProps } from './types'
|
|
17
|
+
import { SiteWithEcsBackendProps, SiteResponseHeadersPolicyProps, SiteCachePolicyProps } from './types'
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
20
|
* @classdesc Provides a construct to create and deploy a site hosted with an clustered ECS/ELB backend
|
|
@@ -92,7 +92,7 @@ export class SiteWithEcsBackend extends CommonConstruct {
|
|
|
92
92
|
this.createEcsBuildArgs()
|
|
93
93
|
this.createEcsContainerImage()
|
|
94
94
|
this.createEcsService()
|
|
95
|
-
this.
|
|
95
|
+
this.createSiteOriginCachePolicy()
|
|
96
96
|
this.createSiteOriginRequestPolicy()
|
|
97
97
|
this.createSiteOriginResponseHeadersPolicy()
|
|
98
98
|
this.createSiteOrigin()
|
|
@@ -410,20 +410,23 @@ export class SiteWithEcsBackend extends CommonConstruct {
|
|
|
410
410
|
this.siteLogBucket = this.s3Manager.createS3Bucket(`${this.id}-site-logs`, this, this.props.siteLogBucket)
|
|
411
411
|
}
|
|
412
412
|
|
|
413
|
-
protected
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
cachePolicyName: `${this.id}-site-cache-policy`,
|
|
413
|
+
protected createSiteCachePolicy(id: string, siteCachePolicy: SiteCachePolicyProps) {
|
|
414
|
+
return new cloudfront.CachePolicy(this, `${id}`, {
|
|
415
|
+
cachePolicyName: `${this.id}-${siteCachePolicy.cachePolicyName}`,
|
|
417
416
|
comment: `Policy for ${this.id}-distribution - ${this.props.stage} stage`,
|
|
418
|
-
defaultTtl: cdk.Duration.seconds(
|
|
419
|
-
minTtl: cdk.Duration.seconds(
|
|
420
|
-
maxTtl: cdk.Duration.seconds(
|
|
421
|
-
enableAcceptEncodingGzip:
|
|
422
|
-
queryStringBehavior:
|
|
423
|
-
headerBehavior:
|
|
424
|
-
cookieBehavior:
|
|
417
|
+
defaultTtl: cdk.Duration.seconds(siteCachePolicy.defaultTtlInSeconds),
|
|
418
|
+
minTtl: cdk.Duration.seconds(siteCachePolicy.minTtlInSeconds),
|
|
419
|
+
maxTtl: cdk.Duration.seconds(siteCachePolicy.maxTtlInSeconds),
|
|
420
|
+
enableAcceptEncodingGzip: siteCachePolicy.enableAcceptEncodingGzip,
|
|
421
|
+
queryStringBehavior: siteCachePolicy.queryStringBehavior,
|
|
422
|
+
headerBehavior: siteCachePolicy.headerBehavior,
|
|
423
|
+
cookieBehavior: siteCachePolicy.cookieBehavior,
|
|
425
424
|
})
|
|
425
|
+
}
|
|
426
426
|
|
|
427
|
+
protected createSiteOriginCachePolicy() {
|
|
428
|
+
if (!this.props.siteCachePolicy) return
|
|
429
|
+
this.siteCachePolicy = this.createSiteCachePolicy(`${this.id}-site-cache-policy`, this.props.siteCachePolicy)
|
|
427
430
|
_.assign(this.props.siteDistribution.defaultBehavior, {
|
|
428
431
|
cachePolicy: this.siteCachePolicy,
|
|
429
432
|
})
|
|
@@ -451,6 +454,7 @@ export class SiteWithEcsBackend extends CommonConstruct {
|
|
|
451
454
|
comment: `Response Header Policy for ${props.type} for ${this.id}-distribution - ${this.props.stage} stage`,
|
|
452
455
|
responseHeadersPolicyName: `${this.id}-${props.type}-response`,
|
|
453
456
|
securityHeadersBehavior: {
|
|
457
|
+
...props.securityHeadersBehavior,
|
|
454
458
|
strictTransportSecurity: {
|
|
455
459
|
...props.securityHeadersBehavior?.strictTransportSecurity,
|
|
456
460
|
accessControlMaxAge: cdk.Duration.seconds(
|
|
@@ -135,7 +135,7 @@ export class ApiManager {
|
|
|
135
135
|
allowedOrigins?: string[],
|
|
136
136
|
allowedMethods?: string[],
|
|
137
137
|
allowedHeaders?: string[],
|
|
138
|
-
methodRequestParameters?:
|
|
138
|
+
methodRequestParameters?: { [param: string]: boolean },
|
|
139
139
|
proxyIntegration?: apig.Integration
|
|
140
140
|
) {
|
|
141
141
|
const methods = allowedMethods ?? apig.Cors.ALL_METHODS
|