Skip to content

Commit 26d617e

Browse files
fvsnippetsFederico Valido
authored andcommitted
Preserving logical names for cachePolicy & originRequestPolicy resources.
1 parent 3271a4d commit 26d617e

File tree

2 files changed

+88
-67
lines changed

2 files changed

+88
-67
lines changed

source/constructs/lib/back-end/back-end-construct.ts

Lines changed: 84 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { Policy, PolicyStatement, Role, ServicePrincipal } from '@aws-cdk/aws-ia
88
import { Code, Function as LambdaFunction, Runtime } from '@aws-cdk/aws-lambda';
99
import { LogGroup, RetentionDays } from '@aws-cdk/aws-logs';
1010
import { Bucket, IBucket } from '@aws-cdk/aws-s3';
11-
import { ArnFormat, Aws, Construct, Duration, Lazy, Stack } from '@aws-cdk/core';
11+
import { ArnFormat, Aws, Construct, Duration, Lazy, Resource, Stack } from '@aws-cdk/core';
1212
import { CloudFrontToApiGatewayToLambda } from '@aws-solutions-constructs/aws-cloudfront-apigateway-lambda';
1313

1414
import { addCfnSuppressRules } from '../../utils/utils';
@@ -92,7 +92,75 @@ export class BackEnd extends Construct {
9292

9393
addCfnSuppressRules(imageHandlerLogGroup, [{ id: 'W84', reason: 'CloudWatch log group is always encrypted by default.' }]);
9494

95-
const cachePolicy = new CfnCachePolicy(this, 'CachePolicy', {
95+
const cachePolicy = new CustomBackEndCachePolicy(this, 'CachePolicy', props);
96+
97+
const originRequestPolicy = new CustomBackEndOriginRequestPolicy(this, 'OriginRequestPolicy', props);
98+
99+
const apiGatewayRestApi = RestApi.fromRestApiId(this, 'ApiGatewayRestApi', Lazy.string({ produce: () => imageHandlerCloudFrontApiGatewayLambda.apiGateway.restApiId }));
100+
101+
const origin: IOrigin = new HttpOrigin(`${apiGatewayRestApi.restApiId}.execute-api.${Aws.REGION}.amazonaws.com`, {
102+
originPath: '/image',
103+
originSslProtocols: [OriginSslPolicy.TLS_V1_1, OriginSslPolicy.TLS_V1_2]
104+
});
105+
106+
const cloudFrontDistributionProps: DistributionProps = {
107+
comment: 'Image Handler Distribution for Serverless Image Handler',
108+
defaultBehavior: {
109+
origin: origin,
110+
allowedMethods: AllowedMethods.ALLOW_GET_HEAD,
111+
viewerProtocolPolicy: ViewerProtocolPolicy.HTTPS_ONLY,
112+
originRequestPolicy: originRequestPolicy,
113+
cachePolicy: cachePolicy
114+
},
115+
priceClass: props.cloudFrontPriceClass as PriceClass,
116+
enableLogging: true,
117+
logBucket: props.logsBucket,
118+
logFilePrefix: 'api-cloudfront/',
119+
errorResponses: [
120+
{ httpStatus: 500, ttl: Duration.minutes(10) },
121+
{ httpStatus: 501, ttl: Duration.minutes(10) },
122+
{ httpStatus: 502, ttl: Duration.minutes(10) },
123+
{ httpStatus: 503, ttl: Duration.minutes(10) },
124+
{ httpStatus: 504, ttl: Duration.minutes(10) }
125+
]
126+
};
127+
128+
const logGroupProps = {
129+
retention: props.logRetentionPeriod as RetentionDays
130+
};
131+
132+
const apiGatewayProps: LambdaRestApiProps = {
133+
handler: imageHandlerLambdaFunction,
134+
deployOptions: {
135+
stageName: 'image'
136+
},
137+
binaryMediaTypes: ['*/*']
138+
};
139+
140+
const imageHandlerCloudFrontApiGatewayLambda = new CloudFrontToApiGatewayToLambda(this, 'ImageHandlerCloudFrontApiGatewayLambda', {
141+
existingLambdaObj: imageHandlerLambdaFunction,
142+
insertHttpSecurityHeaders: false,
143+
logGroupProps: logGroupProps,
144+
cloudFrontDistributionProps: cloudFrontDistributionProps,
145+
apiGatewayProps: apiGatewayProps
146+
});
147+
148+
imageHandlerCloudFrontApiGatewayLambda.apiGateway.node.tryRemoveChild('Endpoint'); // we don't need the RestApi endpoint in the outputs
149+
150+
this.domainName = imageHandlerCloudFrontApiGatewayLambda.cloudFrontWebDistribution.distributionDomainName;
151+
}
152+
}
153+
154+
155+
class CustomBackEndCachePolicy extends Resource implements ICachePolicy {
156+
public readonly cachePolicyId: string;
157+
158+
constructor(scope: Construct, id: string, props: BackEndProps) {
159+
super(scope, id, {
160+
physicalName: `ServerlessImageHandler-${props.uuid}`,
161+
});
162+
163+
const cachePolicy = new CfnCachePolicy(this, 'Resource', {
96164
cachePolicyConfig: {
97165
name: `ServerlessImageHandler-${props.uuid}`,
98166
defaultTtl: Duration.days(1).toSeconds(),
@@ -115,7 +183,7 @@ export class BackEnd extends Construct {
115183
}
116184
}
117185
);
118-
186+
119187
// https://github.com/aws/aws-cdk/issues/8396#issuecomment-857690411
120188
cachePolicy.addOverride(
121189
'Properties.CachePolicyConfig.ParametersInCacheKeyAndForwardedToOrigin.HeadersConfig.Headers',
@@ -128,11 +196,19 @@ export class BackEnd extends Construct {
128196
}
129197
);
130198

131-
const cachePolicyAdapter = new class implements ICachePolicy {
132-
public readonly cachePolicyId = cachePolicy.ref;
133-
}();
199+
this.cachePolicyId = cachePolicy.ref;
200+
}
201+
}
202+
203+
class CustomBackEndOriginRequestPolicy extends Resource implements IOriginRequestPolicy {
204+
public readonly originRequestPolicyId: string;
205+
206+
constructor(scope: Construct, id: string, props: BackEndProps) {
207+
super(scope, id, {
208+
physicalName: `ServerlessImageHandler-${props.uuid}`,
209+
});
134210

135-
const originRequestPolicy = new CfnOriginRequestPolicy(this, 'OriginRequestPolicy', {
211+
const originRequestPolicy = new CfnOriginRequestPolicy(this, 'Resource', {
136212
originRequestPolicyConfig: {
137213
name: `ServerlessImageHandler-${props.uuid}`,
138214
headersConfig: {
@@ -160,61 +236,6 @@ export class BackEnd extends Construct {
160236
}
161237
);
162238

163-
const originRequestPolicyAdapter = new class implements IOriginRequestPolicy {
164-
public readonly originRequestPolicyId = originRequestPolicy.ref;
165-
}();
166-
167-
const apiGatewayRestApi = RestApi.fromRestApiId(this, 'ApiGatewayRestApi', Lazy.string({ produce: () => imageHandlerCloudFrontApiGatewayLambda.apiGateway.restApiId }));
168-
169-
const origin: IOrigin = new HttpOrigin(`${apiGatewayRestApi.restApiId}.execute-api.${Aws.REGION}.amazonaws.com`, {
170-
originPath: '/image',
171-
originSslProtocols: [OriginSslPolicy.TLS_V1_1, OriginSslPolicy.TLS_V1_2]
172-
});
173-
174-
const cloudFrontDistributionProps: DistributionProps = {
175-
comment: 'Image Handler Distribution for Serverless Image Handler',
176-
defaultBehavior: {
177-
origin: origin,
178-
allowedMethods: AllowedMethods.ALLOW_GET_HEAD,
179-
viewerProtocolPolicy: ViewerProtocolPolicy.HTTPS_ONLY,
180-
originRequestPolicy: originRequestPolicyAdapter,
181-
cachePolicy: cachePolicyAdapter
182-
},
183-
priceClass: props.cloudFrontPriceClass as PriceClass,
184-
enableLogging: true,
185-
logBucket: props.logsBucket,
186-
logFilePrefix: 'api-cloudfront/',
187-
errorResponses: [
188-
{ httpStatus: 500, ttl: Duration.minutes(10) },
189-
{ httpStatus: 501, ttl: Duration.minutes(10) },
190-
{ httpStatus: 502, ttl: Duration.minutes(10) },
191-
{ httpStatus: 503, ttl: Duration.minutes(10) },
192-
{ httpStatus: 504, ttl: Duration.minutes(10) }
193-
]
194-
};
195-
196-
const logGroupProps = {
197-
retention: props.logRetentionPeriod as RetentionDays
198-
};
199-
200-
const apiGatewayProps: LambdaRestApiProps = {
201-
handler: imageHandlerLambdaFunction,
202-
deployOptions: {
203-
stageName: 'image'
204-
},
205-
binaryMediaTypes: ['*/*']
206-
};
207-
208-
const imageHandlerCloudFrontApiGatewayLambda = new CloudFrontToApiGatewayToLambda(this, 'ImageHandlerCloudFrontApiGatewayLambda', {
209-
existingLambdaObj: imageHandlerLambdaFunction,
210-
insertHttpSecurityHeaders: false,
211-
logGroupProps: logGroupProps,
212-
cloudFrontDistributionProps: cloudFrontDistributionProps,
213-
apiGatewayProps: apiGatewayProps
214-
});
215-
216-
imageHandlerCloudFrontApiGatewayLambda.apiGateway.node.tryRemoveChild('Endpoint'); // we don't need the RestApi endpoint in the outputs
217-
218-
this.domainName = imageHandlerCloudFrontApiGatewayLambda.cloudFrontWebDistribution.distributionDomainName;
239+
this.originRequestPolicyId = originRequestPolicy.ref;
219240
}
220241
}

source/constructs/test/__snapshots__/constructs.test.ts.snap

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ Object {
329329
},
330330
},
331331
"Resources": Object {
332-
"BackEndCachePolicy85AF2390": Object {
332+
"BackEndCachePolicy1DCE9B1B": Object {
333333
"Properties": Object {
334334
"CachePolicyConfig": Object {
335335
"DefaultTTL": 86400,
@@ -449,11 +449,11 @@ Object {
449449
"HEAD",
450450
],
451451
"CachePolicyId": Object {
452-
"Ref": "BackEndCachePolicy85AF2390",
452+
"Ref": "BackEndCachePolicy1DCE9B1B",
453453
},
454454
"Compress": true,
455455
"OriginRequestPolicyId": Object {
456-
"Ref": "BackEndOriginRequestPolicyAF28A12A",
456+
"Ref": "BackEndOriginRequestPolicy771345D7",
457457
},
458458
"TargetOriginId": "TestStackBackEndImageHandlerCloudFrontApiGatewayLambdaCloudFrontToApiGatewayCloudFrontDistributionOrigin1A053AEB7",
459459
"ViewerProtocolPolicy": "https-only",
@@ -1220,7 +1220,7 @@ Object {
12201220
"Type": "AWS::Logs::LogGroup",
12211221
"UpdateReplacePolicy": "Retain",
12221222
},
1223-
"BackEndOriginRequestPolicyAF28A12A": Object {
1223+
"BackEndOriginRequestPolicy771345D7": Object {
12241224
"Properties": Object {
12251225
"OriginRequestPolicyConfig": Object {
12261226
"CookiesConfig": Object {

0 commit comments

Comments
 (0)