まとめ
- 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
の権限を削除してもファイルのアップロードに失敗した。