🎅

ComformancePackやStackSetsのtemplateもcdkでやりたい

2022/12/01に公開

これは AWS CDK Advent Calendar 2022 の 1日目の記事です。

かわごえです。

先日、CfnOrganizationConformancePackを作成する機会がありドキュメントを眺めていて思ったことがありました。

image

Type: string (optional)

め、め、めんどくさい!!!!

というわけで、ConformancePackのtemplateBodyに渡すCloudFormationのTemplateもCDKでやれないかな〜〜〜〜〜〜と思い、やってみました。

結論:できました。

CDKで定義していく

Config RuleのStackをCDKで定義

export class RuleStack extends Stack{
  constructor(scope: Construct, id: string, props?: StackProps){
      super(scope, id, props)

      new ManagedRule(this, 'rule', {
        identifier: 'ACCESS_KEYS_ROTATED'
      })

  }
}

ConformancePackのStackをCDKで定義

export interface ConformanceStackProps extends StackProps{
  templateBody: string
}
export class ConformanceStack extends Stack{
  constructor(scope: Construct, id: string, props: ConformanceStackProps){
    super(scope, id, props)
    
    new CfnOrganizationConformancePack(this, "conformancePack", {
      templateBody: props.templateBody,
      organizationConformancePackName: 'conformancePack-demo'
    })

  }
}

templateBodyはAppの処理内で受け取ります。

Stage下でConfig RuleのStackをnewする

// Template用のStage
const templateStage = new Stage(app, 'template')
const stack = new RuleStack(templateStage, 'RuleTemplate', {
  analyticsReporting: false,
  synthesizer: new CliCredentialsStackSynthesizer()
})
const artifactId = stack.artifactId


const templateBody = yaml.stringify(templateStage.synth().getStackArtifact(artifactId).template)
new ConformanceStack(app, 'ConformanceStack', {
  templateBody: templateBody
})

同じCDKアプリケーション内に定義しているので、
cdk deployでデプロイされるようなことは起こって欲しくないです。sythesizeだけしてくれたらいい。

なのでTemplateだけ欲しいStackはStageの下に置くことにしました。

これでcdk deployを行うためにはcdk deploy "{StageId}/*"まで実行しないとデプロイされません。
--allでもデプロイされません。

また、BootstrapVersionのパラメータも必要ないので、synthesizerにはCliCredentialsStackSynthesizerを指定します。

ここまでくればStageをsynthして、getStackArtifact()でCloudFormationStackArtifactが取得できます。あとはJSONでstringにしてあげれば完成です。

ソースコード全体

import { App,  CliCredentialsStackSynthesizer,  Stack,  StackProps,  Stage } from 'aws-cdk-lib';
import { CfnOrganizationConformancePack, ManagedRule } from 'aws-cdk-lib/aws-config';
import { Construct } from 'constructs';
import * as yaml from "yaml"

export class RuleStack extends Stack{
  constructor(scope: Construct, id: string, props?: StackProps){
      super(scope, id, props)

      new ManagedRule(this, 'rule', {
        identifier: 'ACCESS_KEYS_ROTATED'
      })

  }
}

export interface ConformanceStackProps extends StackProps{
  templateBody: string
}
export class ConformanceStack extends Stack{
  constructor(scope: Construct, id: string, props: ConformanceStackProps){
    super(scope, id, props)
    
    new CfnOrganizationConformancePack(this, "conformancePack", {
      templateBody: props.templateBody,
      organizationConformancePackName: 'conformancePack-demo'
    })

  }
}

const app = new App();

// Template用のStage
const templateStage = new Stage(app, 'template')
const stack = new RuleStack(templateStage, 'RuleTemplate', {
  analyticsReporting: false,
  synthesizer: new CliCredentialsStackSynthesizer()
})
const artifactId = stack.artifactId


const templateBody = yaml.stringify(templateStage.synth().getStackArtifact(artifactId).template)
new ConformanceStack(app, 'ConformanceStack', {
  templateBody: templateBody
})

app.synth();

で、ここまでやる必要ある???

正直あんまりないかも。自己責任でお願いします!!!!

CloudFormationのテンプレートをyaml/jsonで書くよりは楽にTypescriptの場合は型アサーションの恩恵・L2の恩恵を受けながら楽に定義ができるので、まあいいかなって思ってます。

もうyamlもjsonもあんまり書きたくないんです

ConformacePackの場合はテンプレートの記述量も少ないですが、
StackSetsなどで複雑なリソースを定義する必要がある場合には楽にできるかもです。(まだやってない)

もっと楽にやれるよ〜とかあればそれも教えてください。よろしくお願いします。

以上!!!!

Discussion