AWS Key Management Serviceでキーの”管理”と”利用”を分離する #reinvent

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、虎塚です。

今回のre:Inventで発表されたAWS Key Management Serviceは、データを暗号化するためのキーをAWS内で生成、削除、ローテートなどの管理ができるサービスです。このサービスは、キーを管理するユーザと、キーを利用するユーザを別々に定義できるのが特徴です(同じにすることもできます)。

この記事では、まず、キーの管理と利用の違いを説明します。次に、アカウントをまたいでキーを利用し、S3にアップロードするオブジェクトを暗号化する例を紹介します。

AWS Key Management Serviceのキーを別アカウントで使用することは、まさに管理と利用の分離の一例です。アカウントをまたいで、二つの役割を定義するわけですね。

キーの管理と利用

キーの管理と利用について理解するには、自分で作成したキーのポリシーを見るのが分かりやすいでしょう。大瀧さんの記事([新サービス] AWS Key Management Serviceを触ってみた #reinvent | Developers.IO)の手順にあったように、ウィザードを使ってキーを作成すると、キーの管理者とキーの利用者を定義する画面が区別されています。これがそっくりポリシーに反映されているためです。

キーの管理者を定義する画面がこちら(Default Key Administrators)。

de_1

キーの利用者を定義する画面がこちら(Default Key Usage Permissions)です。

de_2

以下の説明では前提として、上記の記事の手順で、東京リージョンに「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キーを選択します。

a_1

次に、[External Accounts]セクションで、キーの利用を許可する外部AWSアカウントIDを入力し、保存します。

a_2

変更されたポリシーを確認する

上記によってキーのポリシーがどのように変更されたかを確認しておきましょう。

% 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]ボタンを押し、適当なファイルをローカルから選択します。

up_1

次に、[Set Datails]画面に移動し、「Use Server Side Encryption」をチェックして、「Use an AWS Key Management Service master key」を選択します。

[Master Key]テキストボックスには、デフォルトのマスターキーが表示されています。これは、このアカウントが持つデフォルトのS3用マスターキーです。

up_2

それから、test-kmsキーを選択するため、デフォルトの設定を変更します。ドロップダウンリストから[Enter a key ARN]を選択します。

up_3

最後に、test-kmsのARNとIDを、「キーのARN/キーID」の形式で入力します。

up_4

この時、キー管理側のアカウントで、キーのSummaryから値をコピーアンドペーストすると簡単です。

up_4.5

別アカウントのキーを利用した暗号化に成功しました。

up_5

感想

今回のre:Inventで発表されたサービスの中で、個人的に一番気になっているKey Management Serviceを少し触ってみました。

Key Management Service(略してKMS)は、キーの管理と利用という明確な役割の枠組みを用意した点が素晴らしいと思いました。これまでよりも、企業のセキュリティポリシーやアカウント管理ポリシーに則ったキーの管理運用をするために、道具立てが整ってきたのではないでしょうか。

KMSには他にも便利な機能がありますので、これからどんどん使っていきます!

それでは、また。