How do I get a list of subnet IDs from one stack to another using SSM when StringListParameter doesn't work?

874 Views Asked by At

According to this bug and this bug, ssm.StringListParameter doesn't work in the CDK due to some issues with CFT.

I need to be able to export an arbitrarily length list of subnetIds from one stack and import the list into another using SSM, as the lifetime of subnetIds is completely different than the lifetime of the consumer of subnetIds in a second stack (especially in production, though not in a sandbox). I cannot hard code the subnet IDs, as when creating a sandbox the IDs would vary from sandbox to sandbox. I want the latest version of whatever is in the SSM key.

However, the bugs appear to not be resolvable, and I cannot find a work around.

I tried serializing using JSON, but the item passed around the code is is a late binding Token, which is treated as a string, and the deserialized items is a string [], so it's not possible to get such code to compile.

Here's an example of what I attempted. It doesn't compile:

export function getOtherStackOutputList(stack: cdk.Stack, mangledOtherStackName: string, key: string): string [] { 
  const globallyUniqueKey = `/${mangledOtherStackName}/${key}`;
  const jsonResult = ssm.StringParameter.fromStringParameterName(stack, key + 'SSM', globallyUniqueKey).stringValue;
  if (cdk.Token.isUnresolved(jsonResult)) {
    return jsonResult;
  } else { 
    const result = JSON.parse(jsonResult);
    return result;
  } 
};

which would be used by code that looks like this:

const efsVpcIsolatedSubnetsIds = StackValueShare.getOtherStackOutputList(this, mangledStackName + efsDbStackSuffix,
      'efsTimeSeriesDatabaseVpcIsolatedSubnets');
1

There are 1 best solutions below

0
On

This works for me:

import { Construct } from '@aws-cdk/core';
import { AwsCustomResource, AwsSdkCall } from '@aws-cdk/custom-resources';
import iam = require("@aws-cdk/aws-iam");

interface SSMParameterReaderProps {
  parameterName: string;
  region: string;
}

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()} // Update physical id to always fetch the latest version
    };

    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();
  }
}