

# SSL设置

> 译者：[flink.sojb.cn](https://flink.sojb.cn/)


此页面提供有关如何为Flink进程之间和之间的网络通信启用TLS / SSL身份验证和加密的说明。

## 内部和外部连接

通过身份验证和加密保护机器进程之间的网络连接时，Apache Flink可区分_内部_和_外部_连接。 _内部连接_是指Flink进程之间建立的所有连接。这些连接运行Flink自定义协议。用户永远不会直接连接到内部连接端点。 _外部/ REST连接_端点是指从外部到Flink进程的所有连接。这包括用于启动和控制正在运行的Flink作业/应用程序的Web UI和REST命令，包括Flink CLI与JobManager / Dispatcher的通信。

为了获得更大的灵活性，可以单独启用和配置内部和外部连接的安全性。

![内部和外部连接](../img/ssl_internal_external.svg)

#### 内部连接

内部连接包括：

*   控制消息：JobManager / TaskManager / Dispatcher / ResourceManager之间的RPC
*   数据平面：TaskManagers之间的连接，用于在随机播放，广播，再分配等过程中交换数据。
*   Blob服务（库和其他工件的分发）。

所有内部连接都经过SSL身份验证和加密。连接使用**相互身份验证**，这意味着每个连接的服务器端和客户端都需要相互提供证书。证书有效地作为共享密钥。

常见的设置是为Flink部署生成专用证书（可以是自签名的）。任何其他方都不需要与Flink交互的内部通信证书，可以简单地添加到容器镜像或附加到YARN部署。

_注意：由于内部连接使用共享证书进行相互身份验证，因此Flink可以跳过主机名验证。这使基于容器的设置更容易。_

#### 外部/ REST连接

所有外部连接都通过HTTP / REST端点公开，例如由Web UI和CLI使用：

*   与_Dispatcher_通信以提交作业（会话群集）
*   与_JobManager_通信以检查和修改正在运行的作业/应用程序

可以将REST端点配置为需要SSL连接。但是，服务器将接受来自任何客户端的连接，这意味着REST端点不会对客户端进行身份验证。

如果需要验证与REST端点的连接，我们建议部署“侧面汽车代理”：将REST端点绑定到环回接口（或Kubernetes中的pod本地接口）并启动REST代理，以验证和转发要求Flink。Flink用户部署的[代理的](https://www.envoyproxy.io/)[示例](http://nginx.org/en/docs/http/ngx_http_auth_request_module.html)是[Envoy Proxy](https://www.envoyproxy.io/)或 [带有MOD_AUTH的NGINX](http://nginx.org/en/docs/http/ngx_http_auth_request_module.html)。

将身份验证委托给代理的理由是，这些代理提供的许多身份验证选项比Flink项目可以合理地实现自身更多，因此可以更好地集成到现有的基础架构中。

#### 可查询状态

与可查询状态端点的连接当前未经过身份验证或加密。

## 配置SSL

可以单独为_内部_和_外部_连接启用S​​SL ：

*   **security.ssl.internal.enabled**：为所有_内部_连接启用S​​SL 。
*   **security.ssl.rest.enabled**：为_REST /外部_连接启用S​​SL 。

_注意：为了向后兼容，**security.ssl.enabled**选项仍然存在，并为内部和REST端点启用SSL。_

对于内部连接，您可以选择分别禁用不同连接类型的安全性。如果`security.ssl.internal.enabled`设置为`true`，则可以设置以下参数`false`以禁用该特定连接类型的SSL：

*   `taskmanager.data.ssl.enabled`：TaskManagers之间的数据通信
*   `blob.service.ssl.enabled`：将BLOB从JobManager传输到TaskManager
*   `akka.ssl.enabled`：JobManager / TaskManager / ResourceManager之间基于Akka的RPC连接

#### Keystore和Truststores

SSL配置需要配置**Keys库**和**信任****库**。该_Keys库_包含公共证书（公钥）和私钥，而信任库包含可信证书或可信当局。需要设置这两个存储，以便信任库信任Keys库的证书。

**内部连接**

由于内部通信是相互身份验证的，因此Keys库和信任库通常包含相同的专用证书。证书可以使用通配符主机名或地址，因为证书应该是共享Keys，并且不验证主机名。甚至可以使用与信任库相同的文件（Keys库）。



```
security.ssl.internal.keystore: /path/to/file.keystore
security.ssl.internal.keystore-password: keystore_password
security.ssl.internal.key-password: key_password
security.ssl.internal.truststore: /path/to/file.truststore
security.ssl.internal.truststore-password: truststore_password
```



**REST端点（外部连接）**

对于REST端点，Keys库由服务器端点使用，并且REST客户端（包括CLI客户端）使用信任库来接受服务器的证书。在RESTKeys库具有自签名证书的情况下，信任库必须直接信任该证书。如果REST端点使用通过适当的证书层次结构签名的证书，则该层次结构的根应位于信任库中。



```
security.ssl.rest.keystore: /path/to/file.keystore
security.ssl.rest.keystore-password: keystore_password
security.ssl.rest.key-password: key_password
security.ssl.rest.truststore: /path/to/file.truststore
security.ssl.rest.truststore-password: truststore_password
```



**重要**

在[IETF RFC 7525](https://tools.ietf.org/html/rfc7525)建议使用一组特定的密码套件的强大的安全性。由于这些密码套件在开箱即用的许多设置中都不可用，因此Flink的默认值设置为稍弱但更兼容的密码套件。如果可能，我们建议通过在Flink配置中添加以下条目，SSL设置更新到更强大的密码套件：



```
security.ssl.algorithms: TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
```



如果您的设置不支持这些密码套件，您将看到Flink进程无法相互连接。

## 创建和部署Keys库和信任库

可以使用[keytool实用程序](https://docs.oracle.com/javase/8/docs/technotes/tools/unix/keytool.html)生成Keys，证书以及Keys库和信任库。您需要从Flink集群中的每个节点访问适当的Java Keystore和Truststore。

*   对于独立安装，这意味着将文件复制到每个节点，或将它们添加到共享安装目录。
*   对于基于容器的设置，请将Keys库和信任库文件添加到容器镜像中。
*   对于Yarn / Mesos设置，群集部署阶段可以自动分发Keys库和信任库文件。

对于面向外部的REST端点，证书中的公用名称或主题Slave 名称应与节点的主机名和IP地址匹配。

## 示例SSL Setup Standalone和Kubernetes

**内部连接**

执行以下keytool命令以在Keys库中创建Keys对：



```
keytool -genkeypair -alias flink.internal -keystore internal.keystore -dname "CN=flink.internal" -storepass internal_store_password -keypass internal_key_password -keyalg RSA -keysize 4096
```



Keys库中的单个Keys/证书由服务器和客户端端点以相同的方式使用（相互身份验证）。Keys对充当内部安全的共享Keys，我们可以直接将其用作Keys库和信任库。



```
security.ssl.internal.enabled: true
security.ssl.internal.keystore: /path/to/flink/conf/internal.keystore
security.ssl.internal.truststore: /path/to/flink/conf/internal.keystore
security.ssl.internal.keystore-password: internal_store_password
security.ssl.internal.truststore-password: internal_store_password
security.ssl.internal.key-password: internal_key_password
```



**REST端点**

REST端点可以从外部进程接收连接，包括不属于Flink的工具（例如，对REST API的curl请求）。设置通过CA层次结构签名的正确证书可能对REST端点有意义。

但是，如上所述，REST端点不会对客户端进行身份验证，因此通常需要通过代理进行安全保护。

**REST端点（简单的自签名证书）**

此示例显示如何创建简单的Keys库/信任库对。信任库不包含主键，可以与其他应用程序共享。在此示例中，_myhost.company.org / ip：10.0.2.15_是Flink主节点的节点（或服务）。



```
keytool -genkeypair -alias flink.rest -keystore rest.keystore -dname "CN=myhost.company.org" -ext "SAN=dns:myhost.company.org,ip:10.0.2.15" -storepass rest_keystore_password -keypass rest_key_password -keyalg RSA -keysize 4096

keytool -exportcert -keystore rest.keystore -alias flink.rest -storepass rest_keystore_password -file flink.cer

keytool -importcert -keystore rest.truststore -alias flink.rest -storepass rest_truststore_password -file flink.cer -noprompt
```





```
security.ssl.rest.enabled: true
security.ssl.rest.keystore: /path/to/flink/conf/rest.keystore
security.ssl.rest.truststore: /path/to/flink/conf/rest.truststore
security.ssl.rest.keystore-password: rest_keystore_password
security.ssl.rest.truststore-password: rest_truststore_password
security.ssl.rest.key-password: rest_key_password
```



**REST端点（带有自签名CA）**

执行以下keytool命令以使用自签名CA创建信任库。



```
keytool -genkeypair -alias ca -keystore ca.keystore -dname "CN=Sample CA" -storepass ca_keystore_password -keypass ca_key_password -keyalg RSA -keysize 4096 -ext "bc=ca:true"

keytool -exportcert -keystore ca.keystore -alias ca -storepass ca_keystore_password -file ca.cer

keytool -importcert -keystore ca.truststore -alias ca -storepass ca_truststore_password -file ca.cer -noprompt
```



现在使用由上述CA签名的证书为REST端点创建Keys库。让_flink.company.org / ip：10.0.2.15_成为Flink master（_JobManager）_的主机名。



```
keytool -genkeypair -alias flink.rest -keystore rest.signed.keystore -dname "CN=flink.company.org" -ext "SAN=dns:flink.company.org" -storepass rest_keystore_password -keypass rest_key_password -keyalg RSA -keysize 4096

keytool -certreq -alias flink.rest -keystore rest.signed.keystore -storepass rest_keystore_password -keypass rest_key_password -file rest.csr

keytool -gencert -alias ca -keystore ca.keystore -storepass ca_keystore_password -keypass ca_key_password -ext "SAN=dns:flink.company.org,ip:10.0.2.15" -infile rest.csr -outfile rest.cer

keytool -importcert -keystore rest.signed.keystore -storepass rest_keystore_password -file ca.cer -alias ca -noprompt

keytool -importcert -keystore rest.signed.keystore -storepass rest_keystore_password -keypass rest_key_password -file rest.cer -alias flink.rest -noprompt
```



现在将以下配置添加到您的`flink-conf.yaml`：



```
security.ssl.rest.enabled: true
security.ssl.rest.keystore: /path/to/flink/conf/rest.signed.keystore
security.ssl.rest.truststore: /path/to/flink/conf/ca.truststore
security.ssl.rest.keystore-password: rest_keystore_password
security.ssl.rest.key-password: rest_key_password
security.ssl.rest.truststore-password: ca_truststore_password
```



## YARN / Mesos部署提示

对于YARN和Mesos，您可以使用Yarn和Mesos的工具来帮助：

*   配置内部通信的安全性与上面的示例完全相同。

*   要保护REST端点，您需要颁发REST端点的证书，使其对Flink主服务器可能部署到的所有主机都有效。这可以使用通配符DNS名称或通过添加多个DNS名称来完成。

*   部署Keys库和信任库的最简单方法是通过YARN客户端的_发送文件_选项（`-yt`）。将Keys库和信任库文件复制到本地目录（例如`deploy-keys/`）并按如下方式启动YARN会话：`flink run -m yarn-cluster -yt deploy-keys/ flinkapp.jar`

*   使用YARN部署时，可以通过YARN代理的跟踪URL访问Flink的Web仪表板。要确保YARN代理能够访问Flink的HTTPS URL，您需要配置YARN代理以接受Flink的SSL证书。为此，将自定义CA证书添加到YARN代理节点上的Java默认信任库中。

