【问题标题】:PCF Container TrustManager adds certificates, but TrustManagerFactory loads certificates twicePCF Container TrustManager 添加证书,但 TrustManagerFactory 加载证书两次
【发布时间】:2022-01-13 16:49:36
【问题描述】:

我使用 apache-httpclient 4.x 在 PCF 上运行 Spring Boot 应用程序。客户端创建一个 ssl 上下文:

        final SSLContext sslcontext = SSLContext.getInstance(algorithm);
        sslcontext.init(keymanagers, trustmanagers, params.getSecureRandom());

我得到的trustmanagers如下:

        final TrustManagerFactory tmfactory =
              TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmfactory.init((KeyStore) null);

我记录它找到的证书数量并记录找到的 CN。但是我发现它列出了每个证书两次!

如果我提供带有 1 个证书的密钥库:

 tmfactory.init((KeyStore) truststore);

它将记录该证书+所有环境证书。如下:

   private static void logAcceptedIssuers(TrustManager[] trustmanagers) {
        log.info("Adding the following trusted certificates to the SSL context: ");
        Arrays.stream(trustmanagers)
                .filter(X509TrustManagerWrapper.class::isInstance)
                .map(X509TrustManagerWrapper.class::cast)
                .map(X509TrustManagerWrapper::getAcceptedIssuers)
                .forEach(SSLContextFactory::logAcceptedIssuers);
    }

    private static void logAcceptedIssuers(final X509Certificate[] certificates) {
        final int certificatesCount = certificates.length;
        final String prefix = "Trusted certificates (total=" + certificatesCount + "): \n";
        final String certDNs = Arrays.stream(certificates)
                .map(X509Certificate::getSubjectDN)
                .map(Principal::getName)
                .map(SSLContextFactory::extractCommonName)
                .collect(Collectors.joining(" |#| ", prefix, "\n"));

        log.info(certDNs);
    }

    @VisibleForTesting
    static String extractCommonName(String principalName) {
        ... Some code for extracting commonname from principal name...
    return cn;
    }

TrustManagerFactory 在哪里找到 pcf 可信证书?

如何检查这些 pcf 证书是否可用并已加载,或者我在哪里可以获得仅 pcf 证书的 TrustManager。我担心如果我加载两次它可能会导致问题,但我没有迹象表明它会导致问题(但现在我的 SSLContext 中有 288 个而不是 144 个证书,这会影响性能吗?它会导致问题吗?))。

问候,

瑞克

【问题讨论】:

    标签: spring-boot cloud-foundry apache-httpclient-4.x


    【解决方案1】:

    Java buildpack 添加了一个名为 Container Security Provider 的组件。这就是添加自动加载 Platform/Bosh 可信 CA 证书以及容器实例 ID 证书和密钥的功能。

    为确保平台/Bosh 可信 CA 证书是可信的,容器安全提供程序添加了a TrustManagerFactory。这会查看文件 /etc/ssl/certs/ca-certificates.crt 并信任该文件中的所有内容。

    这是对 JVM 的默认行为的补充。

    我记录它找到的证书数量并记录找到的 CN。但是我发现它列出了每个证书两次!

    你没有分享代码来展示你是如何做到这一点的,所以我只能推测。我怀疑您看到的是重复项,因为容器安全提供程序不会替换 JVM 中信任 CA 证书的默认行为,它添加了一个额外的 TrustManager。

    加上/etc/ssl/certs/ca-certificates.crt 中的内容与 JVM 的默认信任存储中的内容之间可能有很多重叠的事实。我想我可以看到有重复。

    如果我提供带有 1 个证书的密钥库: 它将记录该证书 + 所有环境证书。

    这进一步是我的怀疑,因为当您覆盖默认的 JVM 信任库时,听起来重复项消失了。这意味着您只剩下自定义信任库以及 CSP 添加的内容。

    TrustManagerFactory 在哪里找到 pcf 可信证书。

    https://github.com/cloudfoundry/java-buildpack-security-provider/blob/main/src/main/java/org/cloudfoundry/security/CloudFoundryContainerTrustManagerFactory.java#L41

    如何检查这些 pcf 证书是否可用并已加载,或者我在哪里可以获得仅 pcf 证书的 TrustManager。我希望这样可以防止两次加载证书。

    这里有更大的问题吗?我明白您所说的看到两次列出的证书,但这实际上会导致您的应用程序出现问题吗?如果是这样,请更新您的问题并解释发生了什么?这可能有助于提供更多背景信息。

    除此之外:

    1. 您可以禁用 CSP。设置和环境变量JBP_CONFIG_CONTAINER_SECURITY_PROVIDER='{trust_manager_enabled: false}'

      https://github.com/cloudfoundry/java-buildpack/blob/main/docs/framework-container_security_provider.md#security-provider

      请理解,禁用此功能后,您的应用程序将不会自动信任平台/Bosh 部署的 CA 证书。这可能会导致失败。例如,如果您的应用程序绑定到使用由 CA 签名的证书的 CF 市场服务,该 CA 通过平台/Bosh 受信任的 CA 证书分发。

    2. 您可以执行相反的操作并将默认 Java 信任库设置为指向一个空的密钥库。您可能需要在您的应用程序下创建一个空密钥库,然后设置 -Djavax.net.ssl.keyStore=/home/vcap/app/empty.jks/home/vcap/app 是您的应用程序的根,将其余部分更改为指向您存储空密钥库文件的位置)。

      https://stackoverflow.com/a/2138670/1585136

    如果我的怀疑属实,其中任何一个都会导致重复项消失。

    【讨论】:

    • 嗨丹尼尔,非常感谢您的详细解释。这解释了我认为我看到的行为。我已经在考虑使用空密钥库的工作了。我确实不想忽略 pcf 证书。我只是担心如果它们被加载两次会导致问题。目前我没有任何迹象表明它会导致问题,我只是认为它不是很“干净”(它会影响性能吗?现在我的商店中有 288 个证书而不是 144 个证书)。我将使用日志记录代码更新我的问题。
    • 我不确定性能。我的怀疑是否定的,或者至少不明显。它委托给不同的信任管理器,因此在证书受信任的情况下,它只会检查第一个信任管理器。我想也许如果您的证书失败,则必须询问所有信托经理。您的代码将发送给所有信任经理并说给我您所有的证书,这可能是最坏的情况,但这不是常见/实际情况,恕我直言。
    • 我启用了 javax 网络调试。我在通话中看到它会检查所有证书,每次通话都会再次检查,直到找到有效的证书。它正在阅读途中的​​所有证书。所以我认为它会影响性能,但不会太大。
    • 好的,有趣。我确实相信它会将证书缓存在内存中,所以第一次看会从磁盘读取,然后它已经在内存中。我想如果性能没有达到标准,或者如果你有大量的容器证书,你可以采取上述步骤之一来减少一点。
    • 是的,我认为你是对的。另外,如果我没记错的话,SSL 会根据“sessionId”跟踪以前使用的密钥等。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-01-17
    • 2012-08-30
    • 2013-09-18
    • 1970-01-01
    • 2019-07-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多