6.4基于证书的安全

在本章前面部分,我们描述了ActiveMQ插件被用来验证客户端和授权对destinations的访问来进行安全化。这些插件适宜的完成它们的工作,但是他们使用明文用户名和密码存储客户端证书。虽然对于大多数的用户和用例都是sufficient,一些组织倾向于通过SSL certificate实现安全化。我们已经在第4章讨论过SSL传输和它如何使用证书的。在这一节我们将关于那个material进行扩展并向你展示SSL传输(和支持插件一起)如何被用来对代理进行安全化。我们将看到不仅是我们该如何通过客户端的证书进行客户端验证,还有我们该如何基于他们连接代理使用的证书非配不同的访问权限。
举例来说在这一节我们将使用stock portfolio的publisher和consumer。就是这次,他们将使用不同的证书,这些证书将标志他们并赋予他们从代理的destination那publish和consume的权限。
6.4.1准备证书
让我们建立合适的证书。这个步骤和在第4章我们用于基本SSL传输的类似。我们提供这本书所有示例的证书,所以你能使用他们运行示例。
我们建立两个证书:一个名叫producer并被包含在myproducer.ks :

$ keytool -genkey -alias producer -keyalg RSA -keystore myproducer.ks
Enter keystore password: test123
Re-enter new password: test123
What is your first and last name? [Unknown]: producer
What is the name of your organizational unit? [Unknown]:
Chapter 6
What is the name of your organization? [Unknown]: ActiveMQ in Action
What is the name of your City or Locality? [Unknown]: Belgrade
What is the name of your State or Province? [Unknown]:
What is the two-letter country filename for this unit? [Unknown]: RS
Is CN=producer, OU=Chapter 6, O=ActiveMQ in Action,
L=Belgrade, ST=Unknown, C=RS correct? [no]: yes
Enter key password for <producer> (RETURN if same as keystore password):

并且另一个名为consumer并被存储在myconsumer.ks keystore:

$ keytool -genkey -alias consumer -keyalg RSA -keystore myconsumer.ks
Enter keystore password: test123
What is your first and last name? [Unknown]: consumer
What is the name of your organizational unit? [Unknown]: Chapter 6
What is the name of your organization? [Unknown]: ActiveMQ in Action
What is the name of your City or Locality? [Unknown]: Belgrade
What is the name of your State or Province? [Unknown]:
What is the two-letter country code for this unit? [Unknown]: RS
Is CN=consumer, OU=Chapter 6, O=ActiveMQ in Action,
L=Belgrade, ST=Unknown, C=RS correct? [no]: yes
Enter key password for <client> (RETURN if same as keystore password):

注意我们建立证书的信息,因为稍后我们将使用它去grant或deny访问代理的权限。当然在产品环境你应考虑保证证书于安全的位置来为整个系统提供更好的安全性。
6.4.2建立truststore
接下来我们需要做的是讲这些证书导入到代理的truststore。但是首先我们需要将它们从keystores中导出。使用下面的命令来导出producer keystore:

$ keytool -export -alias producer -keystore myproducer.ks \
-file producer_cert
Enter keystore password: test123
Certificate stored in file <producer_cert>

同样下面是导出consumer的keystore:
$ keytool -export -alias consumer -keystore myconsumer.ks \
-file consumer_cert
Enter keystore password: test123
Certificate stored in file <consumer_cert>
现在JMS客户端证书已经被导出了,代理的truststore必须被建立。
建立一个代理的truststore并导入producer和consumer证书是一个相当straightforward的工作。首先导入producer证书到代理的truststore:

$ keytool -import -alias producer -keystore mybroker.ts \
-file producer_cert
Enter keystore password:
Re-enter new password:
Owner: CN=producer, OU=Chapter 6, O=ActiveMQ in Action,
L=Belgrade, ST=Unknown, C=RS Issuer: CN=producer, OU=Chapter 6,
O=ActiveMQ in Action, L=Belgrade, ST=Unknown, C=RS
Serial number: 4b6f0cf0
Valid from: Sun Feb 07 19:56:48 CET 2010 until: Sat May 08
20:56:48 CEST 2010
Certificate fingerprints: MD5:
9A:8C:02:17:0D:B1:11:CB:4E:14:63:37:03:F3:31:AD SHA1:
21:3B:A8:15:B8:67:39:28:9C:1B:23:35:E9:9F:30:2C:4C:8D:16:85 Signature
algorithm name: SHA1withRSA Version: 3
Trust this certificate? [no]: yes
Certificate was added to keystore

接下来导入consumer证书到代理truststore:

$ keytool -import -alias consumer -keystore mybroker.ts \
-file consumer_cert
Enter keystore password:
Owner: CN=consumer, OU=Chapter 6, O=ActiveMQ in Action,
L=Belgrade, ST=Unknown, C=RS Issuer: CN=consumer, OU=Chapter 6,
O=ActiveMQ in Action, L=Belgrade, ST=Unknown, C=RS
Serial number: 4b6f0ed4
Valid from: Sun Feb 07 20:04:52 CET 2010 until: Sat May 08
21:04:52 CEST 2010 Certificate fingerprints: MD5:
6D:C9:AF:3C:AB:1D:E3:8A:C1:5D:70:71:DE:17:CE:95 SHA1:
73:F6:7B:E9:42:5C:90:EB:6F:4F:8C:CB:9E:DB:59:66:B0:EF:02:2E Signature
algorithm name: SHA1withRSA Version: 3
Trust this certificate? [no]:yes
Certificate was added to keystore

当代理的truststore已经就绪,我们需要将它置于我们能从配置文件中引用它的地方。这经常是${ACTIVEMQ_HOME}/conf/ 文件夹,这个文件夹下还有所有其他的配置资源。我们将通过示例提供truststore,所以你所必须做的仅是复制它到正确的位置:

$ cp src/main/resources/org/apache/activemq/book/ch6/mybroker.ts \
${ACTIVEMQ_HOME}/conf/

现在让我们focus on配置文件和我们该如何只用truststore来配置ActiveMQ安全性。
6.4.3配置代理
在下面类表中显示的XML配置文件使用提供的truststore来instruct SSL传输(通过它客户端被允许连接代理),然后使用jaasCertificateAuthenticationPlugin(以粗体显示)来授权他们对代理资源的访问。
Listing 6.7 Configuring certificate-based security

...
<broker xmlns="http://activemq.apache.org/schema/core" brokerName="localhost" dataDirectory="${activemq.base}/data">
<plugins>
<jaasCertificateAuthenticationPlugin configuration="activemq-certificate" />
<authorizationPlugin>
<map>
<authorizationMap>
<authorizationEntries>
<authorizationEntry topic=">" read="admins" write="admins" admin="admins" />
<authorizationEntry topic="STOCKS.>" read="consumers" write="publishers" admin="publishers" />
<authorizationEntry topic="STOCKS.ORCL" read="guests" />
<authorizationEntry topic="ActiveMQ.Advisory.>" read="admins,publishers,consumers,guests" write="admins,publishers,consumers,guests" admin="admins,publishers,consumers,guests" />
</authorizationEntries>
</authorizationMap>
</map>
</authorizationPlugin>
</plugins>
<sslContext>
<sslContext keyStore="file:${activemq.base}/conf/mybroker.ks" keyStorePassword="test123" trustStore="file:${activemq.base}/conf/mybroker.ts" trustStorePassword="test123"/>
</sslContext>
<transportConnectors>
<transportConnector name="openwire" uri="tcp://localhost:61616"/>
<transportConnector name="ssl" uri="ssl://localhost:61617?needClientAuth=true" />
</transportConnectors>
</broker>
...

配置文件中的一些东西值得注意,已用粗体显示。首先,我们添加了trustStore和trustStorePassword属性到<sslContext>配置,这允许我们使用我们的先前定义的代理的truststore。然后,我们在SSL传输URI中设置needClientAuth属性,它将instruct代理去check连接的客户端的证书并允许那些能在truststore中找到的进行访问。
6.4.4授权解释[/b。
现在我们已经cover authentication with certificates,该来关心一下authorization了,这就是为什么我们使用jaasCertificateAuthenticationPlugin。这个插件和我们在这章早先使用的JAAS插件类似。我们现在配置它来看看在login.config中的activemq-certificate配置,它看起来应该像这样:

activemq-certificate {
  org.apache.activemq.jaas.TextFileCertificateLoginModule
  required debug=true
  org.apache.activemq.jaas.textfiledn.user="users.properties"
  org.apache.activemq.jaas.textfiledn.group="groups.properties";
};

login.config文件现在不同了,它使用TextFileCertificateLoginModule而不是PropertiesLoginModule了,被配置使用合适的属性。
现在该来看看user.properties文件长什么样了:

admin=password
publisher=password
consumer=password
guest=password
[b]
sslconsumer=CN=consumer, OU=Chapter 6, O=ActiveMQ in Action, L=Belgrade,
ST=Unknown, C=RS
sslpublisher=CN=producer, OU=Chapter 6,
O=ActiveMQ in Action, L=Belgrade, ST=Unknown, C=RS


正如你所见的,我们添加了两个证书(sslconsumer 和 sslpublisher 用户)。你可能注意到了user.properties使你映射你的证书到某个特定名字上的地方,并且我们使用合适的证书信息来映射它到desired用户名。现在我们有一个用户名,我们能使用groups.properties文件将它放到特定的组中:

admins=admin
publishers=admin,publisher,sslpublisher
consumers=admin,publisher,consumer,sslconsumer
guests=guest

一旦我们在他们的组中有我们的用户,authorizationPlugin开始生效并且授权对代理destinations的访问。
6.4.5测试
现在让我们使用先前的配置和login.config文件启动代理:

${ACTIVEMQ_HOME}/bin/activemq console \
-Djava.security.auth.login.config=\
src/main/resources/org/apache/activemq/book/ch6/login.config \
xbean:src/main/resources/org/apache/activemq/book/ch6/activemq-ssl.xml
...
Loading message broker from:
xbean:src/main/resources/org/apache/activemq/book/ch6/activemq-ssl.xml
...
00:15:26,144 | INFO | PListStore:
/Users/bsnyder/amq/apache-activemq-5.4.1/data/localhost/tmp_storage started
00:15:26,312 | INFO | Using Persistence Adapter: KahaDBPersistenceAdapter
[/Users/bsnyder/amq/apache-activemq-5.4.1/data/localhost/KahaDB]
00:15:26,387 | INFO | JMX consoles can connect to service:
jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi
00:15:26,882 | INFO | KahaDB is version 2
00:15:26,905 | INFO | ActiveMQ 5.4.1 JMS Message Broker (localhost) is
starting
00:15:26,906 | INFO | For help or more information please see:
http://activemq.apache.org/
00:15:27,044 | INFO | Scheduler using directory:
/Users/bsnyder/amq/apache-activemq-5.4.1/data/localhost/scheduler
00:15:27,086 | INFO | JobSchedulerStore:
/Users/bsnyder/amq/apache-activemq-5.4.1/data/localhost/scheduler started
00:15:27,113 | INFO | Listening for connections at: tcp://localhost:61616
00:15:27,114 | INFO | Connector openwire Started
00:15:27,810 | INFO | Listening for connections at:
ssl://localhost:61617?needClientAuth=true
00:15:27,811 | INFO | Connector ssl Started
00:15:27,820 | INFO | ActiveMQ JMS Message Broker
(localhost, ID:mongoose.local-51704-1289978126925-0:0) started
...

代理准备就绪,所以让我们看看基于使用的证书客户端如何表现。例如,如果我们尝试通过使用第四章中的原始证书访问代理,我们预计访问将被拒绝,因为证书不在代理的truststore中。

$ mvn -Djavax.net.ssl.keyStore=\
src/main/resources/org/apache/activemq/book/ch4/myclient.ks \
-Djavax.net.ssl.keyStorePassword=test123 \
-Djavax.net.ssl.trustStore=${ACTIVEMQ_HOME}/conf/myclient.ts \
-Djavax.net.ssl.trustStorePassword=test123 exec:java
-Dexec.mainClass=org.apache.activemq.book.ch4.Publisher \
-Dexec.args="ssl://localhost:61617 CSCO ORCL"
...
No user for client certificate: CN=Dejan Bosanac,
OU=Chapter 4, O=ActiveMQ in Action, L=Belgrade, ST=Unknown,
C=RS
...

注意我们正从原始的SSL示例中使用客户端truststore,因为关于代理端的证书没有什么改变。
现在让我们使用合适的证书启动它并看它是如何工作的:

$ mvn -Djavax.net.ssl.keyStore=\
src/main/resources/org/apache/activemq/book/ch6/myproducer.ks \
-Djavax.net.ssl.keyStorePassword=test123 \
-Djavax.net.ssl.trustStore=${ACTIVEMQ_HOME}/conf/myclient.ts \
-Djavax.net.ssl.trustStorePassword=test123 exec:java \
-Dexec.mainClass=org.apache.activemq.book.ch4.Publisher \
-Dexec.args="ssl://localhost:61617 CSCO ORCL"
...
Sending: {price=22.67337141688392, stock=ORCL, offer=22.696044788300803,
up=true} on destination: topic://STOCKS.ORCL
Sending: {price=22.783456638853973, stock=ORCL, offer=22.806240095492825,
up=true} on destination: topic://STOCKS.ORCL
Sending: {price=35.92652907541019, stock=CSCO, offer=35.96245560448559,
up=false} on destination: topic://STOCKS.CSCO
Sending: {price=35.81608910812595, stock=CSCO, offer=35.851905197234075,
up=false} on destination: topic://STOCKS.CSCO
Sending: {price=35.49430393012775, stock=CSCO, offer=35.52979823405787,
up=false} on destination: topic://STOCKS.CSCO
Sending: {price=22.613210876407855, stock=ORCL, offer=22.63582408728426,
up=false} on destination: topic://STOCKS.ORCL
Sending: {price=22.584893337535, stock=ORCL, offer=22.607478230872534,
up=false} on destination: topic://STOCKS.ORCL
Sending: {price=35.81521985692496, stock=CSCO, offer=35.85103507678188,
up=true} on destination: topic://STOCKS.CSCO
Sending: {price=35.8020033885887, stock=CSCO, offer=35.837805391977284,
up=false} on destination: topic://STOCKS.CSCO
Sending: {price=22.570064862430183, stock=ORCL, offer=22.59263492729261,
up=false} on destination: topic://STOCKS.ORCL
Published '10' of '10' price messages
...

如预期的,这个情况下publisher成功地发送了stock portfolio更新到代理。现在让我们看看如何使用一个合适的证书启动一个consumer:

$ mvn -Djavax.net.ssl.keyStore=\
src/main/resources/org/apache/activemq/book/ch6/myconsumer.ks \
-Djavax.net.ssl.keyStorePassword=test123 \
-Djavax.net.ssl.trustStor${ACTIVEMQ_HOME}/conf/myclient.ts \
-Djavax.net.ssl.trustStorePassword=test123 exec:java \
-Dexec.mainClass=org.apache.activemq.book.ch4.Consumer \
-Dexec.args="ssl://localhost:61617 CSCO ORCL"
...
ORCL 82.20 82.28 up
CSCO 88.52 88.61 down
CSCO 89.10 89.19 up
ORCL 81.90 81.98 down
ORCL 81.16 81.24 down
CSCO 89.84 89.93 up
ORCL 81.19 81.27 up
ORCL 81.38 81.46 up
CSCO 90.14 90.23 up
ORCL 81.03 81.12 down
ORCL 80.71 80.79 down
ORCL 80.01 80.09 down
ORCL 79.51 79.59 down
CSCO 90.52 90.61 up
ORCL 79.52 79.60 up
ORCL 78.77 78.85 down
...

最终,我们能测试我们的authorization设置工作正常。正如你能从代理的配置中看到的,consumer不应被允许来发送消息到我们 stockrelated 主题。所以如果你尝试这么做,操作应该会失败:

$ mvn -Djavax.net.ssl.keyStore=\
src/main/resources/org/apache/activemq/book/ch6/myconsumer.ks \
-Djavax.net.ssl.keyStorePassword=test123 \
-Djavax.net.ssl.trustStore=${ACTIVEMQ_HOME}/conf/myclient.ts \
-Djavax.net.ssl.trustStorePassword=test123 exec:java \
-Dexec.mainClass=org.apache.activemq.book.ch4.Publisher \
-Dexec.args="ssl://localhost:61617 CSCO ORCL"
...
role="bold">User CN=consumer, OU=Chapter 6, O=ActiveMQ in Action,
L=Belgrade, ST=Unknown, C=RS is not authorized to write to:
topic://STOCKS.CSCO
...

在这一节中,我们学习了如何leverage我们所知道的关于SSL传输(和配置证书)和一点配置基于证书的安全的ActiveMQ代理。这将ActiveMQ安全性带到了完全新的等级并使它完美地满足了organization的tight安全需求。

猜你喜欢

转载自flxchy4.iteye.com/blog/1741370
6.4