We have used Camel for routing between different destination using Spring with EMS messaging:
EMS Queues/TOpics hosted on tcp/http protocol working fine, whereease SSL causes following exception:
Error: Error occured while reading identity data: failed to decrypt safe contents entry: javax.crypto.BadPaddingException: Given final block not properly padded: url that returned this exceptio= ssl://random.host.com:41943
For normal spring tibco EMS SSL connection we need to set following by overriding ListenerContainer:
TibjmsSSL.setPassword(passwordCharArray);
How can we do with camel configuration:
<bean id="jmsConfig" class="org.apache.camel.component.jms.JmsConfiguration">
<property name="connectionFactory" ref="userCredentialsConnectionFactory" />
<property name="transacted" value="false" />
<property name="concurrentConsumers" value="1" />
</property>
</bean>
This is my camel jms config
I tried overriding following with my own custom implementation by setting below property, it doesnt seem to override required functionality:
org.apache.camel.component.jms.JmsConfiguration.messageListenerContainerFactory
[Fixed]
Overrided doCreateConnection(String,String) method of import org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter
and set required password in TibjmsSSL.setPassword(passwordCharArray)
Related
I am updating the client of an existing SOAP webservice since the service provider has made some changes to thier security headers in the request.
The requirement is to digitally sign the Timestamp which should be present in the request header and the body should not be digitally signed. I am using XML config to create my SOAP request header and digitally sign the Timestamp.
I am basically using org.springframework.ws.soap.security.wss4j.Wss4jSecurityInterceptor as an interceptor. The problem is that Timestamp gets created in the request header however the SignatureValue and DigestValue tags are empty
I have referred https://docs.spring.io/spring-ws/site/reference/html/security.html#security-wss4j-digital-signatures
Versions:
Spring-ws-core --> 2.0.0.RELEASE
spring-ws-security --> 2.0.0.RELEASE
<bean id="wsClientSecurityInterceptor" class="org.springframework.ws.soap.security.wss4j.Wss4jSecurityInterceptor">
<property name="securementActions" value="Timestamp Signature"/>
<property name="securementSignatureKeyIdentifier" value="DirectReference" />
<property name="securementUsername" value="username" />
<property name="securementPassword" value="keystorepassword" />
<property name="securementSignatureCrypto" ref="clientCrypto"/>
<property name="securementSignatureUser" value="username" />
<property name="securementSignatureParts" value="{}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd}Timestamp"/>
</bean>
<bean id="clientCrypto" class="org.springframework.ws.soap.security.wss4j.support.CryptoFactoryBean">
<property name="keyStorePassword" value="keystorepassword" />
<property name="keyStoreLocation" value="file:${key.store.location}"/>
<property name="keyStoreType" value="jks" />
<property name="keyStoreProvider" value="IBMJCE" />
</bean>
Though the timestamp gets added to the wsse:Security element in the header, the DigestValue and SignatureValue elements belonging to the xmlns:ds="http://www.w3.org/2000/09/xmldsig#" namespace are always empty
This does not happen if I only sign the Body
I also tried using another Interceptor XwsSecurityInterceptor but that does not work without the Wss4jSecurityInterceptor and gives me the same result when used with Wss4jSecurityInterceptor
<bean id="xwsSecurityInterceptor" class="org.springframework.ws.soap.security.xwss.XwsSecurityInterceptor">
<property name="policyConfiguration" value="classpath:securityPolicy.xml"/>
<property name="callbackHandlers">
<list>
<ref bean="keyStoreHandler"/>
</list>
</property>
</bean>
<bean id="keyStoreHandler" class="org.springframework.ws.soap.security.xwss.callback.KeyStoreCallbackHandler">
<property name="keyStore" ref="keyStore"/>
<property name="privateKeyPassword" value="keystorepassword"/>
</bean>
<bean id="keyStore" class="org.springframework.ws.soap.security.support.KeyStoreFactoryBean">
<property name="location" value="file:${key.store.location}"/>
<property name="password" value="keystorepassword"/>
</bean>
After referring a number of IBM support posts, I have finally come to the solution and have received a QA signoff too on the implementation. I had to replace all my spring mvc config for creating SSL context with configurations on the WAS server itself.You can configure all this using either scripts or using the WAS console manually.
Steps:
Add an entry to ur applications web.xml.Please refer this post https://www.ibm.com/support/knowledgecenter/en/SSAW57_8.5.5/com.ibm.websphere.nd.multiplatform.doc/ae/twbs_jaxwsclientdd.html
The link below will give you a step by step guide as to how to configure the request payload to have a signed timestamp on WAS server.
http://pglezen.github.io/was-config/html/signts.html#sec.signts.keystores.consumer
It basically focusses on :
Policy Set Creation:This will Specify the element or elements to be signed or encrypted in this message part.In our case its the timestamp in the header
Client Policy Set Bindings. If you are the provider you have to refer the provider Policy set bindings section.This involves creation of truststore and keystore required to configure your SSL context. Also has configurations for any proxy settings that you might require.
Finally take a JNDI reference of the service whereever you need to call a particular operation in the service.Refer https://www.ibm.com/support/knowledgecenter/SSAW57_9.0.5/com.ibm.websphere.nd.multiplatform.doc/ae/twbs_jaxwsclientdd.html
Once this done, Simply navigate to Services--> Service Clients and you should have your service refs visible there. You should now attach the Policy set and the bindings created above to the Service client references created in WAS due to point 1 above.You might have to write a script to attach the polict set and binding since after deployment you dont want to do this step manually
Please note: this solution came into picture sicne the version of WAS 8.5.5.16,spring -3.0.5.RELEASE and spring-ws-2.0.0.RELEASE did not support signing of timestamp in the request payload of the SOAP service request. Hope this helps someone !!
We are upgrading our project from Spring 2.5.6 to 3.2.3 and Hibernate/JPA to 4.2.3.
In spring-ds.xml for transaction management we replaced original below config
<bean id="transactionManager"
class="org.springframework.transaction.jta.WebSphereUowTransactionManager">
<!-- This property is specifically required for JMS -->
<property name="transactionManager" ref="baseTransactionManager" />
</bean>
<bean id="baseTransactionManager"
class="org.springframework.transaction.jta.WebSphereTransactionManagerFactoryBean" />
<tx:annotation-driven transaction-manager="transactionManager" />
to below as WebSphereTransactionManagerFactoryBean class is superseded in latest WAS :
<bean id="transactionManager"
class="org.springframework.transaction.jta.WebSphereUowTransactionManager" />
and JMS msg listener config looks like below :
<bean id="xxtMsgListenerContainer"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="jmsxxConnectionFactory" />
<property name="destination" ref="jmsxxQueue" />
<property name="messageListener" ref="xxMessageListener" />
<property name="transactionManager" ref="transactionManager" />
<property name="taskExecutor" ref="taskExecutor" />
</bean>
With above config we are getting below error in WAS logs :
Setup of JMS message listener invoker failed for destination
queue://xxQueue?busName=zzBus' - trying to recover. Cause: No JTA UserTransactionavailable - programmatic PlatformTransactionManager.getTransaction usage not supported
Is there any other config/property required to upgrade to spring 3.2.3 ? or to config WebSphereUowTransactionManager do we need to set any property ?
In case you are using Hibernate in your application, the actual Hibernate version used can be the root cause of the problem.
We spent half a day debugging it (on a WebSphere box), and then found that indeed it was the hibernate version upgrade (from 4.2.7.Final to 4.2.12.Final) which caused issue, not the JMS configuration.
UPDATE: It seems that Hibernate includes transaction-api jboss-transaction-api_1.1_spec which was not compatible with the one present on Websphere. Simply excluding this from hibernate resolved the issue.
on the DefaultMessageListenerContainer, try setting the sessionTransacted property to true. this should enable transaction support with WebSphere
The error happens because you have used JTA transaction manager, while your connection factory is not XA capable. Essentially injected implementation of ConnectionFactory does not implement JTA interfaces. Thus transaction manager isn't able of enrolling a message consumption into a new instance of UserTransaction.
In other to fix this issues the one needs to use XA capable ConnectionFactory, or other non-jta transaction manager like Spring's JmsTransactionManager.
I have a web service client implemented in Spring-ws, using a Wss4jSecurityInterceptor for ws-security.
Calling the endpoint works, data is encrypted, signed and sent, but when the reply is received it is not decrypted. Instead JAXB's unmarshaller is called, resulting in an error like :
Error : org.springframework.oxm.jaxb.JaxbUnmarshallingFailureException:
JAXB unmarshalling exception: unexpected element
(uri:"http://www.w3.org/2001/04/xmlenc#", local:"EncryptedData").
Expected elements are...
Expected elements then goes on to list every data type in the xdd.
This is what my Wss4jSecurityIntercepter is configured with :
<!-- username / password for signing -->
<property name="enableSignatureConfirmation" value="false" />
<property name="securementUsername" value="${securementUsername}" />
<property name="securementSignatureKeyIdentifier" value="DirectReference" />
<property name="securementPassword" value="${keystore.password}" />
<property name="securementSignatureCrypto" ref="crypto" />
<!-- username (certificate) and keystore for encryption -->
<property name="securementEncryptionUser" value="${securementEncryptionUsername}" />
<property name="securementEncryptionKeyIdentifier" value="SKIKeyIdentifier" />
<property name="securementEncryptionCrypto" ref="crypto" />
<!-- validate incoming message signature and decrypt -->
<property name="validationActions" value="Signature Encrypt Timestamp" />
<property name="validationDecryptionCrypto" ref="crypto" />
<property name="validationSignatureCrypto" ref="crypto" />
<property name="validationCallbackHandler">
<bean
class="org.springframework.ws.soap.security.wss4j.callback.KeyStoreCallbackHandler">
<property name="privateKeyPassword" value="${keystore.password}" />
</bean>
</property>
Any idea what goes wrong ?
Thanks.
EDIT: This was caused by a ClientInterceptor that returned false on handleResponse, and was located before the wss4j interceptor, causing all Interceptor processing to stop.
Your root cause is probably related to the order in which the securement of the message was made from the other side:
The order of the actions is significant and is enforced by the
interceptor. The interceptor will reject an incoming SOAP message if
its security actions were performed in a different order than the one
specified by validationActions.
I would recommend that you increase your log level (Add log4j if you are not already using it to see why the interceptor was not able to decrypt the message.
Last but not least, you should implement validator to prevent your process to go further if the message was not decrypted.
Caused by misconfiguration of the Interceptors. (see EDIT in original question)
Do I have to use jetty embeded server to test my active mq structure in a Spring project? Any help would be appreciated.
Please see the following links from ActiveMQ:
How to unit test JMS code
Integration Tests > Example Testing Scenario
Unit testing with JMS (ActiveMQ)
At first, add context your listener container bean like the following:
<bean id="sampleListenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="concurrency" value="20-100"/>
<property name="connectionFactory" ref="connectionFactory"/>
<property name="destination" ref="sampleDestination"/>
<property name="messageListener" ref="sampleListenerConsumer"/>
</bean>
Secondly,
DefaultMessageListenerContainer container = BeanProvider.getBeanFactory().getBean("sampleListenerContainer", DefaultMessageListenerContainer.class);
container.start();
Similarly,
container.stop();
In the past, I've been able to successfully connect Camel to a Message Queue exposed as a JNDI resource in WebSphere [1]. This works with a Connection Factory. Great.
Now today, I have a situation where sys admins have only provided an Activation Specification. No Connection Factory. Here's what we've got:
SIBus name: ________
Provider endpoint: ________
Topic space: Default.Topic.Space
Messaging Engine Name: ________
Topic name: ________
From what I've read, Activation Specification is intended for MDBs (Message Driven Beans). But Spring has some APIs for ActivationSpec -- DefaultJmsActivationSpecFactory, for example -- so I'm optimistic I can configure Camel / Spring to work with an Activation Specification. I'm not sure that it matters, but this is an SIBus with a foreign bus.
My question is:
Has anyone had any luck configuring Camel to communicate with an Activation Specification?
See also:
What's the difference between ActivationSpec and ConnectionFactory?
Spring JMS and WebSphere
Spring Support for JCA Message Endpoints
[1] For reference, here's our hard-won Camel config that connects Camel to a Message Queue via a JNDI resource (Connection Factory). Since we had to piece this config together with almost no documentation, I'm hoping a similar config can be done for Activation Spec.
<jee:jndi-lookup id="myTargetConnectionFactory" jndi-name="${mq.jndi-name}"/>
<bean id="jmsDestResolver" class="org.springframework.jms.support.destination.JndiDestinationResolver"/>
<bean id="myConnectionFactory" class="org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter">
<property name="targetConnectionFactory" ref="myTargetConnectionFactory"/>
<property name="username" value="${mq.username}"/>
<property name="password" value=""/>
</bean>
<bean id="jmsConfig" class="org.apache.camel.component.jms.JmsConfiguration">
<property name="connectionFactory" ref="myConnectionFactory" />
<property name="destinationResolver" ref="jmsDestResolver" />
<property name="concurrentConsumers" value="1" />
<property name="maxConcurrentConsumers" value="10" />
<property name="cacheLevelName" value="CACHE_NONE" />
</bean>