LoginSignup
1
0

More than 3 years have passed since last update.

【AWS】【Cloudformation】CustomResource作ったら、Stack更新時にDeleteアクション実行してしまう件

Last updated at Posted at 2020-03-11

TL;DR

  • CustomResource作ったら、Stack更新時にDeleteアクション実行してしまう
  • これが、起きるのはCustomResourceのlambda処理を更新したとき
  • 原因はStackのCleanUp処理とPhysicalResourceIdの仕組み
  • CustomResourceの更新時にPhysicalResourceIdが変わってしまうと、CustomResourceにDelete Requestを送ってしまう
  • cfnresponse.sendで送るPhysicalResourceIdを固定することで、変更がなくなり、結果としてDeleteアクションを防げる

    • こんな感じで固定。Create時はeventにPhysicalResourceIdを持たないので、そこはうまくハンドル
  • pycfnresponse.send(event, context, cfnresponse.SUCCESS, response_data, event.get('PhysicalResourceId'))
    

環境

  • cfnresponseを使用したCustomResource
  • CustomResourceのlambdaはpythonで作成
    • SESのidentityにnotificationを設定するCustomResource
  • "RequestType": "Create", "RequestType": "Update", "RequestType": "Delete" それぞれ処理をハンドルしている

CustomResourceに送られるリクエストって?

  • こんな感じのが変数eventの中に入って送られてます

  • Create

{
  "RequestType": "Create",
  "ServiceToken": "arn:aws:lambda:us-west-2:******:function:set_identity_notifications",
  "ResponseURL": "https://cloudformation-custom-resource-response-uswest2.s3-us-west-2.amazonaws.com/arn%3Aaws%3Acloudformation%3Aus-west-2%3A535996888546%3Astack/ses-suppression-register/fa440490-497e-11ea-b69e-06fe8be0ff5e%7CProvideSetIdentityNotifications*******",
  "StackId": "arn:aws:cloudformation:us-west-2:535996888546:stack/ses-suppression-register/fa440490-497e-11ea-b69e-06fe8be0ff5e",
  "RequestId": "fe0f6642-9115-46d2-856d-98047f5c214b",
  "LogicalResourceId": "ProvideSetIdentityNotifications",
  "ResourceType": "AWS::CloudFormation::CustomResource",
  "ResourceProperties": {
    "ServiceToken": "arn:aws:lambda:us-west-2:******:function:set_identity_notifications",
    "HeadersInBounceNotificationsEnabled": "False",
    "ComplaintTopic": "",
    "HeadersInComplaintNotificationsEnabled": "False",
    "BounceTopic": "arn:aws:sns:us-west-2:*******:ses-suppression-list-topic",
    "Identities": "willco21.test.com"
  }
}
  • Update
{
  "RequestType": "Update",
  "ServiceToken": "arn:aws:lambda:us-west-2:*******:function:set_identity_notifications",
  "ResponseURL": "https://cloudformation-custom-resource-response-uswest2.s3-us-west-2.amazonaws.com/arn%3Aaws%3Acloudformation%3Aus-west-2%3A*******%3Astack/ses-suppression-register/6ba8e740-4989-11ea-9aac-06be751c1bd6%7CProvideSetId******",
  "StackId": "arn:aws:cloudformation:us-west-2:*******:stack/ses-suppression-register/6ba8e740-4989-11ea-9aac-06be751c1bd6",
  "RequestId": "c3a874a5-a181-4a5c-88fc-d2b2e1504aa0",
  "LogicalResourceId": "ProvideSetIdentityNotifications",
  "PhysicalResourceId": "2020/02/07/[$LATEST]0b367e84e59e46798738c00bece897be",
  "ResourceType": "AWS::CloudFormation::CustomResource",
  "ResourceProperties": {
    "ServiceToken": "arn:aws:lambda:us-west-2:*******:function:set_identity_notifications",
    "HeadersInBounceNotificationsEnabled": "False",
    "ComplaintTopic": "",
    "HeadersInComplaintNotificationsEnabled": "False",
    "BounceTopic": "arn:aws:sns:us-west-2:*******:ses-suppression-list-topic",
    "Identities": ["willco21.test.com", "example.co.jp"]
  },
  "OldResourceProperties": {
    "ServiceToken": "arn:aws:lambda:us-west-2:*******:function:set_identity_notifications",
    "HeadersInBounceNotificationsEnabled": "False",
    "ComplaintTopic": "",
    "HeadersInComplaintNotificationsEnabled": "False",
    "BounceTopic": "arn:aws:sns:us-west-2:*******:ses-suppression-list-topic",
    "Identities": ["willco21.test.com"]
  }
}
  • Delete
{
  "RequestType": "Delete",
  "ServiceToken": "arn:aws:lambda:us-west-2:*******:function:set_identity_notifications",
  "ResponseURL": "https://cloudformation-custom-resource-response-uswest2.s3-us-west-2.amazonaws.com/arn%3Aaws%3Acloudformation%3Aus-west-2%3A*******%3Astack/ses-suppression-register/6ba8e740-4989-11ea-9aac-06be751c1bd6%7C*******************",
  "StackId": "arn:aws:cloudformation:us-west-2:*******:stack/ses-suppression-register/6ba8e740-4989-11ea-9aac-06be751c1bd6",
  "RequestId": "33c8a15c-d8c1-477e-a88d-38c43fa46c67",
  "LogicalResourceId": "ProvideSetIdentityNotifications",
  "PhysicalResourceId": "2020/02/07/[$LATEST]0b367e84e59e46798738c00bece897be",
  "ResourceType": "AWS::CloudFormation::CustomResource",
  "ResourceProperties": {
    "ServiceToken": "arn:aws:lambda:us-west-2:*******:function:set_identity_notifications",
    "HeadersInBounceNotificationsEnabled": "False",
    "ComplaintTopic": "",
    "HeadersInComplaintNotificationsEnabled": "False",
    "BounceTopic": "arn:aws:sns:us-west-2:*******:ses-suppression-list-topic",
    "Identities": ["willco21.test.com"]
  }
}

PhysicalResourceIdについて

  • CFNで作成したリソースを判別するもの。実際に作成されたリソースを指すのが基本。PhysicalResourceId
  • LogicalResourceIdとは違う。
    • LogicalResourceIdはテンプレートのResourceで定義するリソース名
  • CustomResourceのlambdaには作成されたlambdaように作成された、CloudWatchLogsのLog streamが入る

なぜUpdateでDeleteアクション実行されるの??

  • cfnresponse.sendは5つ目の引数にPhysicalResourceIdが渡せる。
  • PhysicalResourceIdを渡さない場合は、新しいPhysicalResourceIdが勝手に送られる
  • 順番はこんな感じ
  1. CustomResourceのlambdaが更新
  2. 更新されたものでCustomResource実行
  3. 新しいLog stream作成
  4. cfnresponse.sendを実行するとそのLog streamでPhysicalResourceIdが更新される
  5. PhysicalResourceIdが更新されたので、StackのCleanUp処理で古いPhysicalResourceIdに関連するリソースはDelete リクエストが送られる
  6. CustomResourceがDeteleリクエストで実行される

回避策

  • cfnresponse.sendで送るPhysicalResourceIdを固定することで、変更がなくなり、結果としてDeleteアクションを防げる

    • こんな感じで固定。Create時はeventにPhysicalResourceIdを持たないので、そこはうまくハンドル
  • pycfnresponse.send(event, context, cfnresponse.SUCCESS, response_data, event.get('PhysicalResourceId'))
    

参考

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0