[アップデート] Volume Shadow Copy Service用のIAMマネージドポリシーが追加されました

2024.03.31

しばたです。

先日AWSよりWindows EC2インスタンスでVolume Shadow Copy Service(VSS)を使ったバックアップをする際に必要な権限をマネージドポリシー化した旨のアナウンスがありました。

過去の経緯を踏まえつつポリシーの利用条件などを解説していきます。

従来の挙動

VSSを使ったEC2インスタンスのバックアップ自体は以前から存在する機能でありAWS Backupでもサポートされています。

このVSSを使ったバックアップ(以後VSSバックアップと記載)はOS内部にあるVSSの機能を使いながらアプリケーション整合性をもったEBSスナップショット(およびAMI)を作成するため、バックアップ対象となるEC2インスタンスに所定の権限を持ったIAMロールをアタッチする必要がありました。

これまではその権限を持つIAMポリシーを自作する必要があったのですが、今回AWSマネージドなポリシーが用意され自作せずに済む様になりました。

追加されたポリシー

追加されたポリシーはAWSEC2VssSnapshotPolicyという名前です。

ポリシーのバージョンを確認するとアナウンスが成された3日前(3月29日)に作成されていることが分かります。

そして、本日時点でのポリシー定義は以下の通りです。

AWSEC2VssSnapshotPolicy

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "DescribeInstanceInfo",
            "Effect": "Allow",
            "Action": [
                "ec2:DescribeInstanceAttribute"
            ],
            "Resource": [
                "arn:aws:ec2:*:*:instance/*"
            ],
            "Condition": {
                "StringLike": {
                    "ec2:SourceInstanceARN": "*${ec2:InstanceId}"
                }
            }
        },
        {
            "Sid": "CreateSnapshotsWithTag",
            "Effect": "Allow",
            "Action": [
                "ec2:CreateSnapshots"
            ],
            "Resource": [
                "arn:aws:ec2:*:*:snapshot/*"
            ],
            "Condition": {
                "StringLike": {
                    "aws:RequestTag/AwsVssConfig": "*"
                }
            }
        },
        {
            "Sid": "CreateSnapshotsAccessInstance",
            "Effect": "Allow",
            "Action": [
                "ec2:CreateSnapshots"
            ],
            "Resource": [
                "arn:aws:ec2:*:*:instance/*"
            ],
            "Condition": {
                "StringLike": {
                    "ec2:SourceInstanceARN": "*${ec2:InstanceId}"
                }
            }
        },
        {
            "Sid": "CreateSnapshotsAccessVolume",
            "Effect": "Allow",
            "Action": [
                "ec2:CreateSnapshots"
            ],
            "Resource": [
                "arn:aws:ec2:*:*:volume/*"
            ]
        },
        {
            "Sid": "CreateImageWithTag",
            "Effect": "Allow",
            "Action": [
                "ec2:CreateImage"
            ],
            "Resource": [
                "arn:aws:ec2:*:*:snapshot/*",
                "arn:aws:ec2:*:*:image/*"
            ],
            "Condition": {
                "StringLike": {
                    "aws:RequestTag/AwsVssConfig": "*"
                }
            }
        },
        {
            "Sid": "CreateImageAccessInstance",
            "Effect": "Allow",
            "Action": [
                "ec2:CreateImage"
            ],
            "Resource": [
                "arn:aws:ec2:*:*:instance/*"
            ],
            "Condition": {
                "StringLike": {
                    "ec2:SourceInstanceARN": "*${ec2:InstanceId}"
                }
            }
        },
        {
            "Sid": "CreateTagsOnResourceCreation",
            "Effect": "Allow",
            "Action": "ec2:CreateTags",
            "Resource": [
                "arn:aws:ec2:*:*:snapshot/*",
                "arn:aws:ec2:*:*:image/*"
            ],
            "Condition": {
                "StringEquals": {
                    "ec2:CreateAction": [
                        "CreateImage",
                        "CreateSnapshots"
                    ]
                }
            }
        },
        {
            "Sid": "CreateTagsAfterResourceCreation",
            "Effect": "Allow",
            "Action": "ec2:CreateTags",
            "Resource": [
                "arn:aws:ec2:*:*:snapshot/*",
                "arn:aws:ec2:*:*:image/*"
            ],
            "Condition": {
                "StringLike": {
                    "ec2:ResourceTag/AwsVssConfig": "*"
                },
                "ForAllValues:StringEquals": {
                    "aws:TagKeys": [
                        "AppConsistent",
                        "Device"
                    ]
                }
            }
        },
        {
            "Sid": "DescribeImagesAndSnapshots",
            "Effect": "Allow",
            "Action": [
                "ec2:DescribeImages",
                "ec2:DescribeSnapshots"
            ],
            "Resource": "*"
        }
    ]
}

設定する権限自体はほぼ従来通りなのですが、権限を与える条件のCondition要素がかなり細かく追加されています。
EC2インスタンスに関わる権限についてはec2:SourceInstanceARNを使って当該インスタンスのみに制限しています。

"Condition": {
    "StringLike": {
        "ec2:SourceInstanceARN": "*${ec2:InstanceId}"
    }
}

加えてスナップショットやAMIを作る権限についてはaws:RequestTagを使い「AwsVssConfigタグ」があるリソースだけを対象としています。

"Condition": {
    "StringLike": {
        "aws:RequestTag/AwsVssConfig": "*"
    }
}

これらの条件付けにより「当該インスタンスのみ」「VSSスナップショットに関する処理のみ」という必要最低限の権限を実現できています。

すばらしいですね。

利用可能なAWS VSS solutionのバージョン

AWS VSS solutionはVSSバックアップの仕組み全体、およびそのための専用コンポーネントを指します。

本日時点での最新バージョンはVer.2.3.1となり、このバージョンからスナップショットを取得する際にAwsVssConfigタグを設定する様になっています。
このためAWSEC2VssSnapshotPolicyはVer.2.3.1以降でないと利用できません。

AWSEC2VssSnapshotPolicyを使う際はあらかじめAWS VSS solutionのバージョンを上げておく必要があるのでご注意ください。

サンプルCloudFormationテンプレート

サンプルとして最低限必要な権限をまとめたCloudFormationテンプレートを共有します。
VSSバックアップはSSMの機能を使って実現しているため、

  • AmazonSSMManagedInstanceCore
  • AWSEC2VssSnapshotPolicy

の2マネージドポリシーを与えてやります。
以前は自作していた部分がAWSEC2VssSnapshotPolicyに置き換わったことにより非常にシンプルになりました。

IAMロールのサンプル (EC2RoleforSSMVSSSnapshotV2.yaml)

AWSTemplateFormatVersion: 2010-09-09
Parameters:
  RoleName:
    Description: "Input role name."
    Type: String
    Default: "EC2RoleforSSMVSSSnapshotV2"
Resources:
  # IAM Role
  SSMVSSRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName:
        Fn::Sub: "${RoleName}"
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: "Allow"
            Principal:
              Service:
                - "ec2.amazonaws.com"
            Action:
              - "sts:AssumeRole"
      Path: "/"
      ManagedPolicyArns:
        - "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
        - "arn:aws:iam::aws:policy/AWSEC2VssSnapshotPolicy"
  # Instance Profile
  SSMVSSInstanceProfile:
    Type: "AWS::IAM::InstanceProfile"
    Properties:
      InstanceProfileName:
        Fn::Sub: "${RoleName}"
      Path: "/"
      Roles:
        - Ref: SSMVSSRole

試してみた

最後に簡単に動作確認してみます。

私の検証用AWSアカウントの東京リージョンに日本語版Windows Server 2022のEC2インスタンスを1台用意しました。
AMIは本時時点で最新のami-0daf778bcac2c1a3d : Windows_Server-2022-Japanese-Full-Base-2024.03.13を使い、前掲のIAMロールをアタッチ済みです。

このインスタンスに対しSSM Run CommandでAWS VSS solution(AwsVssComponents)をインストールします。
今回はCloudShellから以下のコマンドを実行しています。

# CloudShellから実行
aws ssm send-command --document-name "AWS-ConfigureAWSPackage" --targets '[{"Key":"InstanceIds","Values":["i-05087e10fc4c09512"]}]' --parameters '{"action":["Install"],"installationType":["Uninstall and reinstall"],"name":["AwsVssComponents"]}'

Run Commandの実行結果はこんな感じで正常終了しました。

これでOS内部のC:\Program Files\Amazon\AwsVssComponents配下にコンポーネントがインストールされ、本日時点で最新のVer.2.3.1がインストールであることが確認できます。

この状態でAWS Backupからインスタンスのオンデマンドバックアップを取得します。

バックアップを実行し、しばらく待つと無事正常終了しました。

バックアップの実体であるAMIとEBSスナップショットをそれぞれ確認してみるとAwsVssConfig等のタグが付与されていることが分かります。

AwsVssConfigタグにはバージョン番号が設定され、アプリケーション整合性を示すAppConsistentタグにTrueが設定されていました。

終わりに

以上となります。

非常に良く考えられたポリシーだと思います。
今後はVSSバックアップの事前準備が非常に楽になりますね。