FileDocCategorySizeDatePackage
RoleMapper.javaAPI DocGlassfish v2 API26994Fri May 04 22:35:24 BST 2007com.sun.enterprise.security.acl

RoleMapper

public class RoleMapper extends Object implements Serializable, com.sun.enterprise.deployment.interfaces.SecurityRoleMapper
This Object maintains a mapping of users and groups to application specific Roles. Using this object this mapping information could be maintained and queried at a later time. This is a complete rewrite of the previous RoleMapper for JACC related changes.
author
Harpreet Singh

Fields Summary
private static Map
ROLEMAPPER
private static final String
DEFAULT_ROLE_NAME
private static com.sun.enterprise.deployment.Role
defaultRole
private static String
defaultRoleName
private String
appName
private final Map
roleToSubject
private String
defaultP2RMappingClassName
private DefaultRoleToSubjectMapping
defaultRTSM
private final Map
roleToPrincipal
private final Map
roleToGroup
private Mapping
currentMapping
private Set
topLevelRoles
private static final String
TOP_LEVEL
private boolean
conflictLogged
private Set
conflictedRoles
private static Logger
_logger
Constructors Summary
private RoleMapper(String appName)

    
       
        this.appName = appName;
        Switch sw = Switch.getSwitch();
        if (sw.getContainerType() == Switch.EJBWEB_CONTAINER) { // 4735725
            initDefaultRole();
        }
        defaultP2RMappingClassName = getDefaultP2RMappingClassName();
    
public RoleMapper(RoleMapper r)
Copy constructor. This is called from the JSR88 implementation. This is not stored into the internal rolemapper maps.

        this.appName = r.getName();
        for(Iterator it = r.getRoles();it.hasNext(); ){
            String role = (String) it.next();
            // recover groups
            Enumeration groups = r.getGroupsAssignedTo(new Role(role));
            Set<Group> groupsToRole = new HashSet<Group>();
            for(;groups.hasMoreElements(); ){
                Group gp = (Group) groups.nextElement();
                groupsToRole.add(new Group(gp.getName()));
                addRoleToPrincipal(gp,role);
            }
            this.roleToGroup.put(role,groupsToRole);
            
            // recover principles
            Enumeration users = r.getUsersAssignedTo(new Role(role));
            Set<Principal> usersToRole = new HashSet<Principal>();
            for(;users.hasMoreElements(); ){
                PrincipalImpl gp = (PrincipalImpl) users.nextElement();
                usersToRole.add(new PrincipalImpl(gp.getName()));
                addRoleToPrincipal(gp,role);
            }
            this.roleToPrincipal.put(role,usersToRole);
        }
    
Methods Summary
private voidaddRoleToPrincipal(java.security.Principal principal, java.lang.String role)

param
principal A principal that corresponds to the role
param
role A role corresponding to this principal

        assert roleToSubject != null;
        Subject subject = roleToSubject.get(role);
        final Subject sub = (subject == null)?new Subject(): subject;
        AppservAccessController.doPrivileged(new PrivilegedAction() {
            public java.lang.Object run() {
                sub.getPrincipals().add(principal);
                return null;
            }
        });
        roleToSubject.put(role, sub);
    
public voidassignRole(java.security.Principal p, com.sun.enterprise.deployment.Role r, com.sun.enterprise.deployment.RootDeploymentDescriptor rdd)
Assigns a Principal to the specified role. This method delegates work to internalAssignRole() after checking for conflicts. RootDeploymentDescriptor added as a fix for: https://glassfish.dev.java.net/issues/show_bug.cgi?id=2475 The first time this is called, a new Mapping object is created to store the role mapping information. When called again from a different module, the old mapping information is checked and stored and a new Mapping object is created.

param
p The principal that needs to be assigned to the role.
param
r The Role the principal is being assigned to.
param
rdd The descriptor of the module containing the role mapping

        assert rdd != null;
        String callingModuleID = getModuleID(rdd);
        
        if (currentMapping == null) {
            currentMapping = new Mapping(callingModuleID);
        } else if (!callingModuleID.equals(currentMapping.owner)) {
            checkAndAddMappings();
            currentMapping = new Mapping(callingModuleID);
        }

        // when using the top level mapping
        if (callingModuleID.equals(TOP_LEVEL) &&
            topLevelRoles == null) {
            topLevelRoles = new HashSet<Role>();
        }
        
        // store principal and role temporarily until stopMappingFor called
        currentMapping.addMapping(p, r);
    
private voidcheckAndAddMappings()

        if (currentMapping == null) {
            return;
        }

        for (Role r : currentMapping.getRoles()) {
            
            if (topLevelRoles != null && topLevelRoles.contains(r)) {
                logConflictWarning();
                if (_logger.isLoggable(Level.FINE)) {
                    _logger.log(Level.FINE, "Role " + r +
                        " from module " + currentMapping.owner +
                        " is being overridden by top-level mapping.");
                }
                continue;
            }
            
            if (currentMapping.owner.equals(TOP_LEVEL)) {
                topLevelRoles.add(r);
                if (roleToSubject.keySet().contains(r.getName())) {
                    logConflictWarning();
                    if (_logger.isLoggable(Level.FINE)) {
                        _logger.log(Level.FINE, "Role " + r +
                            " from top-level mapping descriptor is " +
                            "overriding existing role in sub module.");
                    }
                    unassignRole(r);
                }
            } else if (roleConflicts(r, currentMapping.getPrincipals(r))) {
                // detail message already logged
                logConflictWarning();
                unassignRole(r);
                continue;
            }
            
            // no problems, so assign role
            for (Principal p : currentMapping.getPrincipals(r)) {
                internalAssignRole(p, r);
            }
        }
        
        // clear current mapping
        currentMapping = null;
    
private static java.lang.StringgetDefaultP2RMappingClassName()

returns
the class name used for default Principal to role mapping return null if default P2R mapping is not supported.

        String className=null;
        try {
            ServerContext serverContext = ApplicationServer.getServerContext();
            if (serverContext != null) {
                ConfigContext configContext = serverContext.getConfigContext();
                if (configContext != null) {
                    SecurityService securityService =
                        ServerBeansFactory.getSecurityServiceBean(configContext);
                    if (securityService != null && 
                        securityService.isActivateDefaultPrincipalToRoleMapping()==true) {
                        className = securityService.getMappedPrincipalClass();
                        if (className==null || "".equals(className))
			    className = "com.sun.enterprise.deployment.Group";
                    }
                }
            }
            if (className==null)
                return null;
            Class clazz = Class.forName(className);
            Class[] argClasses = new Class[]  { String.class };
            Object[] arg       = new Object[] { "anystring" };
            Constructor c = clazz.getConstructor(argClasses); 
            Principal principal = (Principal) c.newInstance(arg);
                  //verify that this class is a Principal class and has a constructor(string)
            return className;
        } catch (Exception e) {
            _logger.log(Level.SEVERE,"pc.getDefaultP2RMappingClass: " + e);
            return null;
        }
    
public java.util.EnumerationgetGroupsAssignedTo(com.sun.enterprise.deployment.Role r)
Returns an enumeration of Groups assigned to the given role

param
The Role to which the groups are assigned to.

        assert roleToGroup != null;
        Set<Group> s = roleToGroup.get(r.getName());
        if (s == null) {
            return Collections.enumeration(Collections.EMPTY_SET);
        }
        return Collections.enumeration(s);
    
private java.lang.StringgetModuleID(com.sun.enterprise.deployment.RootDeploymentDescriptor rdd)

        if (rdd instanceof Application) {
            return TOP_LEVEL;
        } else if (rdd instanceof BundleDescriptor) {
            return
                ((BundleDescriptor) rdd).getModuleDescriptor().getArchiveUri();
        } else {
            // cannot happen unless glassfish code is changed
            throw new AssertionError(rdd.getClass() +
                " is not a known descriptor type");
        }
    
public java.lang.StringgetName()

return
The application/module name for this RoleMapper

        return appName;
    
public static com.sun.enterprise.security.acl.RoleMappergetRoleMapper(java.lang.String appName)
Returns a RoleMapper corresponding to the AppName.

param
appName Application Name of this RoleMapper.
return
SecurityRoleMapper for the application

        RoleMapper r = (RoleMapper)ROLEMAPPER.get(appName);
        if(r == null){
            r = new RoleMapper(appName);
            synchronized(RoleMapper.class){
                ROLEMAPPER.put(appName,r);
            }
        }
        return r;
    
public java.util.MapgetRoleToSubjectMapping()
Returns the RoleToSubjectMapping for the RoleMapping

return
Map of role->subject mapping

        // this causes the last currentMapping information to be added
        checkAndAddMappings();
        assert roleToSubject != null;
        if (roleToSubject.isEmpty() && isDefaultRTSMActivated()) {
            return defaultRTSM;
        }
        return roleToSubject;
    
public java.util.IteratorgetRoles()
Returns an enumeration of roles for this rolemapper.

        assert roleToSubject != null;
        return roleToSubject.keySet().iterator(); // All the roles
    
public java.util.EnumerationgetUsersAssignedTo(com.sun.enterprise.deployment.Role r)
Returns an enumeration of Principals assigned to the given role

param
The Role to which the principals are assigned to.

        
        assert roleToPrincipal != null;
        Set<Principal> s = roleToPrincipal.get(r.getName());
        if (s == null) {
            return Collections.enumeration(Collections.EMPTY_SET);
        }
        return Collections.enumeration(s);
    
private static synchronized voidinitDefaultRole()

        
        if(defaultRole == null) {
            
            defaultRoleName = DEFAULT_ROLE_NAME;
            
            try {
                ConfigContext configContext =
                ApplicationServer.getServerContext().getConfigContext();
                assert(configContext != null);
                
                Server configBean =
                ServerBeansFactory.getServerBean(configContext);
                assert(configBean != null);
                
                SecurityService securityBean =
                ServerBeansFactory.getSecurityServiceBean(configContext);
                assert(securityBean != null);
                
                defaultRoleName = securityBean.getAnonymousRole();
                
            } catch (Exception e) {
                _logger.log(Level.WARNING,
                "java_security.anonymous_role_reading_exception",
                e);
            }
            
            if(_logger.isLoggable(Level.FINE)){
                _logger.log(Level.FINE, "Default role is: " +  defaultRoleName);
            }
            defaultRole = new Role(defaultRoleName);
        }
    
private voidinternalAssignRole(java.security.Principal p, com.sun.enterprise.deployment.Role r)

        String role = r.getName();
        if(_logger.isLoggable(Level.FINE)){
            _logger.log(Level.FINE, "SECURITY:RoleMapper Assigning Role "+ role +
                " to  "+ p.getName());
        }
        addRoleToPrincipal(p, role);
        if (p instanceof Group) {
            Set<Group> groups = roleToGroup.get(role) ;
            if(groups == null) {
                groups = new HashSet<Group>();
            }
            groups.add((Group) p);
            roleToGroup.put(role, groups);
        } else {
            Set<Principal> principals = roleToPrincipal.get(role) ;
            if(principals == null) {
                principals = new HashSet<Principal>();
            }
            principals.add(p);
            roleToPrincipal.put(role, principals);
        }
    
booleanisDefaultRTSMActivated()

	return (defaultP2RMappingClassName!=null);
    
private voidlogConflictWarning()

        if (!conflictLogged) {
            _logger.log(Level.WARNING, "java_security.role_mapping_conflict",
                getName());
            conflictLogged = true;
        }
    
public static voidremoveRoleMapper(java.lang.String appName)

param
appName Application/module name.

        
        if( ROLEMAPPER.containsKey(appName)){
            synchronized(RoleMapper.class){
                ROLEMAPPER.remove(appName);
            }
        }
    
private booleanroleConflicts(com.sun.enterprise.deployment.Role r, java.util.Set ps)

        
        // check to see if there has been a previous conflict
        if (conflictedRoles != null && conflictedRoles.contains(r)) {
            if (_logger.isLoggable(Level.FINE)) {
                _logger.log(Level.FINE,
                    "Role " + r + " from module " + currentMapping.owner +
                    " has already had a conflict with other modules.");
            }
            return true;
        }
        
        // if role not previously mapped, no conflict
        if (!roleToSubject.keySet().contains(r.getName())) {
            return false;
        }
        
        // check number of mappings first
        int targetNumPrin = ps.size();
        int actualNum = 0;
        Set<Principal> pSet = roleToPrincipal.get(r.getName());
        Set<Group> gSet = roleToGroup.get(r.getName());
        actualNum += (pSet == null) ? 0 : pSet.size();
        actualNum += (gSet == null) ? 0 : gSet.size();
        if (targetNumPrin != actualNum) {
            if (_logger.isLoggable(Level.FINE)) {
                _logger.log(Level.FINE,
                    "Module " + currentMapping.owner +
                    " has different number of mappings for role " +
                    r.getName() +
                    " than other mapping files");
            }
            if (conflictedRoles == null) {
                conflictedRoles = new HashSet<Role>();
            }
            conflictedRoles.add(r);
            return true;
        }
        
        // check the principals and groups
        boolean fail = false;
        for (Principal p : ps) {
            if (p instanceof Group) {
                if (gSet != null && !gSet.contains((Group) p)) {
                    fail = true;
                }
            } else if (pSet != null && !pSet.contains(p)) {
                fail = true;
            }
            if (fail) {
                if (_logger.isLoggable(Level.FINE)) {
                    _logger.log(Level.FINE,
                        "Role " + r + " in module " + currentMapping.owner +
                        " is not included in other modules.");
                }
                if (conflictedRoles == null) {
                    conflictedRoles = new HashSet<Role>();
                }
                conflictedRoles.add(r);
                return true;
            }
        }
        
        // no conflicts
        return false;
    
public voidsetName(java.lang.String name)

param
name The application/module name

        
        this.appName = name;
    
public static voidsetRoleMapper(java.lang.String appName, com.sun.enterprise.deployment.interfaces.SecurityRoleMapper rmap)
Set a RoleMapper for the application

param
appName Application or module name
param
rmap SecurityRoleMapper for the application or the module

        synchronized(RoleMapper.class){
            ROLEMAPPER.put(appName, rmap);
        }
    
public java.lang.StringtoString()

return
String. String representation of the RoleToPrincipal Mapping

        
        StringBuffer s = new StringBuffer("RoleMapper:");
        for (Iterator e = this.getRoles(); e.hasNext();) {
            String r = (String) e.next();
            s.append("\n\tRole (" + r + ") has Principals(");
            Subject sub = roleToSubject.get(r);
            Iterator it = sub.getPrincipals().iterator();
            for(; it.hasNext(); ){
                Principal p = (Principal) it.next();
                s.append(p.getName()+" ");
            }
            s.append(")");
        }
        if(_logger.isLoggable(Level.FINER)){
            _logger.log(Level.FINER,s.toString());
        }
        return s.toString();
    
public voidunassignPrincipalFromRole(com.sun.enterprise.deployment.Role role, java.security.Principal principal)
Remove the given role-principal mapping

param
role, Role object
param
principal, the principal

        assert roleToSubject != null;
        String mrole = role.getName();
        final Subject sub = roleToSubject.get(mrole);
        final Principal p = principal;
        if (sub != null){
            AppservAccessController.doPrivileged(new PrivilegedAction() {
                public java.lang.Object run() {
                    sub.getPrincipals().remove(p);
                    return null;
                }
            });
            roleToSubject.put(mrole, sub);
        }
        if (principal instanceof Group) {
            Set<Group> groups = roleToGroup.get(mrole);
            if (groups != null) {
                groups.remove((Group) principal);
                roleToGroup.put(mrole, groups);
            }
        } else {
            Set<Principal> principals = roleToPrincipal.get(mrole);
            if (principals != null) {
                principals.remove(principal);
                roleToPrincipal.put(mrole, principals);
            }
        }
    
public voidunassignRole(com.sun.enterprise.deployment.Role r)

        if (r != null){
            String role = r.getName();
            roleToSubject.remove(role);
            roleToPrincipal.remove(role);
            roleToGroup.remove(role);
        }