aws / aws-cdk

The AWS Cloud Development Kit is a framework for defining cloud infrastructure in code
https://aws.amazon.com/cdk
Apache License 2.0
11.35k stars 3.76k forks source link

MachineImage: resolveSsmParameterAtLaunch fails CloudFormation #26712

Open mgwidmann opened 10 months ago

mgwidmann commented 10 months ago

Describe the bug

MachineImage.resolveSsmParameterAtLaunch("...") does not produce the correct imageId string required by CloudFormation.

As can be seen here: https://github.com/aws/aws-cdk/blob/main/packages/aws-cdk-lib/aws-ec2/lib/machine-image/machine-image.ts#L259

The string produced is resolve:ssm:${this.parameterName}${versionString} when the CloudFormation documentation states it should be {{resolve:ssm:${this.parameterName}${versionString}}} instead (two extra open and close braces at start and end).

CloudFormation Documentation on dynamic SSM parameter references: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/dynamic-references.html

Expected Behavior

The imageId value is produced with the correct syntax and CloudFormation is able to successfully process the value.

Current Behavior

CloudFormation currently fails with the following error message:

Resource handler returned message: "Unsupported data type. The following parameter data types are supported: aws:ec2:image (Service: AmazonEC2; Status Code: 400; Error Code: SsmInvalidParameter; Request ID: b045aa93-4c28-40b6-80da-c654e4daab78; Proxy: null)" (RequestToken: 5d1c2355-257a-79a1-bc99-d9ac75740c23, HandlerErrorCode: GeneralServiceException)

Reproduction Steps

Use MachineImage.resolveSsmParameterAtLaunch("any-ssm-parameter-name") in a LaunchTemplate for an ASG.

Possible Solution

Current workaround is to use MachineImage.fromSsmParameter("any-ssm-parameter-name").

Additional Information/Context

No response

CDK CLI Version

2.90.0

Framework Version

No response

Node.js Version

18.17.1

OS

Mac M1

Language

Python

Language Version

3.10.11

Other information

No response

pahud commented 10 months ago

resolveSsmParameterAtLaunch creates the resolve:ssm:{ParameterName} string which will only be resolved at instance launch time rather than cloudformation deployment time so we can't see the imageId until instance is launched.

This means cloudformation does not know if that will be resolved to any imageId because it points to a custom SSM parameter name and we will only know that when a new instance is launched.

check out the following documents for more details:

Using SSM Parameter with Autoscaling and Launch Template Launch an instance using a Systems Manager parameter

mgwidmann commented 10 months ago

I don't get it, if CloudFormation doesn't know about this feature and crashes on it, why put it into CDK?

IwoTens commented 7 months ago

If I read the error message correct, then it just means that your ssm parameter has the wrong data type. See here and note the distinction between type and data type. (This tripped me up as well)

kliuModerna commented 4 months ago

Any updated on this issue?

DinosaurDad commented 1 month ago

For me, it doesn't matter if I use fromSsmParameter() or resolveSsmParameterAtLaunch(). In both cases, I have success only if I append /image_id to the parameter. Took a lot of exploration to figure out the workaround. For ECS instances, this works for me:

MachineImage.resolveSsmParameterAtLaunch("/aws/service/ecs/optimized-ami/amazon-linux-2/recommended/image_id")

MachineImage.fromSsmParameter("/aws/service/ami-windows-latest/Windows_Server-2022-English-Core-ECS_Optimized/image_id")