🐩

AWS Backupの通知設定をCloudFormationテンプレートに組み込む

に公開

1.はじめに

AWS Backupの通知設定は下記ドキュメントに示す通り、2つの方法が存在します。(2025年5月現在)

https://docs.aws.amazon.com/ja_jp/aws-backup/latest/devguide/backup-notifications.html

  • ①User Notifications
    Amazon Q Developer in chat applications(旧称: AWS Chatbot)と統合して、SlackやMicrosoft Teamsへの通知も可能です。

  • ②SNS
    SlackやMicrosoft Teamsへの通知が必要な場合はLambdaへさらに関連付けを行います。


※どちらの方法でもEventBridgeルールが作成されますが、AWS管理のルールのためマネジメントコンソールのEventBridgeからは編集ができません。

本記事では、②SNSを用いる方法でAWS Backupの通知設定を組み込んだバックアップボールト、バックアッププランを作成します。

2.各通知方法の特徴

各通知方法の特徴を簡単にまとめます。

  • ①User Notificationsを使う方法
    • Eメール通知の場合のメッセージが見やすい
      SNSからEメールを送信すると通知のJSONがそのまま表示されて見づらくなりますが、User Notificationsの場合は見やすく整えてくれるようです。

    • マネジメントコンソール上から設定可能
      AWS Backupの「マイアカウント」 > 「設定」 > 「AWS通知をカスタマイズ」からUser Notificationsの設定画面に飛んで通知設定をすることができます。

    • CloudFormationで設定可能
      2025年1月にCloudFormationでサポートされるようになっています。

https://aws.amazon.com/jp/about-aws/whats-new/2025/01/aws-user-notifications-ga-cloudformation/

https://dev.classmethod.jp/articles/user-notifications-ga-cloudformation/

  • ②SNSを使う方法
    • マネジメントコンソール上から設定不可
      AWS CLIまたはCloudFormationでバックアップボールトにSNSトピックを関連付ける必要があります。

      • CLIの場合はput-backup-vault-notifications--sns-topic-arnオプションや--backup-vault-eventsでバックアップボールトにSNSトピックを関連付けます。

      • CloudFormationの場合はバックアップボールトのプロパティNotificationsでSNSトピックを関連付けます。

    • CloudFormationテンプレート化が容易

    • Lambdaと連携することで通知内容のカスタマイズが可能

各通知方法の使い分けの判断基準として、以下のように整理しました。

  • 作成するリソースをなるべくCloudFormationテンプレートで管理したい、テンプレート作成コストは小さくしたい
    • ⇒SNSを使う方法
  • 通知がメール形式だけで良い
    • ⇒User Notificationsを使う方法
  • メール以外の通知(Teams, Slack等)を重視する
    • ⇒SNSを使う方法
    • ※旧Chatbotでも可能ですが、通知内容の拡張性という面ではLambdaを使うほうが良いと思います。
  • グローバルサービスを使いたくない
    • ⇒SNSを使う方法
    • ※User Notifications と旧Chatbotはどちらもグローバルサービスです。

3.CloudFormationテンプレート

AWSTemplateFormatVersion: 2010-09-09
Description: >-
  Create backup vault and backup plan

# ------------------------------------------------------------#
#  MetaData
# ------------------------------------------------------------#
Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
      - Label:
          default: resource name parameters
        Parameters:
          - EnvCode

      - Label:
          default: backup target resource type and ARN
        Parameters:
          - ResourceType
          - BackupResourceARN
        
      - Label:
          default: backup target setting
        Parameters:
          - ScheduleExpression
          - RetentionDays
          - ContinuousBackupBoolean
          # - EnableCopyAction
          - BackupRoleArn

# ------------------------------------------------------------#
#  Parameters
# ------------------------------------------------------------#
Parameters:
  EnvCode:
    Description: An environment name that will be part of resource names.
    Type: String
    Default: test
  ResourceType:
    Description: Backup Resource Type(example:ec2, s3, aurora)
    Type: String
  ScheduleExpression:
    Type: String
    Default: "cron(0 1 * * ? *)"
    Description: Backup schedule in cron format (Asia/Tokyo).
  RetentionDays:
    Type: Number
    Default: 5
    Description: Number of days to retain the backup
  ContinuousBackupBoolean:
    Type: String
    AllowedValues:
      - true
      - false
    Default: false
    Description: Whether to enable continuous backups (point-in-time recovery)
  # EnableCopyAction:
  #   Type: String
  #   AllowedValues:
  #     - true
  #     - false
  #   Default: false
  #   Description: Whether to enable CopyActions for cross-region backup
  BackupResourceARN:
    Description: Backup Resource ARN
    Type: String
  BackupRoleArn:
    Type: String
    Description: "Specify an existing IAM role ARN or leave blank to create a new one"
    Default: ""

# ------------------------------------------------------------#
#  Conditions
# ------------------------------------------------------------#
Conditions:
  # EnableCopyActionCondition: !Equals [ !Ref EnableCopyAction, true ]
  CreateBackupRole: !Equals [ !Ref BackupRoleArn, "" ]

# ------------------------------------------------------------#
#  Resources
# ------------------------------------------------------------#
Resources:
# ------------------------------------------------------------#
#  BackupVault
# ------------------------------------------------------------#
  BackupVault:
    Type: AWS::Backup::BackupVault
    Properties:
      BackupVaultName: !Sub "${EnvCode}-${ResourceType}-${AWS::Region}-vault"
      AccessPolicy:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              AWS: !Sub "arn:aws:iam::${AWS::AccountId}:root"
            Action:
              - backup:CopyFromBackupVault
              - backup:CopyIntoBackupVault
              - backup:DeleteBackupVault
              - backup:DeleteBackupVaultAccessPolicy
              - backup:DeleteBackupVaultLockConfiguration
              - backup:DeleteBackupVaultNotifications
              - backup:DeleteRecoveryPoint
              - backup:DescribeBackupVault
              - backup:DescribeRecoveryPoint
              - backup:DisassociateRecoveryPoint
              - backup:DisassociateRecoveryPointFromParent
              - backup:GetBackupVaultAccessPolicy
              - backup:GetBackupVaultNotifications
              - backup:GetRecoveryPointRestoreMetadata
              - backup:ListRecoveryPointsByBackupVault
              - backup:PutBackupVaultAccessPolicy
              - backup:PutBackupVaultLockConfiguration
              - backup:PutBackupVaultNotifications
              - backup:StartBackupJob
              - backup:StartCopyJob
              - backup:StartRestoreJob
              - backup:UpdateRecoveryPointLifecycle
            Resource: "*"
      Notifications:
        SNSTopicArn: !Ref BackupNotificationTopic
        BackupVaultEvents:
        - BACKUP_JOB_COMPLETED
        - BACKUP_JOB_FAILED

  BackupNotificationTopic:
    Type: AWS::SNS::Topic
    Properties:
      TopicName: !Sub ${EnvCode}-backup-notification-topic
      Tags:
        - Key: Environment
          Value: !Ref EnvCode

  BackupNotificationTopicPolicy:
    Type: AWS::SNS::TopicPolicy
    Properties:
      Topics:
        - !Ref BackupNotificationTopic
      PolicyDocument:
        Version: "2008-10-17"
        Statement:
          - Sid: backup_publish
            Effect: Allow
            Principal:
              Service: backup.amazonaws.com
            Action: "SNS:Publish"
            Resource: !Ref BackupNotificationTopic

# ------------------------------------------------------------#
#  BackupPlan
# ------------------------------------------------------------#
  BackupPlan:
    Type: AWS::Backup::BackupPlan
    Properties:
      BackupPlan:
        BackupPlanName: !Sub ${EnvCode}-${ResourceType}-${RetentionDays}days-retain-backup-plan
        BackupPlanRule:
          - RuleName: !Sub ${EnvCode}-${ResourceType}-backup-rule
            TargetBackupVault: !Sub ${EnvCode}-${AWS::Region}-vault
            ScheduleExpression: !Ref ScheduleExpression
            ScheduleExpressionTimezone: Asia/Tokyo
            StartWindowMinutes: 60
            CompletionWindowMinutes: 240
            Lifecycle:
              DeleteAfterDays: !Ref RetentionDays
            EnableContinuousBackup: !Ref ContinuousBackupBoolean
            # CopyActions: !If
            #   - EnableCopyActionCondition
            #   - 
            #     - DestinationBackupVaultArn: !Sub arn:aws:backup:ap-northeast-3:${AWS::AccountId}:backup-vault:${EnvCode}-ap-northeast-3-vault
            #       Lifecycle:
            #         DeleteAfterDays: !Ref RetentionDays
            #   - []

  BackupSelection:
    Type: AWS::Backup::BackupSelection
    Properties:
      BackupPlanId: !Ref BackupPlan
      BackupSelection:
        SelectionName: !Sub ${EnvCode}-${ResourceType}-backup-selection
        IamRoleArn: !If
          - CreateBackupRole
          - !GetAtt BackupRole.Arn
          - !Ref BackupRoleArn
        Resources:
          - !Ref BackupResourceARN
        # Conditions:
        #   StringEquals:
        #     - ConditionKey: "aws:ResourceTag/Name"
        #       ConditionValue: !Sub ${EnvCode}-ec2
        #   StringNotEquals:
        #     - ConditionKey: "aws:ResourceTag/Name"
        #       ConditionValue: !Sub ${EnvCode}-ec2-sg

  BackupRole:
    Type: AWS::IAM::Role
    Condition: CreateBackupRole
    Properties:
      RoleName: !Sub ${EnvCode}-aws-backup-role
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: backup.amazonaws.com
            Action: sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSBackupServiceRolePolicyForRestores
        - arn:aws:iam::aws:policy/service-role/AWSBackupServiceRolePolicyForBackup
        - arn:aws:iam::aws:policy/AWSBackupServiceRolePolicyForS3Backup
        - arn:aws:iam::aws:policy/AWSBackupServiceRolePolicyForS3Restore

テンプレートの説明

パラメータ

  • EnvCode
    • リソースに付与する接頭辞です。今回は環境名のみを設定。
  • ResourceType
    • リソースに付与する接頭辞です。説明にあるようにec2, s3, auroraのようにバックアップ対象のサービス名を入力することを想定しています。
  • ScheduleExpression
    • バックアップジョブ実行時間をJSTのCron式で指定します。
  • RetentionDays
    • バックアップ保持日数です。
  • ContinuousBackupBoolean
    • 継続的バックアップを有効化するかどうかのフラグです。
  • EnableCopyAction
    • 別リージョンのバックアップボールトへのコピーを有効化するかどうかのフラグです。コピー先でバックアップボールトが作成されていることが前提条件となるため、本記事のテンプレート上ではコメントアウトしています。
  • BackupResourceARN
    • バックアッププランに紐づけるIAMロールが作成済みであればARNを指定します。パラメータが空の場合は新規作成されます。

AWS::Backup::BackupVault

アクセスポリシーは特に制御しない設定としているため、必要に応じて絞ってください。
本記事では以下記事の通り、アクセスポリシーに付与可能なポリシーを全て付与しています。
https://qiita.com/jonhyoku_imu/items/d26bb4deaedcaac5130b

BackupVaultEventsでバックアップジョブの成功か失敗のみを通知対象としていますが、以下ドキュメントに沿って必要なイベントを設定してください。
https://docs.aws.amazon.com/ja_jp/aws-backup/latest/devguide/backup-notifications.html#backup-notifications-section

ジョブタイプ イベント
バックアップジョブ BACKUP_JOB_STARTED
BACKUP_JOB_COMPLETED
BACKUP_JOB_FAILED
CONTINUOUS_BACKUP_INTERRUPTED
コピージョブ COPY_JOB_STARTED
COPY_JOB_SUCCESSFUL
COPY_JOB_FAILED
復元ジョブ RESTORE_JOB_STARTED
RESTORE_JOB_COMPLETED
復旧ポイント RECOVERY_POINT_MODIFIED

AWS::Backup::BackupPlan

バックアップボールトの指定の仕方について、TargetBackupVaultはバックアップボールト名を指定し、DestinationBackupVaultArnはARNで指定する必要がある点に注意してください。

AWS::Backup::BackupSelection

本記事ではバックアップ対象をARNで指定する記載の仕方としていますが、タグでバックアップ対象を絞り込みたい場合は以下の記事のようにConditionsで絞ると良いと思います。

        Resources:
          - !Ref BackupResourceARN
        # Conditions:
        #   StringEquals:
        #     - ConditionKey: "aws:ResourceTag/Name"
        #       ConditionValue: !Sub ${EnvCode}-ec2
        #   StringNotEquals:
        #     - ConditionKey: "aws:ResourceTag/Name"
        #       ConditionValue: !Sub ${EnvCode}-ec2-sg

https://qiita.com/Keiichi_Kinoshita/items/2de0795d1e35474af94c

AWS::IAM::Role

S3をバックアップする場合、AWS Backupのデフォルトのロールだと権限不足でバックアップが失敗するため以下のポリシーを付与しています。

  • AWSBackupServiceRolePolicyForS3Backup
  • AWSBackupServiceRolePolicyForS3Restore

https://dev.classmethod.jp/articles/aws-backup-s3/

参考記事

https://qiita.com/KikuLabo/items/c55b0a90a02d7df6bdc1

https://iret.media/117960

Discussion