SCP を使用して EC2 インスタンスの EBS ボリュームサイズとボリュームタイプを制限してみた

2022.06.04

AWS Organizaions を利用して AWS 初学者が AWS を学習するための環境を構築していました。学習対象者には AWS 1アカウントを払い出して自由に学習してもらいます。最低限守って欲しいことを制限するために SCP の設定していた中で思っていたほど単純ではなかったものを紹介します。

お題

EC2 インスタンス作成時の EBS ボリュームサイズを制限したい。

必要以上に大きな容量の EBS を作成できないように SCP で制限をかけます。ケースとしては EBS 単体で作成することよりも EC2 作成時に EBS のサイズを指定する機会の方が多いのではないでしょうか。

おまけで高価なインスタンスタイプ(io1, io2)の制限例も紹介します。

ボリュームサイズ制限

EBS のボリュームサイズ 30GB までは許可し 31GB 以上は禁止するポリシーを作成しました。root ユーザーは SCP が適用されないよう除外しています。

ポイント

  • アクションに ec2:RunInstances を含めないと EC2 インスタンス作成時の EBS ボリュームサイズを制限できない
  • ボリュームサイズ変更(拡張)の制限にアクション ec2:ModifyVolume + 条件 ec2:VolumeSize を設定しても実質制限できない
    • ボリュームサイズ変更前のボリュームサイズが判定条件に使われる
    • 変更後のボリュームサイズで判定できない
    • ec2:VolumeSizeで指定した制限値より大きなボリュームサイズへ変更ができる
{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Sid": "NotUseLargeSizeEBS",
			"Effect": "Deny",
			"Action": [
				"ec2:RunInstances",
				"ec2:CreateVolume",
				"ec2:ModifyVolume"
			],
			"Resource": [
				"arn:aws:ec2:*:*:volume/*"
			],
			"Condition": {
				"NumericGreaterThan": {
					"ec2:VolumeSize": [
						"30"
					]
				},
				"StringNotLike": {
					"aws:PrincipalARN": [
						"arn:aws:iam::*:root"
					]
				}
			}
		}
	]
}

ボリュームサイズの変更成功・失敗例

上記 SCP を採用すると変更前のサイズが判定条件に使われるため、ボリュームサイズの変更を行うと以下の結果になる。

変更前サイズ 変更後サイズ 結果
8GB 30GB できる
8GB 500GB できる
30GB 31GB できる
31GB 32GB できない
500GB 1000GB できない

リソースを作成してテストしてみる

EBS 単体の作成

31GB 指定の EBS を作成してみます。30GB 以下のサイズしか許可していないためエラーで作成できません。期待した通りの結果です。

$ aws ec2 create-volume \
    --volume-type gp3 \
    --size 31 \
    --availability-zone ap-northeast-1a

# 実行結果
An error occurred (UnauthorizedOperation) when calling the CreateVolume operation: You are not authorized to perform this operation. Encoded authorization failure message: 1PWOGeY0rn_SuPeGAMLEnF1wUblWrBuZ3Sd_XRm8jqoU16XatxOUwZW5PhByJD0gktzj_RHCnmsD_gmsmPdex1UZdLGLIcG1NCyamIIad0lu921mzFEwZ-hNoHIk7gvKtcF49aDlH2CHgP6GVdVt33he2j8gXLjrEygoGMAsNxARlYMd873Z1fqguRBWgLdEV_SVQ7-QMd8iHERW3C1bewc54oEe33bE0LmYfSCDG6Btehnk5OAMtnX5nwLYfV_0AAYOq3zBBoSuYWbSoncZ9nldkNzqZJbDtr-X1RxkgytFFtBtJaP1SiXwgL5ERtQ3CnTa7YWdGHCmT6r9JfZ4h5kN1oB6NtYkM8YiAmfbH_CdNOWOCSARFcUY5mS4Mw3INkiq8Va7M-q7H4hUpUfK0UlkQ3txlcL2KCMm66a8lviSwBBgbChKZ0qvWUHBgHani36afHgV0o5xvfRzbtkLqCB2MIlh_fx1TKKOgtquCml6fpjYBIfjd0JU2RWwhEdQ2e9syZ6U9NCcnjFXzVbhFzdF4iZXQtbi5CLYy-z9WizHWWmv18_uutjOWen0lgVWg_q0hub0L9NxKer7E-obCIlFPEt3jPhEItDYw-o0ILE16GcK8ltdy7IKdIKJcCzb2A8TclujT2UiatAxrF4cF4vEJ4TvyQCSl3Cgq22PXDrFSCCuNiYKyBx0zpBbRNJW5b6UY5pNFaGzOTK_4N7qqyXhNbw5k-YLh2OzUyzC5GvzA0ATRC8zIdRMjyPZ5zw7qQlHs4nFUrSAqPOX50Wgs9HgzyYqjJdrCTxyqgwW0102W6Ll8jJPOwqGLrURvPSIRg

30GB 指定で作成してみました。作成できました。期待した通りの結果です。

$ aws ec2 create-volume \
    --volume-type gp3 \
    --size 30 \
    --availability-zone ap-northeast-1a

# 実行結果
{
    "AvailabilityZone": "ap-northeast-1a",
    "CreateTime": "2022-06-01T05:30:11+00:00",
    "Encrypted": false,
    "Size": 30,
    "SnapshotId": "",
    "State": "creating",
    "VolumeId": "vol-0cccb5fbfb44a39f5",
    "Iops": 3000,
    "Tags": [],
    "VolumeType": "gp3",
    "MultiAttachEnabled": false,
    "Throughput": 125
}

EBS ボリュームサイズ変更

30GB で作成した EBS を 31GB にボリュームサイズを変更すると変更できてしまう。

$ aws ec2 modify-volume \
  --size 31 \
  --volume-id vol-0cccb5fbfb44a39f5

# 実行結果
{
    "VolumeModification": {
        "VolumeId": "vol-0cccb5fbfb44a39f5",
        "ModificationState": "modifying",
        "TargetSize": 31,
        "TargetIops": 3000,
        "TargetVolumeType": "gp3",
        "TargetThroughput": 125,
        "TargetMultiAttachEnabled": false,
        "OriginalSize": 30,
        "OriginalIops": 3000,
        "OriginalVolumeType": "gp3",
        "OriginalThroughput": 125,
        "OriginalMultiAttachEnabled": false,
        "Progress": 0,
        "StartTime": "2022-06-01T05:46:33+00:00"
    }
}

今度は 31GB に拡張された EBS を 32GB へさらに拡張してみるとエラーで失敗します。

$ aws ec2 modify-volume \
  --size 32 \
  --volume-id vol-0cccb5fbfb44a39f5

# 実行結果
An error occurred (UnauthorizedOperation) when calling the ModifyVolume operation: You are not authorized to perform this operation. Encoded authorization failure message: cYCI2TdgLslW0yCtpdd_GJu-9IjK3wEwJuL_oXmi-95bfmaFSuWBt8G1-fd4b0LCoYB_lDLWHfLQbyDMkg3-dxlROCUoqEgGHX6kT63TeMHDUWkSHUcSgWCgWnxI590ImrNVNzxAV-zgMQTEcmKXtmVxLe65igQvRC_yp-jTnESUtyZqvRzd1yC8ZRr0ltnscDOETWVF3u_K28uZYMBh80HBQFKSMMChvD9YuR40-iR6TecISkYSgn_BH1VE2aD2_9xxxSLNnY-4UCLdwMlnUX_yswJzbkMN-_fRpczGCo__WGxyvjUWP2VeKm-QTsZw339KFpVAholR_lMp2MosEKN6n8ztXvL8kWH5b48XJ_c3_qyfXFe5LXAtLr28YD8p05jpMVaB3VRFekCWddLnOL_3Q_9Qqjnkrm49TbLmtAEOrOEQABo5Fx_sGoPCKCaHA00jBBe1jNnxtsAqv3bqgzbenTAPSLt_KcxXjY9JYpnpxTMou-9fHEaNalmKLAyRsv10DslX9xbyhW1shx8c_NMeI9tUDnxUvQXs9WqNYwHv2UnpPD2tqdQjove0LKOUfPu1HSt6f-Ay615wu3Sr0ynwTiM20cIVzTVqo5hnZNbCYzCgTKhp5xrJnHR_R_fVmPBBhLnZgJbz3iqPhzwKpASduESyt7_LBWcM2qwa6lRe4noGQJS8phh5fnxHBFxPvMVvPRz_4n2pI4AVLH4QIwyLJf1TL_7Y7vcDJhEzBWTl0hGS0bsChN2Y914EymogjxiQP84K6X3DDjTGNeHMZY_X8nPi3SlZftqQXqsg2Kg1llcGLFsVkpM6D-uNrzg9bBJLfaRa8VCmhC3H8RsrbQaKGk4bsa9pLSb1gvBILq1fQyrVxUQjkh7b1z-9YoLwEAcQc7vNZ2o_8GAB8R4H

※ 連続した変更操作はもともとできません。6時間以上待機する必要があります。

After modifying a volume, you must wait at least six hours and ensure that the volume is in the in-use or available state before you can modify the same volume. This is sometimes referred to as a cooldown period.

Requirements when modifying volumes - Amazon Elastic Compute Cloud

原因

条件キーにec2:VolumeSize は変更後のサイズ(TargetSize)ではなく今現在のサイズ(OriginalSize)で判定しています。ec2:VolumeSize に代わる変更後のボリュームサイズで判定する条件キーが存在していなく制限できませんでした。

Amazon EC2 のアクション、リソース、および条件キー - サービス認証リファレンス

つまり、30GB以下のボリュームサイズであれば自由に変更(拡張)可能です。今回の SCP だと 31GB以上のボリュームからさらに拡張するときは ec2:VolumeSize で指定した 30GB 制限が適用され変更不可となります。

EC2 インスタンス作成時の EBS ボリュームサイズ指定

Actions に ec2:RunInstances含めないと 31GB以上の EBS を指定して EC2 の作成が可能です。

SCP抜粋

			"Effect": "Deny",
			"Action": [
				"ec2:RunInstances",
				"ec2:CreateVolume",
				"ec2:ModifyVolume"
			],

当初は ec2:CreateVolume の制限しておけば EC2 作成時に作られる EBS も制限されるかと思っていました。試してみてアクションが別だったことをはじめて知りました。

EC2 インスタンス作成

31GB 指定で作成します。

失敗しました。

30GB で作成します。

成功しました。

EC2 作成時の EBS に関する制限をするときは ec2:RunInstances のことを忘れないようにしましょう。

ボリュームタイプの制限

おまけで高価なボリュームタイプ(io1, io2)の作成は禁止するポリシーを作成しました。同様に root ユーザーは SCP が適用されないよう除外しています。

ポイント

  • アクションに ec2:RunInstances を含めないと EC2 インスタンス作成時の EBS ボリュームタイプを制限できない
  • ボリュームタイプ変更の制限にアクション ec2:ModifyVolume + 条件 ec2:VolumeType を設定しても実質制限できない
    • ボリュームタイプ変更前のボリュームタイプが判定条件に使われる
    • 変更後のボリュームタイプで判定できない
    • ec2:VolumeTypeで制限したボリュームタイプへも変更ができる

この条件で Actions の対象に ec2:ModifyVolume 含めると io1, io2 に変更後、gp3 などの他のボリュームタイプへ変更できなくなります。先ほどのボリュームサイズ変更制限は拡張しかできない(不可逆)のですが、ボリュームタイプ変更は元のタイプに戻すことができるため逆に迷惑な制限となりました。そのため、ec2:ModifyVolume は含めないポリシーにしました。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "NotUsePIOPSEBS",
      "Effect": "Deny",
      "Action": [
     "ec2:RunInstances",
        "ec2:CreateVolume"
      ],
      "Resource": [
        "arn:aws:ec2:*:*:volume/*"
      ],
      "Condition": {
        "StringLike": {
          "ec2:VolumeType": [
            "io1",
            "io2"
          ]
        },
        "StringNotLike": {
          "aws:PrincipalARN": [
            "arn:aws:iam::*:root"
          ]
        }
      }
    }
  ]
}

ec2:ModifyVolume アクションは条件なしに禁止すればボリュームサイズ、タイプ共に制限の悩みは減ります。今回の目的は学習用の AWS 環境ですので大きな影響はありませんが、勉強のために変更操作することもあるでしょう。ユースケースに応じて他の条件キーで回避できないかどうか検討してみてください。

まとめ

  • EC2 作成と同時に作成される EBS のサイズ・タイプを制限したいときはアクションに ec2:RunInstances が必要
  • EBS のボリューム変更操作(ec2:ModifyVolume)アクションと条件を組み合わせたいときは変更前の値か、変更後の値で判定されるのか要確認

おわりに

EBS のボリュームサイズと、タイプの制限を侮っていました。アクションと、条件キーを改めて見直してみると悩ましいものでした。こういったつまづきポイントがあることを事前に把握できていれば何も問題ない話でしたので、ご参考になれば幸いです。