

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 使用 Amazon EMR 为数据加密创建密钥和证书
<a name="emr-encryption-enable"></a>

在使用安全配置指定加密选项前，确定要用于密钥和加密构件的提供程序。例如，您可以使用 AWS KMS 或您创建的自定义提供商。接下来，创建密钥或密钥提供程序，如本节中所述。

## 提供加密静态数据的密钥
<a name="emr-encryption-create-keys"></a>

在 Amazon EMR 中，您可以使用 AWS Key Management Service (AWS KMS) 或自定义密钥提供程序进行静态数据加密。使用时 AWS KMS，会收取加密密钥的存储和使用费用。有关更多信息，请参阅[AWS KMS 定价](https://aws.amazon.com/kms/pricing/)。

本主题介绍可与 Amazon EMR 结合使用的 KMS 密钥的密钥策略详细信息，以及编写适用于 Amazon S3 加密的自定义密钥提供程序类的准则和代码示例。有关创建密钥的更多信息，请参阅《AWS Key Management Service 开发人员指南》**中的[创建密钥](https://docs.aws.amazon.com/kms/latest/developerguide/create-keys.html)。

### AWS KMS keys 用于加密
<a name="emr-awskms-keys"></a>

 AWS KMS 加密密钥必须与您的 Amazon EMR 集群实例和与 EMRFS 一起使用的 Amazon S3 存储桶所在的区域创建。如果指定的密钥没有位于用于配置集群的账户中，则必须使用它的 ARN 指定密钥。

Amazon EC2 实例配置文件的角色必须具有使用您指定的 KMS 密钥的权限。Amazon EMR 中实例配置文件的默认角色是 `EMR_EC2_DefaultRole`。如果您对实例配置文件使用不同的角色，或者对 Amazon S3 的 EMRFS 请求使用 IAM 角色，请确保根据需要将每个角色添加为密钥用户。这会为该角色授予使用该 KMS 密钥的权限。有关更多信息，请参阅*《AWS Key Management Service 开发人员指南》*和[为向 Amazon S3 发出的 EMRFS 请求配置 IAM 角色](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-emrfs-iam-roles.html)中的[使用密钥策略](https://docs.aws.amazon.com/kms/latest/developerguide/key-policies.html#key-policy-default-allow-users)。

您可以使用将您的实例配置文件或 EC2 实例配置文件 AWS 管理控制台 添加到指定 KMS 密钥的密钥用户列表中，也可以使用 AWS CLI 或 AWS 软件开发工具包来附加相应的密钥策略。

请注意 Amazon EMR 仅支持[对称 KMS 密钥](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#symmetric-cmks)。不能使用[非对称 KMS 密钥](https://docs.aws.amazon.com/kms/latest/developerguide/symmetric-asymmetric.html#asymmetric-cmks)加密 Amazon EMR 集群中的静态数据。要获取确定 KMS 密钥是对称还是非对称的帮助，请参阅[识别对称密钥和非对称密钥](https://docs.aws.amazon.com/kms/latest/developerguide/find-symm-asymm.html)。

以下步骤介绍了如何使用 AWS 管理控制台将 Amazon EMR 实例配置文件 `EMR_EC2_DefaultRole` 作为*密钥用户*添加。它假定您已创建一个 KMS 密钥。要创建新的 KMS 密钥，请参阅*《AWS Key Management Service 开发人员指南》*中的[创建密钥](https://docs.aws.amazon.com/kms/latest/developerguide/create-keys.html)。

**将 Amazon EMR 的 EC2 实例配置文件添加到加密密钥用户列表中**

1. 登录 AWS 管理控制台 并在 [https://console.aws.amazon.com/km](https://console.aws.amazon.com/kms) s 处打开 AWS Key Management Service (AWS KMS) 控制台。

1. 要更改 AWS 区域，请使用页面右上角的区域选择器。

1. 选择要修改的 KMS 密钥的别名。

1. 在密钥详细信息页面的 **Key Users (密钥用户)** 下，选择 **Add (添加)**。

1. 在 **Add key users (添加密钥用户)** 对话框中，选择适当的角色。默认角色的名称为 `EMR_EC2_DefaultRole`。

1. 选择**添加**。

### 通过为 KMS 密钥提供额外的权限来启用 EBS 加密
<a name="emr-awskms-ebs-encryption"></a>

从 Amazon EMR 版本 5.24.0 开始，您可以使用安全配置选项加密 EBS 根设备和存储卷。要启用此类选项，必须指定 AWS KMS 为密钥提供商。此外，您必须向服务角色`EMR_DefaultRole`授予使用 AWS KMS key 您指定的权限。

您可以使用将服务角色 AWS 管理控制台 添加到指定 KMS 密钥的密钥用户列表中，也可以使用 AWS CLI 或 S AWS DK 来附加相应的密钥策略。

以下过程介绍如何使用将默认 Amazon EMR 服务角色添加`EMR_DefaultRole`为*关键*用户。 AWS 管理控制台 它假定您已创建一个 KMS 密钥。要创建新的 KMS 密钥，请参阅*《AWS Key Management Service 开发人员指南》*中的[创建密钥](https://docs.aws.amazon.com/kms/latest/developerguide/create-keys.html)。

**将 Amazon EMR 服务角色添加到加密密钥用户列表中**

1. 登录 AWS 管理控制台 并在 [https://console.aws.amazon.com/km](https://console.aws.amazon.com/kms) s 处打开 AWS Key Management Service (AWS KMS) 控制台。

1. 要更改 AWS 区域，请使用页面右上角的区域选择器。

1. 在左侧边栏中选择 **Customer managed keys (客户托管密钥)**。

1. 选择要修改的 KMS 密钥的别名。

1. 在密钥详细信息页面的 **Key Users (密钥用户)** 下，选择 **Add (添加)**。

1. 在**添加密钥用户**部分，选择适当的角色。Amazon EMR 的默认服务角色的名称为 `EMR_DefaultRole`。

1. 选择**添加**。

### 创建自定义密钥提供程序
<a name="emr-custom-keys"></a>

当使用安全配置时，您必须为本地磁盘加密和 Amazon S3 加密指定不同的提供程序类名。对自定义密钥提供程序的要求取决于您是否使用本地磁盘加密和 Amazon S3 加密，以及 Amazon EMR 发行版本。

根据您在创建自定义密钥提供程序时使用的加密类型，应用程序还必须实现不同的 EncryptionMaterialsProvider 接口。这两个接口在适用于 Java 的 AWS SDK 版本 1.11.0 及更高版本中都可用。
+ 要实现亚马逊 S3 加密，请使用 [com.amazonaws.services.s3.model。 EncryptionMaterialsProvider 接口](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/model/EncryptionMaterialsProvider.html)。
+ 要实现本地磁盘加密，请使用 [com.amazonaws.services.elasticmapreduce.spi.security。 EncryptionMaterialsProvider 接口](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/elasticmapreduce/spi/security/EncryptionMaterialsProvider.html)。

您可以使用任何策略为实施提供加密材料。例如，您可以选择提供静态加密材料，也可以选择与更复杂的密钥管理系统集成。

如果您使用的是 Amazon S3 加密，则必须**AES/GCM/NoPadding**对自定义加密材料使用加密算法。

如果您使用的是本地磁盘加密，则用于自定义加密材料的加密算法因 EMR 发行版而异。对于亚马逊 EMR 7.0.0 及更低版本，您必须使用。**AES/GCM/NoPadding**对于 Amazon EMR 7.1.0 及更高版本，您必须使用 **AES**。

该 EncryptionMaterialsProvider 类通过加密上下文获取加密材料。Amazon EMR 在运行时填充加密上下文信息，以帮助调用者确定要返回的正确加密材料。

**Example 示例：通过 EMRFS 使用自定义密钥提供程序对 Amazon S3 进行加密**  
当 Amazon EMR 从EncryptionMaterialsProvider 类中提取加密材料以执行加密时，EMRFS 可以选择在材料描述参数中填充两个字段：对象的 Amazon S3 URI 和 JobFlowId 集群的 URI，该类可以选择性地使用这两个字段来有选择地返回加密材料。EncryptionMaterialsProvider   
例如，提供程序可能会为不同的 Amazon S3 URI 前缀返回不同的密钥。它是最终与 Amazon S3 对象一起存储的返回加密材料的描述，而不是 EMRFS 生成并传递给提供程序的 materialsDescription 值。解密 Amazon S3 对象时，加密材料描述会传递给该EncryptionMaterialsProvider 类，这样它就可以有选择地返回匹配的密钥来解密该对象。  
下面提供了一个 EncryptionMaterialsProvider 参考实现。另一个自定义提供程序可从中获得 GitHub。[EMRFSRSAEncryptionMaterialsProvider](https://github.com/awslabs/emr-sample-apps/tree/master/emrfs-plugins/EMRFSRSAEncryptionMaterialsProvider)  

```
import com.amazonaws.services.s3.model.EncryptionMaterials;
import com.amazonaws.services.s3.model.EncryptionMaterialsProvider;
import com.amazonaws.services.s3.model.KMSEncryptionMaterials;
import org.apache.hadoop.conf.Configurable;
import org.apache.hadoop.conf.Configuration;

import java.util.Map;

/**
 * Provides KMSEncryptionMaterials according to Configuration
 */
public class MyEncryptionMaterialsProviders implements EncryptionMaterialsProvider, Configurable{
  private Configuration conf;
  private String kmsKeyId;
  private EncryptionMaterials encryptionMaterials;

  private void init() {
    this.kmsKeyId = conf.get("my.kms.key.id");
    this.encryptionMaterials = new KMSEncryptionMaterials(kmsKeyId);
  }

  @Override
  public void setConf(Configuration conf) {
    this.conf = conf;
    init();
  }

  @Override
  public Configuration getConf() {
    return this.conf;
  }

  @Override
  public void refresh() {

  }

  @Override
  public EncryptionMaterials getEncryptionMaterials(Map<String, String> materialsDescription) {
    return this.encryptionMaterials;
  }

  @Override
  public EncryptionMaterials getEncryptionMaterials() {
    return this.encryptionMaterials;
  }
}
```

## 为通过 Amazon EMR 加密来加密传输中的数据提供凭证
<a name="emr-encryption-certificates"></a>

使用 Amazon EMR 发行版 4.8.0 或更高版本，您有两个选项可指定使用安全配置对传输中的数据进行加密的构件：
+ nin 可以手动创建 PEM 凭证，将它们包含一个 zip 文件中，然后在 Amazon S3 中引用该 .zip 文件。
+ 可以将一个自定义凭证提供程序作为 Java 类实现。在 Amazon S3 中指定应用程序的 JAR 文件，然后提供与应用程序声明中相同的完整提供程序类名。该类必须实现从 1.11.0 适用于 Java 的 AWS SDK 版本开始可用的[TLSArtifacts提供者](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/elasticmapreduce/spi/security/TLSArtifactsProvider.html)接口。

Amazon EMR 自动将构件下载到集群中的每个节点，然后使用它们实现开源传输中加密功能。有关可用选项的更多信息，请参阅[传输中加密](emr-data-encryption-options.md#emr-encryption-intransit)。

### 使用 PEM 凭证
<a name="emr-encryption-pem-certificate"></a>

在为传输中加密指定 .zip 文件时，安全配置要求 .zip 文件中的 PEM 文件的命名方式与下面完全一致：


**传输中加密凭证**  

| 文件名 | 必需/可选 | Details | 
| --- | --- | --- | 
| privateKey.pem | 必需 | 私有密钥 | 
| certificateChain.pem | 必需 | 凭证链 | 
| trustedCertificates.pem | 可选 | 建议您提供未经 Java 默认受信任根证书颁发机构（CA）或可链接到 Java 默认受信任根 CA 的中间 CA 签名的证书。我们不建议您在使用通配符证书或禁用主机名验证 CAs时使用 public。 | 

您可能需要将私有密钥 PEM 文件配置为支持访问您的集群实例所在的 Amazon VPC 域的通配符凭证。例如，如果您的集群位于 us-east-1（弗吉尼亚北部），则可以选择通过在凭证主题定义中指定 `CN=*.ec2.internal` 在凭证配置中指定一个通用名称以允许访问集群。如果您的集群位于 us-west-2（俄勒冈），则可以指定 `CN=*.us-west-2.compute.internal`。

如果加密工件中提供的 PEM 文件在公用名中没有该域的通配符，则必须将的`hadoop.ssl.hostname.verifier`值更改为。`ALLOW_ALL`要在 Amazon EMR 7.3.0 及更高版本中执行此操作，请在向集群提交配置时添加 `core-site` 分类。在低于 7.3.0 的版本中，将配置 `"hadoop.ssl.hostname.verifier": "ALLOW_ALL"` 直接添加到 `core-site.xml` 文件中。必须进行此更改，因为默认主机名验证程序要求主机名不带通配符，而集群中的所有主机都使用通配符。有关 Amazon VPC 中的 EMR 集群配置的更多信息，请参阅 [在 VPC 中为 Amazon EMR 配置联网](emr-plan-vpc-subnet.md)。

以下示例演示如何使用 [OpenSSL](https://www.openssl.org/) 生成具有 2048 位 RSA 私钥的自签名 X.509 证书。该密钥允许访问发布者在 `us-west-2`（俄勒冈）区域中的 Amazon EMR 集群实例，这是用 `*.us-west-2.compute.internal` 域名作为通用名称来表示的。

指定其它可选项（如国家/地区 (C)、州/省 (S)、区域设置 (L) 等）。由于生成了自签名凭证，因此，该示例中的第二个命令会将 `certificateChain.pem` 文件复制到 `trustedCertificates.pem` 文件。第三个命令使用 `zip` 创建包含这些凭证的 `my-certs.zip` 文件。



**重要**  
此示例仅供演 proof-of-concept示。不建议使用自签名凭证，可能存在潜在安全风险。对于生产系统，应使用可信凭证颁发机构 (CA) 颁发凭证。

```
$ openssl req -x509 -newkey rsa:2048 -keyout privateKey.pem -out certificateChain.pem -days 365 -nodes -subj '/C=US/ST=Washington/L=Seattle/O=MyOrg/OU=MyDept/CN=*.us-west-2.compute.internal'
$ cp certificateChain.pem trustedCertificates.pem
$ zip -r -X my-certs.zip certificateChain.pem privateKey.pem trustedCertificates.pem
```