AWS CDKのL1 Constructs(CfnXXX)のGetAttでリストが返ってくるときの処理方法

CDKでL1 Constructs(CfnXXX)を使う際に、CloudFormationのGetAttでリストが返ってくる場合にどうやって処理をしたらいいのかハマってしまいました。その解決方法を紹介します。
2020.12.28

AWS CDK使ってますか?

僕は環境構築にバリバリ使っていますが、時にはまだ高級レイヤーでは対応していないので低レイヤーのL1 Constructs(CfnXXX)を使ったりすることもあります。

そんな時にちょっと困ってしまったのが、CloudFormationの GetAtt でリストが返ってくる場合にどうやって処理をしたらいいのかハマってしまいました。

具体例をあげると、 MicrosoftAD を作ると GetAtt を利用して DnsIpAddresses をリストで取得できます。

そして、これをそのまま DHCPオプションセットDNS として設定したい。そんな場面です。

GetAttでリストを取得したとしても、プログラムコード上ではリストとして取り扱われていないので、単純に当て込めただけではうまくいきません。 その解決方法を紹介します。

解決方法

@aws-cdk/coreToken.asList() を利用します。

具体的に環境を構築するコードを書くとこんな感じです。

#!/usr/bin/env node
import "source-map-support/register";
import * as Core from "@aws-cdk/core";
import * as EC2 from "@aws-cdk/aws-ec2";
import * as DirectoryService from "@aws-cdk/aws-directoryservice";

class TestStack extends Core.Stack {
  constructor(scope: Core.Construct, id: string, props?: Core.StackProps) {
    super(scope, id, props);

    const domainName: string = 'kitano.local';
    const adPassword: string = 'Password01!';

    const vpc = new EC2.Vpc(this, "VpcAD", {
      enableDnsHostnames: true,
      enableDnsSupport: true,
      maxAzs: 2,
      subnetConfiguration: [{
        name: 'PublicSubnet',
        subnetType: EC2.SubnetType.PUBLIC,
        cidrMask: 24,
        reserved: false,
      },
      ],
    });

    const subnetIds: string[] = vpc.publicSubnets.map((iSubnet: EC2.ISubnet): string => iSubnet.subnetId);

    const microsoftAD = new DirectoryService.CfnMicrosoftAD(this, 'MicrosoftAD', {
      name: domainName,
      password: adPassword,
      vpcSettings: {
        subnetIds: subnetIds,
        vpcId: vpc.vpcId,
      },
      edition: 'Standard',
    });

    const dhcpOptionSet = new EC2.CfnDHCPOptions(this, 'DHCPOptions', {
      domainName: domainName,
      domainNameServers: Core.Token.asList(microsoftAD.getAtt('DnsIpAddresses')),
    });

    new EC2.CfnVPCDHCPOptionsAssociation(this, 'VPCDHCPOptionsAssociation', {
      dhcpOptionsId: dhcpOptionSet.ref,
      vpcId: vpc.vpcId,
    });
  }
}

const app = new Core.App();
new TestStack(app, 'TestStack');

microsoftAD.getAtt('DnsIpAddresses') でIPアドレスのリストを取得したうえで、 Token.asList() をかまして CfnDHCPOptionsdomainNameServers にセットするとうまくいきます。

参考にしたページ

aws-cdkのissueに似たような問題が載っていたので参考にしました。