Author: anil.saldhana(a)jboss.com
Date: 2011-07-12 20:52:18 -0400 (Tue, 12 Jul 2011)
New Revision: 1085
Added:
trust/trunk/jbossws/src/test/java/org/picketlink/test/trust/jbossws/handler/
trust/trunk/jbossws/src/test/java/org/picketlink/test/trust/jbossws/handler/SAML2HandlerUnitTestCase.java
trust/trunk/jbossws/src/test/resources/jbossws/xml/
trust/trunk/jbossws/src/test/resources/jbossws/xml/wsse-saml.xml
Modified:
trust/trunk/jbossws/src/main/java/org/picketlink/trust/jbossws/handler/SAML2Handler.java
trust/trunk/jbossws/src/main/java/org/picketlink/trust/jbossws/handler/SecurityActions.java
Log:
PLFED-171: add group principal to subject if roles
Modified:
trust/trunk/jbossws/src/main/java/org/picketlink/trust/jbossws/handler/SAML2Handler.java
===================================================================
---
trust/trunk/jbossws/src/main/java/org/picketlink/trust/jbossws/handler/SAML2Handler.java 2011-07-12
21:11:12 UTC (rev 1084)
+++
trust/trunk/jbossws/src/main/java/org/picketlink/trust/jbossws/handler/SAML2Handler.java 2011-07-13
00:52:18 UTC (rev 1085)
@@ -21,6 +21,10 @@
*/
package org.picketlink.trust.jbossws.handler;
+import java.security.acl.Group;
+import java.util.ArrayList;
+import java.util.List;
+
import javax.security.auth.Subject;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPMessage;
@@ -30,7 +34,11 @@
import org.jboss.security.SecurityContext;
import org.picketlink.identity.federation.bindings.jboss.subject.PicketLinkPrincipal;
import org.picketlink.identity.federation.core.saml.v2.constants.JBossSAMLURIConstants;
+import org.picketlink.identity.federation.core.saml.v2.util.AssertionUtil;
+import org.picketlink.identity.federation.core.util.StringUtil;
import org.picketlink.identity.federation.core.wstrust.SamlCredential;
+import org.picketlink.identity.federation.core.wstrust.plugins.saml.SAMLUtil;
+import org.picketlink.identity.federation.saml.v2.assertion.AssertionType;
import org.picketlink.trust.jbossws.SAML2Constants;
import org.picketlink.trust.jbossws.Util;
import org.w3c.dom.Document;
@@ -59,12 +67,26 @@
SOAPMessageContext ctx = (SOAPMessageContext) msgContext;
SOAPMessage soapMessage = ctx.getMessage();
+ if(soapMessage == null)
+ throw new IllegalStateException("SOAP Message is null");
+
// retrieve the assertion
Document document = soapMessage.getSOAPPart();
Element soapHeader = Util.findOrCreateSoapHeader(document.getDocumentElement());
Element assertion = Util.findElement(soapHeader, new QName(assertionNS,
"Assertion"));
if (assertion != null)
{
+ AssertionType assertionType = null;
+ try
+ {
+ assertionType = SAMLUtil.fromElement(assertion);
+ if(AssertionUtil.hasExpired(assertionType))
+ throw new RuntimeException("Assertion has expired");
+ }
+ catch(Exception e )
+ {
+ log.error("Exception in parsing the assertion:",e);
+ }
SamlCredential credential = new SamlCredential(assertion);
if (log.isTraceEnabled())
{
@@ -75,15 +97,41 @@
Element nameID = Util.findElement(subject, new QName(assertionNS,
"NameID"));
String username = getUsername(nameID);
// set SecurityContext
- Subject s = new Subject();
- SecurityContext sc = SecurityActions.createSecurityContext(new
PicketLinkPrincipal(username), credential, s);
+ Subject theSubject = new Subject();
+ SecurityContext sc = SecurityActions.createSecurityContext(new
PicketLinkPrincipal(username), credential, theSubject);
SecurityActions.setSecurityContext(sc);
+
+ if(assertionType != null )
+ {
+ List<String> roleKeys = new ArrayList<String>();
+ String roleKey =
SecurityActions.getSystemProperty("picketlink.rolekey", "Role");
+ if(StringUtil.isNotNull(roleKey))
+ {
+ roleKeys.addAll(StringUtil.tokenize(roleKey));
+ }
+
+ if(trace)
+ log.trace("Rolekeys to extract roles from the assertion:" +
roleKeys);
+
+ List<String> roles = AssertionUtil.getRoles(assertionType, roleKeys);
+ if(roles.size() > 0 )
+ {
+ if(trace)
+ log.trace("Roles in the assertion:" + roles);
+ Group roleGroup = SecurityActions.group(roles);
+ theSubject.getPrincipals().add(roleGroup);
+ }
+ else
+ {
+ if(trace)
+ log.trace("Did not find roles in the assertion");
+ }
+ }
}
else
{
log.warn("We did not find any assertion");
- }
-
+ }
return true;
}
Modified:
trust/trunk/jbossws/src/main/java/org/picketlink/trust/jbossws/handler/SecurityActions.java
===================================================================
---
trust/trunk/jbossws/src/main/java/org/picketlink/trust/jbossws/handler/SecurityActions.java 2011-07-12
21:11:12 UTC (rev 1084)
+++
trust/trunk/jbossws/src/main/java/org/picketlink/trust/jbossws/handler/SecurityActions.java 2011-07-13
00:52:18 UTC (rev 1085)
@@ -24,12 +24,17 @@
import java.security.AccessController;
import java.security.Principal;
import java.security.PrivilegedAction;
+import java.security.acl.Group;
+import java.util.List;
import javax.security.auth.Subject;
+import org.jboss.security.SecurityConstants;
import org.jboss.security.SecurityContext;
import org.jboss.security.SecurityContextAssociation;
import org.jboss.security.SecurityContextFactory;
+import org.jboss.security.SimplePrincipal;
+import org.picketlink.identity.federation.bindings.jboss.subject.PicketLinkGroup;
/**
* Privileged actions.
@@ -138,4 +143,25 @@
}
});
}
+
+ /**
+ * Given a {@link List} of role names, construct a group principal of type {@link
Group}
+ * @param roles
+ * @return
+ */
+ static Group group(final List<String> roles)
+ {
+ return AccessController.doPrivileged(new PrivilegedAction<Group>()
+ {
+ public Group run()
+ {
+ Group theGroup = new PicketLinkGroup(SecurityConstants.ROLES_IDENTIFIER);
+ for(String role: roles)
+ {
+ theGroup.addMember(new SimplePrincipal(role));
+ }
+ return theGroup;
+ }
+ });
+ }
}
\ No newline at end of file
Added:
trust/trunk/jbossws/src/test/java/org/picketlink/test/trust/jbossws/handler/SAML2HandlerUnitTestCase.java
===================================================================
---
trust/trunk/jbossws/src/test/java/org/picketlink/test/trust/jbossws/handler/SAML2HandlerUnitTestCase.java
(rev 0)
+++
trust/trunk/jbossws/src/test/java/org/picketlink/test/trust/jbossws/handler/SAML2HandlerUnitTestCase.java 2011-07-13
00:52:18 UTC (rev 1085)
@@ -0,0 +1,193 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.picketlink.test.trust.jbossws.handler;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.acl.Group;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import javax.security.auth.Subject;
+import javax.xml.bind.JAXBContext;
+import javax.xml.namespace.QName;
+import javax.xml.soap.SOAPException;
+import javax.xml.soap.SOAPMessage;
+import javax.xml.ws.handler.MessageContext;
+import javax.xml.ws.handler.soap.SOAPMessageContext;
+
+import org.jboss.security.SecurityContext;
+import org.jboss.security.SecurityContextAssociation;
+import org.jboss.security.SimplePrincipal;
+import org.junit.Test;
+import org.picketlink.identity.federation.core.util.SOAPUtil;
+import org.picketlink.trust.jbossws.handler.SAML2Handler;
+
+/**
+ * Unit test the {@link SAML2Handler}
+ * @author Anil.Saldhana(a)redhat.com
+ * @since Jul 12, 2011
+ */
+public class SAML2HandlerUnitTestCase
+{
+ @Test
+ public void testIn() throws Exception
+ {
+ DelegatingHandler handler = new DelegatingHandler();
+ SAML2HandlerUnitTestCaseMessageContext msgContext = new
SAML2HandlerUnitTestCaseMessageContext();
+ SOAPMessage soapMessage = get();
+
+ System.setProperty("picketlink.rolekey",
"Role,Roles,Membership");
+ msgContext.setMessage(soapMessage);
+ handler.handleInbound(msgContext);
+
+ SecurityContext securityContext = SecurityContextAssociation.getSecurityContext();
+ assertNotNull(securityContext);
+ assertEquals("admin", securityContext.getUtil().getUserName());
+ Subject subject = securityContext.getUtil().getSubject();
+ Set<Group> groups = subject.getPrincipals(Group.class);
+ assertEquals(1, groups.size());
+ Group grp = groups.iterator().next();
+ assertTrue(grp.isMember(new SimplePrincipal("meco")));
+ }
+
+ private SOAPMessage get() throws SOAPException, IOException
+ {
+ InputStream is =
Thread.currentThread().getContextClassLoader().getResourceAsStream("jbossws/xml/wsse-saml.xml");
+ SOAPMessage soapMessage = SOAPUtil.getSOAPMessage(is);
+ return soapMessage;
+ }
+
+ private static class DelegatingHandler extends SAML2Handler
+ {
+ @Override
+ protected boolean handleInbound(MessageContext msgContext)
+ {
+ return super.handleInbound(msgContext);
+ }
+ }
+
+ private static class SAML2HandlerUnitTestCaseMessageContext implements
SOAPMessageContext
+ {
+ private Map<String,Object> map = new HashMap<String, Object>();
+
+ private Map<String,Scope> scopes = new HashMap<String,
MessageContext.Scope>();
+
+ private SOAPMessage msg;
+
+ public int size()
+ {
+ return 0;
+ }
+
+ public boolean isEmpty()
+ {
+ return false;
+ }
+
+ public boolean containsKey(Object key)
+ {
+ return map.containsKey(key);
+ }
+
+ public boolean containsValue(Object value)
+ {
+ return map.containsValue(value);
+ }
+
+ public Object get(Object key)
+ {
+ return map.get(key);
+ }
+
+ public Object put(String key, Object value)
+ {
+ return map.put(key, value);
+ }
+
+ public Object remove(Object key)
+ {
+ return map.remove(key);
+ }
+
+ public void putAll(Map<? extends String, ? extends Object> m)
+ {
+ map.putAll(m);
+ }
+
+ public void clear()
+ {
+ map.clear();
+ }
+
+ public Set<String> keySet()
+ {
+ return map.keySet();
+ }
+
+ public Collection<Object> values()
+ {
+ return map.values();
+ }
+
+ public Set<java.util.Map.Entry<String, Object>> entrySet()
+ {
+ return map.entrySet();
+ }
+
+ public Scope getScope(String arg0)
+ {
+ return scopes.get(arg0);
+ }
+
+ public void setScope(String arg0, Scope arg1)
+ {
+ scopes.put(arg0, arg1);
+ }
+
+ public Object[] getHeaders(QName arg0, JAXBContext arg1, boolean arg2)
+ {
+ throw new RuntimeException("NYI");
+ }
+
+ public SOAPMessage getMessage()
+ {
+ return msg;
+ }
+
+ public Set<String> getRoles()
+ {
+ throw new RuntimeException("NYI");
+ }
+
+ public void setMessage(SOAPMessage arg0)
+ {
+ msg =arg0;
+ }
+ }
+}
\ No newline at end of file
Added: trust/trunk/jbossws/src/test/resources/jbossws/xml/wsse-saml.xml
===================================================================
--- trust/trunk/jbossws/src/test/resources/jbossws/xml/wsse-saml.xml
(rev 0)
+++ trust/trunk/jbossws/src/test/resources/jbossws/xml/wsse-saml.xml 2011-07-13 00:52:18
UTC (rev 1085)
@@ -0,0 +1,58 @@
+<env:Envelope
xmlns:env='http://schemas.xmlsoap.org/soap/envelope/'>
+ " +
+ <env:Header>
+ <wsse:Security
+
xmlns:wsse='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-w...
+ <saml:Assertion xmlns:saml='urn:oasis:names:tc:SAML:2.0:assertion'
+ xmlns='urn:oasis:names:tc:SAML:2.0:assertion'
ID='ID_7069926b-792e-4f90-8727-0e16ec9c3073'
+ IssueInstant='2011-07-13T00:16:13.990Z' Version='2.0'>
+ <Issuer
xmlns:saml='urn:oasis:names:tc:SAML:2.0:assertion'>PicketLinkSTS</Issuer>
+ <saml:Subject>
+ <saml:NameID NameQualifier='urn:picketlink:identity-federation'
+ xmlns:saml='urn:oasis:names:tc:SAML:2.0:assertion'>admin</saml:NameID>
+ <saml:SubjectConfirmation Method='urn:oasis:names:tc:SAML:2.0:cm:bearer'
/>
+ </saml:Subject>
+ <saml:Conditions NotBefore='2011-07-13T00:16:13.990Z'
+ NotOnOrAfter='2030-07-13T02:16:13.990Z'>
+ <saml:AudienceRestriction>
+ <
saml:Audience>http://services.testcorp.org/provider1
+ </saml:Audience>
+ </saml:AudienceRestriction>
+ </saml:Conditions>
+ <saml:AuthnStatement AuthnInstant="2011-06-06T21:30:07Z"
+ xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
+ <saml:AuthnContext
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
+ <saml:AuthnContextClassRef
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">urn:oasis:names:tc:SAML:2.0:ac:classes:Password
+ </saml:AuthnContextClassRef>
+ </saml:AuthnContext>
+ </saml:AuthnStatement>
+ <saml:AttributeStatement
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
+ <saml:Attribute Name="FGADataset"
+ NameFormat="urn:oasis:names:tc:SAML:2.0:assertion"
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
+ <saml:AttributeValue
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:type="xs:string">1234
+ </saml:AttributeValue>
+ <saml:AttributeValue
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:type="xs:string">4768
+ </saml:AttributeValue>
+ </saml:Attribute>
+ <saml:Attribute Name="Roles"
+ NameFormat="urn:oasis:names:tc:SAML:2.0:profiles:attribute:DCE:groups">
+ <saml:AttributeValue
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:type="xs:string">meco</saml:AttributeValue>
+ <saml:AttributeValue
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:type="xs:string">aispoc_grp1</saml:AttributeValue>
+ <saml:AttributeValue
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:type="xs:string">grp-poc</saml:AttributeValue>
+ </saml:Attribute>
+ <saml:Attribute Name="Membership"
+ NameFormat="urn:oasis:names:tc:SAML:2.0:profiles:attribute:DCE:groups">
+ <saml:AttributeValue
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:type="xs:string">meco</saml:AttributeValue>
+ </saml:Attribute>
+ </saml:AttributeStatement>
+ </saml:Assertion>
+ </wsse:Security>
+ </env:Header>
+ <env:Body />
+</env:Envelope>
\ No newline at end of file