AWS CDKで管理しているスタックの削除保護を有効化してみた

AWS CDKで管理しているスタックの削除保護を有効化の方法を調べて、試してみました。
2022.03.12

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

AWS CDKで管理しているスタックの削除保護ってどうするんだろう

こんにちは、のんピ(@non____97)です。

「AWS CDKで管理しているスタックの削除保護ってどうするんだろう」と思ったことはありますか? 私はあります。

AWS CDKではcdk destroyで簡単にスタックを削除できます。私は非常にうっかりさんなので、絶対に削除したくないスタックには念のため削除保護をしたいなと思いました。

そこで、「よし、じゃあ削除保護を有効化するか!」と思ったのですが、実際設定を知らなかったので今回確認してみました。

API Referenceに書いてある

困った時はAPI Referenceということで、確認したら早速見つけました。

スタックを作成する際のプロパティとして、terminationProtectiontrueにすれば良さそうですね。

やってみた

実際にやってみます。

まず、terminationProtectionを指定しない場合の削除保護はどうなっているか確認します。

./bin/vpc.ts

#!/usr/bin/env node
import "source-map-support/register";
import * as cdk from "aws-cdk-lib";
import { VpcStack } from "../lib/vpc-stack";

const app = new cdk.App();
new VpcStack(app, "VpcStack");

こちらのスタック(VpcStack)では以下のようにVPCを作成します。

./lib/vpc-stack.ts

import { Stack, StackProps, aws_ec2 as ec2 } from "aws-cdk-lib";
import { Construct } from "constructs";

export class VpcStack extends Stack {
  public readonly vpc: ec2.IVpc;

  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    new ec2.Vpc(this, "Vpc", {
      cidr: "10.11.0.0/24",
      natGateways: 0,
    });
  }
}

npx cdk deploy VpcStackでスタックを作成します。

作成後のスタックをマネージメントコンソールから確認すると削除保護は無効になっていました。

terminationProtectionを指定しない場合

次に、terminationProtectiontrueにした場合を確認します。

以下のようにVpcStackの第3引数で指定しました。

./lib/vpc-stack.ts

#!/usr/bin/env node
import "source-map-support/register";
import * as cdk from "aws-cdk-lib";
import { VpcStack } from "../lib/vpc-stack";

const app = new cdk.App();
new VpcStack(app, "VpcStack", {
  terminationProtection: true,
});

変更後、npx cdk deploy VpcStackでスタックを更新します。

更新後のスタックをマネージメントコンソールから確認すると削除保護は有効になっていました。

terminationProtectionでtrueを指定した場合

この状態でスタックを削除しようとすると、とてつもなく怒られました。確かに削除保護が動作していますね。

> npx cdk destroy VpcStack
MFA token for arn:aws:iam::<AWSアカウントID>:mfa/<IAMユーザー名>: 768613
Are you sure you want to delete: VpcStack (y/n)? y
VpcStack: destroying...

 ❌  VpcStack: destroy failed Error [ValidationError]: Stack [VpcStack] cannot be deleted while TerminationProtection is enabled
    at Request.extractError (/<ディレクトリパス>/cdk/database/node_modules/aws-sdk/lib/protocol/query.js:50:29)
    at Request.callListeners (/<ディレクトリパス>/cdk/database/node_modules/aws-sdk/lib/sequential_executor.js:106:20)
    at Request.emit (/<ディレクトリパス>/cdk/database/node_modules/aws-sdk/lib/sequential_executor.js:78:10)
    at Request.emit (/<ディレクトリパス>/cdk/database/node_modules/aws-sdk/lib/request.js:686:14)
    at Request.transition (/<ディレクトリパス>/cdk/database/node_modules/aws-sdk/lib/request.js:22:10)
    at AcceptorStateMachine.runTo (/<ディレクトリパス>/cdk/database/node_modules/aws-sdk/lib/state_machine.js:14:12)
    at /<ディレクトリパス>/cdk/database/node_modules/aws-sdk/lib/state_machine.js:26:10
    at Request.<anonymous> (/<ディレクトリパス>/cdk/database/node_modules/aws-sdk/lib/request.js:38:9)
    at Request.<anonymous> (/<ディレクトリパス>/cdk/database/node_modules/aws-sdk/lib/request.js:688:12)
    at Request.callListeners (/<ディレクトリパス>/cdk/database/node_modules/aws-sdk/lib/sequential_executor.js:116:18) {
  code: 'ValidationError',
  time: 2022-03-11T08:37:57.965Z,
  requestId: '68d8d382-b030-4dcb-aef0-d6f17863e8b2',
  statusCode: 400,
  retryable: false,
  retryDelay: 791.5998092652587
}

Stack [VpcStack] cannot be deleted while TerminationProtection is enabled

最後にこの状態で、terminationProtectionfalseにして、npx cdk destroy VpcStackを実行します。

./bin/vpc.ts

#!/usr/bin/env node
import "source-map-support/register";
import * as cdk from "aws-cdk-lib";
import { VpcStack } from "../lib/vpc-stack";

const app = new cdk.App();
new VpcStack(app, "VpcStack", {
  terminationProtection: false,
});
MFA token for arn:aws:iam::<AWSアカウントID>:mfa/<IAMユーザー名>: 722992
Are you sure you want to delete: VpcStack (y/n)? y
VpcStack: destroying...

 ❌  VpcStack: destroy failed Error [ValidationError]: Stack [VpcStack] cannot be deleted while TerminationProtection is enabled
    at Request.extractError (/<ディレクトリパス>/cdk/database/node_modules/aws-sdk/lib/protocol/query.js:50:29)
    at Request.callListeners (/<ディレクトリパス>/cdk/database/node_modules/aws-sdk/lib/sequential_executor.js:106:20)
    at Request.emit (/<ディレクトリパス>/cdk/database/node_modules/aws-sdk/lib/sequential_executor.js:78:10)
    at Request.emit (/<ディレクトリパス>/cdk/database/node_modules/aws-sdk/lib/request.js:686:14)
    at Request.transition (/<ディレクトリパス>/cdk/database/node_modules/aws-sdk/lib/request.js:22:10)
    at AcceptorStateMachine.runTo (/<ディレクトリパス>/cdk/database/node_modules/aws-sdk/lib/state_machine.js:14:12)
    at /<ディレクトリパス>/cdk/database/node_modules/aws-sdk/lib/state_machine.js:26:10
    at Request.<anonymous> (/<ディレクトリパス>/cdk/database/node_modules/aws-sdk/lib/request.js:38:9)
    at Request.<anonymous> (/<ディレクトリパス>/cdk/database/node_modules/aws-sdk/lib/request.js:688:12)
    at Request.callListeners (/<ディレクトリパス>/cdk/database/node_modules/aws-sdk/lib/sequential_executor.js:116:18) {
  code: 'ValidationError',
  time: 2022-03-11T08:44:43.218Z,
  requestId: 'd33ac328-2491-47a7-bcbf-77bb4c4c0b30',
  statusCode: 400,
  retryable: false,
  retryDelay: 532.5637111139594
}

Stack [VpcStack] cannot be deleted while TerminationProtection is enabled

やはりとてつもなく怒られました。スタックの更新をせずに削除しようとするな。横着するな。ということですね。

そのため、スタックを削除したい場合は、一度terminationProtectionfalseにした状態でcdk deployをした上で、cdk destroyをする必要があります。

本番運用中は削除保護の有効化がオススメ

AWS CDKで管理しているスタックの削除保護を有効化してみました。

クロススタック参照している場合、参照先のスタックを削除してしまうと、参照元のスタックも削除されてしまいます。そういった意図しないスタック削除を防ぐ意味で削除保護が非常に大切です。開発期間中はterminationProtectionfalseにしておいて、本番稼働後はterminationProtectiontrueにするといった運用をすれば安心かと思います。

この記事が誰かの助けになれば幸いです。

以上、AWS事業本部 コンサルティング部の のんピ(@non____97)でした!