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

标签 spring-boot ssl cloud-foundry mutual-authentication

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

对于我在 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 配置了 keystore 和配置了所需证书的信任库:

@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 上启动,但是日志没问题,没有抛出异常。为服务器关闭 SSL enabled: false,让我推送应用程序,所以看起来这就是问题所在。

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

最佳答案

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

如果您想处理 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 的操作会更容易一些。如果您正在进行应用程序到应用程序的通信,您实际上不需要对证书做任何事情,该平台会为您提供并验证它们。如果您有正在连接的平台外的客户端,则比较棘手,因为您必须向他们提供证书,并且您的运营商必须配置平台以信任他们。不过,它仍然可以完成,而且您的应用无需更改即可支持它。


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

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

这里有一个部分描述了创建 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

希望对您有所帮助!

关于spring-boot - 在 Pivotal Cloud Foundry 上设置双向 SSL 身份验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50949443/

相关文章:

java - Spring安全身份验证问题: HTTP 401

cassandra - 在开源 Cloud Foundry 中实现 Cassandra 和 Aerospike 的 Service Broker API

ssl - 我是否需要 target-http-proxy 才能在 GKE 上使用 Google 管理的 SSL 证书设置 HTTPS 负载平衡器?

ruby-on-rails - treSTLe HTTP Origin header (https :.。)。与 request.base_url (http://) 不匹配

ssl - 通过我的代理的 HTTPS 隧道

java - Cloud Foundry Spring Boot 应用程序中的连接被拒绝错误

Go worker 应用程序未在 Cloud Foundry 中启动

java - Spring @ConfigurationProperties 解析器忽略外部化属性

java - 使用 Hibernate Envers 审核可嵌入实体

java - 注入(inject)的 Bean 在抽象类中为 null