何が起きたか
弊社ではインスタンスの定期起動やWindows Updateの実施などでCloud Automatorを大活用しています。
その日常の中で事態は突然起こりました。
Cloud AutomatorジョブでEC2インスタンスの起動に失敗したのです。
ジョブの設定を変えたか? →変えてない
起動されるEC2インスタンスで何を変えたか? →変えました。CMK(カスタマーマスターキー)を設定してこれでEBSボリュームを暗号化したのでした
ちなみに、AWSマネジメントコンソール上で当該EC2インスタンスの起動は難なくできました。 CMKの持ち主ユーザとEC2インスタンスを起動させたユーザは同一だったからです。
直す方針
Cloud AutomatorジョブでEC2インスタンスを起動させることは、EC2インスタンスがあるAWSアカウントにクロスアカウントアクセスして実行しています。
起動させるEC2インスタンスにアタッチされているEBSボリュームにCMKによる暗号化がされている場合、クロスアカウントアクセスするIAMロールに「CMKにもアクセスしてよい」許可を与える必要があります。
直す方法
これに倣ってポリシーを作成します。
AWSマネジメントコンソールにて、サービスメニューから「KMS」を選択し、「カスタマー管理型のキー」を選択し、該当キーを選択して、「キーポリシー」のところで「編集」を選択して、CMKのキーポリシーに下記の2つのポリシーを追加します。
キーポリシーに下記のポリシーを追加します。
このポリシー内容はこのCMKを利用して何かするという許可になります。キーユーザ(この場合はCloudAutomator-1a〜ロール)に以下のアクセス許可を与えています。
EC2インスタンスの起動・稼働にはEBSボリュームの読み書きが行われることになり、EBSボリュームに暗号化が有効になっている場合はEBSボリュームの読み書きの過程で暗号化・復号化されます。
参考: Amazon EBS 暗号化 - Amazon Elastic Compute Cloud
今回の場合、EBSボリュームの暗号化・復号化でこのCMKが指定されているため、このCMKを利用してEBSボリュームの暗号化・復号化を行ってよい許可をキーユーザに付与している設定になります。
- kms:Encrypt: キーユーザがこのCMKを使用してデータを暗号化できる
- kms:Decrypt: キーユーザがこのCMKを使用してデータを復号化できる
- kms:ReEncrypt*: キーユーザはこのCMKで最初に暗号化されたデータを再暗号化するか、このCMKを使用して以前に暗号化されたデータを再暗号できる
- kms:GenerateDataKey*: キーユーザはクライアント側の暗号化操作のために対称データキーまたは非対称データキーペアを要求できる
- kms:DescribeKey: キーユーザは識別子、作成日、キー状態など、このCMKに関する詳細情報を取得できる
上記のアクセス許可を「"kms:ViaService": "ec2.ap-northeast-1.amazonaws.com"」によって、東京リージョンのEC2サービスに限って許可を与えるようにしています。
{ "Sid": "Allow external account Cloud Automator use of the customer managed key", "Effect": "Allow", "Principal": { "AWS": [ "arn:aws:iam::111122223333:role/CloudAutomator-1a2b3c4d5e6f7g8h9i0j-CloudAutomator-1a2b3c4d5e6f" ] }, "Action": [ "kms:Encrypt", "kms:Decrypt", "kms:ReEncrypt*", "kms:GenerateDataKey*", "kms:DescribeKey" ], "Resource": "*", "Condition": { "StringEquals": { "kms:ViaService": "ec2.ap-northeast-1.amazonaws.com" } } }
キーポリシーに下記のポリシーを追加します。
このポリシー内容は暗号化操作にこのCMKを使用することの許可になります。
このポリシー内容はこのCMKの利用の許可になります。キーユーザ(この場合はCloudAutomator-1a〜ロール)にアクセス許可を与えています。
「"kms:GrantIsForAWSResource": "true"」を追加することでEBSなどのKMSと統合されたAWSサービスが、指定されたプリンシパル(この場合はCloudAutomator-1a〜ロール)に代わって、このCMKを利用してよいという許可を与えています。
参考: CreateGrant - AWS Key Management Service
参考: Using policy conditions with AWS KMS - AWS Key Management Service
{ "Sid": "Allow attachment of persistent resources in external account Cloud Automator", "Effect": "Allow", "Principal": { "AWS": [ "arn:aws:iam::111122223333:role/CloudAutomator-1a2b3c4d5e6f7g8h9i0j-CloudAutomator-1a2b3c4d5e6f" ] }, "Action": [ "kms:CreateGrant" ], "Resource": "*", "Condition": { "Bool": { "kms:GrantIsForAWSResource": "true" } } }
上記の「arn:aws:iam::111122223333:role/CloudAutomator-1a2b3c4d5e6f7g8h9i0j-CloudAutomator-1a2b3c4d5e6f」は実際にはCloud AutomatorがスイッチロールしてくるIAMロールになります。
Cloud AutomatorがどのIAMロールを使用しているか、AWSマネジメントコンソールのIAMロール一覧から判別できない場合は、Cloud Automatorにログインし、下記のメニューをたどって確認することができます。
グループ管理 → グループ一覧 → 一覧から該当グループを選択 → AWSアカウント → 操作対象のアカウント名の「編集」を選択
「IAMロールARN」の設定値をメモし、「role/」以降がロール名になります。
ここまで確認できたら、「IAMロールARN」の設定値にあるarnから始まるすべてをポリシーに書けます。
解決
起動させられなかったEC2インスタンスを起動させられるかCloud Automatorジョブを発火させてみます。
見事成功しました。