【问题标题】:Amazon SDK not using custom default SSL Socket FactoryAmazon SDK 未使用自定义默认 SSL 套接字工厂
【发布时间】:2018-06-03 10:49:58
【问题描述】:

我正在尝试使用 Amazon S3 开发工具包连接到内部 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 套接字工厂没有问题。

但是,Amazon SDK 确实存在问题。如果我用 S3 客户端实例替换对公共 ECS 资源的 Http 调用,则会失败并出现以下错误:

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 上下文)。

有什么想法吗?

【问题讨论】:

    标签: java scala ssl amazon-s3


    【解决方案1】:

    为了在运行时使用自定义 SSL,我们需要使用以下代码 sn-p 加载 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")
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-11
      • 1970-01-01
      • 2012-02-29
      • 2011-09-19
      • 1970-01-01
      相关资源
      最近更新 更多