EMR で KMS のカスタマー管理CMKを利用するには、S3 バケットのデフォルト暗号化で CMK を指定し、S3 と KMS に対する必要な権限を持つロールを EMR にアタッチすればよい。
また、S3 のバケットポリシーで特定の CMK 以外での PUT を禁止すると、「CMK 指定なし」と「許可した CMK 指定する」とアップロードできるが、「許可した CMK 以外を指定する」と失敗する。
検証結果
- ファイルを作成する。
$ perl -le 'print for 1..10000' > number10000.txt
$ aws s3 cp number10000.txt s3://az-emr-kms-test/ upload: ./number10000.txt to s3://az-emr-kms-test/number10000.txt
$ aws s3 cp number10000.txt s3://az-emr-kms-test/number10000.txt --sse aws:kms --sse-kms-key-id 'arn:aws:kms:ap-northeast-1:123456789012:key/c3******-168d-4***-9***-9***********' upload: ./number10000.txt to s3://az-emr-kms-test/number10000.txt
$ aws s3 cp number10000.txt s3://az-emr-kms-test/number10000.txt --sse aws:kms --sse-kms-key-id 'arn:aws:kms:ap-northeast-1:123456789012:key/2a******-8b8f-4***-9***-0***********' upload failed: ./number10000.txt to s3://az-emr-kms-test/number10000.txt An error occurred (AccessDenied) when calling the PutObject operation: Access Denied
- PySpark on EMR で、EMRFS で S3 に書ける(CMK指定なし)。
$ pyspark Python 2.7.15 (default, Nov 28 2018, 22:38:08) [GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux2 Type "help", "copyright", "credits" or "license" for more information. Setting default log level to "WARN". To adjust logging level use sc.setLogLevel(newLevel). For SparkR, use setLogLevel(newLevel). 19/04/01 07:54:31 WARN Utils: Service 'SparkUI' could not bind on port 4040. Attempting port 4041. 19/04/01 07:54:31 WARN Utils: Service 'SparkUI' could not bind on port 4041. Attempting port 4042. 19/04/01 07:54:31 WARN Utils: Service 'SparkUI' could not bind on port 4042. Attempting port 4043. 19/04/01 07:54:34 WARN Client: Neither spark.yarn.jars nor spark.yarn.archive is set, falling back to uploading libraries under SPARK_HOME. Welcome to ____ __ / __/__ ___ _____/ /__ _\ \/ _ \/ _ `/ __/ '_/ /__ / .__/\_,_/_/ /_/\_\ version 2.4.0 /_/ Using Python version 2.7.15 (default, Nov 28 2018 22:38:08) SparkSession available as 'spark'. >>> df = spark.read.csv("s3://az-emr-kms-test/number10000.txt") >>> df.head(10) [Row(_c0=u'1'), Row(_c0=u'2'), Row(_c0=u'3'), Row(_c0=u'4'), Row(_c0=u'5'), Row(_c0=u'6'), Row(_c0=u'7'), Row(_c0=u'8'), Row(_c0=u'9'), Row(_c0=u'10')] >>> df.write.mode('overwrite').parquet("s3://az-emr-kms-test/number10000.parquet") >>> exit
- Sparkから書いたファイルを確認する。
$ aws s3 ls --recursive s3://az-emr-kms-test/ 2019-04-01 07:34:49 48894 num1 2019-04-01 05:39:51 888888898 number.txt 2019-04-01 07:55:47 0 number10000.parquet/_SUCCESS 2019-04-01 07:55:47 43888 number10000.parquet/part-00000-4c91ddce-b347-4239-85ec-0eba160c6c15-c000.snappy.parquet 2019-04-01 07:53:21 48894 number10000.txt
準備
- EMRクラスタを作成する。
- IAMポリシー「KMSUserPolicy1」を作成して、ロール「EMR_EC2_DefaultRole」にアタッチする
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "kms:Encrypt", "kms:Decrypt", "kms:ReEncrypt*", "kms:GenerateDataKey*", "kms:DescribeKey", "kms:ListAliases" ], "Resource": "*" } ] }
- S3バケットポリシーで指定したCMK以外での暗号化を禁止する。
{ "Version": "2012-10-17", "Id": "S3KeyPolicy", "Statement": [ { "Sid": "Force KMS Key", "Effect": "Deny", "Principal": "*", "Action": "s3:PutObject", "Resource": "arn:aws:s3:::az-emr-kms-test/*", "Condition": { "StringNotEquals": { "s3:x-amz-server-side-encryption-aws-kms-key-id": "arn:aws:kms:ap-northeast-1:123456789012:key/c3******-168d-4***-9***-9***********" } } } ] }