在 Pivotal Cloud Foundry 上设置双向 SSL 身份验证

Setting up Two way SSL Authentication on Pivotal Cloud Foundry

我的任务是在 Zuul 代理应用程序(客户端)和其中一个微服务(服务器)之间设置两种方式的 ssl 身份验证。两者都是 Spring 启动应用程序。 我能够使用自签名证书和下一个配置在本地完成:

对于我在 yml 文件中设置 SSL 的服务器:

server:
  port: 8081
  ssl:
    enabled: true
    key-store: classpath:MyServer.jks
    key-store-password: password
    trust-store: classpath:MyServer.jks
    trust-store-password: password
    client-auth: need

对于 Zuul Proxy 应用程序,我已经配置 CloseableHttpClient 密钥库和信任库,并配置了所需的证书:

@Bean
    public CloseableHttpClient zuulHttpClient() throws Throwable {
        final KeyStore ks = KeyStore.getInstance("JKS");
        ks.load(keyStore.getInputStream(), keyStorePassword.toCharArray());

        LOGGER.info("Loaded keyStore: " + keyStore.getURI().toString());
        try {
            keyStore.getInputStream().close();
        } catch (final IOException e) {
            LOGGER.warning("IOException during loading keyStore");
        }
        final KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        keyManagerFactory.init(ks, keyStorePassword.toCharArray());


        final KeyStore ts = KeyStore.getInstance("JKS");
        ts.load(trustStore.getInputStream(), trustStorePassword.toCharArray());
        LOGGER.info("Loaded trustStore: " + trustStore.getURI().toString());
        try {
            trustStore.getInputStream().close();
        } catch (final IOException e) {
            LOGGER.warning("IOException during loading trustStore");
        }
        final TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        trustManagerFactory.init(ts);

        final SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(ts, new TrustSelfSignedStrategy()).loadKeyMaterial(ks, keyStorePassword.toCharArray()).build();
        final HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
        httpClientBuilder.setSSLContext(sslContext);
        return httpClientBuilder.build();
    }

它在本地工作,但我在 PCF 上设置它时遇到问题。我能够推送客户端应用程序,但不能推送服务器应用程序。它只是冻结了一段时间,并且无法在 PCF 上启动,但是日志没问题,没有抛出异常。关闭服务器 enabled: false 的 SSL,让我推送应用程序,所以看起来问题出在这里。

所以我的问题是,是否有任何简单的方法可以开箱即用地在 PCF 上设置 2 路 ssl?我找到了一些关于这个的主题,说的是配置 Gorouter,目前正在阅读关于这个主题的文档,但正在考虑是否有更简单明了的解决方案。

目前,当您 运行 Cloud Foundry 上的应用程序时,它们 从不 侦听 HTTPS 请求。它们总是在分配的端口上侦听 HTTP 请求。 HTTPS 由 GoRouter 或贵公司的负载均衡器在上游处理。 HTTPS 信息通过 x-forwarded-* header 传播到您的应用程序。这意味着您将不需要将 server.ssl.enabled 与 Spring 启动应用程序一起使用,并且您无需担心提供任何证书。

如果您想处理 mTLS,那就有点棘手了。您可以让上游 LB 或 GoRouter 为您处理。它以类似于 x-forwarded-* 的方式验证客户端证书并确保它是可信的。如果它不受信任,则连接将失败。如果它是可信的,它将通过 HTTP header、X-Forwarded-Client-Cert 向您传递证书信息。此时,您知道证书是有效和可信的,您可以进一步使用证书信息来选择授权和访问。

这里有更多关于这一切的信息:https://docs.pivotal.io/pivotalcf/2-1/adminguide/securing-traffic.html#gorouter_mutual_auth

该平台还为每个应用程序实例管理和分配证书。您可以使用这些证书来识别您的客户。有关这些的更多信息:https://docs.pivotal.io/pivotalcf/2-1/devguide/deploy-apps/instance-identity.html

如果您的运营商已为您设置好所有这些,那么执行 mTLS 会更容易一些。如果您正在进行 app-to-app 通信,您实际上不需要对证书做任何事情,该平台会为您提供并验证它们。如果您有正在连接的平台外的客户端,则比较棘手,因为您必须向他们提供证书,并且您的运营商必须配置平台以信任他们。不过,它仍然可以完成,您的应用程序无需更改即可支持它。


换档。如果你真的想采用传统方法,你可以这样做。我知道我在上面暗示过那是不可能的。以上信息适用于 HTTP 路由,HTTP 路由是不可能的。但是,如果您为您的应用程序使用 TCP 路由,它就可以工作。使用 TCP 路由,您的应用程序只需获取 TCP 数据包,因此它可以对它们做任何想做的事情。这包括执行 HTTPS。如果这是您想要的,则由应用程序来处理 TLS。该平台只是将 TCP 数据包路由到您的应用程序,剩下的由应用程序完成。

这意味着您需要提供服务器证书、客户端证书并配置您的 app/server 以验证它们。它与您在本地或传统服务器上的设置非常相似。使用这种方法,该平台对您的帮助很小。

这里有一节描述了创建 TCP 路由。它非常简单并且与 HTTP 路由相同,但只是一个额外的标志来设置端口。

https://docs.cloudfoundry.org/devguide/deploy-apps/routes-domains.html#create-route

您还可以在此处详细了解 HTTP 和 TCP 路由之间的区别:https://docs.cloudfoundry.org/devguide/deploy-apps/routes-domains.html#http-vs-tcp-routes

希望对您有所帮助!