You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by co...@apache.org on 2016/02/16 14:54:39 UTC

[3/3] cxf git commit: Adding a custom WSS4JSecurityContextCreator for an STS system test

Adding a custom WSS4JSecurityContextCreator for an STS system test


Project: http://git-wip-us.apache.org/repos/asf/cxf/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/d68286f7
Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/d68286f7
Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/d68286f7

Branch: refs/heads/master
Commit: d68286f715ef4a545989a04d31313a64078cf0cb
Parents: 864d3f3
Author: Colm O hEigeartaigh <co...@apache.org>
Authored: Tue Feb 16 13:48:18 2016 +0000
Committer: Colm O hEigeartaigh <co...@apache.org>
Committed: Tue Feb 16 13:48:18 2016 +0000

----------------------------------------------------------------------
 ...tUsernameTokenAuthenticatingInterceptor.java |  15 +++
 .../DefaultWSS4JSecurityContextCreator.java     |  13 --
 .../ws/security/wss4j/WSS4JInInterceptor.java   |  11 ++
 .../x509/CustomWSS4JSecurityContextCreator.java | 118 +++++++++++++++++++
 .../systest/sts/x509/cxf-asymmetric-service.xml |   4 +
 5 files changed, 148 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf/blob/d68286f7/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractUsernameTokenAuthenticatingInterceptor.java
----------------------------------------------------------------------
diff --git a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractUsernameTokenAuthenticatingInterceptor.java b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractUsernameTokenAuthenticatingInterceptor.java
index 3b3fa01..0d8d415 100644
--- a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractUsernameTokenAuthenticatingInterceptor.java
+++ b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractUsernameTokenAuthenticatingInterceptor.java
@@ -20,6 +20,8 @@ package org.apache.cxf.ws.security.wss4j;
 
 import java.security.Principal;
 import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
 import java.util.Map;
 import java.util.logging.Logger;
 
@@ -34,6 +36,7 @@ import org.apache.cxf.binding.soap.SoapMessage;
 import org.apache.cxf.common.logging.LogUtils;
 import org.apache.cxf.common.security.SecurityToken;
 import org.apache.cxf.common.security.UsernameToken;
+import org.apache.cxf.helpers.CastUtils;
 import org.apache.cxf.interceptor.Fault;
 import org.apache.cxf.interceptor.security.DefaultSecurityContext;
 import org.apache.cxf.message.Message;
@@ -43,6 +46,7 @@ import org.apache.wss4j.common.ext.WSSecurityException;
 import org.apache.wss4j.dom.WSConstants;
 import org.apache.wss4j.dom.engine.WSSecurityEngine;
 import org.apache.wss4j.dom.handler.RequestData;
+import org.apache.wss4j.dom.handler.WSHandlerConstants;
 import org.apache.wss4j.dom.handler.WSHandlerResult;
 import org.apache.wss4j.dom.validate.UsernameTokenValidator;
 import org.apache.wss4j.dom.validate.Validator;
@@ -115,6 +119,17 @@ public abstract class AbstractUsernameTokenAuthenticatingInterceptor extends WSS
                              WSHandlerResult wsResult, 
                              boolean utWithCallbacks
     ) throws SOAPException, XMLStreamException, WSSecurityException {
+        /*
+         * All ok up to this point. Now construct and setup the security result
+         * structure. The service may fetch this and check it.
+         */
+        List<WSHandlerResult> results = CastUtils.cast((List<?>)msg.get(WSHandlerConstants.RECV_RESULTS));
+        if (results == null) {
+            results = new LinkedList<>();
+            msg.put(WSHandlerConstants.RECV_RESULTS, results);
+        }
+        results.add(0, wsResult);
+        
         new UsernameTokenSecurityContextCreator().createSecurityContext(msg, wsResult);
     }
     

http://git-wip-us.apache.org/repos/asf/cxf/blob/d68286f7/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/DefaultWSS4JSecurityContextCreator.java
----------------------------------------------------------------------
diff --git a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/DefaultWSS4JSecurityContextCreator.java b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/DefaultWSS4JSecurityContextCreator.java
index 8069a95..5a832ef 100644
--- a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/DefaultWSS4JSecurityContextCreator.java
+++ b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/DefaultWSS4JSecurityContextCreator.java
@@ -22,7 +22,6 @@ import java.security.Principal;
 import java.security.PublicKey;
 import java.security.cert.X509Certificate;
 import java.util.ArrayList;
-import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -31,7 +30,6 @@ import javax.security.auth.Subject;
 import javax.security.auth.kerberos.KerberosPrincipal;
 
 import org.apache.cxf.binding.soap.SoapMessage;
-import org.apache.cxf.helpers.CastUtils;
 import org.apache.cxf.interceptor.security.DefaultSecurityContext;
 import org.apache.cxf.interceptor.security.RolePrefixSecurityContextImpl;
 import org.apache.cxf.message.MessageUtils;
@@ -44,7 +42,6 @@ import org.apache.cxf.ws.security.SecurityConstants;
 import org.apache.wss4j.common.saml.SamlAssertionWrapper;
 import org.apache.wss4j.dom.WSConstants;
 import org.apache.wss4j.dom.engine.WSSecurityEngineResult;
-import org.apache.wss4j.dom.handler.WSHandlerConstants;
 import org.apache.wss4j.dom.handler.WSHandlerResult;
 import org.apache.wss4j.dom.message.token.KerberosSecurity;
 
@@ -69,16 +66,6 @@ public class DefaultWSS4JSecurityContextCreator implements WSS4JSecurityContextC
      * Create a SecurityContext and store it on the SoapMessage parameter
      */
     public void createSecurityContext(SoapMessage msg, WSHandlerResult handlerResult) {
-        /*
-         * All ok up to this point. Now construct and setup the security result
-         * structure. The service may fetch this and check it.
-         */
-        List<WSHandlerResult> results = CastUtils.cast((List<?>)msg.get(WSHandlerConstants.RECV_RESULTS));
-        if (results == null) {
-            results = new LinkedList<>();
-            msg.put(WSHandlerConstants.RECV_RESULTS, results);
-        }
-        results.add(0, handlerResult);
         
         String allowUnsigned = 
             (String)SecurityUtils.getSecurityPropertyValue(

http://git-wip-us.apache.org/repos/asf/cxf/blob/d68286f7/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 d996711..1a0a758 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
@@ -22,6 +22,7 @@ import java.security.Provider;
 import java.security.cert.Certificate;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.logging.Level;
@@ -472,6 +473,16 @@ public class WSS4JInInterceptor extends AbstractWSS4JInterceptor {
         WSHandlerResult wsResult,
         boolean utWithCallbacks
     ) throws SOAPException, XMLStreamException, WSSecurityException {
+        /*
+         * All ok up to this point. Now construct and setup the security result
+         * structure. The service may fetch this and check it.
+         */
+        List<WSHandlerResult> results = CastUtils.cast((List<?>)msg.get(WSHandlerConstants.RECV_RESULTS));
+        if (results == null) {
+            results = new LinkedList<>();
+            msg.put(WSHandlerConstants.RECV_RESULTS, results);
+        }
+        results.add(0, wsResult);
         
         WSS4JSecurityContextCreator contextCreator = 
             (WSS4JSecurityContextCreator)SecurityUtils.getSecurityPropertyValue(

http://git-wip-us.apache.org/repos/asf/cxf/blob/d68286f7/services/sts/systests/basic/src/test/java/org/apache/cxf/systest/sts/x509/CustomWSS4JSecurityContextCreator.java
----------------------------------------------------------------------
diff --git a/services/sts/systests/basic/src/test/java/org/apache/cxf/systest/sts/x509/CustomWSS4JSecurityContextCreator.java b/services/sts/systests/basic/src/test/java/org/apache/cxf/systest/sts/x509/CustomWSS4JSecurityContextCreator.java
new file mode 100644
index 0000000..31ec71b
--- /dev/null
+++ b/services/sts/systests/basic/src/test/java/org/apache/cxf/systest/sts/x509/CustomWSS4JSecurityContextCreator.java
@@ -0,0 +1,118 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.systest.sts.x509;
+
+import java.security.Principal;
+import java.security.PublicKey;
+import java.security.cert.X509Certificate;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.cxf.binding.soap.SoapMessage;
+import org.apache.cxf.rt.security.claims.ClaimCollection;
+import org.apache.cxf.rt.security.saml.claims.SAMLSecurityContext;
+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.ws.security.SecurityConstants;
+import org.apache.cxf.ws.security.wss4j.DefaultWSS4JSecurityContextCreator;
+import org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor;
+import org.apache.wss4j.common.saml.SamlAssertionWrapper;
+import org.apache.wss4j.dom.WSConstants;
+import org.apache.wss4j.dom.engine.WSSecurityEngineResult;
+import org.apache.wss4j.dom.handler.WSHandlerResult;
+
+/**
+ * A custom WSS4JSecurityContextCreator implementation. It creates a SecurityContext using the principal from an
+ * asymmetric signature, but populates the roles from a SAML Token.
+ */
+public class CustomWSS4JSecurityContextCreator extends DefaultWSS4JSecurityContextCreator {
+    
+    /**
+     * Create a SecurityContext and store it on the SoapMessage parameter
+     */
+    public void createSecurityContext(SoapMessage msg, WSHandlerResult handlerResult) {
+        Map<Integer, List<WSSecurityEngineResult>> actionResults = handlerResult.getActionResults();
+        
+        Principal asymmetricPrincipal = null;
+        
+        // Get Asymmetric Signature action
+        List<WSSecurityEngineResult> foundResults = actionResults.get(WSConstants.SIGN);
+        if (foundResults != null && !foundResults.isEmpty()) {
+            for (WSSecurityEngineResult result : foundResults) {
+                PublicKey publickey = 
+                    (PublicKey)result.get(WSSecurityEngineResult.TAG_PUBLIC_KEY);
+                X509Certificate cert = 
+                    (X509Certificate)result.get(WSSecurityEngineResult.TAG_X509_CERTIFICATE);
+                
+                if (publickey == null && cert == null) {
+                    continue;
+                }
+                SecurityContext context = createSecurityContext(msg, true, result);
+                if (context != null && context.getUserPrincipal() != null) {
+                    asymmetricPrincipal = context.getUserPrincipal();
+                    break;
+                }
+            }
+        }
+        
+        // We must have an asymmetric principal
+        if (asymmetricPrincipal == null) {
+            return;
+        }
+        
+        // Get signed SAML action
+        SAMLSecurityContext context = null;
+        foundResults = actionResults.get(WSConstants.ST_SIGNED);
+        if (foundResults != null && !foundResults.isEmpty()) {
+            for (WSSecurityEngineResult result : foundResults) {
+                Object receivedAssertion = result.get(WSSecurityEngineResult.TAG_TRANSFORMED_TOKEN);
+                if (receivedAssertion == null) {
+                    receivedAssertion = result.get(WSSecurityEngineResult.TAG_SAML_ASSERTION);
+                }
+
+                if (receivedAssertion instanceof SamlAssertionWrapper) {
+                    String roleAttributeName = 
+                        (String)SecurityUtils.getSecurityPropertyValue(SecurityConstants.SAML_ROLE_ATTRIBUTENAME, 
+                                                                       msg);
+                    if (roleAttributeName == null || roleAttributeName.length() == 0) {
+                        roleAttributeName = WSS4JInInterceptor.SAML_ROLE_ATTRIBUTENAME_DEFAULT;
+                    }
+
+                    ClaimCollection claims = 
+                        SAMLUtils.getClaims((SamlAssertionWrapper)receivedAssertion);
+                    Set<Principal> roles = 
+                        SAMLUtils.parseRolesFromClaims(claims, roleAttributeName, null);
+
+                    context = new SAMLSecurityContext(asymmetricPrincipal, roles, claims);
+                    context.setIssuer(SAMLUtils.getIssuer(receivedAssertion));
+                    context.setAssertionElement(SAMLUtils.getAssertionElement(receivedAssertion));
+                    break;
+                }
+            }
+        }
+        
+        if (context != null) {
+            msg.put(SecurityContext.class, context);
+        }
+        
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/d68286f7/services/sts/systests/basic/src/test/resources/org/apache/cxf/systest/sts/x509/cxf-asymmetric-service.xml
----------------------------------------------------------------------
diff --git a/services/sts/systests/basic/src/test/resources/org/apache/cxf/systest/sts/x509/cxf-asymmetric-service.xml b/services/sts/systests/basic/src/test/resources/org/apache/cxf/systest/sts/x509/cxf-asymmetric-service.xml
index 02d3158..4402a09 100644
--- a/services/sts/systests/basic/src/test/resources/org/apache/cxf/systest/sts/x509/cxf-asymmetric-service.xml
+++ b/services/sts/systests/basic/src/test/resources/org/apache/cxf/systest/sts/x509/cxf-asymmetric-service.xml
@@ -35,12 +35,16 @@
        </property>
     </bean>
     
+    <bean id="customSecurityContextCreator" 
+          class="org.apache.cxf.systest.sts.x509.CustomWSS4JSecurityContextCreator" />
+    
     <jaxws:endpoint xmlns:s="http://www.example.org/contract/DoubleIt" id="doubleitasymmetricsaml2" implementor="org.apache.cxf.systest.sts.common.DoubleItPortTypeImpl" endpointName="s:DoubleItAsymmetricSAML2Port" serviceName="s:DoubleItService" address="http://localhost:${testutil.ports.AsymmetricServer}/doubleit/services/doubleitasymmetricsaml2" wsdlLocation="org/apache/cxf/systest/sts/x509/DoubleItAsymmetric.wsdl">
         <jaxws:properties>
             <entry key="security.signature.username" value="myservicekey"/>
             <entry key="security.callback-handler" value="org.apache.cxf.systest.sts.common.CommonCallbackHandler"/>
             <entry key="security.signature.properties" value="serviceKeystore2.properties"/>
             <entry key="security.encryption.username" value="useReqSigCert"/>
+            <entry key="ws-security.security.context.creator" value-ref="customSecurityContextCreator"/>
         </jaxws:properties>
         <jaxws:inInterceptors>
              <ref bean="authorizationInterceptor"/>