【发布时间】: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 上下文)。
有什么想法吗?
【问题讨论】: