でこてっくろぐ ねお

でこてっくろぐ(http://dekokun.github.io/)から進化しました。でこらいふろぐ(http://dekolife.hatenablog.com/)の姉妹版。デコテックログ(deko tech log)である

CloudFormationのスタックポリシーでUpdate:*をDenyしててもやはり消える時は消える、という話及び削除への対処

このエントリで伝えたいこと

  • CloudFormationのスタックポリシーでUpdate:*をDenyしてても安心はできない。消える時は消える
  • 上記はある程度皆知ってるかもしれませんが、一応試してみた、及び考えられる削除に対する保護の方法を考えるという感じのエントリ

スタックポリシーについて

CloudFormationにおいて、一度作成したリソースが変更されたり削除されたり置換されたりするのを防ぐ方法があります。 スタックポリシーですね。例えば、以下のようなJSONhoge_policy.json というファイルに保存し aws cloudformation set-stack-policy --stack-name hoge-stack --stack-policy-body=file://./hoge_policy.json のようなコマンドで適用すると、CloudFormation経由では対象のstackのリソースに対しては更新が一切できないようになります

{
  "Statement" : [
    {
      "Effect" : "Deny",
      "Action" : "Update:*",
      "Principal": "*",
      "Resource" : "*"
    }
  ]
}

実際に上記のようなポリシーを適用したスタックに対してCloudFormation経由で変更を加えようとすると、以下のようなエラーが出力されて変更ができません。

Action denied by stack policy: Statement [#1] does not allow [Update:*] for resource [*];

ではこれで安心かというと、もちろんそうではないんですよね。スタックポリシーについては以下ドキュメントにあるように、スタックの更新時にしか適用されません。 逆に、スタックの更新時以外の場面では無力ということになります。

スタックポリシーは、スタックの更新時のみ適用されます

参照: スタックのリソースが更新されないようにする - AWS CloudFormation

それは具体的にどのような時かというと、パッと思いつく範囲では以下のような時になります。一応以下両方とも試してみて、スタックポリシーで Update:*Deny されている状態で対象のリソースが削除できることを確認しました。

  • 対象のstack自体を削除
  • CloudFormationを経由せずに手(もしくはAPI)で削除

対処法

stackの削除への対処

stackが削除された際でも対象のリソースを残しておきたい場合は、以下のようにDeletionPolicyを指定する方法が有効です。 docs.aws.amazon.com

具体的には、CloudFormationにおいては以下のように DeletionPolicy : Retain を指定しておく、という感じになります。こうしておくと、Stackが何かによって削除されても、そのリソース自体は残り続けます(一応試しました)

exampleSecurityGroup:
  Type: "AWS::EC2::SecurityGroup"
  Properties: 
     ... 中略
  DeletionPolicy : Retain # これ

このエントリを公開した後に、以下のような反響をもらいました。 確かに、上記の場合、対象のセキュリティグループにDeletionPolicyをつけた状態でVPCごとstackを削除したりするとどうなるのか、大変気になりますね。また試してみたらエントリにしてみます。

手動やAPI等の、CloudFormation以外での対象のリソースの削除

こちらの対策については、CloudFormation関係なく、一般的なAWSのリソースの保護方法を採ることになるかと思います。 と言ってもこちらは私はあまり詳しくなく、EC2の場合はterminateion protectionを付ける、くらいしか知りません。 他のリソースでも削除から保護することはできるのでしょうか。是非教えていただきたい。

CloudFormationでEC2のtermination protectionを付ける方法は以下のとおりです

  SampleEC2: 
    Type: "AWS::EC2::Instance"
    Properties: 
      DisableApiTermination: true # これ

雑感

今回は、かなりわかりきった内容、という感じではありますが、一応テストしてみたのでブログにまとめてみたという感じでした。 実際CloudFormationにおいては重要なリソースの保護をどのように行うかについてはある程度考えておく必要があるなというのが最近の思いであり、そのあたりはまた別エントリにまとめたいなと思っています。