Hi Andrew,
On the soapUI side my team and I had a 2 week experience getting soapUI
working with signing requests so that Oracle Service Bus could process the
request. For the XML Signature we found we *had* to have the following
defined in the *parts* section identified within the XML Signature property
section of soapUI. We were signing the Body of the Request, the timestamp
and the token. :
*
1.
1.
*
*
1.
Signature policy with the following settings:
1.
Keystore = <previously configured keystore>
2.
Alias = <alias of the key to use in keystore>
3.
Signature Algorithm = http://www.w3.org/2000/09/xmldsig#rsh-sha1
4.
Digest Algorithm = http://www.w3.org/2000/09/xmldsig#sha1
5.
Canonicalization Algorithm =
http://www.w3.org/2001/10/xml-exc-c14#
6.
Use Single Certificate = checked
7.
Parts
1.
Name = Body, Namespace =
http://schemas.xmlsoap.org/soap/envelope/, Encoding = Element
2.
Name = Timestamp, Namespace =
http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd,
Encoding = Element
3. Name = Token, Namspace = N/A (leave field empty),
Encoding = N/A (leave field empty)
*
Good Luck!
Chris
On Wed, Apr 17, 2013 at 8:27 PM, Andrew Hart <[email protected]> wrote:
> I am using JBoss AS 6.1 with CXF 2.3.1 bundled and I believe the version
> of WSS4J included in that is 1.5.8. My version of the JDK is 1.6.
>
> I have been struggling for several days now to get a simple test going
> using SOAPUi 4.5.1 as the client. I have reviewed the WS-Security spec,
> looked at numerous tutorials, including the documentation on the CXF
> website and Mr. Mazza's blog describing the process. I cannot be sure
> whether the problem is SOAPUi or my service. In any case, I am sort of
> constrained to use this old version of JBoss AS along with it's old
> versions of CXF and WSS4j, so many of the features described on the CXF
> tutorial are not applicable, I believe, for example the
> DefaultCryptoCoverageChecker. I think I would prefer to use the
> interceptors rather than the WS-Policy as I am not using the WSDL first
> method. I have not tried the WS-Policy annotations.
>
> I have a server.keystore which contains the public/private key pair for
> the server. Into this I have also imported the client certs for two
> test clients, client1 and client2.
> So, I have the inverse, a client1.keystore with client1 public/private
> keys and the server public key certificate is imported into this file.
> Likewise for client2. The aliases for these are server, client1, and
> client2, respectively. The passwords for all the keystores and aliases
> is currently just "password".
>
>
> First, here is an excerpt of my service implementation:
>
> @WebService(serviceName = "My_Web_Service", name = "MyWebService",
> targetNamespace = "http://mycompany.com")
> @SOAPBinding(style = SOAPBinding.Style.DOCUMENT, use =
> SOAPBinding.Use.LITERAL, parameterStyle =
> SOAPBinding.ParameterStyle.WRAPPED)
> //@EndpointConfig(configFile = "WEB-INF/jaxws-endpoint-config.xml",
> configName = "Standard WSSecurity Endpoint")
> public class MyWebService {
>
> private static Log log = LogFactory.getLog(MyWebService.class);
>
> /**
> * Returns the list of Area of Operation codes.
> *
> * @return List<AreaOfOperationsBean>
> */
> @WebMethod()
> @WebResult(name = "payLoad")
> public PayLoad getAreaOfOperationsData()
>
> {
> log.debug("Req method: getCipAreaOfOperationsData!");
>
> [... setup the payload object deleted]
> return p;
>
> } // getAreaOfOperationsData()
>
> [...]
> }
>
> Configuration of the WSS4J interceptors is done using the
> jbossws-cxf.xml file which is in the WEB-INF directory of my service
> WAR:
>
>
> <beans
> xmlns='http://www.springframework.org/schema/beans'
> xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
> xmlns:beans='http://www.springframework.org/schema/beans'
> xmlns:jaxws='http://cxf.apache.org/jaxws'
> xsi:schemaLocation='http://cxf.apache.org/core
> http://cxf.apache.org/schemas/core.xsd
> http://www.springframework.org/schema/beans
> http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
> http://cxf.apache.org/jaxws
> http://cxf.apache.org/schemas/jaxws.xsd'>
>
>
> <bean id="Sign_Request"
> class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
> <constructor-arg>
> <map>
> <entry key="action" value="Timestamp Signature"/>
> <entry key="signaturePropFile" value="security.properties"/>
> <entry key="decryptionPropFile" value="security.properties"/>
> <entry key="passwordCallbackClass"
> value="com.mycompany.ws.common.KeystorePasswordCallback"/>
> </map>
> </constructor-arg>
> </bean>
>
>
> <bean id="Sign_Response"
> class="org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor">
> <constructor-arg>
> <map>
> <entry key="action" value="Timestamp Signature Encrypt"/>
> <entry key="user" value="server "/>
> <entry key="signaturePropFile" value="security.properties"/>
> <entry key="encryptionPropFile" value="security.properties"/>
> <!-- <entry key="encryptionUser" value="useReqSigCert"/> -->
> <entry key="encryptionUser" value="client1 " />
> <entry key="signatureKeyIdentifier" value="DirectReference"/>
> <entry key="encryptionKeyIdentifier" value="DirectReference" />
> <entry key="passwordCallbackClass"
> value="com.mycompany.ws.common.KeystorePasswordCallback"/>
> <entry key="signatureParts"
> value="{Element}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss
> -wssecurity-utility-1.0.xsd}Timestamp;{Element}{http://schemas.xmlsoap.o
> rg/soap/envelope/}Body"/>
> <entry key="encryptionParts"
> value="{Element}{http://www.w3.org/2000/09/xmldsig#}Signature;{Content}{
> http://schemas.xmlsoap.org/soap/envelope/}Body"/>
> <entry key="encryptionKeyTransportAlgorithm"
> value="http://www.w3.org/2001/04/xmlenc#rsa-1_5"/>
> <entry key="encryptionSymAlgorithm"
> value="http://www.w3.org/2001/04/xmlenc#tripledes-cbc"/>
> </map>
> </constructor-arg>
> </bean>
>
> <jaxws:endpoint
> id='CipService'
> address='http://@jboss.bind.address@:8080/ws-cip'
> implementor='com.mycompany.ws.MyService'>
> <jaxws:invoker>
> <bean class='org.jboss.wsf.stack.cxf.InvokerJSE'/>
> </jaxws:invoker>
> <jaxws:outInterceptors>
> <bean
> class="org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor"/>
> <ref bean="Sign_Response"/>
> </jaxws:outInterceptors>
>
> <jaxws:inInterceptors>
> <ref bean="Sign_Request"/>
> <bean
> class="org.apache.cxf.binding.soap.saaj.SAAJInInterceptor"/>
> </jaxws:inInterceptors>
>
> </jaxws:endpoint>
> </beans>
>
> You'll note that I have encryptionUser = useReqSigCert commented out at
> the moment because I haven't been able to get it working, so I'm trying
> to just hardcode the client alias, but alas, that isn't working either
> as you will see.
>
> My password callback handler is simple:
>
> package com.mycompany.ws.common;
>
> import java.io.IOException;
> import java.util.HashMap;
> import java.util.Map;
>
> import javax.security.auth.callback.Callback;
> import javax.security.auth.callback.CallbackHandler;
> import javax.security.auth.callback.UnsupportedCallbackException;
>
> import org.apache.log4j.Logger;
> import org.apache.ws.security.WSPasswordCallback;
>
> public class KeystorePasswordCallback implements CallbackHandler {
>
> private static Logger log = Logger
> .getLogger(KeystorePasswordCallback.class);
> private Map<String, String> passwords = new HashMap<String,
> String>();
>
> public KeystorePasswordCallback() {
> log.info("Creating ws security callback handler...");
> passwords.put("server ", "password");
> passwords.put("client1 ", "password");
> passwords.put("client2 ", "password");
> }
>
> public void handle(Callback[] callbacks) throws IOException,
> UnsupportedCallbackException {
> log.info("KeystorePasswordCallback invoked handle");
> for (int i = 0; i < callbacks.length; i++) {
> WSPasswordCallback pc = (WSPasswordCallback)
> callbacks[i];
> String id = pc.getIdentifier();
> log.info("Looking up password for identifier: "
> + id);
> String pass = passwords.get(pc.getIdentifier());
> if (pass != null) {
> pc.setPassword(pass);
> return;
> }
> }
> }
>
> public void setAliasPassword(String alias, String password) {
> passwords.put(alias, password);
> }
> }
>
>
> My security.properties file is located in the WEB-INF directory (since
> my service is a POJO):
>
> org.apache.ws.security.crypto.provider=org.apache.ws.security.components
> .crypto.Merlin
> org.apache.ws.security.crypto.merlin.keystore.type=jks
> org.apache.ws.security.crypto.merlin.keystore.password=password
> org.apache.ws.security.crypto.merlin.keystore.alias=server
> org.apache.ws.security.crypto.merlin.file=server.keystore
>
>
> Since I have the client certs with their public keys in there, I don't
> think I need a separate truststore.
>
> OK, so that's all of the server side. My goal is to test this using
> soapUi version 4.5.1. This version of soapUi is using an embedded Java
> JRE 1.7 if that makes a difference.
> I hope someone is familiar with it, but basically, under my project
> configuration I have defined the two client keystores, client1.keystore
> and client2.keystore and entered their password.
> My "incoming" WS-Security configuration is simple; there isn't much to
> configure there: I have specified the decrypt and signature keystores
> as client1.keystore and included the password.
>
> For the "outgoing" WS-Security configuration, I currently have a default
> Username/alias of "client1", the default password of "password", no
> actor specified, and "Must Understand" is not checked. For the
> actions:
>
> "Timestamp" with a TTL of 1800000 and millisecond precision.
>
> "Signature" with
> Keystore = client1.keystore
> Alias = client1
> Password = password
> Key Identifier Type: [options are "Issurer Name and Serial
> Number", "Binary Security Token", "X509 Certificate", and "Subject Key
> Identifier"]. I have tried all of them and my current setting is
> "Binary Security Token". (In the WS-Security spec it said an X.509 cert
> was an example of such)
> Signature Algorithm is:
> http://www.w3.org/2000/09/xmldsig#rsa-sha1
> Signature Canonicalization is:
> http://www.w3.org/2001/10/xml-exc-c14n#
> Digest Algorithm is: http://www.w3.org/2000/09/xmldsig#sha1
> Use Single Certificate: true
> I currently do not have any Parts specified. I think this may
> be incorrect, or at least not recommended.
>
>
> OK, so when I create a request in SoapUi and attach the "outgoing"
> ws-security stuff and send it to the server, I see this in the console:
>
> 17:44:10,348 INFO [com.mycompany.ws.common.KeystorePasswordCallback]
> Creating ws security callback handler...
> 17:44:10,348 INFO [com. mycompany.ws.common.KeystorePasswordCallback]
> KeystorePasswordCallback invoked handle
> 17:44:10,348 INFO [com. mycompany.ws.common.KeystorePasswordCallback]
> Looking up password for identifier: server
>
> And, then, in the soapUi error log, I see this stack trace:
>
> Wed Apr 17 17:44:10 CDT
> 2013:ERROR:org.apache.ws.security.WSSecurityException: The signature or
> decryption was invalid
> org.apache.ws.security.WSSecurityException: The signature or
> decryption was invalid
> at
> org.apache.ws.security.processor.EncryptedKeyProcessor.handleToken(Encry
> ptedKeyProcessor.java:106)
> at
> org.apache.ws.security.WSSecurityEngine.processSecurityHeader(WSSecurity
> Engine.java:396)
> at
> org.apache.ws.security.WSSecurityEngine.processSecurityHeader(WSSecurity
> Engine.java:304)
> at
> org.apache.ws.security.WSSecurityEngine.processSecurityHeader(WSSecurity
> Engine.java:249)
> at
> com.eviware.soapui.impl.wsdl.support.wss.IncomingWss.processIncoming(Inc
> omingWss.java:121)
> at
> com.eviware.soapui.impl.wsdl.submit.transports.http.support.attachments.
> WsdlSinglePartHttpResponse.processIncomingWss(WsdlSinglePartHttpResponse
> .java:49)
> at
> com.eviware.soapui.impl.wsdl.submit.transports.http.support.attachments.
> WsdlSinglePartHttpResponse.<init>(WsdlSinglePartHttpResponse.java:38)
> at
> com.eviware.soapui.impl.wsdl.submit.filters.HttpPackagingResponseFilter.
> wsdlRequest(HttpPackagingResponseFilter.java:71)
> at
> com.eviware.soapui.impl.wsdl.submit.filters.HttpPackagingResponseFilter.
> afterAbstractHttpResponse(HttpPackagingResponseFilter.java:48)
> at
> com.eviware.soapui.impl.wsdl.submit.filters.AbstractRequestFilter.afterR
> equest(AbstractRequestFilter.java:64)
> at
> com.eviware.soapui.impl.wsdl.submit.transports.http.HttpClientRequestTra
> nsport.sendRequest(HttpClientRequestTransport.java:297)
> at
> com.eviware.soapui.impl.wsdl.WsdlSubmit.run(WsdlSubmit.java:123)
> at java.util.concurrent.Executors$RunnableAdapter.call(Unknown
> Source)
> at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source)
> at java.util.concurrent.FutureTask.run(Unknown Source)
> at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown
> Source)
> at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown
> Source)
> at java.lang.Thread.run(Unknown Source)
> Caused by: org.apache.ws.security.WSSecurityException: General
> security error (The private key for the supplied alias does not exist in
> the keystore)
> at
> org.apache.ws.security.components.crypto.Merlin.getPrivateKey(Merlin.jav
> a:661)
> at
> org.apache.ws.security.processor.EncryptedKeyProcessor.handleToken(Encry
> ptedKeyProcessor.java:103)
> ... 17 more
> Caused by: java.security.UnrecoverableKeyException: Cannot recover
> key
> at sun.security.provider.KeyProtector.recover(Unknown Source)
> at sun.security.provider.JavaKeyStore.engineGetKey(Unknown
> Source)
> at sun.security.provider.JavaKeyStore$JKS.engineGetKey(Unknown
> Source)
> at java.security.KeyStore.getKey(Unknown Source)
> at
> org.apache.ws.security.components.crypto.Merlin.getPrivateKey(Merlin.jav
> a:647)
> ... 18 more
>
>
> But, I know that the alias DOES exist in the keystore. I was confused
> by the fact that the PasswordCallbackhandler is looking up the password
> for "server", so I tried putting "client1" in there instead of "
> useReqSigCert" for that reason, but the result is the same. I read
> somewhere on a JBoss forum something about useReqSigCert not working
> correctly unless the request was also encrypted, so I have tried also
> encrypting the request from SoapUi.
>
> When encrypting from the client, I add a third action "Encryption" using
> the following settings:
> Keystore = client1.keystore
> Alias = server
> Password = "password"
> Key Identifier Type = "Binary Security Token" [ in addition to the
> options for signing, it also adds "Embedded KeyInfo", "Embed Security
> Token Reference", and "Thumbprint SHA1 Identifier". Again, I've tried
> them all with the exception of Embedded Key Info because I am unclear
> what to enter for "Embedded KeyName" and "Embedded Key Password"
>
> Embedded Keyname = blank
> Embedded Key Password = blank
> Symmetric Encoding Algorithm =
> http://www.w3.org/2001/04/xmlenc#tripledes-cbc
> Key Encryption Algorithm = http://www.w2.org/2001/04/xmlenc#rsa-1_5
> Create Encrypted Key = checked. (I've tried it both ways)
> Parts = blank. (My understanding is that when parts are blank, the
> entire SOAP message is signed or encrypted. Again, perhaps not
> recommended?)
>
> When I do that, I get an error on the server:
> org.apache.cxf.interceptor.Fault: Message part
> {http://www.w3.org/2001/04/xmlenc#}EncryptedData was not recognized.
> (Does it exist in service WSDL?)
>
> Ok, so I uncheck the "Create Encrypted Key" and try again and I get:
> 19:06:57,547 INFO [com.mycompany.ws.common.KeystorePasswordCallback]
> Creating Akimeka ws security callback handler...
> 19:06:57,547 INFO [com.mycompany.ws.common.KeystorePasswordCallback]
> KeystorePasswordCallback invoked handle
> 19:06:57,547 INFO [com.mycompany.ws.common.KeystorePasswordCallback]
> Looking up password for identifier: null
> 19:06:57,547 WARN [org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor]
> : org.apache.ws.security.WSSecurityException: The signature or
> decryption was invalid (Unsupported key identification)
>
> I switch to Key Identifier = "X509 Certificate" I get the same error.
> I switch to "Issuer Name and Serial", same error. "Embedded KeyInfo"
> gets me an "actions mismatch" error on the server.
>
> And, so you get the drift: I'm basically a chimp with a keyboard here,
> trying to stumble upon a Shakespearean sonnet. I have no idea what the
> correct settings should be. (Although I swear I have some dim
> recollection of getting client to server decrypting working at some
> point over the past several days.)
>
> So... I feel like what I want to do should be very simple, but I'm not
> sure how to proceed at this point. I may be dealing with problems with
> SoapUi, with this old version of CXF/WSS4j/Jboss, or just plain
> ignorance, but I sure could use some help.
>
> Sorry for the long mail, thanks in advance.
>
>
>
>
>
>
>
>
>
> NOTICE: This transmission (including all attachments) is company
> confidential, is intended only for the individual or entity named above,
> and is likely to contain privileged, proprietary and confidential
> information that is exempt from disclosure requests under applicable law.
> If you are not the intended recipient, you are hereby notified that any
> disclosure, copying, distribution, use of or reliance upon any of the
> information contained in this transmission is strictly prohibited. Any
> inadvertent or unauthorized disclosure shall not compromise or waive the
> confidentiality of this transmission. If you have received this
> transmission in error, please forward this message immediately to
> [email protected] <mailto:[email protected]> and delete or
> otherwise remove this email from your system. Thank you
>
>
--
Chris Riley, Partner
HKM Consulting LLC
(w) hkmconsultingllc.com
(o) 774.553.5314
(m) 508.273.3102
(f) 774.553.5316