本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
Hive 中的 Parquet 模块化加密
Parquet 模块化加密提供列级访问控制和加密功能,以增强以 Parquet 文件格式存储的数据的隐私和数据完整性。此功能从 6.6.0 版本开始在 Amazon EMR Hive 中可用。
Amazon EMR 管理指南中的加密选项中描述了以前支持的安全和完整性解决方案,包括加密文件或加密存储层。这些解决方案可以用于 Parquet 文件,但是利用集成 Parquet 加密机制的新功能可以在列级别实现精细访问控制,并提高性能和安全性。有关此功能的更多信息,请访问 Apache github 页面 Parquet 模块化加密
用户使用 Hadoop 配置将配置传递给 Parquet 读取器和写入器。用户配置读取器和写入器以启用加密以及切换高级功能的详细配置记录在 PARQUET-1854:Parquet 加密管理的属性驱动接口
用法示例
以下示例涉及使用 Amazon KMS 创建加密密钥并写入 Hive 表以进行加密密钥管理。
-
如文档 PARQUET-1373:加密密钥管理工具
中所述,为 Amazon KMS 服务实现。 KmsClient 以下示例演示了一个实施片段。 package org.apache.parquet.crypto.keytools; import com.amazonaws.AmazonClientException; import com.amazonaws.AmazonServiceException; import com.amazonaws.regions.Regions; import com.amazonaws.services.kms.AWSKMS; import com.amazonaws.services.kms.AWSKMSClientBuilder; import com.amazonaws.services.kms.model.DecryptRequest; import com.amazonaws.services.kms.model.EncryptRequest; import com.amazonaws.util.Base64; import org.apache.hadoop.conf.Configuration; import org.apache.parquet.crypto.KeyAccessDeniedException; import org.apache.parquet.crypto.ParquetCryptoRuntimeException; import org.apache.parquet.crypto.keytools.KmsClient; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.nio.ByteBuffer; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; public class AwsKmsClient implements KmsClient { private static final AWSKMS AWSKMS_CLIENT = AWSKMSClientBuilder .standard() .withRegion(Regions.US_WEST_2) .build(); public static final Logger LOG = LoggerFactory.getLogger(AwsKmsClient.class); private String kmsToken; private Configuration hadoopConfiguration; @Override public void initialize(Configuration configuration, String kmsInstanceID, String kmsInstanceURL, String accessToken) throws KeyAccessDeniedException { hadoopConfiguration = configuration; kmsToken = accessToken; } @Override public String wrapKey(byte[] keyBytes, String masterKeyIdentifier) throws KeyAccessDeniedException { String value = null; try { ByteBuffer plaintext = ByteBuffer.wrap(keyBytes); EncryptRequest req = new EncryptRequest().withKeyId(masterKeyIdentifier).withPlaintext(plaintext); ByteBuffer ciphertext = AWSKMS_CLIENT.encrypt(req).getCiphertextBlob(); byte[] base64EncodedValue = Base64.encode(ciphertext.array()); value = new String(base64EncodedValue, Charset.forName("UTF-8")); } catch (AmazonClientException ae) { throw new KeyAccessDeniedException(ae.getMessage()); } return value; } @Override public byte[] unwrapKey(String wrappedKey, String masterKeyIdentifier) throws KeyAccessDeniedException { byte[] arr = null; try { ByteBuffer ciphertext = ByteBuffer.wrap(Base64.decode(wrappedKey.getBytes(StandardCharsets.UTF_8))); DecryptRequest request = new DecryptRequest().withKeyId(masterKeyIdentifier).withCiphertextBlob(ciphertext); ByteBuffer decipheredtext = AWSKMS_CLIENT.decrypt(request).getPlaintext(); arr = new byte[decipheredtext.remaining()]; decipheredtext.get(arr); } catch (AmazonClientException ae) { throw new KeyAccessDeniedException(ae.getMessage()); } return arr; } }
-
按照《Amazon Key Management Service 开发者指南》中的创建密钥中所述,为页脚以及您的IAM角色具有访问权限的列创建 Amazon KMS 加密密钥。默认IAM角色是 EMR _ ECS _default。
-
在 Amazon EMR 集群上的 Hive 应用程序上,使用上面的
ADD JAR
语句添加上面的客户端,如 Apache Hive 资源文档中所述。下面是一个示例语句: ADD JAR 's3://location-to-custom-jar';
另一种方法是使用引导操作将添加JAR到 Hive 中。
auxlib
以下是要添加到引导操作的示例行:aws s3 cp 's3://location-to-custom-jar' /usr/lib/hive/auxlib
-
设置下列配置值:
set parquet.crypto.factory.class=org.apache.parquet.crypto.keytools.PropertiesDrivenCryptoFactory; set parquet.encryption.kms.client.class=org.apache.parquet.crypto.keytools.AwsKmsClient;
-
创建一个 Parquet 格式的 Hive 表,在其中指定 Amazon KMS 键SERDEPROPERTIES并向其中插入一些数据:
CREATE TABLE my_table(name STRING, credit_card STRING) ROW FORMAT SERDE 'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe’ WITH SERDEPROPERTIES ( 'parquet.encryption.column.key’=<aws-kms-key-id-for-column-1>: credit_card’, 'parquet.encryption.footer.key’='<aws-kms-key-id-for-footer>’) STORED AS parquet LOCATION “s3://<bucket/<warehouse-location>/my_table”; INSERT INTO my_table SELECT java_method ('org.apache.commons.lang.RandomStringUtils','randomAlphabetic',5) as name, java_method ('org.apache.commons.lang.RandomStringUtils','randomAlphabetic',10) as credit_card from (select 1) x lateral view posexplode(split(space(100),' ')) pe as i,x; select * from my_table;
-
验证当您在同一位置创建无法访问 Amazon KMS 密钥的外部表时(例如,IAM角色访问被拒绝),是否无法读取数据。
CREATE EXTERNAL TABLE ext_table (name STRING, credit_card STRING) ROW FORMAT SERDE 'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe’ STORED AS parquet LOCATION “s3://<bucket>/<warehouse-location>/my_table”; SELECT * FROM ext_table;
-
最后一条语句应触发以下异常:
Failed with exception java.io.IOException:org.apache.parquet.crypto.KeyAccessDeniedException: Footer key: access denied