LoginSignup
3
5

More than 5 years have passed since last update.

AWS Key Management System (KMS) を外部アカウントから利用するための設定

Last updated at Posted at 2018-12-20

まとめ

  • AWS KMSのアクセス権限ポリシーは、Customer Master Key(CMK)のキーポリシーと利用者(IAMユーザ/ロール)のIAMポリシーの2箇所に記述できる。評価論理はIAMポリシーのそれと同様である。
  • 外部アカウントへのCMKの利用許可設定は、クロスアカウントでのリソースへのアクセスとなるため、キーポリシーと外部アカウントの利用者の2箇所に許可設定を記述する必要がある。

実験

実験として、2つのアカウント間でKMS CMKの利用ポリシーを設定し、S3デフォルト暗号化(SSE-KMS)されたバケットにオブジェクトをGet, Putを試みた。
(AWS CLIでも確認できるが、コマンドが複雑なため結果がわかりやすいS3バケットで確かめることにする)

実験概要

2つのAWSアカウント KeyStoreAccount, KeyUserAccount を用意する。
KeyStoreAccount では以下を設定する。

  • AWS KMS CMKの作成、キーポリシーの設定
  • S3 バケットの作成、バケットポリシーの設定

KeyUserAccount では以下を設定する。

  • IAM Userの作成、AWS KMS CMKキー利用ポリシーの設定

KeyUserAccount の IAM User 権限を用いてS3バケットにアクセスし、オブジェクトのGet, Putができることを確かめる。
加えて、権限設定を変えた状態でS3バケットへのアクセスを行い、2アカウント間でKMS鍵を利用するために必要な設定を確かめる。

準備

  • AWSアカウント KeyStoreAccount, KeyUserAccount を用意する。
  • AWS CLI を設定する

IAM User を作成する

AWSアカウント KeyUserAccount 上で IAMユーザ kms-test-user を作成し、アクセスキーとシークレットキーを控える。

AWS KMS CMK の作成

KeyStoreAccount 上で AWS KMS CMK を作成し、ARNを控える
マネジメントコンソールでアクセスすると、キーポリシーがGUIで表示される。しかし、実際はJSONで記述されているため、GUIでは選択できないような設定も可能である。コンソールのJSONタブを選択すると、JSONファイルを直接編集できる。 SID Allow use of the key のブロックを以下のように変更する。(↓はIAMユーザ admin を作成して KeyStoreAccount にログインしていた場合の設定である。)

    {
      "Sid": "Allow use of the key",
      "Effect": "Allow",
      "Principal": {
        "AWS": [
          "arn:aws:iam::{{ KeyStoreAccountのアカウント番号 }}:user/admin",
          "arn:aws:iam::{{ KeyUserAccountのアカウント番号 }}:user:kms-test-user"
        ]
      },
      "Action": [
        "kms:Encrypt",
        "kms:Decrypt",
        "kms:ReEncrypt*",
        "kms:GenerateDataKey*",
        "kms:DescribeKey"
      ],
      "Resource": "*"
    },

S3バケットの作成

KeyStoreAccount 上でS3バケットを作成する。バケットのオプションでデフォルト暗号化(SSE-KMS)を設定し、以下をバケットポリシーに追記する。

{
   "Version":"2012-10-17",
   "Id":"PutObjPolicy",
   "Statement":[
      {
         "Sid":"DenyUnEncryptedObjectUploads",
         "Effect":"Deny",
         "Principal":"*",
         "Action":"s3:PutObject",
         "Resource":"arn:aws:s3:::{{ 作成したバケット名 }}/*",
         "Condition":{
            "StringNotEquals":{
               "s3:x-amz-server-side-encryption":"aws:kms"
            }
         }
      },
      {
         "Sid": "Example permissions",
         "Effect": "Allow",
         "Principal": {
             "AWS": "arn:aws:iam::{{ KeyUserAccountのアカウント番号 }}:root"
         },
         "Action": [
             "s3:*"
         ],
         "Resource": [
             "arn:aws:s3:::{{ 作成したバケット名 }}/*",
             "arn:aws:s3:::{{ 作成したバケット名 }}"
         ]
      }
   ]
}

IAM User のポリシー設定

IAMユーザ kms-test-user に以下ポリシーの権限を付与する。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "kms:Encrypt",
        "kms:Decrypt",
        "kms:ReEncrypt*",
        "kms:GenerateDataKey*",
        "kms:DescribeKey"
      ],
      "Resource": "{{ 作成したAWS KMS CMKのARN }}"
    },
    {
      "Effect": "Allow",
      "Action": "s3:*",
      "Resource": "arn:aws:s3:::{{ 作成したバケット名 }}/*"
    }
  ]
}

S3バケットにオブジェクトを配置する

適当なファイルを作成し、 kms-test-user のクレデンシャル情報を用いてS3バケットにオブジェクトを設定する

クレデンシャル情報の設定

控えておいたアクセスキー/シークレットキー情報を環境変数に設定する。環境変数の管理はDirenvがおすすめ。

export AWS_ACCESS_KEY_ID={{ アクセスキー }}
export AWS_SECRET_ACCESS_KEY={{ シークレットキー }}

オブジェクトの配置

以下のコマンドでS3バケットにオブジェクトを配置する。PutObjectの際には暗号化設定を入れる必要があるので、 --sse および --sse-kms-key-id を指定している。

$ aws s3 cp ./test.txt s3://{{ 作成したバケット名 }} --sse "aws:kms" --sse-kms-key-id {{ AWS KMS CMKのARN }}
upload: ./test.txt to s3://{[ 作成したバケット名 }}/test.txt

無事にオブジェクトが配置できた。

補足1

オブジェクトの所有者が KeyUserAccount となるため、 KeyStoreAccount からは test.txt へのGetアクションが拒否される。

補足2

--sse-kms-key-id にはCMKのIDも指定できるが、内部でARNを生成する際にクレデンシャルが所属するアカウント番号が補完されるためキー名がない、とエラーになる。

$ aws s3 cp ./test.txt s3://{{ 作成したバケット名 }} --sse "aws:kms" --sse-kms-key-id {{ AWS KMS CMKのID }}
upload failed: ./test.txt to s3://{{ 作成したバケット名 }}/test.txt An error occurred (KMS.NotFoundException) when calling the PutObject operation: Key 'arn:aws:kms:{{ Region }}:{{ KeyUserAccountのアカウント番号 }}:key/{{ AWS KMS CMKのID}}' does not exist

追加実験 権限を変えて試してみる

KeyUserAccount 側の記述を削除する

上記手順では、CMKのキーポリシーに kms-test-user への利用権限を記述している。IAMポリシーの評価論理に照らし合わせれば、 kms-test-user 側のポリシーに何も書かなくてもCMKは利用可能となるはずである。

そこで、 kms-test-user のポリシーから CMK の権限に関する記述を削除してみる。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "s3:*",
      "Resource": "arn:aws:s3:::{{ 作成したバケット名 }}/*"
    }
  ]
}

この状態で s3 cp を実行すると、下記のように失敗する。

$ aws s3 cp ./test.txt s3://{{ 作成したバケット名 }} --sse "aws:kms" --sse-kms-key-id {{ AWS KMS CMKのARN }}
upload failed: ./test.txt to s3://{{ 作成したバケット名 }}/test.txt An error occurred (AccessDenied) when calling the PutObject operation: Access Denied

おそらく、クロスアカウントでのリソース利用に関わる権限設定に引っかかってるものと思われる。

AWS KMS CMK キーポリシーの記述を削除する

同様に、CMKのキーポリシーから kms-test-user の権限を削除してもファイルのアップロードに失敗した。

参考

3
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
5