Nifi:如何让 ListenHTTP 与 SSL 一起工作

Nifi: how to make ListenHTTP work with SSL

Objective

由于 Nifi 通过 HTTP 与其他工具集成,我必须让 ListenHTTP 处理器面向 public。 API 所有 3 个环境的网关对我来说太贵了。因此,我关闭了外部网络的所有 VM 入口端口(ListenHTTP 所需的端口除外)。

问题

我对 ListenHTTPStandardRestrictedSSLContextService 的配置不起作用。没有 SSL 它可以工作,但不安全。

user$ curl -X POST -H "Content-Type: application/json" --data "test" https://localhost:7070/test
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
curl: (60) SSL certificate problem: self signed certificate
More details here: https://curl.haxx.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.

.....

user$ curl -X POST -H "Content-Type: application/json" --data "test" --cacert cacerts.jks  https://localhost:7070/test
curl: (77) error setting certificate verify locations:
  CAfile: cacerts.jks
  CApath: none

问题

如何使 ListenHTTP 使用 SSL 证书?我做错了什么?

更详细的问题:

  1. 我应该将 cacerts.jsk 复制到发出查询的机器上吗?据我了解,StandardRestrictedSSLContextService 将验证客户端是否在 TrustStore 中有证书。
  2. 如果我只需要保护带有 ListenHTTP 处理器的单个端口 - 那么我不需要 nifi.security.needClientAuth property or all environment variables defined at "Standalone Instance, Two-Way SSL" 部分,对吗?我有点困惑,因为 Docker Image 和 StandardRestrictedSSLContextService 包含相同的配置,即 KEYSTORE_TYPE.

已经完成

  1. 我对 this question and the documentation 的 KeyStore 和 TrustStore 有一个大概的了解。
  2. 我已经在 7070 端口上启动了 Nifi Docker container v1.10.0 和 运行 ListenHTTP 处理器。
  3. 由于 Nifi 容器中的 instruction,我创建了 keystore.jks 和 cacerts.jks 文件。
  4. 我已将 ListenHTTP 配置为使用具有以下配置的 StandardRestrictedSSLContextService 控制器: .

您正在使用的 SSLContextService 可能不包含由 public 仅可访问的证书颁发机构 (CA) 签署的证书,例如(仅用于解释目的;不是认可) Comodo、Verisign、Let's Encrypt 等

由这些 CA 签署的证书通常会被任意客户端自动信任,因为无论谁构建客户端(Java,Google/Microsoft/Mozilla/Apple 对于浏览器,Microsoft/Apple/Linux Distro 对于 OS) 抢先将那些顶级 public 证书包含在客户端的 truststore 中。您创建的 cacerts.jks 信任库采用 Java 密钥库格式,curl 碰巧无法理解。您可以使用 the commands here 将 public 证书从该密钥库导出到 PEM 格式的独立文件,但这只会解决允许 curl 与任意信任库连接的直接问题。

如果您希望通用外部客户端能够通过 TLS 进行连接,您需要使用 NiFi 密钥库中的证书,该证书由知名 CA 签署。您可以为此目的使用任何商业 CA,但 Let's Encrypt 确实免费提供此服务并且使用非常广泛。使用由 CA 签名的证书后,任何*客户端都可以连接。

如果这仅供 internal/enterprise 使用,并且所有允许的客户端都由您控制,那么您可以使用自签名证书(就像您现在按照 Simon 的说明所做的那样),然后导出public 证书转换为您的其他客户需要的任何格式,以便与该特定服务器建立信任。从理论上讲,您还可以强制每个尝试连接的客户端还需要出示 server (NiFi) 可以验证的证书——这称为 mutual-authentication TLS 并增加了另一层安全性,因为只有经过身份验证的客户端才能向该服务器发出请求。如果您选择这样做,那么 ListenHTTP 中的 SSLContextService 也需要信任库组件。

在不知道您具体情况的情况下,我强烈推荐选项 1(签名证书)。