暗号化されたEBSボリュームを作成できずハマった話
こんにちは。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 を制限をする際には気をつける必要があると思いました。
この記事がどなたかのお役に立てたら幸いです。