特定の起動テンプレートのみ起動停止できるIAMポリシーの設定をする必要があったので、備忘録としてまとめています。
詰まりどころ
起動テンプレートを起動する権限というのは無く、ec2:RunInstances
アクションのリソース対象が 起動テンプレートという構成になる。
しかし下記のように設定すると権限不足で実行が失敗してしまう。
{
"Sid": "VisualEditor1",
"Effect": "Allow",
"Action": [
"ec2:RunInstances"
],
"Resource": "arn:aws:ec2:*:{account_id}:launch-template/*"
},
これの理由としては、ec2:RunInstances
は内部にて複数のAPIが実行されているようで、リソース先には launch-template
や instance
の複数が指定されているため、
上記のポリシーではlaunch-template
の指定まではできるが、instance
の立ち上げの際にリソースとして指定がされていないので、権限不足で失敗してしまう。
解決案
ec2:RunInstances
のリソースは*
で制限をかけずに、Deny
のポリシーで特定の起動テンプレートの起動以外は拒否するようにする。
また起動テンプレート以外で単独のインスタンスを起動をしようとしたec2:RunInstances
についても拒否するようにする。
これらを組み合わせれば、ec2:RunInstances
で*
を設定したとしても、特定の起動テンプレートを指定した場合だけ起動が可能になります。
すべてのインスタンス起動を許可する
{
"Sid": "VisualEditor1",
"Effect": "Allow",
"Action": [
"ec2:DescribeInstances",
"ec2:CreateTags",
"ec2:RunInstances"
],
"Resource": "*"
},
lt-xxxxxx
以外の起動テンプレートを指定したec2:RunInstances
を拒否する
{
"Sid": "VisualEditor5",
"Effect": "Deny",
"Action": "ec2:RunInstances",
"Resource": "arn:aws:ec2:*:{account_id}:launch-template/*",
"Condition": {
"ForAnyValue:ArnNotEquals": {
"ec2:LaunchTemplate": "arn:aws:ec2:ap-northeast-1:{account_id}:launch-template/lt-xxxxxx"
}
}
}
単独でインスタンスを起動をしようとした時に拒否されるようにする
{
"Sid": "VisualEditor4",
"Effect": "Deny",
"Action": "ec2:RunInstances",
"Resource": "arn:aws:ec2:*:*:instance/*",
"Condition": {
"ForAnyValue:Bool": {
"ec2:IsLaunchTemplateResource": "false"
}
}
},
また停止時は起動テンプレートを介して停止することはできないため、タグベースで制御を行います。
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": "ec2:TerminateInstances",
"Resource": "*",
"Condition": {
"StringEquals": {
"aws:ResourceTag/Name": "{instance_name_tag}"
}
}
},
検証
- 期待している起動テンプレートで正常に起動できる
- 期待していない起動テンプレートで起動できない
- 起動テンプレートを指定しないと起動できない
の3パターンを検証して問題なさそうでした。
# 期待している起動テンプレートで正常
client.run_instances(
launch_template: { launch_template_id: 'lt-xxxxxx' },
min_count: 1,
max_count: 1
)
# 期待していない起動テンプレートで起動できない
client.run_instances(
launch_template: { launch_template_id: 'lt-yyyyyy' },
min_count: 1,
max_count: 1
)
# 起動テンプレートを指定しないと起動できない
client.run_instances(
image_id: "ami-xxxxxx",
instance_type: "t2.micro",
min_count: 1,
max_count: 1
)
結論
出来上がったポリシーを組み合わせると下記のようなjsonになります。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": "ec2:TerminateInstances",
"Resource": "*",
"Condition": {
"StringEquals": {
"aws:ResourceTag/Name": "{instance_name_tag}"
}
}
},
{
"Sid": "VisualEditor1",
"Effect": "Allow",
"Action": [
"ec2:DescribeInstances",
"ec2:CreateTags",
"ec2:RunInstances"
],
"Resource": "*"
},
{
"Sid": "VisualEditor5",
"Effect": "Deny",
"Action": "ec2:RunInstances",
"Resource": "arn:aws:ec2:*:{account_id}:launch-template/*",
"Condition": {
"ForAnyValue:ArnNotEquals": {
"ec2:LaunchTemplate": "arn:aws:ec2:ap-northeast-1:{account_id}:launch-template/lt-xxxxxx"
}
}
},
{
"Sid": "VisualEditor4",
"Effect": "Deny",
"Action": "ec2:RunInstances",
"Resource": "arn:aws:ec2:*:*:instance/*",
"Condition": {
"ForAnyValue:Bool": {
"ec2:IsLaunchTemplateResource": "false"
}
}
}
]
}