Skip to content

Commit 04427e3

Browse files
fix(api-gateway): add validation to variables property on Stage resource (#25267)
Closes #3635 From the original issue: API Gateway Stage variables must match a regex to be valid ([See the documentation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-stage.html#cfn-apigateway-stage-variables)). When adding variables using CDK, this regex is not enforced, so it can synthesize a CloudFormation template that cannot be deployed. This PR fixes this issue by adding a validation that the strings match that regex along with a unit test for these changes. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent 4c9ce9b commit 04427e3

File tree

5 files changed

+86
-4
lines changed

5 files changed

+86
-4
lines changed

Diff for: packages/@aws-cdk/cx-api/FEATURE_FLAGS.md

+20-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ Flags come in three types:
1717

1818
| Flag | Summary | Since | Type |
1919
| ----- | ----- | ----- | ----- |
20+
| [@aws-cdk/aws-apigateway:requestValidatorUniqueId](#aws-cdkaws-apigatewayrequestvalidatoruniqueid) | Generate a unique id for each RequestValidator added to a method | V2·NEXT | (fix) |
2021
| [@aws-cdk/aws-route53-patters:useCertificate](#aws-cdkaws-route53-pattersusecertificate) | Use the official `Certificate` resource instead of `DnsValidatedCertificate` | V2·NEXT | (default) |
2122
| [@aws-cdk/core:newStyleStackSynthesis](#aws-cdkcorenewstylestacksynthesis) | Switch to new stack synthesis method which enables CI/CD | 2.0.0 | (fix) |
2223
| [@aws-cdk/core:stackRelativeExports](#aws-cdkcorestackrelativeexports) | Name exports based on the construct paths relative to the stack, rather than the global construct path | 2.0.0 | (fix) |
@@ -90,7 +91,8 @@ The following json shows the current recommended set of flags, as `cdk init` wou
9091
"@aws-cdk/aws-ec2:launchTemplateDefaultUserData": true,
9192
"@aws-cdk/aws-secretsmanager:useAttachedSecretResourcePolicyForSecretTargetAttachments": true,
9293
"@aws-cdk/aws-redshift:columnId": true,
93-
"@aws-cdk/aws-stepfunctions-tasks:enableEmrServicePolicyV2": true
94+
"@aws-cdk/aws-stepfunctions-tasks:enableEmrServicePolicyV2": true,
95+
"@aws-cdk/aws-apigateway:requestValidatorUniqueId": true
9496
}
9597
}
9698
```
@@ -320,6 +322,23 @@ Encryption can also be configured explicitly using the `encrypted` property.
320322
**Compatibility with old behavior:** Pass the `encrypted: false` property to the `FileSystem` construct to disable encryption.
321323

322324

325+
### @aws-cdk/aws-apigateway:requestValidatorUniqueId
326+
327+
*Generate a unique id for each RequestValidator added to a method* (fix)
328+
329+
This flag allows multiple RequestValidators to be added to a RestApi when
330+
providing the `RequestValidatorOptions` in the `addMethod()` method.
331+
332+
If the flag is not set then only a single RequestValidator can be added in this way.
333+
Any additional RequestValidators have to be created directly with `new RequestValidator`.
334+
335+
336+
| Since | Default | Recommended |
337+
| ----- | ----- | ----- |
338+
| (not in v1) | | |
339+
| V2·NEXT | `false` | `true` |
340+
341+
323342
### @aws-cdk/aws-route53-patters:useCertificate
324343

325344
*Use the official `Certificate` resource instead of `DnsValidatedCertificate`* (default)

Diff for: packages/aws-cdk-lib/aws-apigateway/lib/lambda-api.ts

+15-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
import * as lambda from '../../aws-lambda';
1+
// import * as cdk from '../../core';
22
import { Construct } from 'constructs';
33
import { LambdaIntegration, LambdaIntegrationOptions } from './integrations';
44
import { Method } from './method';
55
import { ProxyResource, Resource } from './resource';
66
import { RestApi, RestApiProps } from './restapi';
7+
import * as lambda from '../../aws-lambda';
78

89
export interface LambdaRestApiProps extends RestApiProps {
910
/**
@@ -68,6 +69,19 @@ export class LambdaRestApi extends RestApi {
6869
this.root.addMethod = addMethodThrows;
6970
this.root.addProxy = addProxyThrows;
7071
}
72+
73+
this.node.addValidation({
74+
validate() {
75+
for (const value of Object.values(props.deployOptions?.variables ?? {})) {
76+
// Checks that variable Stage values match regex
77+
const regexp = /[A-Za-z0-9-._~:/?#&=,]+/;
78+
if (value.match(regexp) === null) {
79+
return ['Stage variable value ' + value + ' does not match the regex.'];
80+
}
81+
}
82+
return [];
83+
},
84+
});
7185
}
7286
}
7387

Diff for: packages/aws-cdk-lib/aws-apigateway/lib/stage.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ export interface StageOptions extends MethodDeploymentOptions {
102102
/**
103103
* A map that defines the stage variables. Variable names must consist of
104104
* alphanumeric characters, and the values must match the following regular
105-
* expression: [A-Za-z0-9-._~:/?#&=,]+.
105+
* expression: [A-Za-z0-9-._~:/?#&=,]+.
106106
*
107107
* @default - No stage variables.
108108
*/

Diff for: packages/aws-cdk-lib/aws-apigateway/test/lambda-api.test.ts

+30
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { Match, Template } from '../../assertions';
22
import * as lambda from '../../aws-lambda';
33
import * as cdk from '../../core';
44
import * as apigw from '../lib';
5+
import { LambdaRestApi } from '../lib';
56

67
describe('lambda api', () => {
78
test('LambdaRestApi defines a REST API with Lambda proxy integration', () => {
@@ -405,4 +406,33 @@ describe('lambda api', () => {
405406
},
406407
});
407408
});
409+
410+
test('setting deployOptions variable with invalid value throws validation error', () => {
411+
// GIVEN
412+
const app = new cdk.App();
413+
const stack = new cdk.Stack(app);
414+
415+
const handler = new lambda.Function(stack, 'handler', {
416+
handler: 'index.handler',
417+
code: lambda.Code.fromInline('boom'),
418+
runtime: lambda.Runtime.NODEJS_10_X,
419+
});
420+
421+
const versionAlias = lambda.Version.fromVersionAttributes(stack, 'VersionInfo', {
422+
lambda: handler,
423+
version: '${stageVariables.lambdaAlias}',
424+
});
425+
426+
new LambdaRestApi(stack, 'RestApi', {
427+
restApiName: 'my-test-api',
428+
handler: versionAlias,
429+
deployOptions: {
430+
variables: {
431+
functionName: '$$$',
432+
},
433+
},
434+
});
435+
436+
expect(() => app.synth()).toThrow('Validation failed with the following errors:\n [Default/RestApi] Stage variable value $$$ does not match the regex.');
437+
});
408438
});

Diff for: packages/aws-cdk-lib/cx-api/FEATURE_FLAGS.md

+20-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ Flags come in three types:
1717

1818
| Flag | Summary | Since | Type |
1919
| ----- | ----- | ----- | ----- |
20+
| [@aws-cdk/aws-apigateway:requestValidatorUniqueId](#aws-cdkaws-apigatewayrequestvalidatoruniqueid) | Generate a unique id for each RequestValidator added to a method | V2·NEXT | (fix) |
2021
| [@aws-cdk/aws-route53-patters:useCertificate](#aws-cdkaws-route53-pattersusecertificate) | Use the official `Certificate` resource instead of `DnsValidatedCertificate` | V2·NEXT | (default) |
2122
| [@aws-cdk/core:newStyleStackSynthesis](#aws-cdkcorenewstylestacksynthesis) | Switch to new stack synthesis method which enables CI/CD | 2.0.0 | (fix) |
2223
| [@aws-cdk/core:stackRelativeExports](#aws-cdkcorestackrelativeexports) | Name exports based on the construct paths relative to the stack, rather than the global construct path | 2.0.0 | (fix) |
@@ -90,7 +91,8 @@ The following json shows the current recommended set of flags, as `cdk init` wou
9091
"@aws-cdk/aws-ec2:launchTemplateDefaultUserData": true,
9192
"@aws-cdk/aws-secretsmanager:useAttachedSecretResourcePolicyForSecretTargetAttachments": true,
9293
"@aws-cdk/aws-redshift:columnId": true,
93-
"@aws-cdk/aws-stepfunctions-tasks:enableEmrServicePolicyV2": true
94+
"@aws-cdk/aws-stepfunctions-tasks:enableEmrServicePolicyV2": true,
95+
"@aws-cdk/aws-apigateway:requestValidatorUniqueId": true
9496
}
9597
}
9698
```
@@ -320,6 +322,23 @@ Encryption can also be configured explicitly using the `encrypted` property.
320322
**Compatibility with old behavior:** Pass the `encrypted: false` property to the `FileSystem` construct to disable encryption.
321323

322324

325+
### @aws-cdk/aws-apigateway:requestValidatorUniqueId
326+
327+
*Generate a unique id for each RequestValidator added to a method* (fix)
328+
329+
This flag allows multiple RequestValidators to be added to a RestApi when
330+
providing the `RequestValidatorOptions` in the `addMethod()` method.
331+
332+
If the flag is not set then only a single RequestValidator can be added in this way.
333+
Any additional RequestValidators have to be created directly with `new RequestValidator`.
334+
335+
336+
| Since | Default | Recommended |
337+
| ----- | ----- | ----- |
338+
| (not in v1) | | |
339+
| V2·NEXT | `false` | `true` |
340+
341+
323342
### @aws-cdk/aws-route53-patters:useCertificate
324343

325344
*Use the official `Certificate` resource instead of `DnsValidatedCertificate`* (default)

0 commit comments

Comments
 (0)