AWS Key Management Serviceでキーの”管理”と”利用”を分離する #reinvent
こんにちは、虎塚です。
今回のre:Inventで発表されたAWS Key Management Serviceは、データを暗号化するためのキーをAWS内で生成、削除、ローテートなどの管理ができるサービスです。このサービスは、キーを管理するユーザと、キーを利用するユーザを別々に定義できるのが特徴です(同じにすることもできます)。
この記事では、まず、キーの管理と利用の違いを説明します。次に、アカウントをまたいでキーを利用し、S3にアップロードするオブジェクトを暗号化する例を紹介します。
AWS Key Management Serviceのキーを別アカウントで使用することは、まさに管理と利用の分離の一例です。アカウントをまたいで、二つの役割を定義するわけですね。
キーの管理と利用
キーの管理と利用について理解するには、自分で作成したキーのポリシーを見るのが分かりやすいでしょう。大瀧さんの記事([新サービス] AWS Key Management Serviceを触ってみた #reinvent | Developers.IO)の手順にあったように、ウィザードを使ってキーを作成すると、キーの管理者とキーの利用者を定義する画面が区別されています。これがそっくりポリシーに反映されているためです。
キーの管理者を定義する画面がこちら(Default Key Administrators)。
キーの利用者を定義する画面がこちら(Default Key Usage Permissions)です。
以下の説明では前提として、上記の記事の手順で、東京リージョンに「test-kms」というエイリアスのキーを作成済みであるとします。
キーIDを確認する
AWS CLIで、自分が東京リージョンに保有するキーの一覧を見てみます。
% aws kms list-keys False KEYS arn:aws:kms:ap-northeast-1:<ACCOUNT-ID>:key/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX3d0a XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX3d0a KEYS arn:aws:kms:ap-northeast-1:<ACCOUNT-ID>:key/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX2508 XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX2508 KEYS arn:aws:kms:ap-northeast-1:<ACCOUNT-ID>:key/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX9df1 XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX9df1 KEYS arn:aws:kms:ap-northeast-1:<ACCOUNT-ID>:key/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX3fe7 XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX3fe7 KEYS arn:aws:kms:ap-northeast-1:<ACCOUNT-ID>:key/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX55ca XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX55ca
5個のキーが表示されました。
ただ、keyIDもARNも同じ文字列の羅列なので、このままではどれが何のキーか分かりません。せっかくエイリアスをつけてキーを作成できるので、エイリアス一覧を取得してみます。
% aws kms list-aliases False ALIASES arn:aws:kms:ap-northeast-1:<ACCOUNT-ID>:alias/aws/ebs alias/aws/ebs XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX9df1 ALIASES arn:aws:kms:ap-northeast-1:<ACCOUNT-ID>:alias/aws/rds alias/aws/rds XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX2508 ALIASES arn:aws:kms:ap-northeast-1:<ACCOUNT-ID>:alias/aws/redshift alias/aws/redshift XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX3fe7 ALIASES arn:aws:kms:ap-northeast-1:<ACCOUNT-ID>:alias/aws/s3 alias/aws/s3 XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX55ca ALIASES arn:aws:kms:ap-northeast-1:<ACCOUNT-ID>:alias/test-kms alias/test-kms XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX3d0a
5個のキーについて、AliasArn, AliasName, TargetKeyIdが表示されました。
さて、自分で作成したtest-kmsの他に、作成した覚えのないキーが4個あります。alias/aws/ebs, alias/aws/rds, alias/aws/redshift, alias/aws/s3です。
これらは、AWSによって自動的に作成されたキーです。Key Management Serviceでは、AWSが作成するキーとユーザが作成するキーの両方を管理、利用できます。
キーのポリシーを確認する
キーIDが分かりましたので、キーのポリシーを確認します。次のコマンドを使うと、キーを指定して詳細情報を取得できます。
get-key-policy --key-id <value> --policy-name <value> [--cli-input-json <value>] [--generate-cli-skeleton]
ここでは、自分で作成した「test-kms」キーのIDを引数に与えて、実行します。
% aws kms get-key-policy --key-id XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX3d0a --policy-name default { "Id": "key-consolepolicy-2", "Version": "2012-10-17", "Statement": [ { "Sid": "Enable IAM User Permissions", "Effect": "Allow", "Principal": { "AWS": [ "arn:aws:iam::<ACCOUNT-ID>:root" ] }, "Action": "kms:*", "Resource": "*" }, { "Sid": "Allow access for Key Administrators", "Effect": "Allow", "Principal": { "AWS": [ "arn:aws:iam::<ACCOUNT-ID>:user/<IAM-USER-NAME>" ] }, "Action": [ "kms:Create*", "kms:Describe*", "kms:Enable*", "kms:List*", "kms:Put*", "kms:Update*", "kms:Revoke*", "kms:Disable*", "kms:Get*", "kms:Delete*" ], "Resource": "*" }, { "Sid": "Allow use of the key", "Effect": "Allow", "Principal": { "AWS": [ "arn:aws:iam::<ACCOUNT-ID>:user/<IAM-USER-NAME>" ] }, "Action": [ "kms:Encrypt", "kms:Decrypt", "kms:ReEncrypt*", "kms:GenerateDataKey*", "kms:DescribeKey" ], "Resource": "*" }, { "Sid": "Allow attachment of persistent resources", "Effect": "Allow", "Principal": { "AWS": [ "arn:aws:iam::<ACCOUNT-ID>:user/<IAM-USER-NAME>" ] }, "Action": [ "kms:CreateGrant", "kms:ListGrants", "kms:RevokeGrant" ], "Resource": "*", "Condition": { "Bool": { "kms:GrantIsForAWSResource": true } } } ] }
上記のようなポリシーが取得できました。ステートメントごとに見ていきましょう。
まず、「IAMユーザパーミッションの有効化」のステートメントです。自アカウントには、すべてのリソースに対してすべてのKMS APIの実行を許可しています。
{ "Sid": "Enable IAM User Permissions", "Effect": "Allow", "Principal": { "AWS": [ "arn:aws:iam::<ACCOUNT-ID>:root" ] }, "Action": "kms:*", "Resource": "*" }
次に、「キー管理者のためのアクセス許可」のステートメントです。アカウント内の特定のIAMユーザに、すべてのリソースに対する「キーの管理」操作を許可しています。管理操作とは、キーの作成、閲覧、一覧、削除、有効化、無効化などです。
{ "Sid": "Allow access for Key Administrators", "Effect": "Allow", "Principal": { "AWS": [ "arn:aws:iam::<ACCOUNT-ID>:user/<IAM-USER-NAME>" ] }, "Action": [ "kms:Create*", "kms:Describe*", "kms:Enable*", "kms:List*", "kms:Put*", "kms:Update*", "kms:Revoke*", "kms:Disable*", "kms:Get*", "kms:Delete*" ], "Resource": "*" }
それから、「キーの利用許可」のステートメントです。アカウント内の特定のIAMユーザに、すべてのリソースに対する「キーの利用」を許可しています。キーの利用とは、キーを使ったリソースの暗号化や復号などです。
{ "Sid": "Allow use of the key", "Effect": "Allow", "Principal": { "AWS": [ "arn:aws:iam::<ACCOUNT-ID>:user/<IAM-USER-NAME>" ] }, "Action": [ "kms:Encrypt", "kms:Decrypt", "kms:ReEncrypt*", "kms:GenerateDataKey*", "kms:DescribeKey" ], "Resource": "*" }
最後に、「永続化リソースの適用許可」のステートメントです。これについての解説はまた別途。
{ "Sid": "Allow attachment of persistent resources", "Effect": "Allow", "Principal": { "AWS": [ "arn:aws:iam::<ACCOUNT-ID>:user/<IAM-USER-NAME>" ] }, "Action": [ "kms:CreateGrant", "kms:ListGrants", "kms:RevokeGrant" ], "Resource": "*", "Condition": { "Bool": { "kms:GrantIsForAWSResource": true } }
繰り返すと、キーの管理とは、キーの作成、閲覧、一覧、削除、有効化、無効化を、キーの利用とは、管理されたキーを使ってリソースの暗号化や復号をすることを指します。
これでキーの管理とキーの利用の違いが把握できたと思います。
別アカウントからキーを利用する
ようやく本題ですね。外部のAWSアカウントに対してキーの利用を許可してみましょう。
キー管理側アカウントでの作業
自分で作成したキーに対して、利用を許可するAWSアカウントを指定します。なお、AWSが作成したマスターキーを、他のアカウントに利用させることはできないようです。
まず、キーの一覧で、test-kmsキーを選択します。
次に、[External Accounts]セクションで、キーの利用を許可する外部AWSアカウントIDを入力し、保存します。
変更されたポリシーを確認する
上記によってキーのポリシーがどのように変更されたかを確認しておきましょう。
% aws kms get-key-policy --key-id XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX3d0a --policy-name default { "Version" : "2012-10-17", "Id" : "key-consolepolicy-2", "Statement" : [ { "Sid" : "Enable IAM User Permissions", "Effect" : "Allow", "Principal" : { "AWS" : "arn:aws:iam::<ACCOUNT_ID>:root" }, "Action" : "kms:*", "Resource" : "*" }, { "Sid" : "Allow access for Key Administrators", "Effect" : "Allow", "Principal" : { "AWS" : "arn:aws:iam::<ACCOUNT_ID>:user/<IAM_USER_NAME>" }, "Action" : [ "kms:Describe*", "kms:List*", "kms:Create*", "kms:Revoke*", "kms:Enable*", "kms:Get*", "kms:Disable*", "kms:Delete*", "kms:Put*", "kms:Update*" ], "Resource" : "*" }, { "Sid" : "Allow use of the key", "Effect" : "Allow", "Principal" : { "AWS" : [ "arn:aws:iam::<ACCOUNT_ID>:user/<IAM_USER_NAME>", "arn:aws:iam::<EXTERNAL_ACCOUNT_ID>:root" ] }, "Action" : [ "kms:Decrypt", "kms:GenerateDataKey*", "kms:ReEncrypt*", "kms:DescribeKey", "kms:Encrypt" ], "Resource" : "*" }, { "Sid" : "Allow attachment of persistent resources", "Effect" : "Allow", "Principal" : { "AWS" : [ "arn:aws:iam::<ACCOUNT_ID>:user/<IAM_USER_NAME>", "arn:aws:iam::<EXTERNAL_ACCOUNT_ID>:root" ] }, "Action" : [ "kms:ListGrants", "kms:CreateGrant", "kms:RevokeGrant" ], "Resource" : "*", "Condition" : { "Bool" : { "kms:GrantIsForAWSResource" : true } } } ] }
最後の2つのステートメントがポイントです。「キーの利用許可」と「永続化リソースの適用許可」のステートメントで、Principalに外部アカウントが追加されました。
キー利用側(外部)アカウントでの作業
外部アカウントでは、S3にオブジェクトをPUTする際に、暗号化キーとして上記のキーを選択します。
まず、S3のバケットで[Upload]ボタンを押し、適当なファイルをローカルから選択します。
次に、[Set Datails]画面に移動し、「Use Server Side Encryption」をチェックして、「Use an AWS Key Management Service master key」を選択します。
[Master Key]テキストボックスには、デフォルトのマスターキーが表示されています。これは、このアカウントが持つデフォルトのS3用マスターキーです。
それから、test-kmsキーを選択するため、デフォルトの設定を変更します。ドロップダウンリストから[Enter a key ARN]を選択します。
最後に、test-kmsのARNとIDを、「キーのARN/キーID」の形式で入力します。
この時、キー管理側のアカウントで、キーのSummaryから値をコピーアンドペーストすると簡単です。
別アカウントのキーを利用した暗号化に成功しました。
感想
今回のre:Inventで発表されたサービスの中で、個人的に一番気になっているKey Management Serviceを少し触ってみました。
Key Management Service(略してKMS)は、キーの管理と利用という明確な役割の枠組みを用意した点が素晴らしいと思いました。これまでよりも、企業のセキュリティポリシーやアカウント管理ポリシーに則ったキーの管理運用をするために、道具立てが整ってきたのではないでしょうか。
KMSには他にも便利な機能がありますので、これからどんどん使っていきます!
それでは、また。