AWSで環境変数をSystems Managerのパラメータストアに保存して、EC2やLambdaから参照する場面は多くあります。
そういったとき、AWS CDKではこんなコード(EC2インスタンスを作り、既存のパラメータストアのRead権限を付与する例です)を書きますが、
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as ssm from 'aws-cdk-lib/aws-ssm';
export class ExampleStack extends Construct {
constructor(scope: Construct, id: string, props: {}) {
super(scope, id);
const instance = new ec2.Instance(this, 'Instance', {/* 略 */});
const param = ssm.StringParameter.fromStringParameterAttributes(this, 'Param', {
parameterName: '/example/param',
});
param.grantRead(instance);
// 以下略
パラメータの種類がSecureStringの場合、cdk diff は問題ないのですが cdk deploy をすると……
ExampleStack: deploying... [1/1] ExampleStack: creating CloudFormation changeset... ❌ ExampleStack failed: ValidationError: Parameters [/example/param] referenced by template have types not supported by CloudFormation.
“referenced by template have types not supported by CloudFormatin” という何のことだか分かりづらいエラーが発生します。
原因と修正
パラメータストアの「安全な文字列」(SecureString) は暗号化されているため、通常の文字列のパラメータとは扱い方が違います。例えば、通常の文字列のパラメータストアは param.stringValue としてCDK (CFn)の中で文字列を参照できますが、SecureStringだとデプロイ時にエラーとなります。
参照するときに使う関数も異なり、fromStringParameterAttributes関数やfromStringParameterName関数ではなく、fromSecureStringParameterAttributes関数を使う必要があります。
そのため上のコードは、
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as ssm from 'aws-cdk-lib/aws-ssm';
export class ExampleStack extends Construct {
constructor(scope: Construct, id: string, props: {}) {
super(scope, id);
const instance = new ec2.Instance(this, 'Instance', {/* 略 */});
const param = ssm.StringParameter.fromSecureStringParameterAttributes(this, 'Param', {
parameterName: '/example/param',
});
param.grantRead(instance);
// 以下略
とする必要がありました。
最後に
見返すとすごく単純な話ですが、何となくコーディングしていると関数名の “Secure” を見落としまってデプロイ時にエラーが出るという落とし穴の紹介でした。

ちなみにですが、APIキーやパスワードなどの文字列の保管には、Systems ManagerのパラメータストアではなくAWS Secretsを使った方がいいかもしれません。1つのパラメータをJSONで保管できたり、CDKでも参照が柔軟( hogeSecret.unsafeUnwrap()で直接文字列を参照できるなど)になります。





