結論:JSONオブジェクトの静的メソッド(JSON.parse())とString オブジェクトのインスタンスメソッド(replace())を使用します。
概要
IaCでコード化する際、IAMポリシーをjsonファイルとして外だしする記述方法があると思います。
そういった記述方式の際、流用性を高めるにはアカウントIDやリージョン名などはハードコーディングしないのが望ましいです。
Terraformだとtemplatefile
関数を使って動的に対応することが可能です。同じようなことをCDK(TypeScript)でもやりたいと思って調べたところ、私の調査力ではCDK APIに見つけられず、たどり着いたのがJavaScriptの標準オブジェクトとメソッドの組み合わせでした。
本記事ではその手法を備忘録として残します。
実践
簡単ですが、IAMポリシーを作成してみます。
IAMポリシー用jsonファイル
作成するIAMポリシー用jsonファイルを以下のように記述しました。
変換したい個所を{任意の文字列}
で記述しています。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "TestPolicy",
"Effect": "Allow",
"Action": ["ec2:StartInstances"],
"Resource": ["arn:{Partition}:ec2:{Region}:{Account}:instance/*"]
}
]
}
stackファイル
デプロイするstackファイルを以下のように記述しました。
import * as cdk from "aws-cdk-lib";
import { Construct } from "constructs";
import * as iam from "aws-cdk-lib/aws-iam";
import * as path from "path";
import * as fs from "fs";
export class CdkAppStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// 擬似パラメータインスタンス作成
const pseudo = new cdk.ScopedAws(this);
// JSONファイルパス
const filePath = path.join(`${__dirname}`, "./json/test-policy.json");
// JSONファイルをJSON文字列として読み込み
const jsonData = fs.readFileSync(filePath, "utf8");
// 文字列置換&JSONパース(JavaScriptオブジェクトに変換)
const jsonPolicy = JSON.parse(
jsonData
.replace(/{Partition}/g, pseudo.partition)
.replace(/{Region}/g, pseudo.region)
.replace(/{Account}/g, pseudo.accountId)
);
// IAMポリシー作成
new iam.ManagedPolicy(this, "policy", {
managedPolicyName: "iam-policy",
document: iam.PolicyDocument.fromJson(jsonPolicy),
});
}
}
処理フロー
JSONファイルをJSON文字列として読み込み
初めに、指定のjsonファイルをreadFileSync()
でjson文字列として読み込みます。
const jsonData = fs.readFileSync(filePath, "utf8");
文字列置換し、JavaScriptオブジェクトに変換
replace()
を使用して、jsonData
内の文字列を変換します。/g
をつけることで、一括置換が可能です。
const jsonPolicy = JSON.parse(
jsonData
.replace(/{Partition}/g, pseudo.partition)
.replace(/{Region}/g, pseudo.region)
.replace(/{Account}/g, pseudo.accountId)
);
CFnテンプレート確認
cdk synth --no-version-reporting --no-path-metadata
で出力されるCFnテンプレートがこちら。
AWS CloudFormationで使用できる擬似パラメータに変換されていることが確認できます。
Resources:
policyE16B4B70:
Type: AWS::IAM::ManagedPolicy
Properties:
Description: ""
ManagedPolicyName: iam-policy
Path: /
PolicyDocument:
Statement:
- Action: ec2:StartInstances
Effect: Allow
Resource:
Fn::Join:
- ""
- - "arn:"
- Ref: AWS::Partition
- ":ec2:"
- Ref: AWS::Region
- ":"
- Ref: AWS::AccountId
- :instance/*
Sid: TestPolicy
Version: "2012-10-17"
デプロイして確認
cdk deploy
で作成されたIAMポリシーがこちら。問題なく擬似パラメータが変換されているのが確認できます。
まとめ
今回は、CDK(TypeScript)で外部のjsonファイル内の文字列を変換する方法を記事にしました。
もっとスマートなやり方があるかもしれませんが、もしご存じの方がいらっしゃいましたらアドバイスいただけると幸いです。