[アップデート]AWS CloudFormationの変更セットの差分がプロパティレベルで確認できるようになりました

2024.04.17

初めに

本日のAWS CloudFormationのアップデートで変更セット上でより詳細な変更差分が確認できるようになりました。

従来ではCloudFormationで変更セット作成することで変更前後のテンプレートでどのリソースが変更対象となるかまでは確認できたのですが、具体的にどのような変更が発生したかを変更セット上では確認することができないものとなっておりました。

その関係で意図しないリソースの変更は軽減できるものの意図しない設定値の変更までは見ることができなかったのですが、今回のアップデート以降はプロパティレベルで確認できるようになりより具体的な変更をチェックできるようになりました。

デプロイをするときなどはいつも手元でgit diffを確認して本当に大丈夫?gitに乗ってないような変更もないよね?と心配になるシーンは多くありましたが、今回の変更のおかげでマネジメントコンソール上で具体的な差分確認が格納でチェック負荷が軽減されます。

試してみる

以下で構築したテンプレートをベースに設定を変更してみます。

上記記事で利用したリソースにS3バケットがありそちらのバケットポリシーに対して以下のように自アカウント内のアクセスポイントからのアクセスを許可するように設定を追加します。

  MailBucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Sub ${MyDomain}-mail-stocker
      PublicAccessBlockConfiguration:
        BlockPublicAcls: True
        BlockPublicPolicy: True
        IgnorePublicAcls: True
        RestrictPublicBuckets: True
      OwnershipControls:
        Rules:
          - ObjectOwnership: BucketOwnerEnforced
      BucketEncryption:
        ServerSideEncryptionConfiguration:
          - BucketKeyEnabled: True
            ServerSideEncryptionByDefault:
              SSEAlgorithm: AES256
  MailBucketPolicy:
    Type: AWS::S3::BucketPolicy
    Properties:
      Bucket: !Ref MailBucket
      PolicyDocument: 
        Version: 2012-10-17
        Statement: 
          - Sid: AllowPutFromSES
            Effect: Allow
            Principal: 
              Service: ses.amazonaws.com
            Action: s3:PutObject
            Resource: !Sub arn:aws:s3:::${MailBucket}/source/*
            Condition: 
              StringEquals: 
                aws:Referer: !Ref AWS::AccountId
+         - Sid: AllowFromMyAccountAPReadAccess
+           Effect: "Allow"
+           Principal:
+             AWS: "*"
+           Action:
+             - "s3:Get*"
+             - "s3:List*"
+           Resource:
+             - !Sub "arn:aws:s3:::${MailBucket}"
+             - !Sub "arn:aws:s3:::${MailBucket}/*"
+           Condition:
+             StringEquals:
+               s3:DataAccessPointAccount: !Ref AWS::AccountId

変更セットを作成し確認してみると「プロパティレベルの変更」というカラムが追加されています。

「詳細を表示」を開くとそのリソースの変更箇所があったプロパティ名とその内容、変更前後両方のテンプレートの内容が表示されます。

この状態だとdiffの着色がなく分かりづらいのですが、変更のあったプロパティの左側のチェックボックスをいれるとハイライトしてくれます。

ただしあくまで変更差分値はCloudFormatino側のプロパティ単位(今回の場合はPolicyDocument)となっております。
今回のようにJSONをまるっと指定するような値の場合はその部分全体が差分としてハイライトされその内容の具体的な部分のみを示すものとはならない点ご注意ください。

JSONだとやや見づらい部分ではありますがString等のシンプルな値であれば見通しは良さそうです。

JSONの変更のタブ上pathbeforeValueafterValueでも変更は確認可能です。

  {
    "type": "Resource",
    "resourceChange": {
      "action": "Modify",
      "logicalResourceId": "MailBucketPolicy",
      "physicalResourceId": "rua.example.com-mail-stocker",
      "resourceType": "AWS::S3::BucketPolicy",
      "replacement": "False",
      "scope": [
        "Properties"
      ],
      "details": [
        {
          "target": {
            "attribute": "Properties",
            "name": "PolicyDocument",
            "requiresRecreation": "Never",
            "path": "/Properties/PolicyDocument",
            "beforeValue": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Condition\":{\"StringEquals\":{\"aws:Referer\":\"000000000000\"}},\"Action\":\"s3:PutObject\",\"Resource\":\"arn:aws:s3:::rua.example.com-mail-stocker/source/*\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"ses.amazonaws.com\"},\"Sid\":\"AllowPutFromSES\"}]}",
            "afterValue": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Condition\":{\"StringEquals\":{\"aws:Referer\":\"000000000000\"}},\"Action\":\"s3:PutObject\",\"Version\":\"2012-10-17\",\"Resource\":\"arn:aws:s3:::rua.example.com-mail-stocker/source/*\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"ses.amazonaws.com\"},\"Sid\":\"AllowPutFromSES\"},{\"Condition\":{\"StringEquals\":{\"s3:DataAccessPointAccount\":\"000000000000\"}},\"Action\":[\"s3:Get*\",\"s3:List*\"],\"Resource\":[\"arn:aws:s3:::rua.example.com-mail-stocker\",\"arn:aws:s3:::rua.example.com-mail-stocker/*\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"*\"},\"Sid\":\"AllowFromMyAccountAPReadAccess\"}]}",
            "attributeChangeType": "Modify"
          },
          "evaluation": "Static",
          "changeSource": "DirectModification"
        }
      ],
      "beforeContext": "{\"Properties\":{\"Bucket\":\"rua.example.com-mail-stocker\",\"PolicyDocument\":{\"Version\":\"2012-10-17\",\"Statement\":[{\"Condition\":{\"StringEquals\":{\"aws:Referer\":\"000000000000\"}},\"Action\":\"s3:PutObject\",\"Resource\":\"arn:aws:s3:::rua.example.com-mail-stocker/source/*\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"ses.amazonaws.com\"},\"Sid\":\"AllowPutFromSES\"}]}},\"Metadata\":{\"SamResourceId\":\"MailBucketPolicy\"}}",
      "afterContext": "{\"Properties\":{\"Bucket\":\"rua.example.com-mail-stocker\",\"PolicyDocument\":{\"Version\":\"2012-10-17\",\"Statement\":[{\"Condition\":{\"StringEquals\":{\"aws:Referer\":\"000000000000\"}},\"Action\":\"s3:PutObject\",\"Version\":\"2012-10-17\",\"Resource\":\"arn:aws:s3:::rua.example.com-mail-stocker/source/*\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"ses.amazonaws.com\"},\"Sid\":\"AllowPutFromSES\"},{\"Condition\":{\"StringEquals\":{\"s3:DataAccessPointAccount\":\"000000000000\"}},\"Action\":[\"s3:Get*\",\"s3:List*\"],\"Resource\":[\"arn:aws:s3:::rua.example.com-mail-stocker\",\"arn:aws:s3:::rua.example.com-mail-stocker/*\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"*\"},\"Sid\":\"AllowFromMyAccountAPReadAccess\"}]}},\"Metadata\":{\"SamResourceId\":\"MailBucketPolicy\"}}"
    }
  },

なおFn::Ref等で別のリソースを参照しているリソースがあり、その親リソース自体に対して置換が入る場合は{{changeSet:KNOWN_AFTER_APPLY}}と表示されます。
以下はバケット名を変更を加えてチェンジセットを作成した場合のバケットポリシー側の差分です。

すぐ作れそうなちょうどいい環境がなかったので確認していないのですが、直接変更してないリソースでも変更したリソースを参照しているものがあると変更セットに変更扱いで乗ってしまうものの一部はこの辺りの影響だったのでしょうか?

終わりに

今回のアップデートのおかげでより意図しない変更を最小化できるようになりました。マネジメントコンソール上では以前のテンプレートと合わせてリソース単位で全体像も見られるため以前のテンプレート自体が意図しているものかの確認も合わせてしやすく個人的にはかなり嬉しいアップデートです。

ただあくまで変更セットは以前のテンプレートとの差分となり引き続き手動で変更したようなリソースは含まれないものとなりなりますので手動変更が起こるような環境では引き続き変更前にドリフトの検出は忘れないようにしましょう。