I have to consume a web service that was written in .Net and requires the
security policies listed below. We develop in Java to a WAR. I created a
separate project for the WSDL's Java stubs using Maven's cxf-codegen-plugin
(3.1.10). It was added to the main WAR project and compiles fine. But during
initial access to the service, a CXF error occurs.
The manual which came with the WSDL had the following to say about the security
features in use:
Transport Layer Security
Third party X.509 certificate and Tokens
Client X.509 certificate
We received a file from the vendor which was converted into a JKS. It has two
trustedCertEntry entries and one private key of X.509 type.
As I understand the manual, the service does not use the user name/password
type of WS security. All traffic goes over HTTPS of course, and the certificate
is supposed to be used to encrypt the message content both coming and going.
I have tried to configure the necessary values for CXF to work but always get
the same error:
Caused by: org.apache.cxf.ws.policy.PolicyException: Security configuration
could not be detected. Potential cause: Make sure jaxws:client element with
name attribute value matching endpoint port is defined as well as a
security.signature.properties element within it.
I have tried setting the necessary (AFAIK) properties via API and Spring XML
configuration to no avail.
I would greatly appreciate some guidance as to what CXF is looking for (and
where the file is supposed to be if configuration). Currently I have the
client-crypto.properties file under /WEB-INF/cxf along with the jks file. Its
contents:
org.apache.ws.security.crypto.merlin.keystore.file=/WEB-INF/cxf/dlsKeystore.jks
org.apache.ws.security.crypto.merlin.keystore.type=JKS
org.apache.ws.security.crypto.merlin.keystore.alias=1
org.apache.ws.security.crypto.merlin.keystore.password=****
org.apache.ws.security.crypto.merlin.keystore.private.password=****
org.apache.ws.security.crypto.merlin.truststore.file=/WEB-INF/cxf/dlsKeystore.jks
org.apache.ws.security.crypto.merlin.truststore.type=JKS
org.apache.ws.security.crypto.merlin.truststore.password=****
Things I have tried setting via API:
// set up ws-security
/*HashMap<String, Object> crytoProperties = new HashMap<String, Object>();
crytoProperties.put("org.apache.ws.security.crypto.merlin.keystore.file",
KEYSTORE_FILE);
crytoProperties.put("org.apache.ws.security.crypto.merlin.keystore.type",
"JKS");
crytoProperties.put("org.apache.ws.security.crypto.merlin.keystore.alias",
KEYSTORE_KEY_ALIAS);
crytoProperties.put("org.apache.ws.security.crypto.merlin.keystore.password",
KEYSTORE_PASSWORD);
crytoProperties.put("org.apache.ws.security.crypto.merlin.keystore.private.password",
KEYSTORE_KEY_PASSWORD);
crytoProperties.put("org.apache.ws.security.crypto.merlin.truststore.file",
KEYSTORE_FILE);
crytoProperties.put("org.apache.ws.security.crypto.merlin.truststore.type",
"JKS");
crytoProperties.put("org.apache.ws.security.crypto.merlin.truststore.password",
KEYSTORE_PASSWORD);
crytoProperties.put("org.apache.ws.security.crypto.merlin.truststore.alias",
KEYSTORE_KEY_ALIAS);
Map<String, Object> ctx = ((BindingProvider) port).getRequestContext();
ctx.putAll(crytoProperties);*/
// activate ws-security
/*org.apache.cxf.endpoint.Client client = (org.apache.cxf.endpoint.Client) port;
org.apache.cxf.endpoint.Endpoint endpoint = client.getEndpoint();*/
// add intercepters
/*HashMap<String, Object> inProps = new HashMap<String, Object>();
inProps.put(WSHandlerConstants.SIG_KEY_ID, KEYSTORE_KEY_ALIAS);
inProps.put(WSHandlerConstants.ENC_KEY_ID, KEYSTORE_KEY_ALIAS);
inProps.put(WSHandlerConstants.SIG_PROP_FILE, WSS4J_PROPERTIES);
inProps.put(WSHandlerConstants.ENC_PROP_FILE, WSS4J_PROPERTIES);
endpoint.getInInterceptors().add(new WSS4JOutInterceptor(inProps));
endpoint.getInInterceptors().add(new LoggingInInterceptor());
HashMap<String, Object> outProps = new HashMap<String, Object>();
outProps.put(WSHandlerConstants.SIG_KEY_ID, KEYSTORE_KEY_ALIAS);
outProps.put(WSHandlerConstants.ENC_KEY_ID, KEYSTORE_KEY_ALIAS);
outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.TIMESTAMP
+ " " + WSHandlerConstants.SIGNATURE + " " +
WSHandlerConstants.ENCRYPT);
outProps.put(WSHandlerConstants.SIG_PROP_FILE, WSS4J_PROPERTIES);
outProps.put(WSHandlerConstants.ENC_PROP_FILE, WSS4J_PROPERTIES);
outProps.put(WSHandlerConstants.PW_CALLBACK_REF,
"txdps.dl.bpr.common.business.VlsCxfKeystorePasswordCallback");
endpoint.getOutInterceptors().add(new WSS4JOutInterceptor(outProps));
endpoint.getOutInterceptors().add(new LoggingOutInterceptor());*/
// set options
/*HTTPConduit httpConduit = (HTTPConduit)
ClientProxy.getClient(port).getConduit();
final HTTPClientPolicy httpClientPolicy = httpConduit.getClient();
httpClientPolicy.setAllowChunking(false); // MS does not support
httpClientPolicy.setAutoRedirect(true); // hopefully
httpClientPolicy.setConnection(ConnectionType.KEEP_ALIVE); // maybe
TLSClientParameters tlsCP = new TLSClientParameters();
String keyPassword = KEYSTORE_PASSWORD;
KeyStore keyStore = KeyStore.getInstance("JKS");
Resource aamvaJks = applicationContext.getResource(KEYSTORE_FILE);
keyStore.load(aamvaJks.getInputStream(), KEYSTORE_PASSWORD.toCharArray());
KeyManager[] myKeyManagers = getKeyManagers(keyStore, keyPassword);
tlsCP.setKeyManagers(myKeyManagers);
KeyStore trustStore = KeyStore.getInstance("JKS");
aamvaJks = applicationContext.getResource(KEYSTORE_FILE);
trustStore.load(aamvaJks.getInputStream(), KEYSTORE_PASSWORD.toCharArray());
TrustManager[] myTrustStoreKeyManagers = getTrustManagers(trustStore);
tlsCP.setTrustManagers(myTrustStoreKeyManagers);
httpConduit.setTlsClientParameters(tlsCP);*/
Things I have tried setting via configuration (there are actually two WSDLs
compiled into one external jar).
<!-- ********************************************************* -->
<!-- * Configure the CXF Bus * -->
<!-- ********************************************************* -->
<import resource="classpath:META-INF/cxf/cxf.xml" />
<cxf:bus>
<cxf:features>
<p:policies />
<cxf:logging />
</cxf:features>
</cxf:bus>
<jaxws:client id="aamva-authentication"
name="{http://aamva.org/authentication/3.1.0}AuthenticationService"
createdFromAPI="true"
>
<jaxws:properties>
<entry
key="ws-security.signature.properties"
value="/WEB-INF/cxf/client-crypto.properties" />
<entry
key="ws-security.encryption.properties"
value="/WEB-INF/cxf/client-crypto.properties" />
</jaxws:properties>
</jaxws:client>
<jaxws:client id="aamva-vls3"
name="{http://uscis.gov/uscis/services/esb/vls/3.0}VerificationOfLawfulStatusService30"
createdFromAPI="true"
>
<jaxws:properties>
<entry
key="ws-security.signature.properties"
value="/WEB-INF/cxf/client-crypto.properties" />
<entry
key="ws-security.encryption.properties"
value="/WEB-INF/cxf/client-crypto.properties" />
</jaxws:properties>
</jaxws:client>
WSDL policies:
<wsp:Policy wsu:Id="wsHttpEndPoint_policy">
<wsp:ExactlyOne>
<wsp:All>
<sp:TransportBinding
xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"
>
<wsp:Policy>
<sp:TransportToken>
<wsp:Policy>
<sp:HttpsToken
RequireClientCertificate="false" />
</wsp:Policy>
</sp:TransportToken>
<sp:AlgorithmSuite>
<wsp:Policy>
<sp:Basic256 />
</wsp:Policy>
</sp:AlgorithmSuite>
<sp:Layout>
<wsp:Policy>
<sp:Strict />
</wsp:Policy>
</sp:Layout>
<sp:IncludeTimestamp />
</wsp:Policy>
</sp:TransportBinding>
<sp:EndorsingSupportingTokens
xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"
>
<wsp:Policy>
<sp:SecureConversationToken
sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient"
>
<wsp:Policy>
<sp:BootstrapPolicy>
<wsp:Policy>
<sp:SignedParts>
<sp:Body />
<sp:Header
Name="To"
Namespace="http://www.w3.org/2005/08/addressing" />
<sp:Header
Name="From"
Namespace="http://www.w3.org/2005/08/addressing" />
<sp:Header
Name="FaultTo"
Namespace="http://www.w3.org/2005/08/addressing" />
<sp:Header
Name="ReplyTo"
Namespace="http://www.w3.org/2005/08/addressing" />
<sp:Header
Name="MessageID"
Namespace="http://www.w3.org/2005/08/addressing" />
<sp:Header
Name="RelatesTo"
Namespace="http://www.w3.org/2005/08/addressing" />
<sp:Header
Name="Action"
Namespace="http://www.w3.org/2005/08/addressing" />
</sp:SignedParts>
<sp:EncryptedParts>
<sp:Body />
</sp:EncryptedParts>
<sp:TransportBinding>
<wsp:Policy>
<sp:TransportToken>
<wsp:Policy>
<sp:HttpsToken
RequireClientCertificate="false" />
</wsp:Policy>
</sp:TransportToken>
<sp:AlgorithmSuite>
<wsp:Policy>
<sp:Basic256 />
</wsp:Policy>
</sp:AlgorithmSuite>
<sp:Layout>
<wsp:Policy>
<sp:Strict />
</wsp:Policy>
</sp:Layout>
<sp:IncludeTimestamp />
</wsp:Policy>
</sp:TransportBinding>
<sp:EndorsingSupportingTokens>
<wsp:Policy>
<sp:X509Token
sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient"
>
<wsp:Policy>
<sp:RequireThumbprintReference />
<sp:WssX509V3Token10 />
</wsp:Policy>
</sp:X509Token>
<sp:SignedParts>
<sp:Header
Name="To"
Namespace="http://www.w3.org/2005/08/addressing" />
</sp:SignedParts>
</wsp:Policy>
</sp:EndorsingSupportingTokens>
<sp:Wss11>
<wsp:Policy>
<sp:MustSupportRefThumbprint />
</wsp:Policy>
</sp:Wss11>
<sp:Trust10>
<wsp:Policy>
<sp:MustSupportIssuedTokens />
<sp:RequireClientEntropy />
<sp:RequireServerEntropy />
</wsp:Policy>
</sp:Trust10>
</wsp:Policy>
</sp:BootstrapPolicy>
</wsp:Policy>
</sp:SecureConversationToken>
</wsp:Policy>
</sp:EndorsingSupportingTokens>
<sp:Wss11
xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy />
</sp:Wss11>
<sp:Trust10
xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"
>
<wsp:Policy>
<sp:MustSupportIssuedTokens />
<sp:RequireClientEntropy />
<sp:RequireServerEntropy />
</wsp:Policy>
</sp:Trust10>
<wsaw:UsingAddressing />
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>