package org.jboss.resteasy.skeleton.key.as7;
import org.apache.catalina.Realm;
import org.apache.catalina.realm.GenericPrincipal;
import org.jboss.as.web.security.JBossGenericPrincipal;
import org.jboss.security.NestableGroup;
import org.jboss.security.SecurityConstants;
import org.jboss.security.SecurityContext;
import org.jboss.security.SecurityContextAssociation;
import org.jboss.security.SimpleGroup;
import org.jboss.security.SimplePrincipal;
import javax.security.auth.Subject;
import java.security.Principal;
import java.security.acl.Group;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class CatalinaSecurityContextHelper
{
public GenericPrincipal createPrincipal(Realm realm, Principal identity, Collection<String> roleSet)
{
Subject subject = new Subject();
String credentials = "";
Set<Principal> principals = subject.getPrincipals();
principals.add(identity);
Group[] roleSets = getRoleSets(roleSet);
for(int g = 0; g < roleSets.length; g ++)
{
Group group = roleSets[g];
String name = group.getName();
Group subjectGroup = createGroup(name, principals);
if( subjectGroup instanceof NestableGroup)
{
/* A NestableGroup only allows Groups to be added to it so we
need to add a SimpleGroup to subjectRoles to contain the roles
*/
SimpleGroup tmp = new SimpleGroup("Roles");
subjectGroup.addMember(tmp);
subjectGroup = tmp;
}
// Copy the group members to the Subject group
Enumeration<? extends Principal> members = group.members();
while( members.hasMoreElements() )
{
Principal role = (Principal) members.nextElement();
subjectGroup.addMember(role);
}
}
// add the CallerPrincipal group if none has been added in getRoleSets
Group callerGroup = new SimpleGroup(SecurityConstants.CALLER_PRINCIPAL_GROUP);
callerGroup.addMember(identity);
principals.add(callerGroup);
SecurityContext sc = SecurityContextAssociation.getSecurityContext();
Principal userPrincipal = getPrincipal(subject);
sc.getUtil().createSubjectInfo(userPrincipal, credentials, subject);
List<String> rolesAsStringList = new ArrayList<String>();
rolesAsStringList.addAll(roleSet);
return new JBossGenericPrincipal(realm, userPrincipal.getName(), null, rolesAsStringList,
userPrincipal, null, credentials, null, subject);
}
/**
* Get the Principal given the authenticated Subject. Currently the first principal that is not of type {@code Group} is
* considered or the single principal inside the CallerPrincipal group.
*
* @param subject
* @return the authenticated principal
*/
protected Principal getPrincipal(Subject subject) {
Principal principal = null;
Principal callerPrincipal = null;
if (subject != null) {
Set<Principal> principals = subject.getPrincipals();
if (principals != null && !principals.isEmpty()) {
for (Principal p : principals) {
if (!(p instanceof Group) && principal == null) {
principal = p;
}
if (p instanceof Group) {
Group g = Group.class.cast(p);
if (g.getName().equals(SecurityConstants.CALLER_PRINCIPAL_GROUP) && callerPrincipal == null) {
Enumeration<? extends Principal> e = g.members();
if (e.hasMoreElements())
callerPrincipal = e.nextElement();
}
}
}
}
}
return callerPrincipal == null ? principal : callerPrincipal;
}
protected Group createGroup(String name, Set<Principal> principals)
{
Group roles = null;
Iterator<Principal> iter = principals.iterator();
while( iter.hasNext() )
{
Object next = iter.next();
if( (next instanceof Group) == false )
continue;
Group grp = (Group) next;
if( grp.getName().equals(name) )
{
roles = grp;
break;
}
}
// If we did not find a group create one
if( roles == null )
{
roles = new SimpleGroup(name);
principals.add(roles);
}
return roles;
}
protected Group[] getRoleSets(Collection<String> roleSet)
{
SimpleGroup roles = new SimpleGroup("Roles");
Group[] roleSets = {roles};
for (String role : roleSet)
{
roles.addMember(new SimplePrincipal(role));
}
return roleSets;
}
}