I have been using the solution proposed here (https://stackoverflow.com/a/59774628/91403) in order to access configurations stored in an AWS parameter.
export class SSMParameterReader extends AwsCustomResource {
constructor(scope: Construct, name: string, props: SSMParameterReaderProps) {
const { parameterName, region } = props;
const ssmAwsSdkCall: AwsSdkCall = {
service: 'SSM',
action: 'getParameter',
parameters: {
Name: parameterName
},
region,
physicalResourceId: {id:Date.now().toString()}
};
super(scope, name, { onUpdate: ssmAwsSdkCall,policy:{
statements:[new iam.PolicyStatement({
resources : ['*'],
actions : ['ssm:GetParameter'],
effect:iam.Effect.ALLOW,
}
)]
}});
}
public getParameterValue(): string {
return this.getResponseField('Parameter.Value').toString();
}
}
Now I came across a parameter in the JSON format and have found no way to access its value. I can’t seem to be able to parse it. Here is one example: { "subnetId": "subnet-xxxxxx" }
.
I have tried modifying the code in several ways but mainly in the likes of:
...
public getParameterValue(path: string): string {
return this.getResponseField(`Parameter.Value.${path}`).toString();
}
How can I extract the subnetId
value?
2
Answers
The complexity is that during the CDK’s planning phase (known as
synth
), you don’t have the actualsubnetId
value of this parameter. Instead, you have a placeholder.The approach is:
subnetId
value from the JSON-formatted string.{"subnetId": "subnet-xxxxxx"}
, you can use string manipulation functions likesplit
andselect
to dissect the string and grab thesubnetId
.Here’s how you can achieve this:
This method breaks down the JSON string into pieces and picks the part you need. It might seem a bit tricky, but it works for this specific JSON format. ¯(ツ)/¯
Using a lambda-backed custom resource (CR), you can fetch the parameter and parse the JSON string within the custom resource handler itself. The solution below supports (1) optional cross-region parameters and (2) an arbitrary number of keys in the stringified parameter.
Step 1: Define a custom resource
For convenience, I encapsulate the custom resource, the provider, and the lambda handler in a construct wrapper. Pass the SSM parameter name and optionally a region as props. The default region is the stack’s region.
Step 2: Define the CR lambda hander
The Lambda code first gets the parameter with the JS SDK v3 (preloaded with 18.x Lambdas). Then it parses the parameter string and returns the key-value pairs. I am omitting error handling for simplicity.
Step 3: Add the CR to a stack
Instantiate the CR in a stack. The
CfnOutput
is added to illustate how to consume the value. Upon deployment, the output value will print to the console:MyStackDD013518.SubnetId = subnet-xxxxxx
.Note that this solution supports a JSON parameter with multiple keys (e.g.
r.customResource.getAttString("anotherKey")
).