Repository: cxf Updated Branches: refs/heads/master da07e6758 -> 28aa1248b
CXF-7444 - Add the ability to configure custom SAML audience restriction values Project: http://git-wip-us.apache.org/repos/asf/cxf/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/3779d242 Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/3779d242 Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/3779d242 Branch: refs/heads/master Commit: 3779d242296d8329db82b8243e4c5af8acde7ce6 Parents: da07e67 Author: Colm O hEigeartaigh <[email protected]> Authored: Thu Jul 13 10:51:32 2017 +0100 Committer: Colm O hEigeartaigh <[email protected]> Committed: Thu Jul 13 10:51:32 2017 +0100 ---------------------------------------------------------------------- .../rs/security/saml/AbstractSamlInHandler.java | 19 ++--------- .../cxf/rt/security/saml/utils/SAMLUtils.java | 36 ++++++++++++++++++++ .../cxf/rt/security/SecurityConstants.java | 14 ++++++-- .../ws/security/wss4j/WSS4JInInterceptor.java | 30 ++++------------ .../security/wss4j/WSS4JStaxInInterceptor.java | 24 ++----------- .../cxf/systest/ws/saml/SamlTokenTest.java | 10 ++++++ .../cxf/systest/ws/saml/DoubleItSaml.wsdl | 3 ++ .../org/apache/cxf/systest/ws/saml/server.xml | 9 +++++ .../apache/cxf/systest/ws/saml/stax-server.xml | 10 ++++++ 9 files changed, 89 insertions(+), 66 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf/blob/3779d242/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/saml/AbstractSamlInHandler.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/saml/AbstractSamlInHandler.java b/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/saml/AbstractSamlInHandler.java index 7395d82..c71257b 100644 --- a/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/saml/AbstractSamlInHandler.java +++ b/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/saml/AbstractSamlInHandler.java @@ -26,7 +26,6 @@ import java.nio.charset.StandardCharsets; import java.security.PublicKey; import java.security.cert.Certificate; import java.security.cert.X509Certificate; -import java.util.ArrayList; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; @@ -48,6 +47,7 @@ import org.apache.cxf.rs.security.saml.authorization.SecurityContextProvider; import org.apache.cxf.rs.security.saml.authorization.SecurityContextProviderImpl; import org.apache.cxf.rs.security.xml.AbstractXmlSecInHandler; import org.apache.cxf.rt.security.SecurityConstants; +import org.apache.cxf.rt.security.saml.utils.SAMLUtils; import org.apache.cxf.rt.security.utils.SecurityUtils; import org.apache.cxf.security.SecurityContext; import org.apache.cxf.security.transport.TLSSessionInfo; @@ -193,22 +193,7 @@ public abstract class AbstractSamlInHandler implements ContainerRequestFilter { } protected void configureAudienceRestriction(Message msg, RequestData reqData) { - // Add Audience Restrictions for SAML - boolean enableAudienceRestriction = false; - String audRestrStr = - (String)org.apache.cxf.rt.security.utils.SecurityUtils.getSecurityPropertyValue( - SecurityConstants.AUDIENCE_RESTRICTION_VALIDATION, msg); - if (audRestrStr != null) { - enableAudienceRestriction = Boolean.parseBoolean(audRestrStr); - } - - if (enableAudienceRestriction) { - List<String> audiences = new ArrayList<>(); - if (msg.getContextualProperty(org.apache.cxf.message.Message.REQUEST_URL) != null) { - audiences.add((String)msg.getContextualProperty(org.apache.cxf.message.Message.REQUEST_URL)); - } - reqData.setAudienceRestrictions(audiences); - } + reqData.setAudienceRestrictions(SAMLUtils.getAudienceRestrictions(msg)); } protected SAMLKeyInfo createKeyInfoFromDefaultAlias(Crypto sigCrypto) throws WSSecurityException { http://git-wip-us.apache.org/repos/asf/cxf/blob/3779d242/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/utils/SAMLUtils.java ---------------------------------------------------------------------- diff --git a/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/utils/SAMLUtils.java b/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/utils/SAMLUtils.java index 3317ccd..a63a24d 100644 --- a/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/utils/SAMLUtils.java +++ b/rt/security-saml/src/main/java/org/apache/cxf/rt/security/saml/utils/SAMLUtils.java @@ -20,15 +20,20 @@ package org.apache.cxf.rt.security.saml.utils; import java.net.URI; import java.security.Principal; +import java.util.ArrayList; +import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import org.w3c.dom.Element; import org.apache.cxf.common.security.SimpleGroup; +import org.apache.cxf.message.Message; +import org.apache.cxf.rt.security.SecurityConstants; import org.apache.cxf.rt.security.claims.Claim; import org.apache.cxf.rt.security.claims.ClaimCollection; import org.apache.cxf.rt.security.saml.claims.SAMLClaim; +import org.apache.cxf.rt.security.utils.SecurityUtils; import org.apache.wss4j.common.saml.SamlAssertionWrapper; import org.opensaml.core.xml.XMLObject; import org.opensaml.saml.common.SAMLVersion; @@ -138,4 +143,35 @@ public final class SAMLUtils { return ((SamlAssertionWrapper)assertion).getElement(); } + public static List<String> getAudienceRestrictions(Message msg) { + // Add Audience Restrictions for SAML + boolean enableAudienceRestriction = + SecurityUtils.getSecurityPropertyBoolean(SecurityConstants.AUDIENCE_RESTRICTION_VALIDATION, msg, true); + if (enableAudienceRestriction) { + List<String> audiences = new ArrayList<>(); + // See if we have custom audience restriction values specified first + String audienceRestrictions = + (String)SecurityUtils.getSecurityPropertyValue(SecurityConstants.AUDIENCE_RESTRICTIONS, msg); + if (audienceRestrictions != null) { + for (String audienceRestriction : audienceRestrictions.split(",")) { + audiences.add(audienceRestriction); + } + } + + // Defaults + if (audiences.isEmpty()) { + if (msg.get(org.apache.cxf.message.Message.REQUEST_URL) != null) { + audiences.add((String)msg.get(org.apache.cxf.message.Message.REQUEST_URL)); + } else if (msg.get(org.apache.cxf.message.Message.REQUEST_URI) != null) { + audiences.add((String)msg.get(org.apache.cxf.message.Message.REQUEST_URI)); + } + + if (msg.getContextualProperty("javax.xml.ws.wsdl.service") != null) { + audiences.add(msg.getContextualProperty("javax.xml.ws.wsdl.service").toString()); + } + } + return audiences; + } + return Collections.emptyList(); + } } http://git-wip-us.apache.org/repos/asf/cxf/blob/3779d242/rt/security/src/main/java/org/apache/cxf/rt/security/SecurityConstants.java ---------------------------------------------------------------------- diff --git a/rt/security/src/main/java/org/apache/cxf/rt/security/SecurityConstants.java b/rt/security/src/main/java/org/apache/cxf/rt/security/SecurityConstants.java index a3daaa8..1982009 100644 --- a/rt/security/src/main/java/org/apache/cxf/rt/security/SecurityConstants.java +++ b/rt/security/src/main/java/org/apache/cxf/rt/security/SecurityConstants.java @@ -180,8 +180,8 @@ public class SecurityConstants { /** * Enable SAML AudienceRestriction validation. If this is set to "true", then IF the - * SAML Token contains Audience Restriction URIs, one of them must match either the - * request URL or the Service QName. The default is "true". + * SAML Token contains Audience Restriction URIs, one of them must match one of the values of the + * AUDIENCE_RESTRICTIONS property. The default is "true". */ public static final String AUDIENCE_RESTRICTION_VALIDATION = "security.validate.audience-restriction"; @@ -351,6 +351,14 @@ public class SecurityConstants { public static final String STS_TOKEN_CACHER_IMPL = "security.sts.token.cacher.impl"; + /** + * This property contains a comma separated String corresponding to a list of audience restriction URIs. + * The default value for this property contains the request URL and the Service QName. If the + * AUDIENCE_RESTRICTION_VALIDATION property is "true", and if a received SAML Token contains audience + * restriction URIs, then one of them must match one of the values specified in this property. + */ + public static final String AUDIENCE_RESTRICTIONS = "security.audience-restrictions"; + public static final Set<String> COMMON_PROPERTIES; static { @@ -366,7 +374,7 @@ public class SecurityConstants { DISABLE_STS_CLIENT_WSMEX_CALL_USING_EPR_ADDRESS, STS_TOKEN_CRYPTO, STS_TOKEN_PROPERTIES, STS_TOKEN_USERNAME, STS_TOKEN_ACT_AS, STS_TOKEN_ON_BEHALF_OF, STS_CLIENT, STS_APPLIES_TO, CACHE_ISSUED_TOKEN_IN_ENDPOINT, PREFER_WSMEX_OVER_STS_CLIENT_CONFIG, - STS_TOKEN_IMMINENT_EXPIRY_VALUE, STS_TOKEN_CACHER_IMPL + STS_TOKEN_IMMINENT_EXPIRY_VALUE, STS_TOKEN_CACHER_IMPL, AUDIENCE_RESTRICTIONS })); COMMON_PROPERTIES = Collections.unmodifiableSet(s); } http://git-wip-us.apache.org/repos/asf/cxf/blob/3779d242/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JInInterceptor.java ---------------------------------------------------------------------- diff --git a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JInInterceptor.java b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JInInterceptor.java index 1d1c27f..442469e 100644 --- a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JInInterceptor.java +++ b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JInInterceptor.java @@ -55,6 +55,7 @@ import org.apache.cxf.helpers.DOMUtils; import org.apache.cxf.interceptor.Fault; import org.apache.cxf.message.MessageUtils; import org.apache.cxf.phase.Phase; +import org.apache.cxf.rt.security.saml.utils.SAMLUtils; import org.apache.cxf.rt.security.utils.SecurityUtils; import org.apache.cxf.security.transport.TLSSessionInfo; import org.apache.cxf.staxutils.StaxUtils; @@ -202,7 +203,7 @@ public class WSS4JInInterceptor extends AbstractWSS4JInterceptor { reqData.setEncryptionSerializer(new StaxSerializer()); // Add Audience Restrictions for SAML - configureAudienceRestriction(msg, reqData); + reqData.setAudienceRestrictions(SAMLUtils.getAudienceRestrictions(msg)); SOAPMessage doc = getSOAPMessage(msg); @@ -344,7 +345,7 @@ public class WSS4JInInterceptor extends AbstractWSS4JInterceptor { reqData = null; } } - private void importNewDomToSAAJ(SOAPMessage doc, Element elem, + private void importNewDomToSAAJ(SOAPMessage doc, Element elem, Node originalNode, WSHandlerResult wsResult) throws SOAPException { if (DOMUtils.isJava9SAAJ() && originalNode != null && !originalNode.isEqualNode(elem)) { @@ -377,7 +378,7 @@ public class WSS4JInInterceptor extends AbstractWSS4JInterceptor { List<WSSecurityEngineResult> encryptResults = wsResult.getActionResults().get(WSConstants.ENCR); if (encryptResults != null) { for (WSSecurityEngineResult result : wsResult.getActionResults().get(WSConstants.ENCR)) { - for (WSDataRef dataRef + for (WSDataRef dataRef : (List<WSDataRef>)result.get(WSSecurityEngineResult.TAG_DATA_REF_URIS)) { if (dataRef.getProtectedElement() == node) { dataRef.setProtectedElement((Element)newNode); @@ -385,7 +386,7 @@ public class WSS4JInInterceptor extends AbstractWSS4JInterceptor { } } } - + List<WSSecurityEngineResult> signedResults = new ArrayList<>(); if (wsResult.getActionResults().containsKey(WSConstants.SIGN)) { signedResults.addAll(wsResult.getActionResults().get(WSConstants.SIGN)); @@ -397,7 +398,7 @@ public class WSS4JInInterceptor extends AbstractWSS4JInterceptor { signedResults.addAll(wsResult.getActionResults().get(WSConstants.ST_SIGNED)); } for (WSSecurityEngineResult result : signedResults) { - for (WSDataRef dataRef + for (WSDataRef dataRef : (List<WSDataRef>)result.get(WSSecurityEngineResult.TAG_DATA_REF_URIS)) { if (dataRef.getProtectedElement() == node) { dataRef.setProtectedElement((Element)newNode); @@ -414,25 +415,6 @@ public class WSS4JInInterceptor extends AbstractWSS4JInterceptor { } } - private void configureAudienceRestriction(SoapMessage msg, RequestData reqData) { - // Add Audience Restrictions for SAML - boolean enableAudienceRestriction = - SecurityUtils.getSecurityPropertyBoolean(SecurityConstants.AUDIENCE_RESTRICTION_VALIDATION, msg, true); - if (enableAudienceRestriction) { - List<String> audiences = new ArrayList<>(); - if (msg.get(org.apache.cxf.message.Message.REQUEST_URL) != null) { - audiences.add((String)msg.get(org.apache.cxf.message.Message.REQUEST_URL)); - } else if (msg.get(org.apache.cxf.message.Message.REQUEST_URI) != null) { - audiences.add((String)msg.get(org.apache.cxf.message.Message.REQUEST_URI)); - } - - if (msg.getContextualProperty("javax.xml.ws.wsdl.service") != null) { - audiences.add(msg.getContextualProperty("javax.xml.ws.wsdl.service").toString()); - } - reqData.setAudienceRestrictions(audiences); - } - } - private void checkActions( SoapMessage msg, RequestData reqData, http://git-wip-us.apache.org/repos/asf/cxf/blob/3779d242/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JStaxInInterceptor.java ---------------------------------------------------------------------- diff --git a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JStaxInInterceptor.java b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JStaxInInterceptor.java index f860fd4..774f6ba 100644 --- a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JStaxInInterceptor.java +++ b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/WSS4JStaxInInterceptor.java @@ -19,7 +19,6 @@ package org.apache.cxf.ws.security.wss4j; import java.security.Provider; -import java.util.ArrayList; import java.util.Collections; import java.util.LinkedList; import java.util.List; @@ -41,6 +40,7 @@ import org.apache.cxf.interceptor.Fault; import org.apache.cxf.interceptor.StaxInInterceptor; import org.apache.cxf.message.MessageUtils; import org.apache.cxf.phase.Phase; +import org.apache.cxf.rt.security.saml.utils.SAMLUtils; import org.apache.cxf.rt.security.utils.SecurityUtils; import org.apache.cxf.ws.security.SecurityConstants; import org.apache.cxf.ws.security.tokenstore.TokenStoreUtils; @@ -275,27 +275,7 @@ public class WSS4JStaxInInterceptor extends AbstractWSS4JStaxInterceptor { } // Add Audience Restrictions for SAML - configureAudienceRestriction(msg, securityProperties); - } - - private void configureAudienceRestriction(SoapMessage msg, WSSSecurityProperties securityProperties) { - // Add Audience Restrictions for SAML - boolean enableAudienceRestriction = true; - String audRestrStr = - (String)SecurityUtils.getSecurityPropertyValue(SecurityConstants.AUDIENCE_RESTRICTION_VALIDATION, msg); - if (audRestrStr != null) { - enableAudienceRestriction = Boolean.parseBoolean(audRestrStr); - } - if (enableAudienceRestriction) { - List<String> audiences = new ArrayList<>(); - if (msg.getContextualProperty(org.apache.cxf.message.Message.REQUEST_URL) != null) { - audiences.add((String)msg.getContextualProperty(org.apache.cxf.message.Message.REQUEST_URL)); - } - if (msg.getContextualProperty("javax.xml.ws.wsdl.service") != null) { - audiences.add(msg.getContextualProperty("javax.xml.ws.wsdl.service").toString()); - } - securityProperties.setAudienceRestrictions(audiences); - } + securityProperties.setAudienceRestrictions(SAMLUtils.getAudienceRestrictions(msg)); } /** http://git-wip-us.apache.org/repos/asf/cxf/blob/3779d242/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/saml/SamlTokenTest.java ---------------------------------------------------------------------- diff --git a/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/saml/SamlTokenTest.java b/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/saml/SamlTokenTest.java index 575be41..614b1da 100644 --- a/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/saml/SamlTokenTest.java +++ b/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/saml/SamlTokenTest.java @@ -1152,6 +1152,16 @@ public class SamlTokenTest extends AbstractBusClientServerTestBase { SecurityConstants.SAML_CALLBACK_HANDLER, callbackHandler ); saml2Port.doubleIt(25); + + // It should pass because we explicitly allow the given audience restriction + portQName = new QName(NAMESPACE, "DoubleItSaml2TransportPort4"); + saml2Port = service.getPort(portQName, DoubleItPortType.class); + updateAddressPort(saml2Port, portNumber); + + ((BindingProvider)saml2Port).getRequestContext().put( + SecurityConstants.SAML_CALLBACK_HANDLER, callbackHandler + ); + saml2Port.doubleIt(25); } @org.junit.Test http://git-wip-us.apache.org/repos/asf/cxf/blob/3779d242/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/saml/DoubleItSaml.wsdl ---------------------------------------------------------------------- diff --git a/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/saml/DoubleItSaml.wsdl b/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/saml/DoubleItSaml.wsdl index ea0d132..099d828 100644 --- a/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/saml/DoubleItSaml.wsdl +++ b/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/saml/DoubleItSaml.wsdl @@ -386,6 +386,9 @@ <wsdl:port name="DoubleItSaml2TransportPort3" binding="tns:DoubleItSaml2TransportBinding"> <soap:address location="https://localhost:9009/DoubleItSaml2Transport3"/> </wsdl:port> + <wsdl:port name="DoubleItSaml2TransportPort4" binding="tns:DoubleItSaml2TransportBinding"> + <soap:address location="https://localhost:9009/DoubleItSaml2Transport4"/> + </wsdl:port> </wsdl:service> <wsp:Policy wsu:Id="DoubleItSaml1TransportPolicy"> <wsp:ExactlyOne> http://git-wip-us.apache.org/repos/asf/cxf/blob/3779d242/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/saml/server.xml ---------------------------------------------------------------------- diff --git a/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/saml/server.xml b/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/saml/server.xml index 2c816e4..e2152e3 100644 --- a/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/saml/server.xml +++ b/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/saml/server.xml @@ -267,4 +267,13 @@ <entry key="security.validate.audience-restriction" value="false"/> </jaxws:properties> </jaxws:endpoint> + + <jaxws:endpoint xmlns:s="http://www.example.org/contract/DoubleIt" id="Saml2TransportToken4" address="https://localhost:${testutil.ports.saml.Server.2}/DoubleItSaml2Transport4" serviceName="s:DoubleItService" endpointName="s:DoubleItSaml2TransportPort4" implementor="org.apache.cxf.systest.ws.common.DoubleItPortTypeImpl" wsdlLocation="org/apache/cxf/systest/ws/saml/DoubleItSaml.wsdl" depends-on="tls-settings"> + <jaxws:properties> + <entry key="security.callback-handler" value="org.apache.cxf.systest.ws.common.KeystorePasswordCallback"/> + <entry key="security.signature.properties" value="bob.properties"/> + <entry key="security.subject.cert.constraints" value=".*O=apache.org.*"/> + <entry key="security.audience-restrictions" value="{http://www.example.org/contract/DoubleIt}DoubleItService,{http://www.example.org/contract/DoubleIt}DoubleItService.xyz"/> + </jaxws:properties> + </jaxws:endpoint> </beans> http://git-wip-us.apache.org/repos/asf/cxf/blob/3779d242/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/saml/stax-server.xml ---------------------------------------------------------------------- diff --git a/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/saml/stax-server.xml b/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/saml/stax-server.xml index 36c046c..cde7510 100644 --- a/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/saml/stax-server.xml +++ b/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/saml/stax-server.xml @@ -295,4 +295,14 @@ <entry key="security.validate.audience-restriction" value="false"/> </jaxws:properties> </jaxws:endpoint> + + <jaxws:endpoint xmlns:s="http://www.example.org/contract/DoubleIt" id="Saml2TransportToken4" address="https://localhost:${testutil.ports.saml.StaxServer.2}/DoubleItSaml2Transport4" serviceName="s:DoubleItService" endpointName="s:DoubleItSaml2TransportPort4" implementor="org.apache.cxf.systest.ws.common.DoubleItPortTypeImpl" wsdlLocation="org/apache/cxf/systest/ws/saml/DoubleItSaml.wsdl" depends-on="tls-settings"> + <jaxws:properties> + <entry key="security.callback-handler" value="org.apache.cxf.systest.ws.common.KeystorePasswordCallback"/> + <entry key="security.signature.properties" value="bob.properties"/> + <entry key="security.subject.cert.constraints" value=".*O=apache.org.*"/> + <entry key="ws-security.enable.streaming" value="true"/> + <entry key="security.audience-restrictions" value="{http://www.example.org/contract/DoubleIt}DoubleItService,{http://www.example.org/contract/DoubleIt}DoubleItService.xyz"/> + </jaxws:properties> + </jaxws:endpoint> </beans>
