Repository: cxf Updated Branches: refs/heads/master 403a4fb83 -> 417d93849
Adding support for a cross-domain STS test Project: http://git-wip-us.apache.org/repos/asf/cxf/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/417d9384 Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/417d9384 Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/417d9384 Branch: refs/heads/master Commit: 417d9384948f93adcc0ce1c9f2786e8dcafa434d Parents: 68372da Author: Colm O hEigeartaigh <[email protected]> Authored: Thu Jun 26 13:48:07 2014 +0100 Committer: Colm O hEigeartaigh <[email protected]> Committed: Thu Jun 26 13:48:34 2014 +0100 ---------------------------------------------------------------------- .../cxf/ws/security/SecurityConstants.java | 12 +- .../apache/cxf/ws/security/trust/STSUtils.java | 128 +++++++++++++++---- .../sts/cross_domain/CrossDomainTest.java | 3 +- .../cxf/systest/sts/cross_domain/cxf-client.xml | 1 + 4 files changed, 117 insertions(+), 27 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf/blob/417d9384/rt/ws/security/src/main/java/org/apache/cxf/ws/security/SecurityConstants.java ---------------------------------------------------------------------- diff --git a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/SecurityConstants.java b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/SecurityConstants.java index 131a6ac..7938889 100644 --- a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/SecurityConstants.java +++ b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/SecurityConstants.java @@ -455,6 +455,16 @@ public final class SecurityConstants { "ws-security.sts.disable-wsmex-call-using-epr-address"; /** + * Whether to prefer to use WS-MEX over a STSClient's location/wsdlLocation properties + * when making an STS RequestSecurityToken call. This can be set to true for the scenario + * of making a WS-MEX call to an initial STS, and using the returned token to make another + * call to an STS (which is configured using the STSClient configuration). Default is + * "false". + */ + public static final String PREFER_WSMEX_OVER_STS_CLIENT_CONFIG = + "ws-security.sts.prefer-wsmex"; + + /** * Switch STS client to send Soap 1.2 messages */ public static final String STS_CLIENT_SOAP12_BINDING = @@ -568,7 +578,7 @@ public final class SecurityConstants { TOKEN, TOKEN_ID, SUBJECT_ROLE_CLASSIFIER, SUBJECT_ROLE_CLASSIFIER_TYPE, MUST_UNDERSTAND, ASYMMETRIC_SIGNATURE_ALGORITHM, PASSWORD_ENCRYPTOR_INSTANCE, ENABLE_SAML_ONE_TIME_USE_CACHE, SAML_ONE_TIME_USE_CACHE_INSTANCE, ENABLE_STREAMING_SECURITY, RETURN_SECURITY_ERROR, - CACHE_IDENTIFIER, CACHE_ISSUED_TOKEN_IN_ENDPOINT + CACHE_IDENTIFIER, CACHE_ISSUED_TOKEN_IN_ENDPOINT, PREFER_WSMEX_OVER_STS_CLIENT_CONFIG })); ALL_PROPERTIES = Collections.unmodifiableSet(s); } http://git-wip-us.apache.org/repos/asf/cxf/blob/417d9384/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSUtils.java ---------------------------------------------------------------------- diff --git a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSUtils.java b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSUtils.java index 6003439..6e27209 100644 --- a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSUtils.java +++ b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/trust/STSUtils.java @@ -22,6 +22,8 @@ package org.apache.cxf.ws.security.trust; import javax.xml.bind.JAXBException; import javax.xml.namespace.QName; +import org.w3c.dom.Element; + import org.apache.cxf.Bus; import org.apache.cxf.BusException; import org.apache.cxf.binding.BindingFactory; @@ -31,6 +33,7 @@ import org.apache.cxf.databinding.source.SourceDataBinding; import org.apache.cxf.endpoint.Endpoint; import org.apache.cxf.endpoint.EndpointException; import org.apache.cxf.endpoint.EndpointImpl; +import org.apache.cxf.helpers.DOMUtils; import org.apache.cxf.message.Message; import org.apache.cxf.message.MessageUtils; import org.apache.cxf.service.Service; @@ -90,39 +93,116 @@ public final class STSUtils { } public static STSClient getClient(Message message, String type, IssuedToken itok) { - STSClient client = (STSClient)message - .getContextualProperty(SecurityConstants.STS_CLIENT); - if (client == null) { - if (type == null) { - type = ""; - } else { - type = "." + type + "-client"; - } - client = new STSClient(message.getExchange().get(Bus.class)); - Endpoint ep = message.getExchange().get(Endpoint.class); - client.setEndpointName(ep.getEndpointInfo().getName().toString() + type); - client.setBeanName(ep.getEndpointInfo().getName().toString() + type); - if (MessageUtils.getContextualBoolean(message, SecurityConstants.STS_CLIENT_SOAP12_BINDING, false)) { - client.setSoap12(); - } - } - - if (client.getLocation() == null && client.getWsdlLocation() == null - && itok != null && itok.getIssuer() != null) { + // Find out first if we have an EPR to get the STS Address (possibly via WS-MEX) + if (itok != null && itok.getIssuer() != null && message != null) { EndpointReferenceType epr = null; try { epr = VersionTransformer.parseEndpointReference(itok.getIssuer()); } catch (JAXBException e) { throw new IllegalArgumentException(e); } - //configure via mex - boolean useEPRWSAAddrAsMEXLocation = - !Boolean.valueOf((String)message.getContextualProperty( - SecurityConstants.DISABLE_STS_CLIENT_WSMEX_CALL_USING_EPR_ADDRESS)); - client.configureViaEPR(epr, useEPRWSAAddrAsMEXLocation); + + String mexLocation = findMEXLocation(epr); + // Configure via WS-MEX + if (mexLocation != null + && MessageUtils.getContextualBoolean(message, + SecurityConstants.PREFER_WSMEX_OVER_STS_CLIENT_CONFIG, + false)) { + // WS-MEX call. So now either get the WS-MEX specific STSClient or else create one + STSClient client = (STSClient)message + .getContextualProperty(SecurityConstants.STS_CLIENT + ".wsmex"); + if (client == null) { + client = createSTSClient(message, type); + } + client.configureViaEPR(epr, false); + return client; + } else if (configureViaEPR(message, type, epr)) { + // Only use WS-MEX here if the pre-configured STSClient has no location/wsdllocation + boolean useEPRWSAAddrAsMEXLocation = + !Boolean.valueOf((String)message.getContextualProperty( + SecurityConstants.DISABLE_STS_CLIENT_WSMEX_CALL_USING_EPR_ADDRESS)); + + STSClient client = (STSClient)message + .getContextualProperty(SecurityConstants.STS_CLIENT); + if (client == null) { + client = createSTSClient(message, type); + } + client.configureViaEPR(epr, useEPRWSAAddrAsMEXLocation); + return client; + } + } + + // Not a WS-MEX call + STSClient client = (STSClient)message + .getContextualProperty(SecurityConstants.STS_CLIENT); + if (client == null) { + client = createSTSClient(message, type); + } + + return client; + } + + public static boolean configureViaEPR(Message message, String type, EndpointReferenceType epr) { + STSClient client = (STSClient)message + .getContextualProperty(SecurityConstants.STS_CLIENT); + if (epr != null && client == null) { + return true; + } else if (epr != null && client != null && client.getLocation() == null && client.getWsdlLocation() == null) { + return true; + } + + return false; + } + + private static STSClient createSTSClient(Message message, String type) { + if (type == null) { + type = ""; + } else { + type = "." + type + "-client"; + } + STSClient client = new STSClient(message.getExchange().get(Bus.class)); + Endpoint ep = message.getExchange().get(Endpoint.class); + client.setEndpointName(ep.getEndpointInfo().getName().toString() + type); + client.setBeanName(ep.getEndpointInfo().getName().toString() + type); + if (MessageUtils.getContextualBoolean(message, SecurityConstants.STS_CLIENT_SOAP12_BINDING, false)) { + client.setSoap12(); } + return client; } + + public static String findMEXLocation(EndpointReferenceType ref) { + if (ref.getMetadata() != null && ref.getMetadata().getAny() != null) { + for (Object any : ref.getMetadata().getAny()) { + if (any instanceof Element) { + String addr = findMEXLocation((Element)any); + if (addr != null) { + return addr; + } + } + } + } + return null; + } + + public static String findMEXLocation(Element ref) { + Element el = DOMUtils.getFirstElement(ref); + while (el != null) { + if (el.getLocalName().equals("Address") + && VersionTransformer.isSupported(el.getNamespaceURI()) + && "MetadataReference".equals(ref.getLocalName())) { + return DOMUtils.getContent(el); + } else { + String ad = findMEXLocation(el); + if (ad != null) { + return ad; + } + } + el = DOMUtils.getNextElement(el); + } + return null; + } + public static Endpoint createSTSEndpoint(Bus bus, String namespace, String transportId, http://git-wip-us.apache.org/repos/asf/cxf/blob/417d9384/services/sts/systests/advanced/src/test/java/org/apache/cxf/systest/sts/cross_domain/CrossDomainTest.java ---------------------------------------------------------------------- diff --git a/services/sts/systests/advanced/src/test/java/org/apache/cxf/systest/sts/cross_domain/CrossDomainTest.java b/services/sts/systests/advanced/src/test/java/org/apache/cxf/systest/sts/cross_domain/CrossDomainTest.java index 9b169fa..8f340f6 100644 --- a/services/sts/systests/advanced/src/test/java/org/apache/cxf/systest/sts/cross_domain/CrossDomainTest.java +++ b/services/sts/systests/advanced/src/test/java/org/apache/cxf/systest/sts/cross_domain/CrossDomainTest.java @@ -89,7 +89,7 @@ public class CrossDomainTest extends AbstractBusClientServerTestBase { stopAllServers(); } - // In this test, a CXF client checks to see that the location defined on its STSClient is different + // In this test, a CXF client checks to see that the location defined on its STSClient is different // from that configured in the Issuer of the IssuedToken policy supplied in the WSDL of the // service provider. It obtains a SAML Token from the configured STS first, and then sends it in // the security header to the second STS. The returned token is then sent to the service provider. @@ -123,7 +123,6 @@ public class CrossDomainTest extends AbstractBusClientServerTestBase { // The client has a configured STSClient for this + uses it to get a token from "a", and in // turn to use the returned token to get a token from "b", to access the service. @org.junit.Test - @org.junit.Ignore public void testCrossDomainMEX() throws Exception { if (!portFree) { http://git-wip-us.apache.org/repos/asf/cxf/blob/417d9384/services/sts/systests/advanced/src/test/resources/org/apache/cxf/systest/sts/cross_domain/cxf-client.xml ---------------------------------------------------------------------- diff --git a/services/sts/systests/advanced/src/test/resources/org/apache/cxf/systest/sts/cross_domain/cxf-client.xml b/services/sts/systests/advanced/src/test/resources/org/apache/cxf/systest/sts/cross_domain/cxf-client.xml index f854682..26b9fe0 100644 --- a/services/sts/systests/advanced/src/test/resources/org/apache/cxf/systest/sts/cross_domain/cxf-client.xml +++ b/services/sts/systests/advanced/src/test/resources/org/apache/cxf/systest/sts/cross_domain/cxf-client.xml @@ -48,6 +48,7 @@ <jaxws:client name="{http://www.example.org/contract/DoubleIt}DoubleItCrossDomainMEXPort" createdFromAPI="true"> <jaxws:properties> + <entry key="ws-security.sts.prefer-wsmex" value="true"/> <entry key="ws-security.sts.client"> <bean class="org.apache.cxf.ws.security.trust.STSClient"> <constructor-arg ref="cxf"/>
