Skip to content

Commit 1ef5edd

Browse files
authored
Merge branch 'main' into feature/integrate-iam+sasl
2 parents 7ac0720 + 8f7ee2b commit 1ef5edd

20 files changed

Lines changed: 1784 additions & 22 deletions

File tree

packages/@aws-cdk/aws-ec2/lib/machine-image.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ export class GenericSSMParameterImage implements IMachineImage {
165165
* Return the image to use in the given context
166166
*/
167167
public getImage(scope: Construct): MachineImageConfig {
168-
const ami = ssm.StringParameter.valueForTypedStringParameter(scope, this.parameterName, ssm.ParameterType.AWS_EC2_IMAGE_ID);
168+
const ami = ssm.StringParameter.valueForTypedStringParameterV2(scope, this.parameterName, ssm.ParameterValueType.AWS_EC2_IMAGE_ID);
169169
return {
170170
imageId: ami,
171171
osType: this.os,
@@ -732,5 +732,5 @@ export interface LookupMachineImageProps {
732732
function lookupImage(scope: Construct, cachedInContext: boolean | undefined, parameterName: string) {
733733
return cachedInContext
734734
? ssm.StringParameter.valueFromLookup(scope, parameterName)
735-
: ssm.StringParameter.valueForTypedStringParameter(scope, parameterName, ssm.ParameterType.AWS_EC2_IMAGE_ID);
735+
: ssm.StringParameter.valueForTypedStringParameterV2(scope, parameterName, ssm.ParameterValueType.AWS_EC2_IMAGE_ID);
736736
}

packages/@aws-cdk/aws-ecs/lib/amis.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -369,5 +369,5 @@ export class BottleRocketImage implements ec2.IMachineImage {
369369
function lookupImage(scope: Construct, cachedInContext: boolean | undefined, parameterName: string) {
370370
return cachedInContext
371371
? ssm.StringParameter.valueFromLookup(scope, parameterName)
372-
: ssm.StringParameter.valueForTypedStringParameter(scope, parameterName, ssm.ParameterType.AWS_EC2_IMAGE_ID);
372+
: ssm.StringParameter.valueForTypedStringParameterV2(scope, parameterName, ssm.ParameterValueType.AWS_EC2_IMAGE_ID);
373373
}

packages/@aws-cdk/aws-lambda/lib/function.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -898,6 +898,30 @@ export class Function extends FunctionBase {
898898
* @param options Environment variable options.
899899
*/
900900
public addEnvironment(key: string, value: string, options?: EnvironmentOptions): this {
901+
// Reserved environment variables will fail during cloudformation deploy if they're set.
902+
// This check is just to allow CDK to fail faster when these are specified.
903+
const reservedEnvironmentVariables = [
904+
'_HANDLER',
905+
'_X_AMZN_TRACE_ID',
906+
'AWS_REGION',
907+
'AWS_EXECUTION_ENV',
908+
'AWS_LAMBDA_FUNCTION_NAME',
909+
'AWS_LAMBDA_FUNCTION_MEMORY_SIZE',
910+
'AWS_LAMBDA_FUNCTION_VERSION',
911+
'AWS_LAMBDA_INITIALIZATION_TYPE',
912+
'AWS_LAMBDA_LOG_GROUP_NAME',
913+
'AWS_LAMBDA_LOG_STREAM_NAME',
914+
'AWS_ACCESS_KEY',
915+
'AWS_ACCESS_KEY_ID',
916+
'AWS_SECRET_ACCESS_KEY',
917+
'AWS_SESSION_TOKEN',
918+
'AWS_LAMBDA_RUNTIME_API',
919+
'LAMBDA_TASK_ROOT',
920+
'LAMBDA_RUNTIME_DIR',
921+
];
922+
if (reservedEnvironmentVariables.includes(key)) {
923+
throw new Error(`${key} environment variable is reserved by the lambda runtime and can not be set manually. See https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html`);
924+
}
901925
this.environment[key] = { value, ...options };
902926
return this;
903927
}

packages/@aws-cdk/aws-lambda/test/function.test.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3114,6 +3114,18 @@ test('FunctionVersionUpgrade adds new description to function', () => {
31143114
});
31153115
});
31163116

3117+
test('function using a reserved environment variable', () => {
3118+
const stack = new cdk.Stack();
3119+
expect(() => new lambda.Function(stack, 'MyLambda', {
3120+
code: new lambda.InlineCode('foo'),
3121+
handler: 'index.handler',
3122+
runtime: lambda.Runtime.PYTHON_3_9,
3123+
environment: {
3124+
AWS_REGION: 'ap-southeast-2',
3125+
},
3126+
})).toThrow(/AWS_REGION environment variable is reserved/);
3127+
});
3128+
31173129
function newTestLambda(scope: constructs.Construct) {
31183130
return new lambda.Function(scope, 'MyLambda', {
31193131
code: new lambda.InlineCode('foo'),

packages/@aws-cdk/aws-ssm/README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,19 @@ your CDK app by using `ssm.StringParameter.fromStringParameterAttributes`:
2020

2121
[using SSM parameter](test/integ.parameter-store-string.lit.ts)
2222

23+
You can also reference an existing SSM Parameter Store value that matches an
24+
[AWS specific parameter type](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html#aws-specific-parameter-types):
25+
26+
```ts
27+
ssm.StringParameter.valueForTypedStringParameterV2(stack, '/My/Public/Parameter', ssm.ParameterValueType.AWS_EC2_IMAGE_ID);
28+
```
29+
30+
To do the same for a SSM Parameter Store value that is stored as a list:
31+
32+
```ts
33+
ssm.StringListParameter.valueForTypedListParameter(stack, '/My/Public/Parameter', ssm.ParameterValueType.AWS_EC2_IMAGE_ID);
34+
```
35+
2336
### Lookup existing parameters
2437

2538
You can also use an existing parameter by looking up the parameter from the AWS environment.

packages/@aws-cdk/aws-ssm/lib/parameter.ts

Lines changed: 186 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ export interface StringParameterProps extends ParameterOptions {
135135
* The type of the string parameter
136136
*
137137
* @default ParameterType.STRING
138+
* @deprecated - type will always be 'String'
138139
*/
139140
readonly type?: ParameterType;
140141

@@ -199,8 +200,75 @@ abstract class ParameterBase extends Resource implements IParameter {
199200
}
200201
}
201202

203+
/**
204+
* The type of CFN SSM Parameter
205+
*
206+
* Using specific types can be helpful in catching invalid values
207+
* at the start of creating or updating a stack. CloudFormation validates
208+
* the values against existing values in the account.
209+
*
210+
* @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html#aws-ssm-parameter-types
211+
*/
212+
export enum ParameterValueType {
213+
/**
214+
* String
215+
*/
216+
STRING = 'String',
217+
218+
/**
219+
* An Availability Zone, such as us-west-2a.
220+
*/
221+
AWS_EC2_AVAILABILITYZONE_NAME = 'AWS::EC2::AvailabilityZone::Name',
222+
223+
/**
224+
* An Amazon EC2 image ID, such as ami-0ff8a91507f77f867.
225+
*/
226+
AWS_EC2_IMAGE_ID = 'AWS::EC2::Image::Id',
227+
228+
/**
229+
* An Amazon EC2 instance ID, such as i-1e731a32.
230+
*/
231+
AWS_EC2_INSTANCE_ID = 'AWS::EC2::Instance::Id',
232+
233+
/**
234+
* An Amazon EC2 key pair name.
235+
*/
236+
AWS_EC2_KEYPAIR_KEYNAME = 'AWS::EC2::KeyPair::KeyName',
237+
238+
/**
239+
* An EC2-Classic or default VPC security group name, such as my-sg-abc.
240+
*/
241+
AWS_EC2_SECURITYGROUP_GROUPNAME = 'AWS::EC2::SecurityGroup::GroupName',
242+
243+
/**
244+
* A security group ID, such as sg-a123fd85.
245+
*/
246+
AWS_EC2_SECURITYGROUP_ID = 'AWS::EC2::SecurityGroup::Id',
247+
248+
/**
249+
* A subnet ID, such as subnet-123a351e.
250+
*/
251+
AWS_EC2_SUBNET_ID = 'AWS::EC2::Subnet::Id',
252+
253+
/**
254+
* An Amazon EBS volume ID, such as vol-3cdd3f56.
255+
*/
256+
AWS_EC2_VOLUME_ID = 'AWS::EC2::Volume::Id',
257+
258+
/**
259+
* A VPC ID, such as vpc-a123baa3.
260+
*/
261+
AWS_EC2_VPC_ID = 'AWS::EC2::VPC::Id',
262+
263+
/**
264+
* An Amazon Route 53 hosted zone ID, such as Z23YXV4OVPL04A.
265+
*/
266+
AWS_ROUTE53_HOSTEDZONE_ID = 'AWS::Route53::HostedZone::Id',
267+
}
268+
202269
/**
203270
* SSM parameter type
271+
* @deprecated these types are no longer used
204272
*/
205273
export enum ParameterType {
206274
/**
@@ -302,8 +370,55 @@ export interface StringParameterAttributes extends CommonStringParameterAttribut
302370
* The type of the string parameter
303371
*
304372
* @default ParameterType.STRING
373+
* @deprecated - use valueType instead
305374
*/
306375
readonly type?: ParameterType;
376+
377+
/**
378+
* The type of the string parameter value
379+
*
380+
* Using specific types can be helpful in catching invalid values
381+
* at the start of creating or updating a stack. CloudFormation validates
382+
* the values against existing values in the account.
383+
*
384+
* Note - if you want to allow values from different AWS accounts, use
385+
* ParameterValueType.STRING
386+
*
387+
* @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html#aws-ssm-parameter-types
388+
*
389+
* @default ParameterValueType.STRING
390+
*/
391+
readonly valueType?: ParameterValueType;
392+
}
393+
394+
/**
395+
* Attributes for parameters of string list type.
396+
*
397+
* @see ParameterType
398+
*/
399+
export interface ListParameterAttributes extends CommonStringParameterAttributes {
400+
/**
401+
* The version number of the value you wish to retrieve.
402+
*
403+
* @default The latest version will be retrieved.
404+
*/
405+
readonly version?: number;
406+
407+
/**
408+
* The type of the string list parameter value.
409+
*
410+
* Using specific types can be helpful in catching invalid values
411+
* at the start of creating or updating a stack. CloudFormation validates
412+
* the values against existing values in the account.
413+
*
414+
* Note - if you want to allow values from different AWS accounts, use
415+
* ParameterValueType.STRING
416+
*
417+
* @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html#aws-ssm-parameter-types
418+
*
419+
* @default ParameterValueType.STRING
420+
*/
421+
readonly elementType?: ParameterValueType;
307422
}
308423

309424
/**
@@ -331,25 +446,10 @@ export interface SecureStringParameterAttributes extends CommonStringParameterAt
331446
* @resource AWS::SSM::Parameter
332447
*
333448
* @example
334-
*
335449
* const ssmParameter = new ssm.StringParameter(this, 'mySsmParameter', {
336450
* parameterName: 'mySsmParameter',
337451
* stringValue: 'mySsmParameterValue',
338-
* type: ssm.ParameterType.STRING,
339452
* });
340-
*
341-
* const secureParameter = new ssm.StringParameter(this, 'mySecretParameter', {
342-
* parameterName: 'mySecretParameter',
343-
* stringValue: 'mySecretParameterValue',
344-
* type: ssm.ParameterType.SECURE_STRING,
345-
* });
346-
*
347-
* const listParameter = new ssm.StringParameter(this, 'myListParameter', {
348-
* parameterName: 'myListParameter',
349-
* stringValue: ["myListParameterValue1", "myListParameterValue2"],
350-
* type: ssm.ParameterType.STRING_LIST,
351-
* });
352-
*
353453
*/
354454
export class StringParameter extends ParameterBase implements IStringParameter {
355455

@@ -367,8 +467,11 @@ export class StringParameter extends ParameterBase implements IStringParameter {
367467
if (!attrs.parameterName) {
368468
throw new Error('parameterName cannot be an empty string');
369469
}
470+
if (attrs.type && ![ParameterType.STRING, ParameterType.AWS_EC2_IMAGE_ID].includes(attrs.type)) {
471+
throw new Error(`fromStringParameterAttributes does not support ${attrs.type}. Please use ParameterType.STRING or ParameterType.AWS_EC2_IMAGE_ID`);
472+
}
370473

371-
const type = attrs.type || ParameterType.STRING;
474+
const type = attrs.type ?? attrs.valueType ?? ParameterValueType.STRING;
372475

373476
const stringValue = attrs.version
374477
? new CfnDynamicReference(CfnDynamicReferenceService.SSM, `${attrs.parameterName}:${Tokenization.stringifyNumber(attrs.version)}`).toString()
@@ -377,7 +480,7 @@ export class StringParameter extends ParameterBase implements IStringParameter {
377480
class Import extends ParameterBase {
378481
public readonly parameterName = attrs.parameterName;
379482
public readonly parameterArn = arnForParameterName(this, attrs.parameterName, { simpleName: attrs.simpleName });
380-
public readonly parameterType = type;
483+
public readonly parameterType = ParameterType.STRING; // this is the type returned by CFN @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ssm-parameter.html#aws-resource-ssm-parameter-return-values
381484
public readonly stringValue = stringValue;
382485
}
383486

@@ -426,7 +529,24 @@ export class StringParameter extends ParameterBase implements IStringParameter {
426529
* @param version The parameter version (recommended in order to ensure that the value won't change during deployment)
427530
*/
428531
public static valueForStringParameter(scope: Construct, parameterName: string, version?: number): string {
429-
return StringParameter.valueForTypedStringParameter(scope, parameterName, ParameterType.STRING, version);
532+
return StringParameter.valueForTypedStringParameterV2(scope, parameterName, ParameterValueType.STRING, version);
533+
}
534+
535+
/**
536+
* Returns a token that will resolve (during deployment) to the string value of an SSM string parameter.
537+
* @param scope Some scope within a stack
538+
* @param parameterName The name of the SSM parameter.
539+
* @param type The type of the SSM parameter.
540+
* @param version The parameter version (recommended in order to ensure that the value won't change during deployment)
541+
*/
542+
public static valueForTypedStringParameterV2(scope: Construct, parameterName: string, type = ParameterValueType.STRING, version?: number): string {
543+
const stack = Stack.of(scope);
544+
const id = makeIdentityForImportedValue(parameterName);
545+
const exists = stack.node.tryFindChild(id) as IStringParameter;
546+
547+
if (exists) { return exists.stringValue; }
548+
549+
return this.fromStringParameterAttributes(stack, id, { parameterName, version, valueType: type }).stringValue;
430550
}
431551

432552
/**
@@ -435,8 +555,13 @@ export class StringParameter extends ParameterBase implements IStringParameter {
435555
* @param parameterName The name of the SSM parameter.
436556
* @param type The type of the SSM parameter.
437557
* @param version The parameter version (recommended in order to ensure that the value won't change during deployment)
558+
* @deprecated - use valueForTypedStringParameterV2 instead
438559
*/
439560
public static valueForTypedStringParameter(scope: Construct, parameterName: string, type = ParameterType.STRING, version?: number): string {
561+
if (type === ParameterType.STRING_LIST) {
562+
throw new Error('valueForTypedStringParameter does not support STRING_LIST, '
563+
+'use valueForTypedListParameter instead');
564+
}
440565
const stack = Stack.of(scope);
441566
const id = makeIdentityForImportedValue(parameterName);
442567
const exists = stack.node.tryFindChild(id) as IStringParameter;
@@ -528,6 +653,49 @@ export class StringListParameter extends ParameterBase implements IStringListPar
528653
return new Import(scope, id);
529654
}
530655

656+
/**
657+
* Imports an external string list parameter with name and optional version.
658+
*/
659+
public static fromListParameterAttributes(scope: Construct, id: string, attrs: ListParameterAttributes): IStringListParameter {
660+
if (!attrs.parameterName) {
661+
throw new Error('parameterName cannot be an empty string');
662+
}
663+
664+
const type = attrs.elementType ?? ParameterValueType.STRING;
665+
const valueType = `List<${type}>`;
666+
667+
const stringValue = attrs.version
668+
? new CfnDynamicReference(CfnDynamicReferenceService.SSM, `${attrs.parameterName}:${Tokenization.stringifyNumber(attrs.version)}`).toStringList()
669+
: new CfnParameter(scope, `${id}.Parameter`, { type: `AWS::SSM::Parameter::Value<${valueType}>`, default: attrs.parameterName }).valueAsList;
670+
671+
class Import extends ParameterBase {
672+
public readonly parameterName = attrs.parameterName;
673+
public readonly parameterArn = arnForParameterName(this, attrs.parameterName, { simpleName: attrs.simpleName });
674+
public readonly parameterType = valueType; // it doesn't really matter what this is since a CfnParameter can only be `String | StringList`
675+
public readonly stringListValue = stringValue;
676+
}
677+
678+
return new Import(scope, id);
679+
}
680+
681+
/**
682+
* Returns a token that will resolve (during deployment) to the list value of an SSM StringList parameter.
683+
* @param scope Some scope within a stack
684+
* @param parameterName The name of the SSM parameter.
685+
* @param type the type of the SSM list parameter
686+
* @param version The parameter version (recommended in order to ensure that the value won't change during deployment)
687+
*/
688+
public static valueForTypedListParameter(scope: Construct, parameterName: string, type = ParameterValueType.STRING, version?: number): string[] {
689+
const stack = Stack.of(scope);
690+
const id = makeIdentityForImportedValue(parameterName);
691+
const exists = stack.node.tryFindChild(id) as IStringListParameter;
692+
693+
if (exists) { return exists.stringListValue; }
694+
695+
return this.fromListParameterAttributes(stack, id, { parameterName, elementType: type, version }).stringListValue;
696+
}
697+
698+
531699
public readonly parameterArn: string;
532700
public readonly parameterName: string;
533701
public readonly parameterType: string;

packages/@aws-cdk/aws-ssm/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383
"@aws-cdk/assertions": "0.0.0",
8484
"@aws-cdk/cdk-build-tools": "0.0.0",
8585
"@aws-cdk/integ-runner": "0.0.0",
86+
"@aws-cdk/integ-tests": "0.0.0",
8687
"@aws-cdk/cfn2ts": "0.0.0",
8788
"@aws-cdk/pkglint": "0.0.0",
8889
"@types/jest": "^27.5.2",

0 commit comments

Comments
 (0)