如何为Websphere MQ客户端启用使用客户端证书的SSL?

4
我们是一个较大环境中的一个应用程序,也是一些数据接口的客户端,使用Websphere MQ 8.x。我们的应用程序是在WildFly 9上运行的Java EE应用程序,使用资源适配器(wmq.jmsra.rar),该适配器与EAR文件一起部署在同一AS中。我们在两个方向上与MQ服务器交互。因此,我们一方面有一些MDB(由于历史原因仍然采用EJB 2.x格式而没有注释)监听某些队列,并由包含激活配置属性destinationType、channel、queueManager、hostName、username、passwordejb-jar.xml部署描述符进行配置。另一方面,我们有一个发送者,通过JNDI查找队列连接工厂和队列,并创建连接。

现在,我们需要使用新建立的MQ服务器通过SSL和客户端证书进行通信。我们从服务器人员那里得到了这样的机器证书。所以我的问题是:

  • 如何使它与上述设置配合使用?
  • 是否可以纯粹通过配置实现,并对应用程序透明,还是必须特别使用SSL,呈现证书或类似的东西?
  • 是否会与已经由应用程序的其他部分使用的任何密钥库发生冲突?
  • 是否需要其他IBM MQ软件才能使其正常工作?(我们的客户端只是RAR,没有安装任何软件,也不应该在我们这边建立MQ服务器。)

更新:我选择设置VM的全局JSSE属性,因为它解决了我的问题。

必须设置以下参数:

-Djavax.net.ssl.trustStore=<location of trustStore>
-Djavax.net.ssl.keyStore=<location of keyStore>
-Djavax.net.ssl.keyStorePassword=<password>

此外,由于我使用的是非IBM虚拟机,因此需要设置以下参数:

-Dcom.ibm.mq.cfg.useIBMCipherMappings=false

然后,需要在 standalone-full.xml 中的 RAR 配置上设置密码套件属性,以及其他 WildFly 安装的连接参数:

<resource-adapter id="wmq.jms.rar">
...
  <connection-definitions>
    <connection definition ...>
      <config-property name="sslCipherSuite">xxx</config-property>
...
</resource-adapter">

最后,监听队列的MDBs也必须配置使用密码套件,因此在我的情况下,我需要通过为每个MDB添加以下内容来在ejb-jar.xml中进行配置:

<activation-config-property>
  <activation-config-property-name>sslCipherSuite</activation-config-property-name>
  <activation-config-property-value>xxx</activation-config-property-value>
<activation-config-property>

@JoshMc 感谢你的提示。服务器版本是8.0.0.7。目前我的客户端版本是9.0.0.1 - 这会有问题吗?JDK 是 OpenJDK 8。我希望 RAR 支持它并且底层层实际上执行 SSL,但你能指导我如何配置使用 SSL 和特定证书在密钥库中吗? - Alexander Rühl
也许这会有所帮助: "如何配置启用SSL的MQ与JBOSS连接?". 请注意,看起来他有一个有效的JBOSS配置,只是遇到了密码错误,因此如果类似于Wildfly 9的配置可能会有所帮助。 - JoshMc
@JoshMc 我之前遇到过这个问题,对我来说似乎除了将之前的用户和密码替换为正确的sslCipherSuite之外,RAR没有其他需要做的事情,你同意吗?关于证书和密钥库还需要做什么? - Alexander Rühl
@JoshMc 好的,再次感谢。希望这是关于这个问题的最后一个问题:我的WildFly已经在其他部分中使用密钥库,我无法控制,所以我猜我不能将其作为一般VM参数传递。是否有一种方法可以专门指定一个仅用于MQ或JMS子系统的密钥库?我找到的唯一一件事是资源适配器中的sslCertStores属性,但它指向某些LDAP。我觉得必须有一种方法告诉我的WildFly使用具有证书的密钥库来处理所有出站和入站JMS流量。 - Alexander Rühl
1个回答

3

在评论中,OP表示他们使用OpenJDK 8,并使用IBM MQ v9.0.0.1资源适配器,这两个已知问题在该版本中已经修复,但为了使其他尚未升级的人受益,将此信息放在这里:

  • APAR IV66840:非IBM JRE中的TLS密码套件直到8.0.0.2才得到支持。

  • APAR IT10837:如果在WildFly 9中使用非IBM JRE查找包含客户端证书的密钥库,则可能会遇到另一个问题,该问题已在8.0.0.5中得到解决。


资源适配器包含MQ功能以支持TLS,但实际加密使用底层JSSE。基于RFC 5246,它建议TLS客户端仅返回适合的证书,基于服务器发送的“可接受的certificate_authorities的可分辨名称[X501]列表,以DER编码格式表示。”这意味着,如果您密钥库中用于不同用途(例如现有非MQ证书和MQ证书)的证书由相同的CA链签名,并且您连接到的各个TLS服务器不接受来自密钥库中其他证书的CA的证书(例如现有非MQ证书和MQ证书),则JSSE将为每个返回适当的证书。例如,如果现有的非MQ证书由内部CA签名,而MQ证书由另一个公司的CA签名,则MQ公司极不可能信任您的内部CA证书,反之亦然。由于JSSE只会返回远程服务器信任的证书,因此它们不应互相影响。您只需要将MQ证书添加到现有密钥库中。RFC 5246相关部分的引用在本帖子底部。
@a_cornish_pasty对于你的问题"为JMS使用特定的密钥库"的回答也是一种选择,因为它允许你指定一个与Wildfly其余部分不同的密钥库,这个密钥库可以仅包含MQ证书,因此不会与现有的密钥库和证书发生冲突。

RFC 5246 Section 7.4.4 提到:

7.4.4. 证书请求

消息发送的时间:

非匿名服务器可以选择性地要求客户端提供证书,如果所选密码套件需要。 如果发送此消息,则会立即跟随 ServerKeyExchange 消息(如果已发送;否则,此消息将遵循服务器的 Certificate 消息)。

然后它继续说明:

certificate_authorities

可接受证书颁发机构的可分辨名称 [X501],以 DER 编码格式表示。 这些可分辨名称可能指定根 CA 或下级 CA 的所需可分辨名称;因此,此消息可用于描述已知的根以及所需的授权空间。 如果 certificate_authorities 列表为空,则客户端可以发送适当的 ClientCertificateType 证书,除非有其他安排。

RFC 5246第7.4.6节阐述如下:

7.4.6. 客户端证书

发送此消息的时间:

在收到ServerHelloDone消息后,客户端可以发送的第一条消息。仅当服务器请求证书时才发送此消息。 如果没有合适的证书可用,则客户端必须发送一个不包含任何证书的证书消息。也就是说,certificate_list结构的长度为零。如果客户端没有发送任何证书,服务器可以自行决定继续进行无客户端身份验证的握手,或者响应致命的handshake_failure警报。此外,如果证书链中的某些方面不可接受(例如,它未经已知的信任CA签名),则服务器可以自行决定继续握手(将客户端视为未经身份验证),或发送致命的警报。

然后它继续阐明:

如果证书请求消息中的证书颁发机构列表非空,则证书链中应该有一张证书是由列出的证书颁发机构之一签发的。

对于第一个解决方案,我采用了帖子编辑中显示的VM参数。在此,我向您提供的帮助表示感谢,再次感谢。 - Alexander Rühl
@AlexanderRühl 谢谢你,你是如何解决两个不同证书的问题的? - JoshMc
我们还没有检查副作用,但似乎由于另外两个密钥库是特别配置的,所以设置全局参数并不重要。但作为第二步,我们将检查自定义的SSLConnectionFactory解决方案,这似乎更有前途。 - Alexander Rühl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接