You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by sm...@apache.org on 2016/09/26 18:25:02 UTC

[1/4] directory-fortress-core git commit: FC-144 Use Groups of Roles to create Sessions

Repository: directory-fortress-core
Updated Branches:
  refs/heads/master 9271edf9a -> cb34ef224


FC-144 Use Groups of Roles to create Sessions

 There're certain situations where userId is not known to the tenant.
  Possible use case here is federated and multi-tenant login into
  openstack via keystone.  This commit allows to create a Session with
  Group, map the Group to a Role(s) inside the tenant's domain and
  check Session' Permissions.

  There's still more work to do:
  - REST Implementation of managers
  - Add new unit-tests
  - Update Console managers with new functionality


Project: http://git-wip-us.apache.org/repos/asf/directory-fortress-core/repo
Commit: http://git-wip-us.apache.org/repos/asf/directory-fortress-core/commit/098f0a37
Tree: http://git-wip-us.apache.org/repos/asf/directory-fortress-core/tree/098f0a37
Diff: http://git-wip-us.apache.org/repos/asf/directory-fortress-core/diff/098f0a37

Branch: refs/heads/master
Commit: 098f0a37b69be2cf76fa8d6e23ef3d250ccf58fc
Parents: cc3e60f
Author: Vyacheslav Vakhlyuev <vv...@mirantis.com>
Authored: Sun Aug 28 21:45:13 2016 +0300
Committer: Vyacheslav Vakhlyuev <vv...@mirantis.com>
Committed: Sun Aug 28 21:45:13 2016 +0300

----------------------------------------------------------------------
 .../directory/fortress/core/AccessMgr.java      |  77 ++++++++++-
 .../directory/fortress/core/GroupMgr.java       |  20 +++
 .../fortress/core/impl/AccessMgrImpl.java       |  80 ++++++++---
 .../fortress/core/impl/AdminMgrImpl.java        |   3 +-
 .../directory/fortress/core/impl/GroupDAO.java  |  59 +++++++-
 .../fortress/core/impl/GroupMgrImpl.java        |  36 +++++
 .../directory/fortress/core/impl/GroupP.java    | 117 +++++++++++++++-
 .../directory/fortress/core/impl/PermDAO.java   |  30 ++--
 .../directory/fortress/core/impl/UserP.java     |  12 +-
 .../directory/fortress/core/model/Group.java    |  21 +++
 .../directory/fortress/core/model/Session.java  | 137 +++++++++++++++++--
 .../directory/fortress/core/model/UserRole.java |  35 ++++-
 .../fortress/core/rest/AccessMgrRestImpl.java   |  12 +-
 .../directory/fortress/core/util/VUtil.java     |   8 +-
 .../fortress/core/AccessMgrConsole.java         |  14 +-
 15 files changed, 578 insertions(+), 83 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/098f0a37/src/main/java/org/apache/directory/fortress/core/AccessMgr.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/AccessMgr.java b/src/main/java/org/apache/directory/fortress/core/AccessMgr.java
index a45e498..6d2e19a 100755
--- a/src/main/java/org/apache/directory/fortress/core/AccessMgr.java
+++ b/src/main/java/org/apache/directory/fortress/core/AccessMgr.java
@@ -23,10 +23,7 @@ package org.apache.directory.fortress.core;
 import java.util.List;
 import java.util.Set;
 
-import org.apache.directory.fortress.core.model.Permission;
-import org.apache.directory.fortress.core.model.User;
-import org.apache.directory.fortress.core.model.Session;
-import org.apache.directory.fortress.core.model.UserRole;
+import org.apache.directory.fortress.core.model.*;
 
 
 /**
@@ -183,6 +180,78 @@ public interface AccessMgr extends Manageable
     Session createSession( User user, boolean isTrusted )
         throws SecurityException;
 
+    /**
+     * Perform user authentication {@link Group} and role activations {@link Group#members}.<br>
+     * Group sessions are always trusted. <br>
+     * This method must be called once per user prior to calling other methods within this class.
+     * The successful result is {@link org.apache.directory.fortress.core.model.Session} that contains target group's RBAC
+     * {@link Group#members}
+     * <h4> This API will...</h4>
+     * <ul>
+     *   <li>
+     *     fail for any non-existing group
+     *   </li>
+     *   <li>
+     *     evaluate temporal {@link org.apache.directory.fortress.core.model.Constraint}(s) on member {@link UserRole} entities.
+     *   <li>process selective role activations into Group RBAC Session {@link Group#roles}.</li>
+     *   <li>
+     *     check Dynamic Separation of Duties {@link org.apache.directory.fortress.core.impl.DSDChecker#validate(
+     *          org.apache.directory.fortress.core.model.Session,
+     *          org.apache.directory.fortress.core.model.Constraint,
+     *          org.apache.directory.fortress.core.util.time.Time,
+     *          org.apache.directory.fortress.core.util.VUtil.ConstraintType)} on
+     *          {@link org.apache.directory.fortress.core.model.User#roles}.
+     *   </li>
+     *   <li>
+     *     return a {@link org.apache.directory.fortress.core.model.Session} containing
+     *     {@link org.apache.directory.fortress.core.model.Session#getGroup()},
+     *     {@link org.apache.directory.fortress.core.model.Session#getRoles()}
+     *   </li>
+     *   <li>throw a checked exception that will be {@link SecurityException} or its derivation.</li>
+     *   <li>throw a {@link SecurityException} for system failures.</li>
+     *   <li>throw a {@link ValidationException} for data validation errors.</li>
+     *   <li>throw a {@link FinderException} if Group name not found.</li>
+     * </ul>
+     * <h4>
+     * The function is valid if and only if:
+     * </h4>
+     * <ul>
+     *   <li> the group is a member of the GROUPS data set</li>
+     *   <li> the (optional) active role set is a subset of the roles authorized for that group.</li>
+     * </ul>
+     * <h4>
+     * The following attributes may be set when calling this method
+     * </h4>
+     * <ul>
+     *   <li>{@link Group#name} - required</li>
+     *   <li>
+     *     {@link org.apache.directory.fortress.core.model.Group#members} contains a list of RBAC role names authorized for group
+     *     and targeted for activation within this session.  Default is all authorized RBAC roles will be activated into this
+     *     Session.
+     *   </li>
+     * </ul>
+     * <h4>
+     * Notes:
+     * </h4>
+     * <ul>
+     * <li> roles that violate Dynamic Separation of Duty Relationships will not be activated into session.
+     * </ul>
+     *
+     * @param group Contains {@link Group#name}, {@link org.apache.directory.fortress.core.model.Group#members}
+     * (optional), optional {@link Group#type}, optional
+     * @return Session object will contain authentication result code
+     * {@link org.apache.directory.fortress.core.model.Session#errorId},
+     * RBAC role activations {@link org.apache.directory.fortress.core.model.Session#getRoles()},
+     * OpenLDAP pw policy codes {@link org.apache.directory.fortress.core.model.Session#warnings},
+     * {@link org.apache.directory.fortress.core.model.Session#expirationSeconds},
+     * {@link org.apache.directory.fortress.core.model.Session#graceLogins} and more.
+     * @throws SecurityException
+     *          in the event of data validation failure, security policy violation or DAO error.
+     */
+    Session createGroupSession(Group group)
+            throws SecurityException;
+
+
 
     /**
      * Perform user RBAC authorization.  This function returns a Boolean value meaning whether the subject of a given 

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/098f0a37/src/main/java/org/apache/directory/fortress/core/GroupMgr.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/GroupMgr.java b/src/main/java/org/apache/directory/fortress/core/GroupMgr.java
index 56a9fc2..2cbe83c 100755
--- a/src/main/java/org/apache/directory/fortress/core/GroupMgr.java
+++ b/src/main/java/org/apache/directory/fortress/core/GroupMgr.java
@@ -21,7 +21,9 @@ package org.apache.directory.fortress.core;
 
 
 import org.apache.directory.fortress.core.model.Group;
+import org.apache.directory.fortress.core.model.Role;
 import org.apache.directory.fortress.core.model.User;
+import org.apache.directory.fortress.core.model.UserRole;
 
 import java.util.List;
 
@@ -121,6 +123,24 @@ public interface GroupMgr extends Manageable
      */
     List<Group> find( User user ) throws SecurityException;
 
+    /**
+     * Search for groups by role name.  Member (maps to role name) is required.
+     *
+     * @param role contains userId that maps to Group member attribute.
+     * @return {@link Group} containing entity just added.
+     * @throws org.apache.directory.fortress.core.SecurityException in the event system error.
+     */
+    List<Group> roleGroups( Role role ) throws SecurityException;
+
+    /**
+     * Read an existing group node's roles.  The name is required.
+     *
+     * @param group contains {@link Group} with name field set with an existing group name.
+     * @return list of {@link UserRole} for given group. Will return empty list if Group has no roles assigned.
+     * @throws org.apache.directory.fortress.core.SecurityException in the event system error.
+     */
+    List<UserRole> groupRoles( Group group ) throws SecurityException;
+
 
     /**
      * Assign a user to an existing group node.  The group name and member are required.

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/098f0a37/src/main/java/org/apache/directory/fortress/core/impl/AccessMgrImpl.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/impl/AccessMgrImpl.java b/src/main/java/org/apache/directory/fortress/core/impl/AccessMgrImpl.java
index c4ae52a..f13c6b5 100755
--- a/src/main/java/org/apache/directory/fortress/core/impl/AccessMgrImpl.java
+++ b/src/main/java/org/apache/directory/fortress/core/impl/AccessMgrImpl.java
@@ -28,10 +28,7 @@ import org.apache.commons.collections.CollectionUtils;
 import org.apache.directory.fortress.core.AccessMgr;
 import org.apache.directory.fortress.core.GlobalErrIds;
 import org.apache.directory.fortress.core.SecurityException;
-import org.apache.directory.fortress.core.model.Permission;
-import org.apache.directory.fortress.core.model.Session;
-import org.apache.directory.fortress.core.model.User;
-import org.apache.directory.fortress.core.model.UserRole;
+import org.apache.directory.fortress.core.model.*;
 import org.apache.directory.fortress.core.util.VUtil;
 
 
@@ -80,6 +77,7 @@ public class AccessMgrImpl extends Manageable implements AccessMgr, Serializable
 {
     private static final String CLS_NM = AccessMgrImpl.class.getName();
     private static final UserP userP = new UserP();
+    private static final GroupP groupP = new GroupP();
     private static final PermP permP = new PermP();
 
     /**
@@ -118,6 +116,19 @@ public class AccessMgrImpl extends Manageable implements AccessMgr, Serializable
         return userP.createSession( user, isTrusted );
     }
 
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Session createGroupSession(Group group)
+            throws SecurityException
+    {
+        String methodName = "createGroupSession";
+        assertContext( CLS_NM, methodName, group, GlobalErrIds.GROUP_NULL );
+
+        return groupP.createSession( group );
+    }
+
 
     /**
      * {@inheritDoc}
@@ -182,7 +193,14 @@ public class AccessMgrImpl extends Manageable implements AccessMgr, Serializable
     {
         String methodName = "authorizedRoles";
         assertContext( CLS_NM, methodName, session, GlobalErrIds.USER_SESS_NULL );
-        VUtil.getInstance().assertNotNull( session.getUser(), GlobalErrIds.USER_NULL, CLS_NM + ".authorizedRoles" );
+        if (session.isGroupSession())
+        {
+            VUtil.getInstance().assertNotNull(session.getGroup(), GlobalErrIds.GROUP_NULL, CLS_NM + ".authorizedRoles");
+        }
+        else
+        {
+            VUtil.getInstance().assertNotNull(session.getUser(), GlobalErrIds.USER_NULL, CLS_NM + ".authorizedRoles");
+        }
         VUtil.getInstance().validateConstraints( session, VUtil.ConstraintType.USER, false );
         VUtil.getInstance().validateConstraints( session, VUtil.ConstraintType.ROLE, false );
         setEntitySession(CLS_NM, methodName, session);
@@ -200,27 +218,47 @@ public class AccessMgrImpl extends Manageable implements AccessMgr, Serializable
         String methodName = "addActiveRole";
         assertContext( CLS_NM, methodName, session, GlobalErrIds.USER_SESS_NULL );
         assertContext( CLS_NM, methodName, role, GlobalErrIds.ROLE_NULL );
-        role.setUserId( session.getUserId() );
+
+        String entityId;
+        if (session.isGroupSession())
+        {
+            entityId = session.getGroupName();
+        }
+        else
+        {
+            entityId = session.getUserId();
+        }
+        role.setUserId(entityId);
         List<UserRole> uRoles;
         List<UserRole> sRoles = session.getRoles();
         // If session already has same role activated:
         if ( sRoles != null && sRoles.contains( role ) )
         {
-            String info = getFullMethodName( CLS_NM, methodName ) + " User [" + session.getUserId() + "] Role ["
-                + role.getName() + "] role already activated.";
+            String info = getFullMethodName(CLS_NM, methodName) + " Entity [" + entityId + "] Role ["
+                        + role.getName() + "] role already activated.";
             throw new SecurityException( GlobalErrIds.URLE_ALREADY_ACTIVE, info );
         }
 
-        User inUser = new User( session.getUserId() );
-        inUser.setContextId( this.contextId );
-        User ue = userP.read( inUser, true );
-        uRoles = ue.getRoles();
+        if (session.isGroupSession())
+        {
+            Group inGroup = new Group(session.getGroupName());
+            inGroup.setContextId(this.contextId);
+            Group ge = groupP.read(inGroup);
+            uRoles = ge.getRoles();
+        }
+        else
+        {
+            User inUser = new User(session.getUserId());
+            inUser.setContextId(this.contextId);
+            User ue = userP.read(inUser, true);
+            uRoles = ue.getRoles();
+        }
         int indx;
         // Is the role activation target valid for this user?
         if ( !CollectionUtils.isNotEmpty( uRoles ) || ( ( indx = uRoles.indexOf( role ) ) == -1 ) )
         {
-            String info = getFullMethodName( CLS_NM, methodName ) + " Role [" + role.getName() + "] User ["
-                + session.getUserId() + "] role not authorized for user.";
+            String info = getFullMethodName(CLS_NM, methodName) + " Role [" + role.getName() + "] Entity ["
+                        + entityId + "] role not authorized for entity.";
             throw new SecurityException( GlobalErrIds.URLE_ACTIVATE_FAILED, info );
         }
 
@@ -245,7 +283,17 @@ public class AccessMgrImpl extends Manageable implements AccessMgr, Serializable
         String methodName = "dropActiveRole";
         assertContext( CLS_NM, methodName, session, GlobalErrIds.USER_SESS_NULL );
         assertContext( CLS_NM, methodName, role, GlobalErrIds.ROLE_NULL );
-        role.setUserId( session.getUserId() );
+
+        String entityId;
+        if (session.isGroupSession())
+        {
+            entityId = session.getGroupName();
+        }
+        else
+        {
+            entityId = session.getUserId();
+        }
+        role.setUserId(entityId);
         List<UserRole> roles = session.getRoles();
         VUtil.getInstance()
             .assertNotNull( roles, GlobalErrIds.URLE_DEACTIVE_FAILED, CLS_NM + getFullMethodName( CLS_NM, methodName ) );
@@ -256,7 +304,7 @@ public class AccessMgrImpl extends Manageable implements AccessMgr, Serializable
         }
         else
         {
-            String info = getFullMethodName( CLS_NM, methodName ) + " Role [" + role.getName() + "] User ["
+            String info = getFullMethodName( CLS_NM, methodName ) + " Role [" + role.getName() + "] Entity ["
                 + session.getUserId() + "], not previously activated";
             throw new SecurityException( GlobalErrIds.URLE_NOT_ACTIVE, info );
         }

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/098f0a37/src/main/java/org/apache/directory/fortress/core/impl/AdminMgrImpl.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/impl/AdminMgrImpl.java b/src/main/java/org/apache/directory/fortress/core/impl/AdminMgrImpl.java
index e58242a..ec0019e 100755
--- a/src/main/java/org/apache/directory/fortress/core/impl/AdminMgrImpl.java
+++ b/src/main/java/org/apache/directory/fortress/core/impl/AdminMgrImpl.java
@@ -285,7 +285,8 @@ public final class AdminMgrImpl extends Manageable implements AdminMgr, Serializ
             }
         }
         roleP.delete( role );
-    }
+        // TODO: what about groups? Should we remove roles from group members?
+   }
 
 
     /**

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/098f0a37/src/main/java/org/apache/directory/fortress/core/impl/GroupDAO.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/impl/GroupDAO.java b/src/main/java/org/apache/directory/fortress/core/impl/GroupDAO.java
index 7019441..26519a8 100755
--- a/src/main/java/org/apache/directory/fortress/core/impl/GroupDAO.java
+++ b/src/main/java/org/apache/directory/fortress/core/impl/GroupDAO.java
@@ -44,10 +44,7 @@ import org.apache.directory.fortress.core.GlobalIds;
 import org.apache.directory.fortress.core.RemoveException;
 import org.apache.directory.fortress.core.UpdateException;
 import org.apache.directory.fortress.core.ldap.LdapDataProvider;
-import org.apache.directory.fortress.core.model.Group;
-import org.apache.directory.fortress.core.model.ObjectFactory;
-import org.apache.directory.fortress.core.model.PropUtil;
-import org.apache.directory.fortress.core.model.User;
+import org.apache.directory.fortress.core.model.*;
 import org.apache.directory.fortress.core.util.Config;
 import org.apache.directory.ldap.client.api.LdapConnection;
 import org.slf4j.Logger;
@@ -89,6 +86,7 @@ final class GroupDAO extends LdapDataProvider
             {
                 SchemaConstants.CN_AT,
                 SchemaConstants.DESCRIPTION_AT,
+                GlobalIds.TYPE,
                 GROUP_PROTOCOL_ATTR_IMPL,
                 GROUP_PROPERTY_ATTR_IMPL,
                 SchemaConstants.MEMBER_AT };
@@ -484,6 +482,54 @@ final class GroupDAO extends LdapDataProvider
 
 
     /**
+     * @param role
+     * @return
+     * @throws org.apache.directory.fortress.core.FinderException
+     *
+     */
+    List<Group> roleGroups( Role role ) throws FinderException
+    {
+        List<Group> groupList = new ArrayList<>();
+        LdapConnection ld = null;
+        SearchCursor searchResults;
+        String groupRoot = getRootDn( role.getContextId(), GlobalIds.GROUP_ROOT );
+        String filter = null;
+
+        try
+        {
+            encodeSafeText( role.getName(), GlobalIds.ROLE_LEN );
+            filter = GlobalIds.FILTER_PREFIX + GROUP_OBJECT_CLASS_IMPL + ")(" + SchemaConstants.MEMBER_AT + "="
+                    + role.getDn() + "))";
+            ld = getAdminConnection();
+            searchResults = search( ld, groupRoot, SearchScope.ONELEVEL, filter, GROUP_ATRS, false,
+                    GlobalIds.BATCH_SIZE );
+            long sequence = 0;
+
+            while ( searchResults.next() )
+            {
+                groupList.add( unloadLdapEntry( searchResults.getEntry(), sequence++ ) );
+            }
+        }
+        catch ( CursorException e )
+        {
+            String error = "find filter [" + filter + "] caught CursorException=" + e.getMessage();
+            throw new FinderException( GlobalErrIds.GROUP_SEARCH_FAILED, error, e );
+        }
+        catch ( LdapException e )
+        {
+            String error = "find filter [" + filter + "] caught LDAPException=" + e.getMessage();
+            throw new FinderException( GlobalErrIds.GROUP_SEARCH_FAILED, error, e );
+        }
+        finally
+        {
+            closeAdminConnection( ld );
+        }
+
+        return groupList;
+    }
+
+
+    /**
      * @param le
      * @param sequence
      * @return
@@ -495,6 +541,11 @@ final class GroupDAO extends LdapDataProvider
         Group entity = new ObjectFactory().createGroup();
         entity.setName( getAttribute( le, SchemaConstants.CN_AT ) );
         entity.setDescription( getAttribute( le, SchemaConstants.DESCRIPTION_AT ) );
+        String typeAsString = getAttribute( le, GlobalIds.TYPE );
+        if ( StringUtils.isNotEmpty(typeAsString) )
+        {
+            entity.setType( Group.Type.valueOf( typeAsString.toUpperCase() ) );
+        }
         entity.setProtocol( getAttribute( le, GROUP_PROTOCOL_ATTR_IMPL ) );
         entity.setMembers( getAttributes( le, SchemaConstants.MEMBER_AT ) );
         entity.setMemberDn( true );

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/098f0a37/src/main/java/org/apache/directory/fortress/core/impl/GroupMgrImpl.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/impl/GroupMgrImpl.java b/src/main/java/org/apache/directory/fortress/core/impl/GroupMgrImpl.java
index e27f25e..6341600 100755
--- a/src/main/java/org/apache/directory/fortress/core/impl/GroupMgrImpl.java
+++ b/src/main/java/org/apache/directory/fortress/core/impl/GroupMgrImpl.java
@@ -32,6 +32,7 @@ import org.apache.directory.fortress.core.SecurityException;
 import org.apache.directory.fortress.core.model.Group;
 import org.apache.directory.fortress.core.model.Role;
 import org.apache.directory.fortress.core.model.User;
+import org.apache.directory.fortress.core.model.UserRole;
 
 
 /**
@@ -71,6 +72,7 @@ public class GroupMgrImpl extends Manageable implements GroupMgr, Serializable
             {
                 loadUserDns( group );
             }
+            group.setMemberDn(true);
         }
 
         return GROUP_P.add( group );
@@ -169,6 +171,33 @@ public class GroupMgrImpl extends Manageable implements GroupMgr, Serializable
      * {@inheritDoc}
      */
     @Override
+    public List<Group> roleGroups( Role role ) throws SecurityException
+    {
+        String methodName = "roleGroups";
+        assertContext(CLS_NM, methodName, role, GlobalErrIds.ROLE_NULL);
+        checkAccess( CLS_NM, methodName );
+        loadRoleDn( role );
+
+        return GROUP_P.roleGroups( role );
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public List<UserRole> groupRoles( Group group ) throws SecurityException
+    {
+        String methodName = "groupRoles";
+        assertContext(CLS_NM, methodName, group, GlobalErrIds.GROUP_NULL);
+        checkAccess( CLS_NM, methodName );
+
+        return GROUP_P.groupRoles( group );
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
     public Group assign( Group group, String member ) throws SecurityException
     {
         String methodName = "assign";
@@ -255,4 +284,11 @@ public class GroupMgrImpl extends Manageable implements GroupMgr, Serializable
         User outUser = reviewMgr.readUser( inUser );
         inUser.setDn( outUser.getDn() );
     }
+
+    private void loadRoleDn( Role inRole ) throws SecurityException
+    {
+        ReviewMgr reviewMgr = ReviewMgrFactory.createInstance();
+        Role outRole = reviewMgr.readRole( inRole );
+        inRole.setDn( outRole.getDn() );
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/098f0a37/src/main/java/org/apache/directory/fortress/core/impl/GroupP.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/impl/GroupP.java b/src/main/java/org/apache/directory/fortress/core/impl/GroupP.java
index 856d201..31512bb 100755
--- a/src/main/java/org/apache/directory/fortress/core/impl/GroupP.java
+++ b/src/main/java/org/apache/directory/fortress/core/impl/GroupP.java
@@ -20,15 +20,16 @@
 package org.apache.directory.fortress.core.impl;
 
 
+import java.util.ArrayList;
 import java.util.List;
 
+import org.apache.commons.collections.CollectionUtils;
 import org.apache.directory.api.util.Strings;
 import org.apache.directory.fortress.core.GlobalErrIds;
 import org.apache.directory.fortress.core.GlobalIds;
 import org.apache.directory.fortress.core.SecurityException;
 import org.apache.directory.fortress.core.ValidationException;
-import org.apache.directory.fortress.core.model.Group;
-import org.apache.directory.fortress.core.model.User;
+import org.apache.directory.fortress.core.model.*;
 import org.apache.directory.fortress.core.util.VUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -61,7 +62,9 @@ final class GroupP
     {
         validate( group );
 
-        return gDao.create( group );
+        Group outGroup = gDao.create(group);
+        fillRoles(outGroup);
+        return outGroup;
     }
 
 
@@ -162,7 +165,9 @@ final class GroupP
      */
     Group read( Group group ) throws SecurityException
     {
-        return gDao.get( group );
+        Group outGroup = gDao.get(group);
+        fillRoles(outGroup);
+        return outGroup;
     }
 
 
@@ -191,6 +196,110 @@ final class GroupP
         return gDao.find( user );
     }
 
+    /**
+     * Takes a search string that contains full or partial Role name in directory.
+     *
+     * @param role contains full dn name of role
+     * @return List of type Group containing fully populated matching entities.  If no records found this will be empty.
+     * @throws SecurityException in the event of DAO search error.
+     */
+    List<Group> roleGroups( Role role ) throws SecurityException
+    {
+        return gDao.roleGroups( role );
+    }
+
+    /**
+     * Return a list of group Roles for a given Group name.  If matching record not found a
+     * SecurityException will be thrown.
+     *
+     * @param group contains full group name for entry in directory.
+     * @return Group entity containing all attributes associated.
+     * @throws SecurityException in the event not found or DAO search error.
+     */
+    List<UserRole> groupRoles( Group group ) throws SecurityException
+    {
+        Group outGroup = read(group);
+        fillRoles( outGroup );
+
+        return outGroup.getRoles();
+    }
+
+
+    /**
+     * Creates a Session using given Group and its members, if Group type is ROLE
+     * @param group a group to create Session for
+     * @return Session object
+     * @throws SecurityException
+     */
+    Session createSession( Group group ) throws SecurityException
+    {
+        // Create the impl session without authentication of password.
+        Session session = createSessionTrusted( group );
+
+        // Did the caller pass in a set of roles for selective activation?
+        if ( CollectionUtils.isNotEmpty( group.getMembers() ) )
+        {
+            // Process selective activation of user's RBAC roles into session:
+            List<String> availableRoles = session.getGroup().getMembers();
+            availableRoles.retainAll(group.getMembers());
+
+            // Fill aux field 'roles' with Role entities
+            fillRoles(session.getGroup());
+        }
+        // Check role temporal constraints + activate roles:
+        VUtil.getInstance().validateConstraints( session, VUtil.ConstraintType.ROLE, true );
+        return session;
+    }
+
+
+    // TODO: docs
+    private Session createSessionTrusted( Group inGroup) throws SecurityException
+    {
+        Group group = read( inGroup );
+        group.setContextId( inGroup.getContextId() );
+
+        Session session = new Session(group);
+        // Set this flag to false because group was not authenticated.
+        session.setAuthenticated( false );
+        return session;
+    }
+
+    /**
+     * Populates the auxiliary field 'roles' in given group object with
+     * {@link UserRole} data
+     * @param group a group object to populate
+     * @throws SecurityException thrown in the event the attribute is null.
+     */
+    private void fillRoles( Group group ) throws SecurityException {
+        if ( Group.Type.ROLE.equals( group.getType() ) )
+        {
+            RoleP rp = new RoleP();
+            List<UserRole> roles = new ArrayList<>();
+            List<String> members = group.getMembers();
+            for ( String roleDn : members )
+            {
+                String roleRdn = roleDn;
+                if (group.isMemberDn())
+                {
+                    String[] parts = roleDn.split(",");
+                    if (parts.length > 0)
+                    {
+                        roleRdn = parts[ 0 ];
+                    }
+                    roleRdn = roleRdn.replaceFirst("cn=", ""); // remove 'cn='
+                }
+                Role inRole = new Role( roleRdn );
+                inRole.setContextId( group.getContextId() );
+                Role role = rp.read( inRole );
+
+                UserRole ure = new UserRole( group.getName(), roleRdn, true );
+                ConstraintUtil.validateOrCopy( role, ure );
+                roles.add( ure );
+            }
+            group.setRoles( roles );
+        }
+    }
+
 
     /**
      * Method will perform simple validations to ensure the integrity of the {@link Group} entity targeted for insertion

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/098f0a37/src/main/java/org/apache/directory/fortress/core/impl/PermDAO.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/impl/PermDAO.java b/src/main/java/org/apache/directory/fortress/core/impl/PermDAO.java
index f2a7eeb..3152a20 100755
--- a/src/main/java/org/apache/directory/fortress/core/impl/PermDAO.java
+++ b/src/main/java/org/apache/directory/fortress/core/impl/PermDAO.java
@@ -885,18 +885,23 @@ final class PermDAO extends LdapDataProvider
             // There is a switch in fortress config to disable audit ops like this one.
             // But if used the compare method will use OpenLDAP's Proxy Authorization Control to assert identity of end user onto connection.
             // LDAP Operation #2: Compare.
-            addAuthZAudit( ld, dn, session.getUser().getDn(), attributeValue );
+            if ( !session.isGroupSession() )
+            {
+                addAuthZAudit( ld, dn, session.getUser().getDn(), attributeValue );
+            }
         }
-        catch ( LdapException e )
-        {
-            if ( !( e instanceof LdapNoSuchObjectException ) )
+        catch ( LdapException e ) {
+            if (!(e instanceof LdapNoSuchObjectException))
             {
                 String error = "checkPermission caught LdapException=" + e.getMessage();
-                throw new FinderException( GlobalErrIds.PERM_READ_OP_FAILED, error, e );
+                throw new FinderException(GlobalErrIds.PERM_READ_OP_FAILED, error, e);
             }
 
             // There is a switch in fortress config to disable the audit ops.
-            addAuthZAudit( ld, dn, session.getUser().getDn(), "AuthZ Invalid" );
+            if (!session.isGroupSession())
+            {
+                addAuthZAudit(ld, dn, session.getUser().getDn(), "AuthZ Invalid");
+            }
         }
         finally
         {
@@ -1585,11 +1590,14 @@ final class PermDAO extends LdapDataProvider
             filterbuf.append( GlobalIds.FILTER_PREFIX );
             filterbuf.append( PERM_OP_OBJECT_CLASS_NAME );
             filterbuf.append( ")(|" );
-            filterbuf.append( "(" );
-            filterbuf.append( USERS );
-            filterbuf.append( "=" );
-            filterbuf.append( session.getUserId() );
-            filterbuf.append( ")" );
+            if (!session.isGroupSession())
+            {
+                filterbuf.append("(");
+                filterbuf.append(USERS);
+                filterbuf.append("=");
+                filterbuf.append(session.getUserId());
+                filterbuf.append(")");
+            }
             Set<String> roles;
             if ( isAdmin )
             {

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/098f0a37/src/main/java/org/apache/directory/fortress/core/impl/UserP.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/impl/UserP.java b/src/main/java/org/apache/directory/fortress/core/impl/UserP.java
index 30af294..34a4999 100755
--- a/src/main/java/org/apache/directory/fortress/core/impl/UserP.java
+++ b/src/main/java/org/apache/directory/fortress/core/impl/UserP.java
@@ -32,17 +32,7 @@ import org.apache.directory.fortress.core.GlobalIds;
 import org.apache.directory.fortress.core.PasswordException;
 import org.apache.directory.fortress.core.SecurityException;
 import org.apache.directory.fortress.core.ValidationException;
-import org.apache.directory.fortress.core.model.AdminRole;
-import org.apache.directory.fortress.core.model.Administrator;
-import org.apache.directory.fortress.core.model.ConstraintUtil;
-import org.apache.directory.fortress.core.model.ObjectFactory;
-import org.apache.directory.fortress.core.model.OrgUnit;
-import org.apache.directory.fortress.core.model.PwPolicy;
-import org.apache.directory.fortress.core.model.Role;
-import org.apache.directory.fortress.core.model.Session;
-import org.apache.directory.fortress.core.model.User;
-import org.apache.directory.fortress.core.model.UserAdminRole;
-import org.apache.directory.fortress.core.model.UserRole;
+import org.apache.directory.fortress.core.model.*;
 import org.apache.directory.fortress.core.util.VUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/098f0a37/src/main/java/org/apache/directory/fortress/core/model/Group.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/model/Group.java b/src/main/java/org/apache/directory/fortress/core/model/Group.java
index 5c8fe68..5874871 100755
--- a/src/main/java/org/apache/directory/fortress/core/model/Group.java
+++ b/src/main/java/org/apache/directory/fortress/core/model/Group.java
@@ -56,6 +56,11 @@ public class Group extends FortEntity implements Serializable
     private Type type;
 
     /**
+     *  Auxiliary field used to store roles in UserRole format. Used only internally by DAO/Managers.
+     */
+    private List<UserRole> roles = new ArrayList<>();
+
+    /**
      * enum for User or Role data sets.  Both nodes may be stored in the same LDAP container.
      */
     @XmlType(name = "type")
@@ -454,6 +459,22 @@ public class Group extends FortEntity implements Serializable
         this.memberDn = memberDn;
     }
 
+    /**
+     * List of roles for given groups if they were populated. Empty list otherwise.
+     * @return
+     */
+    public List<UserRole> getRoles() {
+        return roles;
+    }
+
+    /**
+     * Setter for auxiliary 'roles' field.
+     * @param roles list of roles to be set
+     */
+    public void setRoles(List<UserRole> roles) {
+        this.roles = roles;
+    }
+
 
     @Override
     public boolean equals( Object o )

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/098f0a37/src/main/java/org/apache/directory/fortress/core/model/Session.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/model/Session.java b/src/main/java/org/apache/directory/fortress/core/model/Session.java
index 8479a3f..c6d2c62 100755
--- a/src/main/java/org/apache/directory/fortress/core/model/Session.java
+++ b/src/main/java/org/apache/directory/fortress/core/model/Session.java
@@ -163,7 +163,9 @@ import java.util.UUID;
 @XmlAccessorType(XmlAccessType.FIELD)
 @XmlType(name = "session", propOrder = {
     "user",
+    "group",
     "isAuthenticated",
+    "isGroupSession",
     "sessionId",
     "lastAccess",
     "timeout",
@@ -178,6 +180,7 @@ public class Session  extends FortEntity implements PwMessage, Serializable
 {
     private static final long serialVersionUID = 1L;
     private User user;
+    private Group group;
     private String sessionId;
     private long lastAccess;
     private int timeout;
@@ -186,6 +189,7 @@ public class Session  extends FortEntity implements PwMessage, Serializable
     private int graceLogins;
     private int expirationSeconds;
     private boolean isAuthenticated;
+    private boolean isGroupSession;
     private String message;
     @XmlElement(nillable = true)
     private List<Warning> warnings;
@@ -199,6 +203,16 @@ public class Session  extends FortEntity implements PwMessage, Serializable
     {
         return isAuthenticated;
     }
+
+    /**
+     * A 'true' value here indicates this Session was created for Group entity
+     *
+     * @return boolean indicating if this Session is created for Group
+     */
+    public boolean isGroupSession()
+    {
+        return isGroupSession;
+    }
     
 
     private void init()
@@ -217,6 +231,7 @@ public class Session  extends FortEntity implements PwMessage, Serializable
     public void copy( Session inSession )
     {
         this.user = inSession.getUser();
+        this.group = inSession.getGroup();
         // don't copy session id:
         //this.sessionId = inSession.getSessionId();
         this.lastAccess = inSession.getLastAccess();
@@ -226,6 +241,7 @@ public class Session  extends FortEntity implements PwMessage, Serializable
         this.graceLogins = inSession.getGraceLogins();
         this.expirationSeconds = inSession.expirationSeconds;
         this.isAuthenticated = inSession.isAuthenticated();
+        this.isGroupSession = inSession.isGroupSession();
         this.message = inSession.getMsg();
         this.warnings = inSession.getWarnings();
     }
@@ -239,6 +255,8 @@ public class Session  extends FortEntity implements PwMessage, Serializable
         init();
         // this class will not check for null on user object.
         user = new User();
+        // by default, the Session is created for user
+        isGroupSession = false;
     }
     
 
@@ -251,6 +269,19 @@ public class Session  extends FortEntity implements PwMessage, Serializable
     {
         init();
         this.user = user;
+        isGroupSession = false;
+    }
+
+    /**
+     * Construct a new Session instance with given Group entity.
+     *
+     * @param group contains the Group attributes that are associated with the Session.
+     */
+    public Session( Group group )
+    {
+        init();
+        this.group = group;
+        isGroupSession = true;
     }
     
 
@@ -263,8 +294,21 @@ public class Session  extends FortEntity implements PwMessage, Serializable
     {
         this.sessionId = sessionId;
         this.user = user;
+        isGroupSession = false;
     }
-    
+
+    /**
+     * Construct a new Session instance with given Group entity.
+     *
+     * @param group contains the Group attributes that are associated with the Session.
+     */
+    public Session( Group group, String sessionId )
+    {
+        this.sessionId = sessionId;
+        this.group = group;
+        isGroupSession = true;
+    }
+
 
     /**
      * Return the unique id that is associated with User.  This attribute is generated automatically
@@ -331,7 +375,12 @@ public class Session  extends FortEntity implements PwMessage, Serializable
     {
         return this.user;
     }
-    
+
+    /**
+     * Return the Group entity that is associated with this entity.
+     */
+    public Group getGroup()    { return this.group; }
+
 
     /**
      * Return the userId that is associated with this Session object.
@@ -342,6 +391,16 @@ public class Session  extends FortEntity implements PwMessage, Serializable
     {
         return this.user.getUserId();
     }
+
+    /**
+     * Return the group name that is associated with this Session object.
+     *
+     * @return group name maps to the 'name' attribute on the 'ftGroup' object class.
+     */
+    public String getGroupName()
+    {
+        return this.group.getName();
+    }
     
 
     /**
@@ -354,10 +413,10 @@ public class Session  extends FortEntity implements PwMessage, Serializable
     {
         return this.user.getInternalId();
     }
-    
+
 
     /**
-     * Return the list of User's RBAC Roles that have been activated into User's session.  This list will not include
+     * Return the list of User's RBAC Roles that have been activated into User's or Group's session.  This list will not include
      * ascendant RBAC roles which may be retrieved using {@link org.apache.directory.fortress.core.impl.AccessMgrImpl#authorizedRoles(Session)}.
      *
      * @return List containing User's RBAC roles.  This list may be empty if User not assigned RBAC.
@@ -366,7 +425,11 @@ public class Session  extends FortEntity implements PwMessage, Serializable
     {
         List<UserRole> roles = null;
 
-        if ( user != null )
+        if ( isGroupSession && group != null )
+        {
+            roles = group.getRoles();
+        }
+        if ( !isGroupSession && user != null )
         {
             roles = user.getRoles();
         }
@@ -385,7 +448,12 @@ public class Session  extends FortEntity implements PwMessage, Serializable
     {
         List<UserAdminRole> roles = null;
 
-        if ( user != null )
+//        TODO: Do we need admin roles for Group?
+//        if ( isGroupSession && group != null )
+//        {
+//            roles = group.getAdminRoles();
+//        }
+        if ( !isGroupSession && user != null )
         {
             roles = user.getAdminRoles();
         }
@@ -548,6 +616,15 @@ public class Session  extends FortEntity implements PwMessage, Serializable
     {
         this.user = user;
     }
+
+    /**
+     * Set a Group entity into the Session.
+     * @param group Contains group name, roles members and other security attributes used for access control.
+     */
+    public void setGroup( Group group )
+    {
+        this.group = group;
+    }
     
 
     /**
@@ -573,7 +650,13 @@ public class Session  extends FortEntity implements PwMessage, Serializable
     {
         isAuthenticated = authenticated;
     }
-    
+
+
+    /**
+     * Set the value to 'true' indicating that Session is created for Group entity
+     * @param isGroupSession indicates if Session is for Group
+     */
+    public void setGroupSession(boolean isGroupSession) { isGroupSession = isGroupSession; }
 
     /**
      * Set the userId that is associated with User.  UserId is required attribute and must be set on add, update, delete, createSession, authenticate, etc..
@@ -585,15 +668,32 @@ public class Session  extends FortEntity implements PwMessage, Serializable
         user.setUserId( userId );
     }
 
+    /**
+     * Set the groupName that is associated with Group.  GroupName is required attribute and must be set on add, update, delete, createSession, authenticate, etc..
+     *
+     * @param groupName maps to 'name' attribute in 'ftGroup' object class.
+     */
+    public void setGroupName ( String groupName )
+    {
+        group.setName( groupName );
+    }
+
 
     /**
      * Add a list of RBAC Roles to this entity that have been activated into Session or are under consideration for activation.
      *
-     * @param roles List of type UserRole that contains at minimum UserId and Role name.
+     * @param roles List of type UserRole that contains at minimum UserId or GroupName and Role name.
      */
     public void setRoles( List<UserRole> roles )
     {
-        user.setRoles( roles );
+        if ( isGroupSession )
+        {
+            group.setRoles( roles );
+        }
+        else
+        {
+            user.setRoles( roles );
+        }
     }
     
 
@@ -604,7 +704,15 @@ public class Session  extends FortEntity implements PwMessage, Serializable
      */
     public void setRole( UserRole role )
     {
-        user.setRole( role );
+        if ( isGroupSession )
+        {
+//            group.setRole( role );
+            group.getRoles().add( role );
+        }
+        else
+        {
+            user.setRole( role );
+        }
     }
     
 
@@ -747,7 +855,14 @@ public class Session  extends FortEntity implements PwMessage, Serializable
         sb.append( "Session object: \n" );
 
         sb.append( "    sessionId :" ).append( sessionId ).append( '\n' );
-        sb.append( "    user :" ).append( user ).append( '\n' );
+        if ( isGroupSession )
+        {
+            sb.append( "    group :" ).append( group ).append( '\n' );
+        }
+        else
+        {
+            sb.append( "    user :" ).append( user ).append( '\n' );
+        }
         sb.append( "    isAuthenticated :" ).append( isAuthenticated ).append( '\n' );
         sb.append( "    lastAccess :" ).append( lastAccess ).append( '\n' );
         sb.append( "    timeout :" ).append( timeout ).append( '\n' );

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/098f0a37/src/main/java/org/apache/directory/fortress/core/model/UserRole.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/model/UserRole.java b/src/main/java/org/apache/directory/fortress/core/model/UserRole.java
index 27c0d70..44bc3d1 100755
--- a/src/main/java/org/apache/directory/fortress/core/model/UserRole.java
+++ b/src/main/java/org/apache/directory/fortress/core/model/UserRole.java
@@ -72,8 +72,8 @@ import org.apache.directory.fortress.core.util.Config;
  */
 @XmlRootElement( name = "fortUserRole" )
 @XmlAccessorType( XmlAccessType.FIELD )
-@XmlType( name = "userRole", propOrder = {"name", "userId", "parents", "beginDate", "beginLockDate", "beginTime",
-    "dayMask", "endDate", "endLockDate", "endTime", "timeout"} )
+@XmlType( name = "userRole", propOrder = {"name", "userId", "isGroupRole", "parents", "beginDate", "beginLockDate",
+        "beginTime", "dayMask", "endDate", "endLockDate", "endTime", "timeout"} )
 @XmlSeeAlso( {UserAdminRole.class} )
 public class UserRole extends FortEntity implements Serializable, Constraint
 {
@@ -81,6 +81,7 @@ public class UserRole extends FortEntity implements Serializable, Constraint
     
     protected String userId;
     protected String name;
+    protected boolean isGroupRole;
     private Integer timeout;
     private String beginTime;
     private String endTime;
@@ -111,9 +112,21 @@ public class UserRole extends FortEntity implements Serializable, Constraint
     {
         this.userId = userId;
         name = role;
-
+        isGroupRole = false;
     }
 
+    /**
+     * Construct a UserRole entity given the required attributes 'userId' and 'role' name.
+     *
+     * @param userId maps to the 'uid' attribute on the 'inetOrgPerson' object class.
+     * @param name role name, maps to the 'ftRA' attribute on the 'ftUserAttrs' object class.
+     * @param isGroupRole defines if value contained in userId is group name rather than user's uid
+     */
+    public UserRole(String userId, String name, boolean isGroupRole) {
+        this.userId = userId;
+        this.name = name;
+        this.isGroupRole = isGroupRole;
+    }
 
     /**
      * Construct an RBAC Role with required attribute 'userId' and optional temporal constraint.
@@ -124,6 +137,7 @@ public class UserRole extends FortEntity implements Serializable, Constraint
     public UserRole( String userId, Constraint con )
     {
         this.userId = userId;
+        isGroupRole = false;
         ConstraintUtil.copy( con, this );
     }
 
@@ -573,6 +587,21 @@ public class UserRole extends FortEntity implements Serializable, Constraint
         this.parents = parents;
     }
 
+    /**
+     * Returns 'true' if value in userId refers to group name
+     * @return if userId contains group name
+     */
+    public boolean isGroupRole() {
+        return isGroupRole;
+    }
+
+    /**
+     * Set to 'true' if userId contains group name
+     * @param groupRole specifies if value in userId contains group name
+     */
+    public void setGroupRole(boolean groupRole) {
+        isGroupRole = groupRole;
+    }
 
     /**
      * Matches the userId and role name from two UserRole entities.

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/098f0a37/src/main/java/org/apache/directory/fortress/core/rest/AccessMgrRestImpl.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/rest/AccessMgrRestImpl.java b/src/main/java/org/apache/directory/fortress/core/rest/AccessMgrRestImpl.java
index ed5b873..416dc0b 100644
--- a/src/main/java/org/apache/directory/fortress/core/rest/AccessMgrRestImpl.java
+++ b/src/main/java/org/apache/directory/fortress/core/rest/AccessMgrRestImpl.java
@@ -28,12 +28,7 @@ import org.apache.directory.fortress.core.GlobalErrIds;
 import org.apache.directory.fortress.core.SecurityException;
 import org.apache.directory.fortress.core.impl.AccessMgrImpl;
 import org.apache.directory.fortress.core.impl.Manageable;
-import org.apache.directory.fortress.core.model.FortRequest;
-import org.apache.directory.fortress.core.model.FortResponse;
-import org.apache.directory.fortress.core.model.Permission;
-import org.apache.directory.fortress.core.model.Session;
-import org.apache.directory.fortress.core.model.User;
-import org.apache.directory.fortress.core.model.UserRole;
+import org.apache.directory.fortress.core.model.*;
 import org.apache.directory.fortress.core.util.VUtil;
 
 /**
@@ -141,6 +136,11 @@ public class AccessMgrRestImpl extends Manageable implements AccessMgr
         return retSession;
     }
 
+    @Override
+    public Session createGroupSession(Group group, boolean isTrusted) throws SecurityException {
+        return null;
+    }
+
     /**
      * {@inheritDoc}
      */

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/098f0a37/src/main/java/org/apache/directory/fortress/core/util/VUtil.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/util/VUtil.java b/src/main/java/org/apache/directory/fortress/core/util/VUtil.java
index 7b042f8..4e5baf6 100755
--- a/src/main/java/org/apache/directory/fortress/core/util/VUtil.java
+++ b/src/main/java/org/apache/directory/fortress/core/util/VUtil.java
@@ -584,7 +584,7 @@ public final class VUtil implements ConstraintValidator
         {
             Time currTime = TUtil.getCurrentTime();
             // first check the constraint on the user:
-            if ( type == ConstraintType.USER )
+            if ( type == ConstraintType.USER && !session.isGroupSession() )
             {
                 rc = val.validate( session, session.getUser(), currTime, type );
                 if ( rc > 0 )
@@ -645,7 +645,11 @@ public final class VUtil implements ConstraintValidator
             && CollectionUtils.isNotEmpty( session.getRoles() ) )
         {
             Validator dsdVal = ( Validator ) ClassUtil.createInstance( DSDVALIDATOR );
-            dsdVal.validate( session, session.getUser(), null, null );
+            // Do not validate for Groups
+            if ( !session.isGroupSession() )
+            {
+                dsdVal.validate( session, session.getUser(), null, null );
+            }
         }
         // reset the user's last access timestamp:
         session.setLastAccess();

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/098f0a37/src/test/java/org/apache/directory/fortress/core/AccessMgrConsole.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/directory/fortress/core/AccessMgrConsole.java b/src/test/java/org/apache/directory/fortress/core/AccessMgrConsole.java
index 3aaa646..05b5648 100755
--- a/src/test/java/org/apache/directory/fortress/core/AccessMgrConsole.java
+++ b/src/test/java/org/apache/directory/fortress/core/AccessMgrConsole.java
@@ -19,17 +19,11 @@
  */
 package org.apache.directory.fortress.core;
 
+import org.apache.directory.fortress.core.impl.OrgUnitP;
 import org.apache.directory.fortress.core.impl.TestUtils;
-import org.apache.directory.fortress.core.model.UserAdminRole;
-import org.apache.directory.fortress.core.model.Permission;
-import org.apache.directory.fortress.core.model.Session;
-import org.apache.directory.fortress.core.model.User;
-import org.apache.directory.fortress.core.model.UserRole;
-
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Enumeration;
-import java.util.List;
+import org.apache.directory.fortress.core.model.*;
+
+import java.util.*;
 
 import org.apache.directory.fortress.core.util.VUtil;
 import org.slf4j.Logger;


[2/4] directory-fortress-core git commit: FC-144 Use Groups of Roles to create Sessions

Posted by sm...@apache.org.
FC-144 Use Groups of Roles to create Sessions

* Modified GroupMgr to support SSD and DSD constraints for roles  assignment
* Added tests for new GroupMgr methods
* Updated info needed by EnMasse project (HttpIds etc.)


Project: http://git-wip-us.apache.org/repos/asf/directory-fortress-core/repo
Commit: http://git-wip-us.apache.org/repos/asf/directory-fortress-core/commit/252e6116
Tree: http://git-wip-us.apache.org/repos/asf/directory-fortress-core/tree/252e6116
Diff: http://git-wip-us.apache.org/repos/asf/directory-fortress-core/diff/252e6116

Branch: refs/heads/master
Commit: 252e6116933c7d37d53159c304fdb1e309a97aa1
Parents: 098f0a3
Author: Vyacheslav Vakhlyuev <vv...@mirantis.com>
Authored: Fri Sep 23 17:17:38 2016 +0300
Committer: Vyacheslav Vakhlyuev <vv...@mirantis.com>
Committed: Fri Sep 23 17:17:38 2016 +0300

----------------------------------------------------------------------
 .../directory/fortress/core/AccessMgr.java      |   6 +-
 .../directory/fortress/core/GlobalErrIds.java   |   7 +
 .../fortress/core/impl/AccessMgrImpl.java       |   4 +-
 .../fortress/core/impl/AdminMgrImpl.java        |  21 +-
 .../fortress/core/impl/DSDChecker.java          |  21 +-
 .../fortress/core/impl/GroupMgrImpl.java        |   2 +
 .../directory/fortress/core/impl/GroupP.java    |  34 ++-
 .../directory/fortress/core/impl/PermDAO.java   |   3 +-
 .../directory/fortress/core/impl/SDUtil.java    |  66 +++--
 .../directory/fortress/core/model/Group.java    |  15 +-
 .../directory/fortress/core/model/Session.java  |   3 +-
 .../fortress/core/rest/AccessMgrRestImpl.java   |  21 +-
 .../directory/fortress/core/rest/HttpIds.java   |   9 +
 .../directory/fortress/core/util/VUtil.java     | 181 +++++++++---
 .../fortress/core/impl/FortressJUnitTest.java   |  12 +
 .../fortress/core/impl/GroupMgrImplTest.java    | 279 +++++++++++++++++++
 .../fortress/core/impl/GroupTestData.java       |  94 +++++++
 17 files changed, 677 insertions(+), 101 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/252e6116/src/main/java/org/apache/directory/fortress/core/AccessMgr.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/AccessMgr.java b/src/main/java/org/apache/directory/fortress/core/AccessMgr.java
index 6d2e19a..51fff40 100755
--- a/src/main/java/org/apache/directory/fortress/core/AccessMgr.java
+++ b/src/main/java/org/apache/directory/fortress/core/AccessMgr.java
@@ -181,9 +181,9 @@ public interface AccessMgr extends Manageable
         throws SecurityException;
 
     /**
-     * Perform user authentication {@link Group} and role activations {@link Group#members}.<br>
+     * Perform group {@link Group} role activations {@link Group#members}.<br>
      * Group sessions are always trusted. <br>
-     * This method must be called once per user prior to calling other methods within this class.
+     * This method must be called once per group prior to calling other methods within this class.
      * The successful result is {@link org.apache.directory.fortress.core.model.Session} that contains target group's RBAC
      * {@link Group#members}
      * <h4> This API will...</h4>
@@ -248,7 +248,7 @@ public interface AccessMgr extends Manageable
      * @throws SecurityException
      *          in the event of data validation failure, security policy violation or DAO error.
      */
-    Session createGroupSession(Group group)
+    Session createSession(Group group)
             throws SecurityException;
 
 

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/252e6116/src/main/java/org/apache/directory/fortress/core/GlobalErrIds.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/GlobalErrIds.java b/src/main/java/org/apache/directory/fortress/core/GlobalErrIds.java
index 363bb37..1fb4ef2 100755
--- a/src/main/java/org/apache/directory/fortress/core/GlobalErrIds.java
+++ b/src/main/java/org/apache/directory/fortress/core/GlobalErrIds.java
@@ -1655,4 +1655,11 @@ public final class GlobalErrIds
      * The supplied group protocol name failed length check.
      */
     public static final int GROUP_PROTOCOL_INVLD = 10313;
+
+    /**
+     * The supplied group type is invalid for operation
+     */
+    public static final int GROUP_TYPE_INVLD = 10314;
+
+
 }

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/252e6116/src/main/java/org/apache/directory/fortress/core/impl/AccessMgrImpl.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/impl/AccessMgrImpl.java b/src/main/java/org/apache/directory/fortress/core/impl/AccessMgrImpl.java
index f13c6b5..da81b8f 100755
--- a/src/main/java/org/apache/directory/fortress/core/impl/AccessMgrImpl.java
+++ b/src/main/java/org/apache/directory/fortress/core/impl/AccessMgrImpl.java
@@ -120,10 +120,10 @@ public class AccessMgrImpl extends Manageable implements AccessMgr, Serializable
      * {@inheritDoc}
      */
     @Override
-    public Session createGroupSession(Group group)
+    public Session createSession( Group group )
             throws SecurityException
     {
-        String methodName = "createGroupSession";
+        String methodName = "createSession";
         assertContext( CLS_NM, methodName, group, GlobalErrIds.GROUP_NULL );
 
         return groupP.createSession( group );

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/252e6116/src/main/java/org/apache/directory/fortress/core/impl/AdminMgrImpl.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/impl/AdminMgrImpl.java b/src/main/java/org/apache/directory/fortress/core/impl/AdminMgrImpl.java
index ec0019e..9b0eba8 100755
--- a/src/main/java/org/apache/directory/fortress/core/impl/AdminMgrImpl.java
+++ b/src/main/java/org/apache/directory/fortress/core/impl/AdminMgrImpl.java
@@ -29,16 +29,7 @@ import org.apache.directory.fortress.core.AdminMgr;
 import org.apache.directory.fortress.core.GlobalErrIds;
 import org.apache.directory.fortress.core.GlobalIds;
 import org.apache.directory.fortress.core.SecurityException;
-import org.apache.directory.fortress.core.model.AdminRole;
-import org.apache.directory.fortress.core.model.ConstraintUtil;
-import org.apache.directory.fortress.core.model.Hier;
-import org.apache.directory.fortress.core.model.PermObj;
-import org.apache.directory.fortress.core.model.Permission;
-import org.apache.directory.fortress.core.model.Relationship;
-import org.apache.directory.fortress.core.model.Role;
-import org.apache.directory.fortress.core.model.SDSet;
-import org.apache.directory.fortress.core.model.User;
-import org.apache.directory.fortress.core.model.UserRole;
+import org.apache.directory.fortress.core.model.*;
 import org.apache.directory.fortress.core.util.VUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -91,6 +82,7 @@ public final class AdminMgrImpl extends Manageable implements AdminMgr, Serializ
     private static final RoleP roleP = new RoleP();
     private static final SdP sdP = new SdP();
     private static final UserP userP = new UserP();
+    private static final GroupP groupP = new GroupP();
     private static final Logger LOG = LoggerFactory.getLogger( CLS_NM );
 
 
@@ -262,6 +254,14 @@ public final class AdminMgrImpl extends Manageable implements AdminMgr, Serializ
             LOG.error( error );
             throw new SecurityException( GlobalErrIds.HIER_DEL_FAILED_HAS_CHILD, error, null );
         }
+        Role outRole = roleP.read( role );
+        outRole.setContextId( role.getContextId() );
+        // deassign all groups assigned to this role first (because of schema's configGroup class constraints)
+        List<Group> groups = groupP.roleGroups( outRole );
+        for ( Group group : groups )
+        {
+            groupP.deassign( group, outRole.getDn() );
+        }
         // search for all users assigned this role and deassign:
         List<User> users = userP.getAssignedUsers( role );
         if ( users != null )
@@ -285,7 +285,6 @@ public final class AdminMgrImpl extends Manageable implements AdminMgr, Serializ
             }
         }
         roleP.delete( role );
-        // TODO: what about groups? Should we remove roles from group members?
    }
 
 

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/252e6116/src/main/java/org/apache/directory/fortress/core/impl/DSDChecker.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/impl/DSDChecker.java b/src/main/java/org/apache/directory/fortress/core/impl/DSDChecker.java
index 8a47857..077ddea 100755
--- a/src/main/java/org/apache/directory/fortress/core/impl/DSDChecker.java
+++ b/src/main/java/org/apache/directory/fortress/core/impl/DSDChecker.java
@@ -88,14 +88,22 @@ public class DSDChecker
         {
             return rc;
         }
-        // get the list of authorized roles for this user:
-        Set<String> authorizedRoleSet = RoleUtil.getInstance().getInheritedRoles( activeRoleList, session.getUser().getContextId() );
+
+        // Depending on if session is group or user session, fill objects
+        String contextId = session.isGroupSession()
+                ? session.getGroup().getContextId()
+                : session.getUser().getContextId();
+        String entityId = session.isGroupSession() ? session.getGroupName() : session.getUserId();
+        String entityType = session.isGroupSession() ? "groupName" : "userId";
+
+        // get the list of authorized roles for this user/group:
+        Set<String> authorizedRoleSet = RoleUtil.getInstance().getInheritedRoles( activeRoleList, contextId);
         // only need to check DSD constraints if more than one role is being activated:
         if ( authorizedRoleSet != null && authorizedRoleSet.size() > 1 )
         {
             // get all DSD sets that contain the candidate activated and authorized roles,
             //If DSD cache is disabled, this will search the directory using authorizedRoleSet
-            Set<SDSet> dsdSets = SDUtil.getInstance().getDsdCache( authorizedRoleSet, session.getUser().getContextId() );
+            Set<SDSet> dsdSets = SDUtil.getInstance().getDsdCache( authorizedRoleSet, contextId);
             if ( dsdSets != null && dsdSets.size() > 0 )
             {
                 for ( SDSet dsd : dsdSets )
@@ -115,7 +123,7 @@ public class DSDChecker
                             if ( matchCount >= dsd.getCardinality() )
                             {
                                 activatedRoles.remove();
-                                String warning = "validate userId [" + session.getUserId()
+                                String warning = "validate " + entityType + " [" + entityId
                                     + "] failed activation of assignedRole [" + activatedRole.getName()
                                     + "] validates DSD Set Name:" + dsd.getName() + " Cardinality:"
                                     + dsd.getCardinality();
@@ -127,8 +135,7 @@ public class DSDChecker
                         }
                         else
                         {
-                            Set<String> parentSet = RoleUtil.getInstance().getAscendants( activatedRole.getName(), session.getUser()
-                                .getContextId() );
+                            Set<String> parentSet = RoleUtil.getInstance().getAscendants( activatedRole.getName(), contextId);
                             // now check for every role inherited from this activated role:
                             for ( String parentRole : parentSet )
                             {
@@ -137,7 +144,7 @@ public class DSDChecker
                                     matchCount++;
                                     if ( matchCount >= dsd.getCardinality() )
                                     {
-                                        String warning = "validate userId [" + session.getUserId()
+                                        String warning = "validate " + entityType + " [" + entityId
                                             + "] assignedRole [" + activatedRole.getName() + "] parentRole ["
                                             + parentRole + "] validates DSD Set Name:" + dsd.getName()
                                             + " Cardinality:" + dsd.getCardinality();

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/252e6116/src/main/java/org/apache/directory/fortress/core/impl/GroupMgrImpl.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/impl/GroupMgrImpl.java b/src/main/java/org/apache/directory/fortress/core/impl/GroupMgrImpl.java
index 6341600..195471d 100755
--- a/src/main/java/org/apache/directory/fortress/core/impl/GroupMgrImpl.java
+++ b/src/main/java/org/apache/directory/fortress/core/impl/GroupMgrImpl.java
@@ -209,6 +209,8 @@ public class GroupMgrImpl extends Manageable implements GroupMgr, Serializable
         {
             Role role = reviewMgr.readRole( new Role( member ) );
             dn = role.getDn();
+            // Validate SSD constraints
+            SDUtil.getInstance().validateSSD( group, role );
         }
         else
         {

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/252e6116/src/main/java/org/apache/directory/fortress/core/impl/GroupP.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/impl/GroupP.java b/src/main/java/org/apache/directory/fortress/core/impl/GroupP.java
index 31512bb..f0bc6b6 100755
--- a/src/main/java/org/apache/directory/fortress/core/impl/GroupP.java
+++ b/src/main/java/org/apache/directory/fortress/core/impl/GroupP.java
@@ -137,7 +137,10 @@ final class GroupP
      */
     Group assign( Group entity, String userDn ) throws SecurityException
     {
-        return gDao.assign( entity, userDn );
+        Group group = read( entity );
+        group.setContextId( entity.getContextId() );
+
+        return gDao.assign( group, userDn );
     }
 
 
@@ -151,7 +154,10 @@ final class GroupP
      */
     Group deassign( Group entity, String userDn ) throws SecurityException
     {
-        return gDao.deassign( entity, userDn );
+        Group group = read( entity );
+        group.setContextId( entity.getContextId() );
+
+        return gDao.deassign( group, userDn );
     }
 
 
@@ -241,29 +247,37 @@ final class GroupP
         {
             // Process selective activation of user's RBAC roles into session:
             List<String> availableRoles = session.getGroup().getMembers();
-            availableRoles.retainAll(group.getMembers());
-
-            // Fill aux field 'roles' with Role entities
-            fillRoles(session.getGroup());
+            availableRoles.retainAll( group.getMembers() );
         }
+        // Fill aux field 'roles' with Role entities
+        fillRoles( session.getGroup() );
+
         // Check role temporal constraints + activate roles:
         VUtil.getInstance().validateConstraints( session, VUtil.ConstraintType.ROLE, true );
         return session;
     }
 
 
-    // TODO: docs
     private Session createSessionTrusted( Group inGroup) throws SecurityException
     {
         Group group = read( inGroup );
         group.setContextId( inGroup.getContextId() );
 
+        if ( group.getType() != Group.Type.ROLE )
+        {
+            String info = "createSession failed for Group ["
+                    + group.getName() + "], group must be of type ROLE.";
+
+            throw new ValidationException( GlobalErrIds.GROUP_TYPE_INVLD, info );
+        }
+
         Session session = new Session(group);
         // Set this flag to false because group was not authenticated.
         session.setAuthenticated( false );
         return session;
     }
 
+
     /**
      * Populates the auxiliary field 'roles' in given group object with
      * {@link UserRole} data
@@ -279,14 +293,14 @@ final class GroupP
             for ( String roleDn : members )
             {
                 String roleRdn = roleDn;
-                if (group.isMemberDn())
+                if ( group.isMemberDn() )
                 {
-                    String[] parts = roleDn.split(",");
+                    String[] parts = roleDn.split( "," );
                     if (parts.length > 0)
                     {
                         roleRdn = parts[ 0 ];
                     }
-                    roleRdn = roleRdn.replaceFirst("cn=", ""); // remove 'cn='
+                    roleRdn = roleRdn.replaceFirst( "cn=", "" ); // remove 'cn='
                 }
                 Role inRole = new Role( roleRdn );
                 inRole.setContextId( group.getContextId() );

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/252e6116/src/main/java/org/apache/directory/fortress/core/impl/PermDAO.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/impl/PermDAO.java b/src/main/java/org/apache/directory/fortress/core/impl/PermDAO.java
index 3152a20..4d45c34 100755
--- a/src/main/java/org/apache/directory/fortress/core/impl/PermDAO.java
+++ b/src/main/java/org/apache/directory/fortress/core/impl/PermDAO.java
@@ -964,7 +964,8 @@ final class PermDAO extends LdapDataProvider
         boolean result = false;
         Set<String> userIds = permission.getUsers();
 
-        if ( CollectionUtils.isNotEmpty( userIds ) && userIds.contains( session.getUserId() ) )
+        if ( !session.isGroupSession() && CollectionUtils.isNotEmpty( userIds )
+                && userIds.contains( session.getUserId() ) )
         {
             // user is assigned directly to this permission, no need to look further.
             return true;

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/252e6116/src/main/java/org/apache/directory/fortress/core/impl/SDUtil.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/impl/SDUtil.java b/src/main/java/org/apache/directory/fortress/core/impl/SDUtil.java
index 635e62b..3f9a501 100755
--- a/src/main/java/org/apache/directory/fortress/core/impl/SDUtil.java
+++ b/src/main/java/org/apache/directory/fortress/core/impl/SDUtil.java
@@ -31,17 +31,9 @@ import net.sf.ehcache.search.Results;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.directory.api.ldap.model.constants.SchemaConstants;
-import org.apache.directory.fortress.core.GlobalErrIds;
-import org.apache.directory.fortress.core.GlobalIds;
-import org.apache.directory.fortress.core.ReviewMgr;
-import org.apache.directory.fortress.core.ReviewMgrFactory;
+import org.apache.directory.fortress.core.*;
 import org.apache.directory.fortress.core.SecurityException;
-import org.apache.directory.fortress.core.model.Constraint;
-import org.apache.directory.fortress.core.model.Role;
-import org.apache.directory.fortress.core.model.SDSet;
-import org.apache.directory.fortress.core.model.Session;
-import org.apache.directory.fortress.core.model.User;
-import org.apache.directory.fortress.core.model.UserRole;
+import org.apache.directory.fortress.core.model.*;
 import org.apache.directory.fortress.core.util.Config;
 import org.apache.directory.fortress.core.util.cache.Cache;
 import org.apache.directory.fortress.core.util.cache.CacheMgr;
@@ -128,34 +120,62 @@ final class SDUtil
     void validateSSD(User user, Role role)
         throws SecurityException
     {
-        int matchCount;
         // get all authorized roles for user
-        ReviewMgr rMgr = ReviewMgrFactory.createInstance(user.getContextId());
-        Set<String> rls = rMgr.authorizedRoles(user);
+        String contextId = user.getContextId();
+        ReviewMgr rMgr = ReviewMgrFactory.createInstance( contextId );
+        Set<String> rls = rMgr.authorizedRoles( user );
+
+        checkSSD( role, rls, contextId);
+    }
+
+    /**
+     * This method is called by GroupMgr.assign and is used to validate Static Separation of Duty
+     * constraints when assigning a role to group.
+     *
+     * @param group
+     * @param role
+     * @throws org.apache.directory.fortress.core.SecurityException
+     *
+     */
+    void validateSSD( Group group, Role role ) throws SecurityException
+    {
+        // get all authorized roles for this group
+        String contextId = group.getContextId();
+        GroupMgr groupMgr = GroupMgrFactory.createInstance(contextId);
+        List<UserRole> roles = groupMgr.groupRoles( group );
+        Set<String> rls = RoleUtil.getInstance().getInheritedRoles( roles, contextId);
+        // check SSD constraints
+        checkSSD( role, rls, contextId);
+    }
+
+    private void checkSSD( Role role, Set<String> authorizedRls, String contextId ) throws SecurityException
+    {
+        int matchCount;
         // Need to proceed?
-        if (!CollectionUtils.isNotEmpty( rls ))
+        if (CollectionUtils.isEmpty( authorizedRls ))
         {
             return;
         }
 
         // get all SSD sets that contain the new role
-        List<SDSet> ssdSets = getSsdCache(role.getName(), user.getContextId());
-        for (SDSet ssd : ssdSets)
+        List<SDSet> ssdSets = getSsdCache( role.getName(), contextId );
+        for ( SDSet ssd : ssdSets )
         {
             matchCount = 0;
             Set<String> map = ssd.getMembers();
-            // iterate over every authorized role for user:
-            for (String authRole : rls)
+            // iterate over every authorized role for user/group:
+            for ( String authRole : authorizedRls )
             {
                 // is there a match found between authorized role and SSD set's members?
-                if (map.contains(authRole))
+                if ( map.contains( authRole ) )
                 {
                     matchCount++;
                     // does the match count exceed the cardinality allowed for this particular SSD set?
-                    if (matchCount >= ssd.getCardinality() - 1)
+                    if ( matchCount >= ssd.getCardinality() - 1 )
                     {
-                        String error = "validateSSD new role [" + role.getName() + "] validates SSD Set Name:" + ssd.getName() + " Cardinality:" + ssd.getCardinality();
-                        throw new SecurityException(GlobalErrIds.SSD_VALIDATION_FAILED, error);
+                        String error = "validateSSD new role [" + role.getName() + "] validates SSD Set Name:"
+                                + ssd.getName() + " Cardinality:" + ssd.getCardinality();
+                        throw new SecurityException( GlobalErrIds.SSD_VALIDATION_FAILED, error );
                     }
                 }
             }
@@ -177,7 +197,7 @@ final class SDUtil
     {
         // get all activated roles from user's session:
         List<UserRole> rls = session.getRoles();
-        if (!CollectionUtils.isNotEmpty( rls ))
+        if (CollectionUtils.isEmpty( rls ))
         {
             // An empty list of roles was passed in the session variable.
             // No need to continue.

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/252e6116/src/main/java/org/apache/directory/fortress/core/model/Group.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/model/Group.java b/src/main/java/org/apache/directory/fortress/core/model/Group.java
index 5874871..73aa6bd 100755
--- a/src/main/java/org/apache/directory/fortress/core/model/Group.java
+++ b/src/main/java/org/apache/directory/fortress/core/model/Group.java
@@ -20,11 +20,7 @@
 package org.apache.directory.fortress.core.model;
 
 
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlEnum;
-import javax.xml.bind.annotation.XmlRootElement;
-import javax.xml.bind.annotation.XmlType;
+import javax.xml.bind.annotation.*;
 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Enumeration;
@@ -42,7 +38,8 @@ import java.util.StringTokenizer;
         "protocol",
         "members",
         "props",
-        "type"
+        "type",
+        "roles"
 })
 public class Group extends FortEntity implements Serializable
 {
@@ -52,18 +49,20 @@ public class Group extends FortEntity implements Serializable
     private String protocol;
     private List<String> members;
     private Props props = new Props();
+    @XmlTransient
     private boolean memberDn;
     private Type type;
 
     /**
-     *  Auxiliary field used to store roles in UserRole format. Used only internally by DAO/Managers.
+     *  Auxiliary field used to store roles in UserRole format.
      */
+    @XmlElement( nillable = true )
     private List<UserRole> roles = new ArrayList<>();
 
     /**
      * enum for User or Role data sets.  Both nodes may be stored in the same LDAP container.
      */
-    @XmlType(name = "type")
+    @XmlType(name = "groupType")
     @XmlEnum
     public enum Type
     {

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/252e6116/src/main/java/org/apache/directory/fortress/core/model/Session.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/model/Session.java b/src/main/java/org/apache/directory/fortress/core/model/Session.java
index c6d2c62..12ff328 100755
--- a/src/main/java/org/apache/directory/fortress/core/model/Session.java
+++ b/src/main/java/org/apache/directory/fortress/core/model/Session.java
@@ -656,7 +656,7 @@ public class Session  extends FortEntity implements PwMessage, Serializable
      * Set the value to 'true' indicating that Session is created for Group entity
      * @param isGroupSession indicates if Session is for Group
      */
-    public void setGroupSession(boolean isGroupSession) { isGroupSession = isGroupSession; }
+    public void setGroupSession(boolean isGroupSession) { this.isGroupSession = isGroupSession; }
 
     /**
      * Set the userId that is associated with User.  UserId is required attribute and must be set on add, update, delete, createSession, authenticate, etc..
@@ -706,7 +706,6 @@ public class Session  extends FortEntity implements PwMessage, Serializable
     {
         if ( isGroupSession )
         {
-//            group.setRole( role );
             group.getRoles().add( role );
         }
         else

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/252e6116/src/main/java/org/apache/directory/fortress/core/rest/AccessMgrRestImpl.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/rest/AccessMgrRestImpl.java b/src/main/java/org/apache/directory/fortress/core/rest/AccessMgrRestImpl.java
index 416dc0b..533988b 100644
--- a/src/main/java/org/apache/directory/fortress/core/rest/AccessMgrRestImpl.java
+++ b/src/main/java/org/apache/directory/fortress/core/rest/AccessMgrRestImpl.java
@@ -137,8 +137,25 @@ public class AccessMgrRestImpl extends Manageable implements AccessMgr
     }
 
     @Override
-    public Session createGroupSession(Group group, boolean isTrusted) throws SecurityException {
-        return null;
+    public Session createSession( Group group ) throws SecurityException
+    {
+        VUtil.assertNotNull( group, GlobalErrIds.GROUP_NULL, CLS_NM + ".createSession" );
+        Session retSession;
+        FortRequest request = new FortRequest();
+        request.setContextId( this.contextId );
+        request.setEntity( group );
+        String szRequest = RestUtils.marshal( request );
+        String szResponse = RestUtils.getInstance().post( szRequest, HttpIds.RBAC_CREATE_GROUP_SESSION );
+        FortResponse response = RestUtils.unmarshall( szResponse );
+        if (response.getErrorCode() == 0)
+        {
+            retSession = response.getSession();
+        }
+        else
+        {
+            throw new SecurityException( response.getErrorCode(), response.getErrorMessage() );
+        }
+        return retSession;
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/252e6116/src/main/java/org/apache/directory/fortress/core/rest/HttpIds.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/rest/HttpIds.java b/src/main/java/org/apache/directory/fortress/core/rest/HttpIds.java
index 30d825c..eb55ec8 100644
--- a/src/main/java/org/apache/directory/fortress/core/rest/HttpIds.java
+++ b/src/main/java/org/apache/directory/fortress/core/rest/HttpIds.java
@@ -155,4 +155,13 @@ public class HttpIds
     public static final String CFG_UPDATE = "cfgUpdate";
     public static final String CFG_DELETE = "cfgDelete";
     public static final String CFG_READ = "cfgRead";
+    public static final String RBAC_CREATE_GROUP_SESSION = "rbacCreateGroup";
+    public static final String GROUP_ADD = "groupAdd";
+    public static final String GROUP_READ = "groupRead";
+    public static final String GROUP_UPDATE = "groupUpdate";
+    public static final String GROUP_DELETE = "groupDelete";
+    public static final String GROUP_ROLE_ASGNED = "roleGroupAsigned";
+    public static final String GROUP_ASGNED = "groupAsigned";
+    public static final String GROUP_ROLE_ASGN = "groupRoleAsgn";
+    public static final String GROUP_ROLE_DEASGN = "groupRoleDeasgn";
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/252e6116/src/main/java/org/apache/directory/fortress/core/util/VUtil.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/util/VUtil.java b/src/main/java/org/apache/directory/fortress/core/util/VUtil.java
index 4e5baf6..622cf9d 100755
--- a/src/main/java/org/apache/directory/fortress/core/util/VUtil.java
+++ b/src/main/java/org/apache/directory/fortress/core/util/VUtil.java
@@ -36,13 +36,7 @@ import org.apache.directory.fortress.core.GlobalErrIds;
 import org.apache.directory.fortress.core.GlobalIds;
 import org.apache.directory.fortress.core.SecurityException;
 import org.apache.directory.fortress.core.ValidationException;
-import org.apache.directory.fortress.core.model.Constraint;
-import org.apache.directory.fortress.core.model.ConstraintValidator;
-import org.apache.directory.fortress.core.model.ObjectFactory;
-import org.apache.directory.fortress.core.model.PropUtil;
-import org.apache.directory.fortress.core.model.Session;
-import org.apache.directory.fortress.core.model.UserRole;
-import org.apache.directory.fortress.core.model.Warning;
+import org.apache.directory.fortress.core.model.*;
 import org.apache.directory.fortress.core.util.time.TUtil;
 import org.apache.directory.fortress.core.util.time.Time;
 import org.apache.directory.fortress.core.util.time.Validator;
@@ -561,22 +555,25 @@ public final class VUtil implements ConstraintValidator
         throws SecurityException
     {
         String location = "validateConstraints";
+        String entityId = session.isGroupSession() ? session.getGroupName() : session.getUserId();
+        String entityType = session.isGroupSession() ? "groupName" : "userId";
         int rc;
+
         if ( validators == null )
         {
             if ( LOG.isDebugEnabled() )
             {
-                LOG.debug( "{} userId [{}]  no constraints enabled", location, session.getUserId() );
+                    LOG.debug("{} " + entityType + " [{}] has no constraints enabled", location, entityId);
             }
             return;
         }
         // no need to continue if the role list is empty and we're trying to check role constraints:
-        else if ( type == ConstraintType.ROLE && !CollectionUtils.isNotEmpty( session.getRoles() )
-            && !CollectionUtils.isNotEmpty( session.getAdminRoles() ) )
+        else if ( type == ConstraintType.ROLE && CollectionUtils.isEmpty( session.getRoles() )
+            && CollectionUtils.isEmpty( session.getAdminRoles() ) )
         {
             if ( LOG.isDebugEnabled() )
             {
-                LOG.debug( "{} userId [{}]  has no roles assigned", location, session.getUserId() );
+                LOG.debug("{} " + entityType + " [{}]  has no roles assigned", location, entityId);
             }
             return;
         }
@@ -589,7 +586,7 @@ public final class VUtil implements ConstraintValidator
                 rc = val.validate( session, session.getUser(), currTime, type );
                 if ( rc > 0 )
                 {
-                    String info = location + " user [" + session.getUserId() + "] was deactivated reason code [" + rc
+                    String info = location + " user [" + entityId + "] was deactivated reason code [" + rc
                         + "]";
                     throw new ValidationException( rc, info );
                 }
@@ -600,42 +597,42 @@ public final class VUtil implements ConstraintValidator
                 if ( CollectionUtils.isNotEmpty( session.getRoles() ) )
                 {
                     // now check the constraint on every role activation candidate contained within session object:
-                    ListIterator<UserRole> roleItems = session.getRoles().listIterator();
-
-                    while ( roleItems.hasNext() )
+                    List<UserRole> rolesToRemove = new ArrayList<>();
+                    for ( UserRole role : session.getRoles() )
                     {
-                        Constraint constraint = roleItems.next();
-                        rc = val.validate( session, constraint, currTime, type );
-
+                        rc = val.validate( session, role, currTime, type );
                         if ( rc > 0 )
                         {
-                            String msg = location + " role [" + constraint.getName() + "] for user ["
-                                + session.getUserId() + "] was deactivated reason code [" + rc + "]";
+                            rolesToRemove.add( role );
+                            String msg = location + " role [" + role.getName() + "] for " + entityType
+                                    + "[" + entityId + "]" + " was deactivated reason code [" + rc + "]";
                             LOG.info( msg );
-                            roleItems.remove();
                             session.setWarning( new ObjectFactory().createWarning( rc, msg, Warning.Type.ROLE,
-                                constraint.getName() ) );
+                                    role.getName() ) );
                         }
                     }
+                    // remove all roles not passing validation
+                    session.getRoles().removeAll( rolesToRemove );
                 }
                 if ( CollectionUtils.isNotEmpty( session.getAdminRoles() ) )
                 {
                     // now check the constraint on every arbac role activation candidate contained within session object:
-                    ListIterator roleItems = session.getAdminRoles().listIterator();
-                    while ( roleItems.hasNext() )
+                    List<UserRole> rolesToRemove = new ArrayList<>();
+                    for ( UserRole role : session.getAdminRoles() )
                     {
-                        Constraint constraint = ( Constraint ) roleItems.next();
-                        rc = val.validate( session, constraint, currTime, ConstraintType.ROLE );
+                        rc = val.validate( session, role, currTime, type );
                         if ( rc > 0 )
                         {
-                            String msg = location + " admin role [" + constraint.getName() + "] for user ["
-                                + session.getUserId() + "] was deactivated reason code [" + rc + "]";
+                            rolesToRemove.add( role );
+                            String msg = location + " admin role [" + role.getName() + "] for " + entityType
+                                    + "[" + entityId + "]" + " was deactivated reason code [" + rc + "]";
                             LOG.info( msg );
-                            roleItems.remove();
                             session.setWarning( new ObjectFactory().createWarning( rc, msg, Warning.Type.ROLE,
-                                constraint.getName() ) );
+                                    role.getName() ) );
                         }
                     }
+                    // remove all roles not passing validation
+                    session.getAdminRoles().removeAll( rolesToRemove );
                 }
             }
         }
@@ -645,8 +642,12 @@ public final class VUtil implements ConstraintValidator
             && CollectionUtils.isNotEmpty( session.getRoles() ) )
         {
             Validator dsdVal = ( Validator ) ClassUtil.createInstance( DSDVALIDATOR );
-            // Do not validate for Groups
-            if ( !session.isGroupSession() )
+            if ( session.isGroupSession() )
+            {
+                // pass session's group wrapped into constraint interface
+                dsdVal.validate( session, new ConstraintedGroup( session.getGroup() ), null, null );
+            }
+            else
             {
                 dsdVal.validate( session, session.getUser(), null, null );
             }
@@ -679,4 +680,120 @@ public final class VUtil implements ConstraintValidator
         }
         return validators;
     }
+
+    /**
+     * A class to wrap the group into constrainted interface to pass to DSD validator.
+     * Group itself doesn't have temporal contraints.
+     */
+    private class ConstraintedGroup implements Constraint {
+        private Group group;
+
+        public ConstraintedGroup(Group group) {
+            this.group = group;
+        }
+
+        public Group getGroup() {
+            return group;
+        }
+
+        @Override
+        public boolean isTemporalSet() {
+            return false;
+        }
+
+        @Override
+        public void setTimeout(Integer timeout) {
+
+        }
+
+        @Override
+        public void setBeginTime(String beginTime) {
+
+        }
+
+        @Override
+        public void setEndTime(String endTime) {
+
+        }
+
+        @Override
+        public void setBeginDate(String beginDate) {
+
+        }
+
+        @Override
+        public void setEndDate(String endDate) {
+
+        }
+
+        @Override
+        public void setDayMask(String dayMask) {
+
+        }
+
+        @Override
+        public void setBeginLockDate(String beginLockDate) {
+
+        }
+
+        @Override
+        public void setEndLockDate(String endLockDate) {
+
+        }
+
+        @Override
+        public void setName(String name) {
+
+        }
+
+        @Override
+        public String getRawData() {
+            return null;
+        }
+
+        @Override
+        public Integer getTimeout() {
+            return null;
+        }
+
+        @Override
+        public String getBeginTime() {
+            return null;
+        }
+
+        @Override
+        public String getEndTime() {
+            return null;
+        }
+
+        @Override
+        public String getBeginDate() {
+            return null;
+        }
+
+        @Override
+        public String getEndDate() {
+            return null;
+        }
+
+        @Override
+        public String getBeginLockDate() {
+            return null;
+        }
+
+        @Override
+        public String getEndLockDate() {
+            return null;
+        }
+
+        @Override
+        public String getDayMask() {
+            return null;
+        }
+
+        @Override
+        public String getName() {
+            return group.getName();
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/252e6116/src/test/java/org/apache/directory/fortress/core/impl/FortressJUnitTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/directory/fortress/core/impl/FortressJUnitTest.java b/src/test/java/org/apache/directory/fortress/core/impl/FortressJUnitTest.java
index c590b68..b7e6166 100755
--- a/src/test/java/org/apache/directory/fortress/core/impl/FortressJUnitTest.java
+++ b/src/test/java/org/apache/directory/fortress/core/impl/FortressJUnitTest.java
@@ -110,6 +110,11 @@ public class FortressJUnitTest extends TestCase
                 suite.addTest( new PswdPolicyMgrImplTest( "testDeletePasswordPolicy" ) );
             }
 
+            // GroupMgr
+            suite.addTest( new GroupMgrImplTest( "testDeassignGroupRoleMember" ) );
+            suite.addTest( new GroupMgrImplTest( "testDeassignGroupUserMember" ) );
+            suite.addTest( new GroupMgrImplTest( "testDeleteGroup" ) );
+
             // AdminMgrImplTest RBAC Teardown APIs:
             suite.addTest( new AdminMgrImplTest( "testRevokePermissionUser" ) );
             suite.addTest( new AdminMgrImplTest( "testRevokePermissionRole" ) );
@@ -200,6 +205,13 @@ public class FortressJUnitTest extends TestCase
         suite.addTest( new AdminMgrImplTest( "testGrantPermissionRole" ) );
         suite.addTest( new AdminMgrImplTest( "testGrantPermissionUser" ) );
 
+        // GroupMgr APIs
+        suite.addTest( new GroupMgrImplTest( "testAddGroup" ) );
+        suite.addTest( new GroupMgrImplTest( "testAssignGroupUserMember" ) );
+        suite.addTest( new GroupMgrImplTest( "testAssignGroupRoleMember" ) );
+        suite.addTest( new GroupMgrImplTest( "testGroupRoles" ) );
+        suite.addTest( new GroupMgrImplTest( "testRoleGroups" ) );
+
         /***********************************************************/
         /* 3. Interrogation                                        */
         /***********************************************************/

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/252e6116/src/test/java/org/apache/directory/fortress/core/impl/GroupMgrImplTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/directory/fortress/core/impl/GroupMgrImplTest.java b/src/test/java/org/apache/directory/fortress/core/impl/GroupMgrImplTest.java
new file mode 100644
index 0000000..e1a4a1d
--- /dev/null
+++ b/src/test/java/org/apache/directory/fortress/core/impl/GroupMgrImplTest.java
@@ -0,0 +1,279 @@
+package org.apache.directory.fortress.core.impl;
+
+import junit.framework.TestCase;
+import org.apache.directory.fortress.core.*;
+import org.apache.directory.fortress.core.SecurityException;
+import org.apache.directory.fortress.core.model.Group;
+import org.apache.directory.fortress.core.model.Role;
+import org.apache.directory.fortress.core.model.User;
+import org.apache.directory.fortress.core.model.UserRole;
+import org.apache.directory.fortress.core.util.LogUtil;
+import org.junit.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+
+
+public class GroupMgrImplTest extends TestCase {
+    private static final String CLS_NM = AdminMgrImplTest.class.getName();
+    private static final Logger LOG = LoggerFactory.getLogger( CLS_NM );
+    private GroupMgr groupMgr;
+
+    public GroupMgrImplTest( String name )
+    {
+        super( name );
+    }
+
+    public void testAddGroup()
+    {
+        addGroups( "ADD-GRP TG1", GroupTestData.TEST_GROUP1 );
+        addGroups( "ADD-GRP TG2", GroupTestData.TEST_GROUP2 );
+        addGroups( "ADD-GRP TG3", GroupTestData.TEST_GROUP3 );
+    }
+
+    private void addGroups( String message, Group group )
+    {
+        LogUtil.logIt( message );
+        try
+        {
+            groupMgr = GroupMgrFactory.createInstance(TestUtils.getContext());
+            groupMgr.add( group );
+            LOG.debug( "addGroup group [" + group.getName() + "] successful" );
+        }
+        catch ( SecurityException ex )
+        {
+            ex.printStackTrace();
+            LOG.error("addGroup: caught SecurityException rc=" + ex.getErrorId() + ", msg=" + ex.getMessage(), ex);
+            fail(ex.getMessage());
+        }
+    }
+
+    public void testDeleteGroup()
+    {
+        deleteGroups( "DEL-GRP TG1", GroupTestData.TEST_GROUP1 );
+        deleteGroups( "DEL-GRP TG2", GroupTestData.TEST_GROUP2 );
+        deleteGroups( "DEL-GRP TG3", GroupTestData.TEST_GROUP3 );
+    }
+
+    private void deleteGroups( String message, Group group )
+    {
+        LogUtil.logIt( message );
+        try
+        {
+            groupMgr = GroupMgrFactory.createInstance(TestUtils.getContext());
+            Group nameOnlyGroup = new Group( group.getName() );
+            groupMgr.delete( nameOnlyGroup );
+            LOG.debug( "addGroup group [" + group.getName() + "] successful" );
+        }
+        catch ( SecurityException ex )
+        {
+            ex.printStackTrace();
+            LOG.error("addGroup: caught SecurityException rc=" + ex.getErrorId() + ", msg=" + ex.getMessage(), ex);
+            fail(ex.getMessage());
+        }
+    }
+
+    public void testAssignGroupRoleMember()
+    {
+        assignRoleMember( "ASGN-GRP TG1 TR2", GroupTestData.TEST_GROUP1, RoleTestData.ROLES_TR2 );
+        assignRoleMember( "ASGN-GRP TG2 TR3", GroupTestData.TEST_GROUP2, RoleTestData.ROLES_TR3 );
+    }
+
+    private void assignRoleMember( String message, Group group, String[][] roles )
+    {
+        LogUtil.logIt( message );
+        try
+        {
+            groupMgr = GroupMgrFactory.createInstance( TestUtils.getContext() );
+
+            for ( String[] roleArray : roles )
+            {
+                Role role = RoleTestData.getRole( roleArray );
+                groupMgr.assign(group, role.getName() );
+            }
+            LOG.debug( "assignRoleMember group [" + group.getName() + "] successful" );
+
+            int countOfOldRoles = group.getMembers().size();
+            int countOfNewRoles = roles.length;
+            // read from LDAP and get count of members
+            Group groupFromLdap = groupMgr.read(group);
+            int actualAmountOfMembers = groupFromLdap.getMembers().size();
+            assertEquals( CLS_NM + ".assignRoleMember failed members size check",
+                    countOfOldRoles + countOfNewRoles, actualAmountOfMembers);
+        }
+        catch ( SecurityException ex )
+        {
+            ex.printStackTrace();
+            LOG.error("assignRoleMember: caught SecurityException rc=" + ex.getErrorId() + ", msg=" + ex.getMessage(), ex);
+            fail(ex.getMessage());
+        }
+    }
+
+    public void testAssignGroupUserMember()
+    {
+        assignUserMember( "ASGN-GRP TG3 TU2", GroupTestData.TEST_GROUP3, UserTestData.USERS_TU2);
+    }
+
+    private void assignUserMember( String message, Group group, String[][] users )
+    {
+        LogUtil.logIt( message );
+        try
+        {
+            groupMgr = GroupMgrFactory.createInstance( TestUtils.getContext() );
+
+            for ( String[] userArray : users )
+            {
+                User user = UserTestData.getUser( userArray );
+                groupMgr.assign(group, user.getUserId() );
+            }
+            LOG.debug( "assignUserMember group [" + group.getName() + "] successful" );
+
+            int countOfOldUsers = group.getMembers().size();
+            int countOfNewUsers = users.length;
+            // read from LDAP and get count of members
+            Group groupFromLdap = groupMgr.read(group);
+            int actualAmountOfMembers = groupFromLdap.getMembers().size();
+            assertEquals( CLS_NM + ".assignUserMember failed members size check",
+                    countOfOldUsers + countOfNewUsers, actualAmountOfMembers);
+        }
+        catch ( SecurityException ex )
+        {
+            ex.printStackTrace();
+            LOG.error("assignUserMember: caught SecurityException rc=" + ex.getErrorId() + ", msg=" + ex.getMessage(), ex);
+            fail(ex.getMessage());
+        }
+    }
+
+    public void testDeassignGroupRoleMember()
+    {
+        deassignRoleMember( "DEASGN-GRP TG1 TR2", GroupTestData.TEST_GROUP1, RoleTestData.ROLES_TR2 );
+        deassignRoleMember( "DEASGN-GRP TG2 TR3", GroupTestData.TEST_GROUP2, RoleTestData.ROLES_TR3 );
+    }
+
+    private void deassignRoleMember( String message, Group group, String[][] roles )
+    {
+        LogUtil.logIt( message );
+        try
+        {
+            groupMgr = GroupMgrFactory.createInstance( TestUtils.getContext() );
+
+            for ( String[] roleArray : roles )
+            {
+                Role role = RoleTestData.getRole( roleArray );
+                groupMgr.deassign(group, role.getName() );
+            }
+            LOG.debug( "deassignRoleMember group [" + group.getName() + "] successful" );
+
+            int countOfOldRoles = group.getMembers().size();
+            // read from LDAP and get count of members
+            Group groupFromLdap = groupMgr.read(group);
+            int actualAmountOfMembers = groupFromLdap.getMembers().size();
+            assertEquals( CLS_NM + ".deassignRoleMember failed members size check",
+                    countOfOldRoles, actualAmountOfMembers);
+        }
+        catch ( SecurityException ex )
+        {
+            ex.printStackTrace();
+            LOG.error("deassignRoleMember: caught SecurityException rc=" + ex.getErrorId() + ", msg=" + ex.getMessage(), ex);
+            fail(ex.getMessage());
+        }
+    }
+
+    public void testDeassignGroupUserMember()
+    {
+        deassignUserMember( "DEASGN-GRP TG3 TU2", GroupTestData.TEST_GROUP3, UserTestData.USERS_TU2);
+    }
+
+    private void deassignUserMember( String message, Group group, String[][] users )
+    {
+        LogUtil.logIt( message );
+        try
+        {
+            groupMgr = GroupMgrFactory.createInstance( TestUtils.getContext() );
+
+            for ( String[] userArray : users )
+            {
+                User user = UserTestData.getUser( userArray );
+                groupMgr.deassign(group, user.getUserId() );
+            }
+            LOG.debug( "deassignUserMember group [" + group.getName() + "] successful" );
+
+            int countOfOldUsers = group.getMembers().size();
+            // read from LDAP and get count of members after deassignment
+            Group groupFromLdap = groupMgr.read(group);
+            int actualAmountOfMembers = groupFromLdap.getMembers().size();
+            assertEquals( CLS_NM + ".deassignUserMember failed members size check",
+                    countOfOldUsers, actualAmountOfMembers);
+        }
+        catch ( SecurityException ex )
+        {
+            ex.printStackTrace();
+            LOG.error("deassignUserMember: caught SecurityException rc=" + ex.getErrorId() + ", msg=" + ex.getMessage(), ex);
+            fail(ex.getMessage());
+        }
+    }
+
+    public void testGroupRoles()
+    {
+        groupRoles( "GRP-RLS TG1 TR1+TR2", GroupTestData.TEST_GROUP1, RoleTestData.ROLES_TR2 );
+        groupRoles( "GRP-RLS TG2 TR2+TR3", GroupTestData.TEST_GROUP2, RoleTestData.ROLES_TR3 );
+    }
+
+    private void groupRoles( String message, Group group, String[][] addedRoles )
+    {
+        LogUtil.logIt( message );
+        try
+        {
+            groupMgr = GroupMgrFactory.createInstance( TestUtils.getContext() );
+            List<UserRole> actualRoles = groupMgr.groupRoles(group);
+            LOG.debug( "groupRoles group [" + group.getName() + "] successful" );
+
+            int initialRolesSize = group.getMembers().size();
+            int addedRolesSize = addedRoles.length;
+            assertEquals( CLS_NM + ".groupRoles failed members size check",
+                    initialRolesSize + addedRolesSize, actualRoles.size() );
+        }
+        catch ( SecurityException ex )
+        {
+            ex.printStackTrace();
+            LOG.error("groupRoles: caught SecurityException rc=" + ex.getErrorId() + ", msg=" + ex.getMessage(), ex);
+            fail(ex.getMessage());
+        }
+    }
+
+    public void testRoleGroups()
+    {
+        roleGroups( "RLE-GRPS TR2 TG1+TG2", RoleTestData.ROLES_TR2,
+                Arrays.asList( GroupTestData.TEST_GROUP1, GroupTestData.TEST_GROUP2 ));
+    }
+
+    private void roleGroups( String message, String[][] roles, List<Group> expectedGroups )
+    {
+        LogUtil.logIt( message );
+        try
+        {
+            groupMgr = GroupMgrFactory.createInstance( TestUtils.getContext() );
+            for ( String[] roleArray : roles )
+            {
+                Role role = RoleTestData.getRole(roleArray);
+                List<Group> actualGroups = groupMgr.roleGroups(role);
+                LOG.debug( "roleGroups role [" + role.getName() + "] successful" );
+
+                assertEquals( CLS_NM + ".roleGroups failed", expectedGroups, actualGroups);
+            }
+        }
+        catch ( SecurityException ex )
+        {
+            ex.printStackTrace();
+            LOG.error("groupRoles: caught SecurityException rc=" + ex.getErrorId() + ", msg=" + ex.getMessage(), ex);
+            fail(ex.getMessage());
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/252e6116/src/test/java/org/apache/directory/fortress/core/impl/GroupTestData.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/directory/fortress/core/impl/GroupTestData.java b/src/test/java/org/apache/directory/fortress/core/impl/GroupTestData.java
new file mode 100755
index 0000000..ff95a15
--- /dev/null
+++ b/src/test/java/org/apache/directory/fortress/core/impl/GroupTestData.java
@@ -0,0 +1,94 @@
+/*
+ *   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.directory.fortress.core.impl;
+
+
+import org.apache.directory.fortress.core.model.Group;
+import org.apache.directory.fortress.core.model.Group.Type;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class GroupTestData
+{
+    public static final Group TEST_GROUP1 =
+            createGroup
+            (
+                    "TestGroup1",
+                    Type.ROLE,
+                    "protocol1",
+                    false,
+                    roleNames( RoleTestData.ROLES_TR1 )
+            );
+
+    public static final Group TEST_GROUP2 =
+            createGroup
+            (
+                    "TestGroup2",
+                    Type.ROLE,
+                    "protocol2",
+                    false,
+                    roleNames( RoleTestData.ROLES_TR2 )
+            );
+
+    public static final Group TEST_GROUP3 =
+            createGroup
+            (
+                    "TestGroup3",
+                    Type.USER,
+                    "protocol3",
+                    false,
+                    userNames( UserTestData.USERS_TU1 )
+            );
+
+    private static List<String> roleNames(String[][] rolesArray )
+    {
+        List<String> names = new ArrayList<>();
+        for (String[] role : rolesArray )
+        {
+            names.add( RoleTestData.getName( role ) );
+        }
+        return names;
+    }
+
+    private static List<String> userNames(String[][] userArray )
+    {
+        List<String> names = new ArrayList<>();
+        for (String[] user : userArray )
+        {
+            names.add( UserTestData.getUserId( user ) );
+        }
+        return names;
+    }
+
+    private static Group createGroup(String name, Type type, String protocol, boolean memberDn, List<String> memberNames)
+    {
+        Group group = new Group();
+        group.setName( name );
+        group.setProtocol( protocol );
+        group.setMemberDn( memberDn );
+        group.setType( type );
+        group.setMembers( memberNames );
+        return group;
+    }
+}
\ No newline at end of file


[4/4] directory-fortress-core git commit: FC-144 Use Groups of Roles to create Sessions. This closes #6

Posted by sm...@apache.org.
FC-144 Use Groups of Roles to create Sessions. This closes #6


Project: http://git-wip-us.apache.org/repos/asf/directory-fortress-core/repo
Commit: http://git-wip-us.apache.org/repos/asf/directory-fortress-core/commit/cb34ef22
Tree: http://git-wip-us.apache.org/repos/asf/directory-fortress-core/tree/cb34ef22
Diff: http://git-wip-us.apache.org/repos/asf/directory-fortress-core/diff/cb34ef22

Branch: refs/heads/master
Commit: cb34ef224bc9b1c680fb4002039e6f3dd988a8fc
Parents: 5192805
Author: Shawn McKinney <sm...@apache.org>
Authored: Sun Sep 25 17:48:05 2016 -0500
Committer: Shawn McKinney <sm...@apache.org>
Committed: Sun Sep 25 17:48:05 2016 -0500

----------------------------------------------------------------------
 README-QUICKSTART-APACHEDS.md | 2 +-
 README-QUICKSTART-SLAPD.md    | 2 +-
 README-TEN-MINUTE-GUIDE.md    | 2 +-
 README.md                     | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/cb34ef22/README-QUICKSTART-APACHEDS.md
----------------------------------------------------------------------
diff --git a/README-QUICKSTART-APACHEDS.md b/README-QUICKSTART-APACHEDS.md
index c791e48..ad3b214 100644
--- a/README-QUICKSTART-APACHEDS.md
+++ b/README-QUICKSTART-APACHEDS.md
@@ -18,7 +18,7 @@
 
 # ApacheDS & Fortress QUICKSTART
 
- Apache Fortress 1.0.1 and ApacheDS Quickstart System Architecture
+ Apache Fortress1.0.2-SNAPSHOT and ApacheDS Quickstart System Architecture
  ![ApacheDS & Fortress System Architecture](images/fortress-apacheds-system-arch.png "ApacheDS & Fortress System Architecture")
 
 -------------------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/cb34ef22/README-QUICKSTART-SLAPD.md
----------------------------------------------------------------------
diff --git a/README-QUICKSTART-SLAPD.md b/README-QUICKSTART-SLAPD.md
index a07a913..de79204 100644
--- a/README-QUICKSTART-SLAPD.md
+++ b/README-QUICKSTART-SLAPD.md
@@ -18,7 +18,7 @@
 
 # OpenLDAP & Fortress QUICKSTART
 
- Apache Fortress 1.0.1 and OpenLDAP Quickstart System Architecture
+ Apache Fortress 1.0.2-SNAPSHOT and OpenLDAP Quickstart System Architecture
  ![OpenLDAP & Fortress System Architecture](images/fortress-openldap-accel-system-arch.png "OpenLDAP & Fortress System Architecture")
 
 -------------------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/cb34ef22/README-TEN-MINUTE-GUIDE.md
----------------------------------------------------------------------
diff --git a/README-TEN-MINUTE-GUIDE.md b/README-TEN-MINUTE-GUIDE.md
index 197e63e..a71b24b 100644
--- a/README-TEN-MINUTE-GUIDE.md
+++ b/README-TEN-MINUTE-GUIDE.md
@@ -19,7 +19,7 @@
 -------------------------------------------------------------------------------
 # README for Apache Fortress Ten Minute Guide
 
- * Version 1.0.1
+ * Version 1.0.2-SNAPSHOT
  * This document has been deprecated in favor of:
     * Follow these instructions: [README-QUICKSTART-APACHEDS](./README-QUICKSTART-APACHEDS.md)
     * Follow these instructions: [README-QUICKSTART-SLAPD](./README-QUICKSTART-SLAPD.md)

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/cb34ef22/README.md
----------------------------------------------------------------------
diff --git a/README.md b/README.md
index 380b69f..b64a762 100644
--- a/README.md
+++ b/README.md
@@ -19,7 +19,7 @@
 -------------------------------------------------------------------------------
 # README for Apache Fortress Core
 
- * Version 1.0.1
+ * Version 1.0.2-SNAPSHOT
  * Apache Fortress Core System Architecture Diagram
  ![Apache Fortress Core System Architecture](images/fortress-core-system-arch.png "Apache Fortress Core System Architecture")
 


[3/4] directory-fortress-core git commit: Merge branch 'FC-144/assign-roles-for-groups' of https://github.com/vvakhlyuev-work/directory-fortress-core

Posted by sm...@apache.org.
Merge branch 'FC-144/assign-roles-for-groups' of https://github.com/vvakhlyuev-work/directory-fortress-core


Project: http://git-wip-us.apache.org/repos/asf/directory-fortress-core/repo
Commit: http://git-wip-us.apache.org/repos/asf/directory-fortress-core/commit/5192805c
Tree: http://git-wip-us.apache.org/repos/asf/directory-fortress-core/tree/5192805c
Diff: http://git-wip-us.apache.org/repos/asf/directory-fortress-core/diff/5192805c

Branch: refs/heads/master
Commit: 5192805c88f4d1216215f340aacd0300937c295c
Parents: 9271edf 252e611
Author: Shawn McKinney <sm...@apache.org>
Authored: Sun Sep 25 17:45:02 2016 -0500
Committer: Shawn McKinney <sm...@apache.org>
Committed: Sun Sep 25 17:45:02 2016 -0500

----------------------------------------------------------------------
 .../directory/fortress/core/AccessMgr.java      |  77 ++++-
 .../directory/fortress/core/GlobalErrIds.java   |   7 +
 .../directory/fortress/core/GroupMgr.java       |  20 ++
 .../fortress/core/impl/AccessMgrImpl.java       |  80 ++++--
 .../fortress/core/impl/AdminMgrImpl.java        |  22 +-
 .../fortress/core/impl/DSDChecker.java          |  21 +-
 .../directory/fortress/core/impl/GroupDAO.java  |  59 +++-
 .../fortress/core/impl/GroupMgrImpl.java        |  38 +++
 .../directory/fortress/core/impl/GroupP.java    | 135 ++++++++-
 .../directory/fortress/core/impl/PermDAO.java   |  33 ++-
 .../directory/fortress/core/impl/SDUtil.java    |  66 +++--
 .../directory/fortress/core/impl/UserP.java     |  12 +-
 .../directory/fortress/core/model/Group.java    |  34 ++-
 .../directory/fortress/core/model/Session.java  | 136 ++++++++-
 .../directory/fortress/core/model/UserRole.java |  35 ++-
 .../fortress/core/rest/AccessMgrRestImpl.java   |  29 +-
 .../directory/fortress/core/rest/HttpIds.java   |   9 +
 .../directory/fortress/core/util/VUtil.java     | 185 +++++++++---
 .../fortress/core/AccessMgrConsole.java         |  14 +-
 .../fortress/core/impl/FortressJUnitTest.java   |  12 +
 .../fortress/core/impl/GroupMgrImplTest.java    | 279 +++++++++++++++++++
 .../fortress/core/impl/GroupTestData.java       |  94 +++++++
 22 files changed, 1234 insertions(+), 163 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/5192805c/src/main/java/org/apache/directory/fortress/core/impl/AdminMgrImpl.java
----------------------------------------------------------------------