使用 HTTPS 调用 REST 服务的 Oracle BPEL (Java 8U92) 会产生 SSL 握手异常
Posted
技术标签:
【中文标题】使用 HTTPS 调用 REST 服务的 Oracle BPEL (Java 8U92) 会产生 SSL 握手异常【英文标题】:Oracle BPEL (Java 8U92) invoking REST service using HTTPS gives SSL Handshake Exception 【发布时间】:2016-11-09 00:13:43 【问题描述】:我已经使用 oracle SOA 12c 设置了一个基本的 weblogic 域,用于开发可以调用 Apple APN 服务的组合。 Apple APN 需要使用 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 和 TLS 1.2 加密的 HTTP2 连接。
JKS 信任库已配置并加载了根证书、中间证书和服务器证书。
geotrustrootca, Jun 21, 2016, trustedCertEntry,
Certificate fingerprint (SHA1): DE:28:F4:A4:FF:E5:B9:2F:A3:C5:03:D1:A3:49:A7:F9:96:2A:82:12
serverc_ss_cert, Jun 21, 2016, trustedCertEntry,
Certificate fingerprint (SHA1): 73:C4:A9:4E:E8:1B:14:58:7B:64:47:02:73:01:15:3E:88:E8:E8:66
appledevpush, Jun 21, 2016, trustedCertEntry,
Certificate fingerprint (SHA1): CC:18:A5:75:04:74:3A:3B:72:D7:A5:07:F2:CD:E4:83:51:11:34:CB
appleintermediate, Jun 21, 2016, trustedCertEntry,
Certificate fingerprint (SHA1): 8E:83:21:CA:08:B0:8E:37:26:FE:1D:82:99:68:84:EE:B5:F0:D6:55
setDomainEnv.sh 已通过添加 java 属性 -Djavax.net.ssl.trustStore=/u01/data/keystores/truststore.jks
进行更改
在测试一个简单的 BPEL 组合时,如果失败并出现 SSLHandshakeException,则对 Apple 的 APN 服务进行 REST 调用:
[ACTIVE] ExecuteThread: '58' for queue: 'weblogic.kernel.Default (self-tuning)', SEND TLSv1.2 ALERT: fatal, description = certificate_unknown
[ACTIVE] ExecuteThread: '58' for queue: 'weblogic.kernel.Default (self-tuning)', WRITE: TLSv1.2 Alert, length = 2
[ACTIVE] ExecuteThread: '58' for queue: 'weblogic.kernel.Default (self-tuning)', called closeSocket()
[ACTIVE] ExecuteThread: '58' for queue: 'weblogic.kernel.Default (self-tuning)', handling exception: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
调试时SSL协商见;
%% No cached client session
*** ClientHello, TLSv1.2
....
*** ServerHello, TLSv1.2
RandomCookie: GMT: 1922117017 bytes = 236, 133, 59, 43, 182, 3, 165, 71, 241, 54, 240, 145, 222, 41, 200, 242, 63, 237, 253, 77, 188, 235, 187, 177, 245, 173, 53, 232
Session ID: 119, 250, 96, 4, 116, 33, 211, 17, 47, 213, 227, 158, 164, 107, 14, 73, 157, 194, 0, 104, 54, 237, 0, 58, 229, 225, 158, 2, 29, 159, 79, 171
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
...
%% Initialized: [Session-7, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384]
** TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
[ACTIVE] ExecuteThread: '58' for queue: 'weblogic.kernel.Default (self-tuning)', READ: TLSv1.2 Handshake, length = 2576
*** Certificate chain
chain [0] = [
[
Version: V3
Subject: C=US, ST=California, O=Apple Inc., OU=management:idms.group.533599, CN=api.development.push.apple.com
Signature Algorithm: SHA256withRSA, OID = 1.2.840.113549.1.1.11
...
chain [1] = [
[
Version: V3
Subject: C=US, O=Apple Inc., OU=Certification Authority, CN=Apple IST CA 2 - G1
Signature Algorithm: SHA256withRSA, OID = 1.2.840.113549.1.1.11
...
***
%% Invalidated: [Session-7, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384]
[ACTIVE] ExecuteThread: '58' for queue: 'weblogic.kernel.Default (self-tuning)', SEND TLSv1.2 ALERT: fatal, description = certificate_unknown
[ACTIVE] ExecuteThread: '58' for queue: 'weblogic.kernel.Default (self-tuning)', WRITE: TLSv1.2 Alert, length = 2
[ACTIVE] ExecuteThread: '58' for queue: 'weblogic.kernel.Default (self-tuning)', called closeSocket()
[ACTIVE] ExecuteThread: '58' for queue: 'weblogic.kernel.Default (self-tuning)', handling exception: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
我的结论是服务器 N=api.development.push.apple.com
的服务器证书被接受,但中间 CA CN=Apple IST CA 2 - G1
的证书被拒绝。
CN=Apple IST CA 2 - G1
的发行者是CN=GeoTrust Global CA, O=GeoTrust Inc., C=US
,序列号为023a74
。此证书也加载到信任库中;
别名:geotrustrootca 创建日期:2016年6月21日 条目类型:trustedCertEntry
Owner: CN=GeoTrust Global CA, O=GeoTrust Inc., C=US
Issuer: CN=GeoTrust Global CA, O=GeoTrust Inc., C=US
Serial number: 23456
Valid from: Tue May 21 06:00:00 CEST 2002 until: Sat May 21 06:00:00 CEST 2022
Certificate fingerprints:
MD5: F7:75:AB:29:FB:51:4E:B7:77:5E:FF:05:3C:99:8E:F5
SHA1: DE:28:F4:A4:FF:E5:B9:2F:A3:C5:03:D1:A3:49:A7:F9:96:2A:82:12
SHA256: FF:85:6A:2D:25:1D:CD:88:D3:66:56:F4:50:12:67:98:CF:AB:AA:DE:40:79:9C:72:2D:E4:D2:B5:DB:36:A7:3A
Signature algorithm name: SHA1withRSA
Version: 3
任何想法(如果我的结论是正确的)为什么中间证书被拒绝或如何进一步调试?使用浏览器打开 APN 的 URI 并检查证书时,我得到的结果与信任库中的相同。
== 更新 1 ==
尝试使用 curl 进行连接。 首先将证书从信任库导出到 /u01/data/keystores
$keytool -keystore truststore.jks -exportcert -alias geotrustrootca | openssl x509 -inform der -text > geotrustrootca.pem
$keytool -keystore truststore.jks -exportcert -alias appledevpush | openssl x509 -inform der -text > appledevpush.pem
$keytool -keystore truststore.jks -exportcert -alias appleintermediate | openssl x509 -inform der -text > appleintermediate.pem
然后尝试使用 curl 进行连接
$ curl --capath /u01/data/keystores --verbose https://api.development.push.apple.com/3/device/
* About to connect() to api.development.push.apple.com port 443 (#0)
* Trying 17.172.238.203... connected
* Connected to api.development.push.apple.com (17.172.238.203) port 443 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* failed to load '/u01/data/keystores/identitykeystore.jks' from CURLOPT_CAPATH
* failed to load '/u01/data/keystores/appledevpush.cer' from CURLOPT_CAPATH
* failed to load '/u01/data/keystores/geotrustrootca.cer' from CURLOPT_CAPATH
* failed to load '/u01/data/keystores/truststore.jks' from CURLOPT_CAPATH
* failed to load '/u01/data/keystores/yum-oracle-8v1ncO' from CURLOPT_CAPATH
* failed to load '/u01/data/keystores/vm0010.localdomain-rootCA.der' from CURLOPT_CAPATH
* failed to load '/u01/data/keystores/appleintermediate.cer' from CURLOPT_CAPATH
* CAfile: /etc/pki/tls/certs/ca-bundle.crt
CApath: /u01/data/keystores
* NSS: client certificate not found (nickname not specified)
* SSL connection using TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
* Server certificate:
* subject: C=US,ST=California,O=Apple Inc.,OU=management:idms.group.533599,CN=api.development.push.apple.com
* start date: Jun 19 01:49:43 2015 GMT
* expire date: Jul 18 01:49:43 2017 GMT
* common name: api.development.push.apple.com
* issuer: C=US,O=Apple Inc.,OU=Certification Authority,CN=Apple IST CA 2 - G1
> GET /3/device/ HTTP/1.1
> User-Agent: curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.21 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2
> Host: api.development.push.apple.com
> Accept: */*
>
* Connection #0 to host api.development.push.apple.com left intact
* Closing connection #0
@@�HTTP/2 client preface string missing or corrupt. Hex dump for received bytes: 474554202f332f6465766963652f20485454502f312e310d
所以证书是正确的。
== 更新 2 ==
再次重新创建了信任库。在netscape中打开urlhttps://api.development.push.apple.com/3/device/
获取pem文件,并将证书保存为pem格式。
在新的 truststore.jks 中导入证书
ls -1 *.der
中的文件;做 keytool -importcert -keystore truststore.jks -file $file -storepass welcome1 -noprompt -alias $file ;完成
没有喜悦...
== 更新 3 ==
现在在 server.out 中观察到重新启动托管服务器时,还会加载默认的自签名证书。
<Jul 11, 2016 10:15:50 PM CEST> <Warning> <oracle.soa.healthcheck> <BEA-000000> <On startup, health check id 881 failed for category 'Startup'. Ran 6 checks. Number of failures=1, errors=1, warnings=0.>
adding as trusted cert:
Subject: CN=CertGenCA, OU=FOR TESTING ONLY, O=MyOrganization, L=MyTown, ST=MyState, C=US
Issuer: CN=CertGenCA, OU=FOR TESTING ONLY, O=MyOrganization, L=MyTown, ST=MyState, C=US
Algorithm: RSA; Serial number: 0x40044886c441ef3b643a8066409afca0
Valid from Sat Dec 01 04:07:51 CET 2012 until Thu Dec 02 04:07:51 CET 2032
adding as trusted cert:
Subject: CN=CertGenCAB, OU=FOR TESTING ONLY, O=MyOrganization, L=MyTown, ST=MyState, C=US
Issuer: CN=CertGenCAB, OU=FOR TESTING ONLY, O=MyOrganization, L=MyTown, ST=MyState, C=US
Algorithm: RSA; Serial number: 0x234b5559d1fa0f3ff5c82bdfed032a87
Valid from Thu Oct 24 17:54:45 CEST 2002 until Tue Oct 25 17:54:45 CEST 2022
javax.net.ssl.trustStore 设置为自定义信任库。同样在 weblogic 中,身份和信任库位置已设置为自定义 JKS 存储。
即使在从 $WLS_HOME/lib 中删除 DemoTrust.jks 之后,证书也会被添加为受信任的证书。我目前不知道这些是从哪里来的。
== 更新 4 ==
$DOMAIN_HOME/security 包含 DemoIdentity.jks。删除此文件并重新启动托管服务器后,不再加载演示可信证书。
== 更新 5 ==
针对目标 URL SAS SSL/TLS 诊断工具验证了信任库。确保正确设置信任库。
正如 user2351802 所指出的,必须使用 OPSS 密钥库而不是 Java 属性 javax.net.ssl.trustStore 中定义的 JKS 密钥库。
在 SOA Suite 10g/11g 中,使用单向 SSL 从组合调用外部 Web 服务时,安全传输的标准方法是创建 JKS 信任库并在 javax.net.ssl.trustStore Java 属性中指定该信任库的位置。甚至在SOA Suite 12.2.1.1 Admin Guide 中仍然记录了使用JKS 信任库来建立来自SOA 组合的单向SSL 连接。 Oracle WebLogic Server 12.2.1.1.0 Admin Guide 提到了(新的)OPSS 密钥库,并参考了“Securing Applications with Oracle Platform Security Services”文档以使用和配置新的 KSS OPSS 密钥库。虽然它提到了为 LDAP 明确设置单向 SSL 的过程,但它似乎是 FMW 应用程序的新常用方法。
在 weblogic 中清理身份和信任库后,仅将服务器证书添加到身份库(因此 JKS 信任库中不再有受信任的证书)并将根证书添加到 OPSS 系统/信任它工作!
【问题讨论】:
文件$JAVA_HOME/lib/security/java.security
中的jdk.certpath.disabledAlgorithms
行包含什么?
它包含; jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize
你能得到任何其他东西来成功建立 SSL 连接,例如带有openssl s_client -connect ...
的 OpenSSL 吗?
可以连接我的浏览器和 curl,今天晚些时候用 openssl 试试
openssl s_client -host api.development.push.apple.com -port 443 CONNECTED(00000003) depth=2 C = US, O = GeoTrust Inc., CN = GeoTrust Global CA 验证返回:1 depth=1 CN = Apple IST CA 2 - G1, OU = 证书颁发机构, O = Apple Inc., C = US verify return:1 depth=0 CN = api.development.push.apple.com, OU = management:idms .group.533599, O = Apple Inc., ST = California, C = US ...验证返回码:0(ok)---
【参考方案1】:
好的。这听起来很奇怪,但它会起作用。我们有相同的 SOA 12c 设置,但我们使用标准 Java 信任密钥库来托管 SOA 服务器。
我可以看到您已修改 setDomainEnv.sh 以指定 /u01/data/keystores/truststore.jks 作为您的密钥库。
理论上,如果根证书在我的情况下的 cacerts 和你的情况下的 truststore.jks 中,它应该可以工作。我可以确认 SOAP 服务可以与密钥库一起正常工作。
由于证书错误,通过 REST 适配器调用 REST 服务以某种方式失败,与您的相同。
Here's what made it to work:
Login to EM
Weblogic Domain -> Security -> Keystore
Select System (stripe) -> trust -> Hit the manage button
Here import the root cert of geotrustrootca.
反弹 SOA 服务器。测试您的服务。它应该可以正常工作。
我不明白的是:系统(条带)-> 信任 = 这是 配置域时预配置为演示信任库。一世 已更改要使用的托管服务器的密钥库设置 证书。不知何故,这个 kss 信任存储似乎仍然存在 在某处引用。问题是在哪里?
分享一下,以防万一你想明白了。与此同时,该解决方案将助您一臂之力。
【讨论】:
以上是关于使用 HTTPS 调用 REST 服务的 Oracle BPEL (Java 8U92) 会产生 SSL 握手异常的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Retrofit @Query 调用 REST API