package org.jentrata.ebms.as4.internal.routes; import org.apache.camel.Exchange; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.impl.DefaultExchange; import org.apache.camel.test.junit4.CamelTestSupport; import org.apache.commons.io.IOUtils; import org.apache.wss4j.common.crypto.Crypto; import org.apache.wss4j.common.crypto.CryptoFactory; import org.apache.wss4j.common.ext.Attachment; import org.apache.wss4j.common.ext.AttachmentRequestCallback; import org.apache.wss4j.common.ext.AttachmentResultCallback; import org.apache.wss4j.common.ext.WSPasswordCallback; import org.apache.wss4j.common.ext.WSSecurityException; import org.apache.wss4j.common.util.XMLUtils; import org.apache.wss4j.dom.WSConstants; import org.apache.wss4j.dom.WSEncryptionPart; import org.apache.wss4j.dom.WSSConfig; import org.apache.wss4j.dom.message.WSSecHeader; import org.apache.wss4j.dom.message.WSSecSignature; import org.apache.wss4j.dom.message.WSSecUsernameToken; import org.apache.xml.security.utils.Base64; import org.jentrata.ebms.EbmsConstants; import org.jentrata.ebms.MessageType; import org.jentrata.ebms.cpa.PartnerAgreement; import org.jentrata.ebms.cpa.pmode.Party; import org.jentrata.ebms.cpa.pmode.Security; import org.jentrata.ebms.cpa.pmode.Signature; import org.jentrata.ebms.cpa.pmode.UsernameToken; import org.jentrata.ebms.internal.messaging.AttachmentDataSource; import org.jentrata.ebms.utils.EbmsUtils; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import javax.activation.DataHandler; import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.UnsupportedCallbackException; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import static org.hamcrest.Matchers.*; /** * Unit test for org.jentrata.ebms.as4.internal.routes.WSSERouteBuilder * * @author aaronwalker */ public class WSSERouteBuilderTest extends CamelTestSupport { private static final Logger LOG = LoggerFactory.getLogger(WSSERouteBuilderTest.class); private Crypto crypto = null; @Test public void testInvalidUsernameToken() throws Exception { Exchange request = new DefaultExchange(context); request.getIn().setBody(generateSoapMessage("unknown")); request.getIn().setHeader(EbmsConstants.MESSAGE_ID, "testMSG-0001"); request.getIn().setHeader(EbmsConstants.CPA_ID,"JentrataTestCPA"); request.getIn().setHeader(EbmsConstants.CPA,generateAgreement()); Exchange response = context().createProducerTemplate().send("direct:wsseSecurityCheck",request); assertThat(request.getIn().getHeader(EbmsConstants.SECURITY_RESULTS,Exception.class),instanceOf(WSSecurityException.class)); assertThat(response.getIn().getHeader(EbmsConstants.SECURITY_CHECK,Boolean.class),is(false)); } @Test public void testEmptyUsernameToken() throws Exception { Exchange request = new DefaultExchange(context); request.getIn().setBody(loadSoapMessage()); request.getIn().setHeader(EbmsConstants.MESSAGE_ID, "testMSG-0001"); request.getIn().setHeader(EbmsConstants.CPA_ID,"JentrataTestCPA"); request.getIn().setHeader(EbmsConstants.CPA,generateAgreement()); Exchange response = context().createProducerTemplate().send("direct:wsseSecurityCheck",request); assertThat(request.isFailed(),is(false)); assertThat(response.getIn().getHeader(EbmsConstants.SECURITY_CHECK,Boolean.class),is(false)); } @Test public void testReceiptWithResponseMepShouldBeAuthenticated() throws Exception { Exchange request = new DefaultExchange(context); request.getIn().setBody(loadSoapReceipt()); request.getIn().setHeader(EbmsConstants.MESSAGE_ID, "testMSG-0001"); request.getIn().setHeader(EbmsConstants.CPA_ID,"JentrataTestCPA"); PartnerAgreement agreement = generateAgreement("jentrata", false); agreement.getSecurity().setSendReceiptReplyPattern(Security.ReplyPatternType.Response); request.getIn().setHeader(EbmsConstants.CPA, agreement); request.getIn().setHeader(EbmsConstants.MESSAGE_TYPE, MessageType.SIGNAL_MESSAGE_WITH_USER_MESSAGE); Exchange response = context().createProducerTemplate().send("direct:wsseSecurityCheck",request); assertThat(request.isFailed(),is(false)); assertThat(response.getIn().getHeader(EbmsConstants.SECURITY_CHECK,Boolean.class),is(true)); } @Test public void testNonReputableReceiptWithResponseMepShouldBeAuthenticated() throws Exception { Exchange request = new DefaultExchange(context); request.getIn().setBody(loadSoapNonReputableReceipt()); request.getIn().setHeader(EbmsConstants.MESSAGE_ID, "testMSG-0001"); request.getIn().setHeader(EbmsConstants.CPA_ID,"JentrataTestCPA"); PartnerAgreement agreement = generateAgreement("jentrata", false); agreement.getSecurity().setSendReceiptReplyPattern(Security.ReplyPatternType.Response); request.getIn().setHeader(EbmsConstants.CPA, agreement); request.getIn().setHeader(EbmsConstants.MESSAGE_TYPE, MessageType.SIGNAL_MESSAGE); Exchange response = context().createProducerTemplate().send("direct:wsseSecurityCheck",request); assertThat(request.isFailed(),is(false)); assertThat(response.getIn().getHeader(EbmsConstants.SECURITY_CHECK,Boolean.class),is(true)); } @Test public void testAddSecurityToHeader() throws Exception { Exchange request = new DefaultExchange(context); request.getIn().setBody(loadSoapMessage()); request.getIn().setHeader(EbmsConstants.MESSAGE_ID, "testMSG-0001"); request.getIn().setHeader(EbmsConstants.CPA_ID,"JentrataTestCPA"); request.getIn().setHeader(EbmsConstants.CPA,generateAgreement()); Exchange response = context().createProducerTemplate().send("direct:wsseAddSecurityToHeader",request); Document body = response.getIn().getBody(Document.class); System.out.println(XMLUtils.PrettyDocumentToString(body)); assertThat(body, hasXPath("//*[local-name()='UsernameToken']")); assertThat(body, hasXPath("//*[local-name()='Username' and text()='jentrata']")); assertThat(body,hasXPath("//*[local-name()='Password']")); assertThat(body,hasXPath("//*[local-name()='Created']")); } @Test public void testSignedMessageWithAttachments() throws Exception { byte [] data = IOUtils.toByteArray(new FileInputStream(fileFromClasspath("sample-payload.xml"))); Attachment attachment = new Attachment(); attachment.setId("attachment1234@jentrata.org"); attachment.setMimeType("application/xml"); attachment.setSourceStream(new ByteArrayInputStream(data)); AttachmentDataSource dataSource = new AttachmentDataSource(attachment); Exchange request = new DefaultExchange(context); request.getIn().setBody(generateSoapMessage("jentrata", attachment)); request.getIn().setHeader(EbmsConstants.MESSAGE_ID, "testMSG-0001"); request.getIn().setHeader(EbmsConstants.CPA_ID,"JentrataTestCPA"); request.getIn().setHeader(EbmsConstants.CPA,generateAgreement("jentrata")); request.getIn().addAttachment(attachment.getId(),new DataHandler(dataSource)); //perform the signing verification and security check Exchange response = context().createProducerTemplate().send("direct:wsseSecurityCheck",request); assertThat(request.isFailed(),is(false)); assertThat(response.getIn().getHeader(EbmsConstants.SECURITY_CHECK,Boolean.class),is(true)); assertThat(response.getIn().hasAttachments(),is(true)); assertThat(response.getIn().getAttachment("attachment1234@jentrata.org"),notNullValue()); assertThat(IOUtils.toByteArray(request.getIn().getAttachment("attachment1234@jentrata.org").getInputStream()),equalTo(data)); } @Test public void testSignedMessageWithMutipleAttachments() throws Exception { byte [] data = IOUtils.toByteArray(new FileInputStream(fileFromClasspath("sample-payload.xml"))); Attachment attachment = new Attachment(); attachment.setId("attachment1234@jentrata.org"); attachment.setMimeType("application/xml"); attachment.setSourceStream(new ByteArrayInputStream(data)); AttachmentDataSource dataSource = new AttachmentDataSource(attachment); Attachment attachment2 = new Attachment(); attachment2.setId("attachment1234_2@jentrata.org"); attachment2.setMimeType("application/xml"); attachment2.setSourceStream(new ByteArrayInputStream(data)); AttachmentDataSource dataSource2 = new AttachmentDataSource(attachment2); Exchange request = new DefaultExchange(context); request.getIn().setBody(generateSoapMessage("jentrata", attachment,attachment2)); request.getIn().setHeader(EbmsConstants.MESSAGE_ID, "testMSG-0001"); request.getIn().setHeader(EbmsConstants.CPA_ID,"JentrataTestCPA"); request.getIn().setHeader(EbmsConstants.CPA,generateAgreement("jentrata")); request.getIn().addAttachment(attachment.getId(),new DataHandler(dataSource)); request.getIn().addAttachment(attachment2.getId(),new DataHandler(dataSource2)); //perform the signing verification and security check Exchange response = context().createProducerTemplate().send("direct:wsseSecurityCheck",request); assertThat(request.isFailed(),is(false)); assertThat(response.getIn().getHeader(EbmsConstants.SECURITY_CHECK,Boolean.class),is(true)); assertThat(response.getIn().hasAttachments(),is(true)); assertThat(response.getIn().getAttachment("attachment1234@jentrata.org"),notNullValue()); assertThat(IOUtils.toByteArray(request.getIn().getAttachment("attachment1234@jentrata.org").getInputStream()),equalTo(data)); assertThat(response.getIn().getAttachment("attachment1234_2@jentrata.org"),notNullValue()); assertThat(IOUtils.toByteArray(request.getIn().getAttachment("attachment1234_2@jentrata.org").getInputStream()),equalTo(data)); } @Test public void testSignedMessageWithCompressedAttachments() throws Exception { byte [] data = EbmsUtils.compress("application/gzip",IOUtils.toByteArray(new FileInputStream(fileFromClasspath("sample-payload.xml")))); Attachment attachment = new Attachment(); attachment.setId("attachment1234@jentrata.org"); attachment.setMimeType("application/gzip"); attachment.setSourceStream(new ByteArrayInputStream(data)); AttachmentDataSource dataSource = new AttachmentDataSource(attachment); Exchange request = new DefaultExchange(context); request.getIn().setBody(generateSoapMessage("jentrata",true, attachment)); request.getIn().setHeader(EbmsConstants.MESSAGE_ID, "testMSG-0001"); request.getIn().setHeader(EbmsConstants.CPA_ID,"JentrataTestCPA"); request.getIn().setHeader(EbmsConstants.CPA,generateAgreement("jentrata")); request.getIn().addAttachment(attachment.getId(),new DataHandler(dataSource)); //perform the signing verification and security check Exchange response = context().createProducerTemplate().send("direct:wsseSecurityCheck",request); assertThat(request.isFailed(),is(false)); assertThat(response.getIn().getHeader(EbmsConstants.SECURITY_CHECK,Boolean.class),is(true)); assertThat(response.getIn().hasAttachments(),is(true)); assertThat(response.getIn().getAttachment("attachment1234@jentrata.org"),notNullValue()); assertThat(IOUtils.toByteArray(request.getIn().getAttachment("attachment1234@jentrata.org").getInputStream()),equalTo(data)); } @Test public void testAttachmentWithInvalidSignature() throws Exception { byte [] data = IOUtils.toByteArray(new FileInputStream(fileFromClasspath("sample-payload.xml"))); Attachment attachment = new Attachment(); attachment.setId("attachment1234@jentrata.org"); attachment.setMimeType("application/xml"); attachment.setSourceStream(new ByteArrayInputStream(data)); Attachment badAttachment = new Attachment(); attachment.setId("attachment1234@jentrata.org"); attachment.setMimeType("application/xml"); attachment.setSourceStream(new ByteArrayInputStream("<bad>Im a bad guy who has modified your attachment</bad>".getBytes())); AttachmentDataSource badDataSource = new AttachmentDataSource(badAttachment); Exchange request = new DefaultExchange(context); request.getIn().setBody(generateSoapMessage("jentrata", attachment)); request.getIn().setHeader(EbmsConstants.MESSAGE_ID, "testMSG-0001"); request.getIn().setHeader(EbmsConstants.CPA_ID,"JentrataTestCPA"); request.getIn().setHeader(EbmsConstants.CPA,generateAgreement("jentrata")); request.getIn().addAttachment(attachment.getId(),new DataHandler(badDataSource)); //perform the signing verification and security check Exchange response = context().createProducerTemplate().send("direct:wsseSecurityCheck",request); assertThat(request.getIn().getHeader(EbmsConstants.SECURITY_RESULTS,Exception.class),instanceOf(WSSecurityException.class)); assertThat(response.getIn().getHeader(EbmsConstants.SECURITY_CHECK,Boolean.class),is(false)); } @Test public void testAddSignatureSecurityToHeader() throws Exception { byte [] data = IOUtils.toByteArray(new FileInputStream(fileFromClasspath("sample-payload.xml"))); List<Map<String,Object>> payloads = new ArrayList<>(); Map<String,Object> payload = new HashMap<>(); payload.put("payloadId", "attachment1234@jentrata.org"); payload.put("contentType", "application/xml"); payload.put("charset", "utf-8"); payload.put("partProperties", "sourceABN=123456789;targetABN=987654321"); payload.put("schema", "test"); payload.put("content", data); payloads.add(payload); Exchange request = new DefaultExchange(context); request.getIn().setBody(loadSoapMessage()); request.getIn().setHeader(EbmsConstants.MESSAGE_ID, "testMSG-0001"); request.getIn().setHeader(EbmsConstants.CPA_ID,"JentrataTestCPA"); request.getIn().setHeader(EbmsConstants.CPA,generateAgreement("jentrata",true)); request.getIn().setHeader(EbmsConstants.MESSAGE_PAYLOADS,payloads); request.getIn().setHeader(EbmsConstants.MESSAGE_TYPE, MessageType.USER_MESSAGE); Exchange response = context().createProducerTemplate().send("direct:wsseAddSecurityToHeader",request); Document body = response.getIn().getBody(Document.class); System.out.println(XMLUtils.PrettyDocumentToString(body)); assertThat(body, hasXPath("//*[local-name()='UsernameToken']")); assertThat(body, hasXPath("//*[local-name()='Username' and text()='jentrata']")); assertThat(body,hasXPath("//*[local-name()='Password']")); assertThat(body,hasXPath("//*[local-name()='Created']")); assertThat(body, hasXPath("//*[local-name()='Signature']")); assertThat(body, hasXPath("//@*[name()='URI' and .='cid:attachment1234@jentrata.org']")); assertThat(body, hasXPath("//@*[name()='href' and .='cid:attachment1234@jentrata.org']")); assertThat(body, hasXPath("//*[local-name()='Reference'][1]")); assertThat(body, hasXPath("//*[local-name()='Reference'][2]")); assertThat(body, hasXPath("//*[local-name()='Reference'][3]")); } @Test public void testAddSignatureSecurityToHeaderForReceipt() throws Exception { Exchange request = new DefaultExchange(context); request.getIn().setBody(loadSoapReceipt()); request.getIn().setHeader(EbmsConstants.MESSAGE_ID, "testMSG-0001"); request.getIn().setHeader(EbmsConstants.CPA_ID,"JentrataTestCPA"); request.getIn().setHeader(EbmsConstants.CPA,generateAgreement("jentrata",true)); request.getIn().setHeader(EbmsConstants.MESSAGE_TYPE, MessageType.SIGNAL_MESSAGE); Exchange response = context().createProducerTemplate().send("direct:wsseAddSecurityToHeader",request); Document body = response.getIn().getBody(Document.class); System.out.println(XMLUtils.PrettyDocumentToString(body)); assertThat(body, hasXPath("//*[local-name()='UsernameToken']")); assertThat(body, hasXPath("//*[local-name()='Username' and text()='jentrata']")); assertThat(body,hasXPath("//*[local-name()='Password']")); assertThat(body,hasXPath("//*[local-name()='Created']")); assertThat(body, hasXPath("//*[local-name()='Signature']")); assertThat(body, hasXPath("//*[local-name()='Reference'][1]")); assertThat(body, hasXPath("//*[local-name()='Reference'][2]")); } @Test public void testShouldNotAddSecurityHeaderForResponseMEPSignalMessage() throws Exception { Exchange request = new DefaultExchange(context); request.getIn().setBody(loadSoapReceipt()); request.getIn().setHeader(EbmsConstants.MESSAGE_ID, "testMSG-0001"); request.getIn().setHeader(EbmsConstants.CPA_ID,"JentrataTestCPA"); PartnerAgreement agreement = generateAgreement("jentrata", false); agreement.getSecurity().setSendReceiptReplyPattern(Security.ReplyPatternType.Response); request.getIn().setHeader(EbmsConstants.CPA, agreement); request.getIn().setHeader(EbmsConstants.MESSAGE_TYPE, MessageType.SIGNAL_MESSAGE); Exchange response = context().createProducerTemplate().send("direct:wsseAddSecurityToHeader",request); Document body = response.getIn().getBody(Document.class); System.out.println(XMLUtils.PrettyDocumentToString(body)); assertThat(body, not(hasXPath("//*[local-name()='Security']"))); assertThat(body, not(hasXPath("//*[local-name()='UsernameToken']"))); assertThat(body, not(hasXPath("//*[local-name()='Signature']"))); } @Test public void testShouldNotAddSecurityHeaderForResponseMEPSignalMessageNonReputable() throws Exception { Exchange request = new DefaultExchange(context); request.getIn().setBody(loadSoapNonReputableReceipt()); request.getIn().setHeader(EbmsConstants.MESSAGE_ID, "testMSG-0001"); request.getIn().setHeader(EbmsConstants.CPA_ID,"JentrataTestCPA"); PartnerAgreement agreement = generateAgreement("jentrata", false); agreement.getSecurity().setSendReceiptReplyPattern(Security.ReplyPatternType.Response); request.getIn().setHeader(EbmsConstants.CPA, agreement); request.getIn().setHeader(EbmsConstants.MESSAGE_TYPE, MessageType.SIGNAL_MESSAGE); Exchange response = context().createProducerTemplate().send("direct:wsseAddSecurityToHeader",request); Document body = response.getIn().getBody(Document.class); System.out.println(XMLUtils.PrettyDocumentToString(body)); assertThat(body, not(hasXPath("//*[local-name()='Security']"))); assertThat(body, not(hasXPath("//*[local-name()='UsernameToken']"))); assertThat(body, not(hasXPath("//*[local-name()='Signature']"))); } @Test public void testShouldNotAddUserTokenForResponseMEPSignalMessage() throws Exception { Exchange request = new DefaultExchange(context); request.getIn().setBody(loadSoapReceipt()); request.getIn().setHeader(EbmsConstants.MESSAGE_ID, "testMSG-0001"); request.getIn().setHeader(EbmsConstants.CPA_ID,"JentrataTestCPA"); PartnerAgreement agreement = generateAgreement("jentrata", true); agreement.getSecurity().setSendReceiptReplyPattern(Security.ReplyPatternType.Response); request.getIn().setHeader(EbmsConstants.CPA, agreement); request.getIn().setHeader(EbmsConstants.MESSAGE_TYPE, MessageType.SIGNAL_MESSAGE); Exchange response = context().createProducerTemplate().send("direct:wsseAddSecurityToHeader",request); Document body = response.getIn().getBody(Document.class); System.out.println(XMLUtils.PrettyDocumentToString(body)); assertThat(body, hasXPath("//*[local-name()='Security']")); assertThat(body, not(hasXPath("//*[local-name()='UsernameToken']"))); assertThat(body, hasXPath("//*[local-name()='Signature']")); } @Test public void testAddSignatureSecurityToHeaderWithCompression() throws Exception { byte [] data = EbmsUtils.compress("application/gzip",IOUtils.toByteArray(new FileInputStream(fileFromClasspath("sample-payload.xml")))); List<Map<String,Object>> payloads = new ArrayList<>(); Map<String,Object> payload = new HashMap<>(); payload.put("payloadId", "attachment1234@jentrata.org"); payload.put("contentType", "application/xml"); payload.put("compressionType","application/gzip"); payload.put("charset", "utf-8"); payload.put("partProperties", "sourceABN=123456789;targetABN=987654321"); payload.put("schema", "test"); payload.put("content", data); payloads.add(payload); Exchange request = new DefaultExchange(context); request.getIn().setBody(loadSoapMessage()); request.getIn().setHeader(EbmsConstants.MESSAGE_ID, "testMSG-0001"); request.getIn().setHeader(EbmsConstants.CPA_ID,"JentrataTestCPA"); request.getIn().setHeader(EbmsConstants.CPA,generateAgreement("jentrata",true)); request.getIn().setHeader(EbmsConstants.MESSAGE_PAYLOADS,payloads); request.getIn().setHeader(EbmsConstants.MESSAGE_TYPE, MessageType.USER_MESSAGE); Exchange response = context().createProducerTemplate().send("direct:wsseAddSecurityToHeader",request); Document body = response.getIn().getBody(Document.class); System.out.println(XMLUtils.PrettyDocumentToString(body)); } @Test public void testAddSignatureSecurityToHeaderWithNullCompression() throws Exception { byte [] data = IOUtils.toByteArray(new FileInputStream(fileFromClasspath("sample-payload.xml"))); List<Map<String,Object>> payloads = new ArrayList<>(); Map<String,Object> payload = new HashMap<>(); payload.put("payloadId", "attachment1234@jentrata.org"); payload.put("contentType", "application/xml"); payload.put("compressionType",null); payload.put("charset", "utf-8"); payload.put("partProperties", "sourceABN=123456789;targetABN=987654321"); payload.put("schema", "test"); payload.put("content", data); payloads.add(payload); Exchange request = new DefaultExchange(context); request.getIn().setBody(loadSoapMessage()); request.getIn().setHeader(EbmsConstants.MESSAGE_ID, "testMSG-0001"); request.getIn().setHeader(EbmsConstants.CPA_ID,"JentrataTestCPA"); request.getIn().setHeader(EbmsConstants.CPA,generateAgreement("jentrata",true)); request.getIn().setHeader(EbmsConstants.MESSAGE_PAYLOADS,payloads); request.getIn().setHeader(EbmsConstants.MESSAGE_TYPE, MessageType.USER_MESSAGE); Exchange response = context().createProducerTemplate().send("direct:wsseAddSecurityToHeader",request); Document body = response.getIn().getBody(Document.class); System.out.println(XMLUtils.PrettyDocumentToString(body)); } @Test public void testAddSignatureWithNoUserToken() throws Exception { byte [] data = IOUtils.toByteArray(new FileInputStream(fileFromClasspath("sample-payload.xml"))); List<Map<String,Object>> payloads = new ArrayList<>(); Map<String,Object> payload = new HashMap<>(); payload.put("payloadId", "attachment1234@jentrata.org"); payload.put("contentType", "application/xml"); payload.put("charset", "utf-8"); payload.put("partProperties", "sourceABN=123456789;targetABN=987654321"); payload.put("schema", "test"); payload.put("content", data); payloads.add(payload); Exchange request = new DefaultExchange(context); request.getIn().setBody(loadSoapMessage()); request.getIn().setHeader(EbmsConstants.MESSAGE_ID, "testMSG-0001"); request.getIn().setHeader(EbmsConstants.CPA_ID,"JentrataTestCPA"); request.getIn().setHeader(EbmsConstants.CPA,generateAgreement(null,true)); request.getIn().setHeader(EbmsConstants.MESSAGE_PAYLOADS,payloads); request.getIn().setHeader(EbmsConstants.MESSAGE_TYPE, MessageType.USER_MESSAGE); Exchange response = context().createProducerTemplate().send("direct:wsseAddSecurityToHeader",request); Document body = response.getIn().getBody(Document.class); System.out.println(XMLUtils.PrettyDocumentToString(body)); assertThat(body, not(hasXPath("//*[local-name()='UsernameToken']"))); assertThat(body, not(hasXPath("//*[local-name()='Username' and text()='jentrata']"))); assertThat(body,not(hasXPath("//*[local-name()='Password']"))); assertThat(body,not(hasXPath("//*[local-name()='Created']"))); assertThat(body, hasXPath("//*[local-name()='Signature']")); assertThat(body, hasXPath("//@*[name()='URI' and .='cid:attachment1234@jentrata.org']")); assertThat(body, hasXPath("//@*[name()='href' and .='cid:attachment1234@jentrata.org']")); assertThat(body, hasXPath("//*[local-name()='Reference'][1]")); assertThat(body, hasXPath("//*[local-name()='Reference'][2]")); assertThat(body, hasXPath("//*[local-name()='Reference'][3]")); } @Test public void testAddSignatureWithInclusiveNamespaces() throws Exception { byte [] data = IOUtils.toByteArray(new FileInputStream(fileFromClasspath("sample-payload.xml"))); List<Map<String,Object>> payloads = new ArrayList<>(); Map<String,Object> payload = new HashMap<>(); payload.put("payloadId", "attachment1234@jentrata.org"); payload.put("contentType", "application/xml"); payload.put("charset", "utf-8"); payload.put("partProperties", "sourceABN=123456789;targetABN=987654321"); payload.put("schema", "test"); payload.put("content", data); payloads.add(payload); Exchange request = new DefaultExchange(context); request.getIn().setBody(loadSoapMessage()); request.getIn().setHeader(EbmsConstants.MESSAGE_ID, "testMSG-0001"); request.getIn().setHeader(EbmsConstants.CPA_ID,"JentrataTestCPA"); request.getIn().setHeader(EbmsConstants.CPA,generateAgreement(null,true)); request.getIn().setHeader(EbmsConstants.MESSAGE_PAYLOADS,payloads); request.getIn().setHeader(EbmsConstants.MESSAGE_TYPE, MessageType.USER_MESSAGE); Exchange response = context().createProducerTemplate().send("direct:wsseAddSecurityToHeader",request); Document body = response.getIn().getBody(Document.class); System.out.println(XMLUtils.PrettyDocumentToString(body)); assertThat(body, not(hasXPath("//*[local-name()='UsernameToken']"))); assertThat(body, not(hasXPath("//*[local-name()='Username' and text()='jentrata']"))); assertThat(body,not(hasXPath("//*[local-name()='Password']"))); assertThat(body,not(hasXPath("//*[local-name()='Created']"))); assertThat(body, hasXPath("//*[local-name()='Signature']")); assertThat(body, hasXPath("//@*[name()='URI' and .='cid:attachment1234@jentrata.org']")); assertThat(body, hasXPath("//@*[name()='href' and .='cid:attachment1234@jentrata.org']")); assertThat(body, hasXPath("//*[local-name()='Reference'][1]")); assertThat(body, hasXPath("//*[local-name()='Reference'][2]")); assertThat(body, hasXPath("//*[local-name()='Reference'][3]")); assertThat(body, hasXPath("//*[local-name()='InclusiveNamespaces'][1]")); } @Test public void testAddSignatureWithoutInclusiveNamespaces() throws Exception { byte [] data = IOUtils.toByteArray(new FileInputStream(fileFromClasspath("sample-payload.xml"))); List<Map<String,Object>> payloads = new ArrayList<>(); Map<String,Object> payload = new HashMap<>(); payload.put("payloadId", "attachment1234@jentrata.org"); payload.put("contentType", "application/xml"); payload.put("charset", "utf-8"); payload.put("partProperties", "sourceABN=123456789;targetABN=987654321"); payload.put("schema", "test"); payload.put("content", data); payloads.add(payload); Exchange request = new DefaultExchange(context); request.getIn().setBody(loadSoapMessage()); request.getIn().setHeader(EbmsConstants.MESSAGE_ID, "testMSG-0001"); request.getIn().setHeader(EbmsConstants.CPA_ID,"JentrataTestCPA"); PartnerAgreement partnerAgreement = generateAgreement(null, true); partnerAgreement.getSecurity().setInclusiveNamespacesEnabled(false); request.getIn().setHeader(EbmsConstants.CPA, partnerAgreement); request.getIn().setHeader(EbmsConstants.MESSAGE_PAYLOADS,payloads); request.getIn().setHeader(EbmsConstants.MESSAGE_TYPE, MessageType.USER_MESSAGE); Exchange response = context().createProducerTemplate().send("direct:wsseAddSecurityToHeader",request); Document body = response.getIn().getBody(Document.class); System.out.println(XMLUtils.PrettyDocumentToString(body)); assertThat(body, not(hasXPath("//*[local-name()='UsernameToken']"))); assertThat(body, not(hasXPath("//*[local-name()='Username' and text()='jentrata']"))); assertThat(body,not(hasXPath("//*[local-name()='Password']"))); assertThat(body,not(hasXPath("//*[local-name()='Created']"))); assertThat(body, hasXPath("//*[local-name()='Signature']")); assertThat(body, hasXPath("//@*[name()='URI' and .='cid:attachment1234@jentrata.org']")); assertThat(body, hasXPath("//@*[name()='href' and .='cid:attachment1234@jentrata.org']")); assertThat(body, hasXPath("//*[local-name()='Reference'][1]")); assertThat(body, hasXPath("//*[local-name()='Reference'][2]")); assertThat(body, hasXPath("//*[local-name()='Reference'][3]")); assertThat(body, not(hasXPath("//*[local-name()='InclusiveNamespaces'][1]"))); } @Override protected RouteBuilder createRouteBuilder() throws Exception { WSSConfig.init(); crypto = CryptoFactory.getInstance(); WSSERouteBuilder routeBuilder = new WSSERouteBuilder(); routeBuilder.setCrypto(crypto); return routeBuilder; } private String generateSoapMessage(String username, final Attachment...attachments) throws Exception { return generateSoapMessage(username, false, attachments); } private String generateSoapMessage(String username, boolean compressed, final Attachment...attachments) throws Exception { WSSecUsernameToken builder = new WSSecUsernameToken(); builder.setPasswordsAreEncoded(true); builder.setUserInfo(username, getEncodedPassword()); LOG.info("Before adding UsernameToken PW Digest...."); Document doc; if(compressed) { doc = loadSoapMessage("sample-wsse-soap-compression.xml"); } else { doc = loadSoapMessage(); } WSSecHeader secHeader = new WSSecHeader(); secHeader.insertSecurityHeader(doc); Document signedDoc = builder.build(doc, secHeader); if(attachments != null && attachments.length > 0) { List<WSEncryptionPart> parts = new ArrayList<>(); parts.add(new WSEncryptionPart("Messaging","http://docs.oasis-open.org/ebxml-msg/ebms/v3.0/ns/core/200704/","")); parts.add(new WSEncryptionPart("Body", "http://www.w3.org/2003/05/soap-envelope", "Content")); parts.add(new WSEncryptionPart("cid:Attachments", "Content")); WSSecSignature signature = new WSSecSignature(); signature.setUserInfo("jentrata", "security"); signature.setSignatureAlgorithm(WSConstants.RSA); signature.setDigestAlgo(WSConstants.SHA256); signature.setParts(parts); signature.setAttachmentCallbackHandler(new CallbackHandler() { @Override public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { for(int i=0;i<callbacks.length;i++) { if (callbacks[i] instanceof AttachmentRequestCallback) { AttachmentRequestCallback attachmentRequestCallback = (AttachmentRequestCallback) callbacks[i]; List<Attachment> attachmentList = new ArrayList<>(); for(Attachment a : attachments) { attachmentList.add(a); } attachmentRequestCallback.setAttachments(attachmentList); } else { AttachmentResultCallback attachmentResultCallback = (AttachmentResultCallback) callbacks[i]; attachments[i] = attachmentResultCallback.getAttachment(); } } } }); signedDoc = signature.build(signedDoc, crypto, secHeader); } String outputString = XMLUtils.PrettyDocumentToString(signedDoc); LOG.info(outputString); return outputString; } private Document loadSoapMessage() throws Exception { return loadSoapMessage("sample-wsse-soap.xml"); } private Document loadSoapMessage(String filename) throws Exception { return context().getTypeConverter().convertTo(Document.class, new FileInputStream(fileFromClasspath(filename))); } private Document loadSoapReceipt() throws Exception { return context().getTypeConverter().convertTo(Document.class, new FileInputStream(fileFromClasspath("simple-as4-receipt.xml"))); } private Document loadSoapNonReputableReceipt() throws Exception { return context().getTypeConverter().convertTo(Document.class, new FileInputStream(fileFromClasspath("non-reputable-receipt.xml"))); } private PartnerAgreement generateAgreement() { return generateAgreement("jentrata"); } private PartnerAgreement generateAgreement(String username) { return generateAgreement("jentrata",false); } private PartnerAgreement generateAgreement(String username, boolean signatureEnabled) { PartnerAgreement agreement = new PartnerAgreement(); agreement.setCpaId("JentrataTestCPA"); Party party = new Party(); if(username != null) { UsernameToken authorization = new UsernameToken(); authorization.setUsername(username); authorization.setPassword(getEncodedPassword()); party.setAuthorization(authorization); } agreement.setInitiator(party); agreement.setResponder(party); Security security = new Security(); agreement.setSecurity(security); if(signatureEnabled) { Signature signature = new Signature(); if(username == null) { signature.setKeyStoreAlias("jentrata"); } else { signature.setKeyStoreAlias(username); } signature.setKeyStorePass("security"); security.setSignature(signature); security.setSendReceipt(true); security.setSendReceiptNonRepudiation(true); } return agreement; } protected static File fileFromClasspath(String filename) { File file = new File(Thread.currentThread().getContextClassLoader().getResource(filename).getFile()); return file; } private String getEncodedPassword() { try { return Base64.encode(MessageDigest.getInstance("SHA-1").digest("verySecret".getBytes("UTF-8"))); } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) { throw new RuntimeException(e); } } private class EncodedPasswordCallbackHandler implements CallbackHandler { @Override public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { for (Callback callback : callbacks) { if (callback instanceof WSPasswordCallback) { WSPasswordCallback pc = (WSPasswordCallback) callback; if (pc.getUsage() == WSPasswordCallback.Usage.USERNAME_TOKEN) { if ("jentrata".equals(pc.getIdentifier())) { pc.setPassword(getEncodedPassword()); } else if("16c73ab6-b892-458f-abf5-2f875f74882e".equals(pc.getIdentifier())) { pc.setPassword(getEncodedPassword()); } } } else { throw new UnsupportedCallbackException(callback, "Unrecognized Callback"); } } } } }