Amazon SDK不使用自定义默认SSL套接字工厂



我正在尝试使用Amazon S3 SDK连接到内部ECS实例。与ECS的连接由内部CA签署的证书确保。我正在尝试通过编程方式加载一个带有CA的Java密钥库文件,但是使用Amazon SDK与ECS的连接不断与证书相关的错误失败。

com.amazonaws.SdkClientException: Unable to execute HTTP request: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

这是加载密钥库的小样本代码。:

val ks = KeyStore.getInstance(KeyStore.getDefaultType)
ks.load(this.getClass.getClassLoader.getResourceAsStream("cacerts.success"), "changeit".toCharArray)
val tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm)
tmf.init(ks)
val sslContext = SSLContext.getInstance("TLSv1.2")
sslContext.init(null, tmf.getTrustManagers, null)
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory)
val response = Http("https://ecsNamespace.ecsHostname.internal.com:9021/bucketName/path/to/file").asString

因此,Http从我创建并设置为默认的自定义SSL上下文对象使用SSL套接字工厂没有问题。

但是,亚马逊SDK确实有问题。如果我用S3客户端的实例将Http调用替换为公共ECS资源,则在此错误中失败:

com.amazonaws.SdkClientException: Unable to execute HTTP request: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

这是代码:

val client2 = AmazonS3ClientBuilder.standard()
  .withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials("keyId", "secret")))
  .withEndpointConfiguration(new EndpointConfiguration("https://ecsNamespace.ecsHostname.internal.com:9021", "us-east-1")) // S3 SDK requires a region, but ECS will ignore it.
  .withPathStyleAccessEnabled(true)
  .build()
client2.getObject("bucketName", "path/to/file")

如果我提前设置系统属性,则Amazon SDK与内部CA一起使用:

export JAVA_OPTS="-Djavax.net.ssl.trustStore=/path/to/my/cacerts.success -Djavax.net.ssl.trustStorePassword=changeit"

因此,似乎Amazon SDK(或任何基础HTTP库)仅在应用程序启动时获得默认的SSL上下文(而不是每次创建SSL连接时获得它,因此可以对运行时更改进行反应对于默认的SSL上下文)。

有什么想法?

为了在运行时使用自定义SSL,我们需要使用以下代码shippet

加载Apacheclient SSL
SSLContext sslcontext = SSLContexts.custom()
            .loadTrustMaterial(new File("/path/to/my/cacerts.success"),  "changeit".toCharArray(),
                    new TrustSelfSignedStrategy())
            .build();
// Allow TLSv1 protocol only add others if required
    SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
            sslcontext,
            new String[] { "TLSv1" },
            null,
            SSLConnectionSocketFactory.getDefaultHostnameVerifier());
// Adding Custom SSL Support
    config.getApacheHttpClientConfig().setSslSocketFactory(sslsf);
    config.setSignerOverride("AWSS3V4SignerType");

一旦加载了证书,我们就可以与以下代码联系:

val client2 = AmazonS3ClientBuilder.standard()
                                   .withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials("keyId", "secret")))
                                   .withEndpointConfiguration(new EndpointConfiguration("https://ecsNamespace.ecsHostname.internal.com:9021", "us-east-1"))                                                                                                                                                             
                                   // S3 SDK requires a region, but ECS will ignore it.
                                   .withPathStyleAccessEnabled(true)
                                   .build()

可以完成此正常操作之后,例如

client2.getObject("bucketName", "path/to/file")

最新更新