jms client authentication with client certificates
perzian Jun 6, 2007 6:40 PMIs it possible to authenticate a jms client with client certificates? Here is what I have tried so far. I had to hand type the code below into this post so there might be some typos
Set up a jaas security domain with an identity and trust keystore in a file I created called default/deploy/ssl-domain-service.xml. The identity and trust keystore are located in the default/conf directory
<server> <mbean code="org.jboss.security.plugins.JaasSecurityDomain" name="jboss.security:service=JaasSecurityDomain,domain=SSL"> <constructor> <arg type="java.lang.String" value="SSL"/> </constructor> <attribute name="KeyStoreURL">resource:identity.jks</attribute> <attribute name="KeyStorePass">password</attribute> <attribute name="KeyStoreType">JKS</attribute> <attribute name="TrustStoreURL">resource:trust.jks</attribute> <attribute name="TrustStorePass">password</attribute> <attribute name="TrustStoreType">JKS</attribute> </mbean> </server>
Set up an application policy in default/conf/login-config.xml to use the BaseCertLoginModule
<application=policy name="SSL"> <authentication> <login-module code="org.jboss.security.auth.spi.BaseCertLoginModule" flag="required"> <module-option name="password-stacking">useFirstPass</module-option> <module-option name="securityDomain">java:/jaas/SSL</module-option> <module-option name="verifier">org.jboss.security.auth.certs.AnyCertVerifier</module-option> </login-module> <login-module code="org.jboss.security.auth.spi.UserRolesLoginModule" flag="required"> <module-option name="password-stacking">useFirstPass</module-option> <module-option name="usersProperties">props/ssl-users.properties</module-option> <module-option name="rolesProperties">props/ssl-roles.properties</module-option> <module-option name="roleGroupSeperator">:</module-option> </login-module> </authentication> </application-policy>
Set up a ssl UIL service in a file I created called ssl-uil2-service.xml in default/deploy/jms/ssl-uil2-service.xml
<server> <mbean code="org.jboss.mq.il.uil2.UILServerILService" name="jboss.mq:service=InvocationLayer,type=SSLUIL2"> <depends optional-attribute-name="Invoker">jboss.mq:service=Invoker</depends> <attribute name="ConnectionFactoryJNDIRef">SSLUIL2ConnectionFactory</attribute> <attribute name="XAConnectionFactoryJNDIRef">SSLUIL2XAConnectionFactory</attribute> <attribute name="BindAddress">${jboss.bind.address}</attribute> <attribute name="ServerBindPort">8193</attribute> <attribute name="PingPeriod">60000</attribute> <attribute name="EnableTcpNoDelay">true</attribute> <attribute name="ReadTimeout">120000</attribute> <attribute name="ClientReadTimeout">120000</attribute> <attribute name="BufferSize">2048</attribute> <attribute name="ChunkSize">1000000</attribute> <attribute name="ClientSocketFactory">org.jboss.security.ssl.ClientSocketFactory</attribute> <attribute name="ServerSocketFactory">org.jboss.security.ssl.DomainServerSocketFactory</attribute> <attribute name="SecurityDomain">java:/jaas/SSL</attribute> </mbean> </server>
Set up the jbossmq security manager in default/deploy/jms/jbossmq-service.xml to only allow users with the jmsUser role to read/write/create destinations associated with the security manager.
<mbean code="org.jboss.mq.security.SecurityManager" name="jboss.mq.service=SecurityManager"> <attribute name="DefaultSecurityConfig"> <security> <role name="jmsUser" read="true" write="true" create="true"/> </security> </attribute> <attribute name="SecurityDomain">java:/jaas/SSL</attribute> <depends optional-attribute-name="NextIntercepter">jboss.mq:service=DestinationManager</depends> </mbean>
Setup a queue that uses the security manager in default/deploy/jms/jbossmq-destinations-service.xml
<mbean code="org.jboss.mq.server.jmx.Queue" name="jboss.mq.destination:service=Queue,name=updateQueue"> <depends optional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depepends> <depends optional-attribute-name="SecurityManager">jboss.mq:service=SecurityManager</depends> </mbean>
Here is the code I run on the client to create the InitialContext and do a jndi lookup for the updateQueue
Properties prop = new Properties(); X509Certificate cert = getCertificate(); prop.put(Context.PROVIDER_URL, "jnp://localhost:1099"); prop.put(Context.SECURITY_PRINCIPAL, cert.getSubjectDN().toString()); prop.put(Context.SECURITY_CREDENTIALS, cert); prop.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.security.jndi.JndiLoginInitialContextFactory"); InitialContext jndiContext = new InitialContext(prop); Object tmp = jndiContext.lookup("SSLUIL2ConnectionFactory"); QueueConnectionFactory qcf = (QueueConnectionFactory)tmp; conn = qcf.createQueueConnection(); que = (Queue)jndiContext.lookup("queue/updateQueue"); session = conn.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE); conn.start();
Here is the server output when I try to connect to the queue. I turned on TRACE logging and when the baseCertLoginModule is run it is unable to find the client certificate.
TRACE [BaseCertLoginModule] initialize, instance=@6960936 TRACE [BaseCertLoginModule] securityDomain=java:/jaas/SSL TRACE [BaseCertLoginModule] found domain: org.jboss.security.plugins.JaasSecurityDomain TRACE [BaseCertLoginModule] exit: initialize(Subject, CallbackHandler, Map, Map) TRACE [BaseCertLoginModule] enter: login() TRACE [BaseCertLoginModule] login TRACE [BaseCertLoginModule] enter: getAliasAndCert() TRACE [BaseCertLoginModule] exit: getAliasAndCert() TRACE [BaseCertLoginModule] Authenticating as unauthenticatedIdentity=null TRACE [BaseCertLoginModule] enter: validateCredentail(String, X509Certificate) TRACE [BaseCertLoginModule] Vaidating cert using: org.jboss.security.auth.certs.AnyCertVerifier@14b4735 TRACE [BaseCertLoginModule] The supplied certificate matched the certificate in the keystore. TRACE [BaseCertLoginModule] exit: validateCredentail(String, X509Certificate) TRACE [BaseCertLoginModule] User 'null' authenticated, loginOk=true DEBUG [BaseCertLoginModule] exit: login()
If i keep the same setup on the server but instead of doing a jndiLookup for a jms queue I do a look up for a session ejb it works fine.