この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
こんにちは。AWS事業本部の中川です。
暗号化されたEBSボリュームを作成できない事象に遭遇しました。
権限を絞りすぎたことで、リソース作成時に権限不足である旨のエラーが表示され失敗するケースはよくあるかと思います。
しかし、今回遭遇した事象は、作成時にエラーは表示されていないのにリソースが作成されないというもので、特殊なケースでした。
エラーが表示されず原因特定にハマったので、備忘録として残します。
前提
以下のようなポリシーが付与されたIAMユーザーを使用しています。(実際にはReadOnlyAccessのポリシーが付与されていたり、他にConditionがあります。)
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ec2:CreateVolume"
],
"Resource": [
"arn:aws:ec2:*:*:volume/*"
]
},
{
"Effect": "Deny",
"Action": "*",
"Resource": "*",
"Condition": {
"NotIpAddress": {
"aws:SourceIp": [
"x.x.x.x"
]
}
}
}
]
}
事象
暗号化のチェックボックスを有効にして、カスタマーマスターキー(以下CMK)はデフォルトを選択し、ボリュームを作成します。
「ボリュームは正常に作成されました」と表示され、EBS ボリュームが作成されたように見えます。ボリュームIDをクリックして、一覧の画面に戻ります。
しかし、一覧でボリュームIDと一致するボリュームが表示されません。右上の更新ボタンをクリックしても表示されず、ボリュームは作成されていないことがわかります。
原因
aws:SourceIpで接続IPアドレスの制限をしながら、EBSの暗号化(EBSからKMSの呼び出し)をしていたことが原因でした。
aws:SourceIpのドキュメントを見ると以下の記述があります。
aws:SourceIp 条件キーをポリシーで使用して、プリンシパルが指定された IP 範囲内からのみリクエストを行うことを許可できます。ただし、このポリシーは、ユーザーに代わって呼び出しを行う AWS のサービスへのアクセスを拒否します。たとえば、AWS CloudFormation がサービスロールを使用して Amazon EC2 を呼び出してインスタンスを停止するとします。この場合、ターゲットサービス (Amazon EC2) が呼び出し元のサービス (AWS CloudFormation) の IP アドレスを認識するため、リクエストは拒否されます。
aws:SourceIpは、「ユーザーに代わって呼び出しを行うAWSサービスへのアクセスを拒否する」ことが仕様のようです。 EBSボリュームの暗号化では、EBSがKMSにリクエストを送信して、暗号化で使用するをCMKを指定しています。 つまり、EBSの暗号化でKMSを呼び出すリクエストは、aws:SourceIpによって拒否されていたことがわかりました。
回避策
本事象の回避策は2つあります。
- aws:SourceIpを一時的に使用しないようにする(または条件から除いてしまう)
- kms:ViaServiceを使用して、CMKを呼び出していないときを条件として追加する
2.は呼び出されるAWSサービスがKMSの場合でのみ有効な回避策です。2.を使う場合、前提のポリシーを以下のように変更します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ec2:CreateVolume"
],
"Resource": [
"arn:aws:ec2:*:*:volume/*"
]
},
{
"Effect": "Deny",
"Action": "*",
"Resource": "*",
"Condition": {
"Null": {
"kms:ViaService": "true"
},
"NotIpAddress": {
"aws:SourceIp": [
"x.x.x.x"
]
}
}
}
]
}
kms:ViaServiceは、CMKの使用を指定のAWSサービスからのリクエストに制限する条件キーです。
Nullは、条件キーの存在を確認する条件演算子です。Nullで{"kms:ViaService": "true"}と指定すると、「kms:ViaServiceが存在しない(≒CMKを呼び出していない)」という条件になります。
これを接続元IPアドレスを制限する条件に追加することで、「CMKを呼び出していない かつ 接続元IPを制限する」という条件になります。
さいごに
aws:SourceIpで接続元IPアドレスを制限すると、ユーザーに代わって呼び出しを行うAWSのサービスへのアクセスは拒否されることがわかりました。 KMS以外のサービスを呼び出す際は、aws:SourceIpを条件から外さなくてはならないので、接続元IPを制限をする際には気をつける必要があると思いました。
この記事がどなたかのお役に立てたら幸いです。