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 2018/08/23 18:44:09 UTC

directory-fortress-core git commit: FC-239 - Some additional methods to manage role constraints.

Repository: directory-fortress-core
Updated Branches:
  refs/heads/master 1f130ed8d -> ab42f7dd1


FC-239 - Some additional methods to manage role constraints.


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/ab42f7dd
Tree: http://git-wip-us.apache.org/repos/asf/directory-fortress-core/tree/ab42f7dd
Diff: http://git-wip-us.apache.org/repos/asf/directory-fortress-core/diff/ab42f7dd

Branch: refs/heads/master
Commit: ab42f7dd13a06d75e9f1905d5b3968db9fbf41e9
Parents: 1f130ed
Author: Shawn McKinney <sm...@apache.org>
Authored: Thu Aug 23 13:44:01 2018 -0500
Committer: Shawn McKinney <sm...@apache.org>
Committed: Thu Aug 23 13:44:01 2018 -0500

----------------------------------------------------------------------
 ldap/setup/RbacAbacSample.xml                   | 154 +++++++++++++++++++
 ldap/setup/refreshLDAPData-src.xml              |   4 +-
 .../directory/fortress/core/GlobalErrIds.java   |   5 +
 .../fortress/core/ant/Addroleconstraint.java    |  87 +++++++++++
 .../fortress/core/ant/Delroleconstraint.java    |  86 +++++++++++
 .../fortress/core/ant/FortressAntTask.java      |  90 +++++++++++
 .../fortress/core/ant/RoleConstraintAnt.java    |  81 ++++++++++
 .../fortress/core/impl/AdminMgrImpl.java        |  13 +-
 .../directory/fortress/core/impl/UserDAO.java   |   5 +-
 .../directory/fortress/core/impl/UserP.java     |  28 ++--
 .../fortress/core/model/Constraint.java         |   8 +
 .../directory/fortress/core/model/Role.java     |  10 +-
 .../fortress/core/model/RoleConstraint.java     |  48 +++++-
 .../directory/fortress/core/model/User.java     |   6 +
 .../directory/fortress/core/model/UserRole.java |  14 +-
 .../directory/fortress/core/util/VUtil.java     |   6 +
 .../fortress/core/util/time/Discriminant.java   |   1 +
 .../core/util/time/UserRoleConstraint.java      |  86 +++++++++++
 .../fortress/core/AdminMgrConsole.java          |  62 +++++++-
 .../fortress/core/ProcessMenuCommand.java       |  66 ++++----
 .../fortress/core/example/Example.java          |   7 +
 21 files changed, 810 insertions(+), 57 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/ab42f7dd/ldap/setup/RbacAbacSample.xml
----------------------------------------------------------------------
diff --git a/ldap/setup/RbacAbacSample.xml b/ldap/setup/RbacAbacSample.xml
new file mode 100644
index 0000000..caaf79b
--- /dev/null
+++ b/ldap/setup/RbacAbacSample.xml
@@ -0,0 +1,154 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   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.
+-->
+<project basedir="." default="all" name="Fortress Sample Data">
+
+    <!-- This script drives fortress core apis to load security policies for this application -->
+
+    <taskdef classname="org.apache.directory.fortress.core.ant.FortressAntTask" name="FortressAdmin">
+        <classpath path="${java.class.path}"/>
+    </taskdef>
+
+    <target name="all">
+        <FortressAdmin>
+
+            <!-- This config setting constrains role activation by locale on Teller and Washer -->
+            <updconfig>
+                <config props="config.realm:DEFAULT"/>
+                <config props="Tellers:locale"/>
+                <config props="Washers:locale"/>
+            </updconfig>
+
+            <adduser>
+                <!-- The userProps attribute is used to map user role activation to locale (branch) attribute. -->
+                <user userId="curly"
+                      password="password"
+                      description="Head Teller of the East, Coin Washer in North and South"
+                      cn="Curly Howrowitz"
+                      sn="Horowitz"
+                      ou="u1" />
+                <user userId="moe"
+                      password="password"
+                      description="Head Teller of the North, Coin Washer in East and South"
+                      cn="Moe Howard"
+                      sn="Howard"
+                      ou="u1" />
+                <user userId="larry"
+                      password="password"
+                      description="Head Teller of the South, Coin Washer in North and East"
+                      cn="Larry Fine"
+                      sn="Fine"
+                      ou="u1" />
+            </adduser>
+
+            <adduserrole>
+                <!-- Although each user is assigned both Teller and Washer, activation is limited by locale. -->
+                <userrole userId="curly" name="Bank_Users"/>
+                <userrole userId="curly" name="Tellers"/>
+                <userrole userId="curly" name="Washers"/>
+                <userrole userId="moe" name="Bank_Users"/>
+                <userrole userId="moe" name="Tellers"/>
+                <userrole userId="moe" name="Washers"/>
+                <userrole userId="larry" name="Bank_Users"/>
+                <userrole userId="larry" name="Tellers"/>
+                <userrole userId="larry" name="Washers"/>
+            </adduserrole>
+
+            <addrole>
+                <role name="Bank_Users" description="Basic rights to log into the web app"/>
+                <role name="Tellers" description="May transact on customer accounts"/>
+                <role name="Washers" description="May wash currency"/>
+            </addrole>
+
+            <addroleconstraint>
+                <roleconstraint userId="curly" role="Tellers" paSetName="locale" value="east" typeName="USER"/>
+                <roleconstraint userId="curly" role="Washers" paSetName="locale" value="north" typeName="USER"/>
+                <roleconstraint userId="curly" role="Washers" paSetName="locale" value="south" typeName="USER"/>
+
+                <roleconstraint userId="moe" role="Tellers" paSetName="locale" value="north" typeName="USER"/>
+                <roleconstraint userId="moe" role="Washers" paSetName="locale" value="east" typeName="USER"/>
+                <roleconstraint userId="moe" role="Washers" paSetName="locale" value="south" typeName="USER"/>
+
+                <roleconstraint userId="larry" role="Tellers" paSetName="locale" value="south" typeName="USER"/>
+                <roleconstraint userId="larry" role="Washers" paSetName="locale" value="north" typeName="USER"/>
+                <roleconstraint userId="larry" role="Washers" paSetName="locale" value="east" typeName="USER"/>
+            </addroleconstraint>
+
+<!--
+            <delroleconstraint>
+                <roleconstraint userId="curly" role="Tellers" paSetName="locale" value="east" typeName="USER"/>
+                <roleconstraint userId="curly" role="Washers" paSetName="locale" value="north" typeName="USER"/>
+                <roleconstraint userId="curly" role="Washers" paSetName="locale" value="south" typeName="USER"/>
+
+                <roleconstraint userId="moe" role="Tellers" paSetName="locale" value="north" typeName="USER"/>
+                <roleconstraint userId="moe" role="Washers" paSetName="locale" value="east" typeName="USER"/>
+                <roleconstraint userId="moe" role="Washers" paSetName="locale" value="south" typeName="USER"/>
+
+                <roleconstraint userId="larry" role="Tellers" paSetName="locale" value="south" typeName="USER"/>
+                <roleconstraint userId="larry" role="Washers" paSetName="locale" value="north" typeName="USER"/>
+                <roleconstraint userId="larry" role="Washers" paSetName="locale" value="east" typeName="USER"/>
+            </delroleconstraint>
+-->
+
+
+            <addsdset>
+                <sdset name="BankSafe" setmembers="Tellers,Washers" cardinality="2" setType="DYNAMIC" description="User may only activate one of these roles"/>
+            </addsdset>
+
+            <addpermobj>
+                <permobj objName="org.rbacabac.HomePage" description="Rbac Abac Sample Home Page" ou="p1" type="Page"/>
+                <permobj objName="TellersPage" description="Used by Tellers" ou="p1" />
+                <permobj objName="WashersPage" description="Used by Washers" ou="p1" />
+                <permobj objName="Branch" description="Corresponds with a particular branch" ou="p1" />
+                <permobj objName="Account" description="Corresponds with a customer account" ou="p1" />
+                <permobj objName="Currency" description="Corresponds to currency" ou="p1" />
+            </addpermobj>
+
+            <addpermop>
+                <permop objName="TellersPage" opName="link" />
+                <permop objName="WashersPage" opName="link" />
+                <permop objName="Account" opName="deposit" description="Deposit funds into an account"/>
+                <permop objName="Account" opName="withdrawal" description="Withdrawal funds from an account"/>
+                <permop objName="Account" opName="inquiry" description="Interrogate balance on an account"/>
+                <permop objName="Currency" opName="soak" description="Permission to soak currency"/>
+                <permop objName="Currency" opName="rinse" description="May rinse currency"/>
+                <permop objName="Currency" opName="dry" description="May dry currency"/>
+                <permop objName="Branch" opName="login" description="May dry currency"/>
+            </addpermop>
+
+            <addpermgrant>
+                <permgrant objName="WashersPage" opName="link" roleNm="Washers"/>
+                <permgrant objName="TellersPage" opName="link" roleNm="Tellers"/>
+                <permgrant objName="Account" opName="deposit" roleNm="Tellers"/>
+                <permgrant objName="Account" opName="withdrawal" roleNm="Tellers"/>
+                <permgrant objName="Account" opName="inquiry" roleNm="Tellers"/>
+                <permgrant objName="Currency" opName="soak" roleNm="Washers"/>
+                <permgrant objName="Currency" opName="rinse" roleNm="Washers"/>
+                <permgrant objName="Currency" opName="dry" roleNm="Washers"/>
+                <permgrant objName="Branch" opName="login" roleNm="Bank_Users"/>
+            </addpermgrant>
+
+            <addorgunit>
+                <orgunit name="u1" typeName="USER" description="Test User Org for RbacAbac Sample"/>
+                <orgunit name="p1" typeName="PERM" description="Test Perm Org for RbacAbac Sample"/>
+            </addorgunit>
+
+        </FortressAdmin>
+    </target>
+</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/ab42f7dd/ldap/setup/refreshLDAPData-src.xml
----------------------------------------------------------------------
diff --git a/ldap/setup/refreshLDAPData-src.xml b/ldap/setup/refreshLDAPData-src.xml
index 70cc8a6..35344dd 100755
--- a/ldap/setup/refreshLDAPData-src.xml
+++ b/ldap/setup/refreshLDAPData-src.xml
@@ -93,7 +93,7 @@
                 <config props="temporal.validator.2:org.apache.directory.fortress.core.util.time.Timeout"/>
                 <config props="temporal.validator.3:org.apache.directory.fortress.core.util.time.ClockTime"/>
                 <config props="temporal.validator.4:org.apache.directory.fortress.core.util.time.Day"/>
-                <config props="temporal.validator.5:org.apache.directory.fortress.core.util.time.Discriminant"/>
+                <config props="temporal.validator.5:org.apache.directory.fortress.core.util.time.UserRoleConstraint"/>
                 <config props="temporal.validator.dsd:org.apache.directory.fortress.core.impl.DSDChecker"/>
                 <config props="user.objectclass:inetOrgPerson"/>
                 <config props="group.objectclass:@GROUP_OBJECT_CLASS@"/>
@@ -163,7 +163,7 @@
                 <config props="temporal.validator.2:org.apache.directory.fortress.core.util.time.Timeout"/>
                 <config props="temporal.validator.3:org.apache.directory.fortress.core.util.time.ClockTime"/>
                 <config props="temporal.validator.4:org.apache.directory.fortress.core.util.time.Day"/>
-                <config props="temporal.validator.5:org.apache.directory.fortress.core.util.time.Discriminant"/>
+                <config props="temporal.validator.5:org.apache.directory.fortress.core.util.time.UserRoleConstraint"/>
                 <config props="temporal.validator.dsd:org.apache.directory.fortress.core.impl.DSDChecker"/>
                 <config props="accessmgr.implementation:org.apache.directory.fortress.core.impl.AccessMgrImpl"/>
                 <config props="auditmgr.implementation:org.apache.directory.fortress.core.impl.AuditMgrImpl"/>

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/ab42f7dd/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 9da13bf..3a85b06 100755
--- a/src/main/java/org/apache/directory/fortress/core/GlobalErrIds.java
+++ b/src/main/java/org/apache/directory/fortress/core/GlobalErrIds.java
@@ -503,6 +503,11 @@ public final class GlobalErrIds
      * Entity activation failed during dynamic discriminator test on Role.
      */
     public static final int ACTV_FAILED_DISCRIMINANT = 2057;
+
+    /**
+     * Entity activation failed during dynamic discriminator test on Role.
+     */
+    public static final int ACTV_FAILED_ABAC = 2058;
     /**
      * 3000's - Permission Entity
      */

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/ab42f7dd/src/main/java/org/apache/directory/fortress/core/ant/Addroleconstraint.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/ant/Addroleconstraint.java b/src/main/java/org/apache/directory/fortress/core/ant/Addroleconstraint.java
new file mode 100644
index 0000000..7f386c1
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/core/ant/Addroleconstraint.java
@@ -0,0 +1,87 @@
+/*
+ *   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.ant;
+
+import org.apache.directory.fortress.core.model.RoleConstraint;
+import org.apache.directory.fortress.core.model.UserRole;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * The class is used by {@link FortressAntTask} to load {@link org.apache.directory.fortress.core.model.RoleConstraint}s used to
+ * drive {@link org.apache.directory.fortress.core.AdminMgr#addRoleConstraint( UserRole uRole, RoleConstraint roleConstraint )}.
+ * It is not intended to be callable by programs outside of the Ant load utility.  The class name itself maps to the xml
+ * tag used by load utility.
+ * <p>
+ * This class name, 'Addroleconstraint', is used for the xml tag in the load script.
+ * <pre>
+ * {@code
+ * <target name="all">
+ *     <FortressAdmin>
+ *         <addroleconstraint>
+ *           ...
+ *         </addroleconstraint>
+ *     </FortressAdmin>
+ * </target>
+ * }
+ * </pre>
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class Addroleconstraint
+{
+    final private List<RoleConstraintAnt> roleconstraints = new ArrayList<>();
+
+    /**
+     * All Ant data entities must have a default constructor.
+     */
+    public Addroleconstraint()
+    {
+    }
+
+    /**
+     * This method name, 'Addroleconstraint', is used for derived xml tag 'roleconstraint' in the load script.
+     * <pre>
+     * {@code
+     * <addroleconstraint>
+     *      <roleconstraint userId="curly" role="Tellers" paSetName="locale" value="east" typeName="USER"/>
+     * </addroleconstraint>
+     * }
+     * </pre>
+     *
+     * @param roleConstraint contains reference to data element targeted for insertion..
+     */
+    public void addRoleConstraint(RoleConstraintAnt roleConstraint)
+    {
+        this.roleconstraints.add(roleConstraint);
+    }
+
+    /**
+     * Used by {@link FortressAntTask#addUserRoles()} to retrieve list of roleconstraints as defined in input xml file.
+     *
+     * @return collection containing {@link org.apache.directory.fortress.core.model.RoleConstraint}s targeted for insertion.
+     */
+    public List<RoleConstraintAnt> getRoleConstraints()
+    {
+        return this.roleconstraints;
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/ab42f7dd/src/main/java/org/apache/directory/fortress/core/ant/Delroleconstraint.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/ant/Delroleconstraint.java b/src/main/java/org/apache/directory/fortress/core/ant/Delroleconstraint.java
new file mode 100644
index 0000000..32a08a1
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/core/ant/Delroleconstraint.java
@@ -0,0 +1,86 @@
+/*
+ *   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.ant;
+
+import org.apache.directory.fortress.core.model.RoleConstraint;
+import org.apache.directory.fortress.core.model.UserRole;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * The class is used by {@link FortressAntTask} to load {@link org.apache.directory.fortress.core.model.RoleConstraint}s used to
+ * drive {@link org.apache.directory.fortress.core.AdminMgr#removeRoleConstraint( UserRole uRole, RoleConstraint roleConstraint )}.
+ * It is not intended to be callable by programs outside of the Ant load utility.  The class name itself maps to the xml
+ * tag used by load utility.
+ * <p>
+ * This class name, 'Delroleconstraint', is used for the xml tag in the load script.
+ * <pre>
+ * {@code
+ * <target name="all">
+ *     <FortressAdmin>
+ *         <delroleconstraint>
+ *           ...
+ *         </delroleconstraint>
+ *     </FortressAdmin>
+ * </target>
+ * }
+ * </pre>
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class Delroleconstraint
+{
+    final private List<RoleConstraintAnt> roleconstraints = new ArrayList<>();
+
+    /**
+     * All Ant data entities must have a default constructor.
+     */
+    public Delroleconstraint()
+    {
+    }
+
+    /**
+     * This method name, 'Addroleconstraint', is used for derived xml tag 'roleconstraint' in the load script.
+     * <pre>
+     * {@code
+     * <delroleconstraint>
+     *      <roleconstraint userId="curly" role="Tellers" paSetName="locale" value="east" typeName="USER"/>
+     * </delroleconstraint>
+     * }
+     * </pre>
+     *
+     * @param roleConstraint contains reference to data element targeted for deletion.
+     */
+    public void addRoleConstraint(RoleConstraintAnt roleConstraint)
+    {
+        this.roleconstraints.add(roleConstraint);
+    }
+
+    /**
+     * Used by {@link FortressAntTask#addUserRoles()} to retrieve list of roleconstraints as defined in input xml file.
+     *
+     * @return collection containing {@link org.apache.directory.fortress.core.model.RoleConstraint}s targeted for insertion.
+     */
+    public List<RoleConstraintAnt> getRoleConstraints()
+    {
+        return this.roleconstraints;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/ab42f7dd/src/main/java/org/apache/directory/fortress/core/ant/FortressAntTask.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/ant/FortressAntTask.java b/src/main/java/org/apache/directory/fortress/core/ant/FortressAntTask.java
index 86e232e..23c810e 100755
--- a/src/main/java/org/apache/directory/fortress/core/ant/FortressAntTask.java
+++ b/src/main/java/org/apache/directory/fortress/core/ant/FortressAntTask.java
@@ -306,6 +306,8 @@ public class FortressAntTask extends Task implements InputHandler
     private final List<Delgroupmember> delgroupmembers = new ArrayList<>();
     private final List<Addgroupproperty> addgroupproperties = new ArrayList<>();
     private final List<Delgroupproperty> delgroupproperties = new ArrayList<>();
+    private final List<Addroleconstraint> addroleconstraints = new ArrayList<>();
+    private final List<Delroleconstraint> delroleconstraints = new ArrayList<>();
 
     private ConfigMgr cfgMgr = null;
     private AdminMgr adminMgr = null;
@@ -877,6 +879,28 @@ public class FortressAntTask extends Task implements InputHandler
 
 
     /**
+     * Load the entity with data.
+     *
+     * @param addroleconstraint contains the ant initialized data entities to be handed off for further processing.
+     */
+    public void addAddroleconstraint( Addroleconstraint addroleconstraint )
+    {
+        this.addroleconstraints.add( addroleconstraint );
+    }
+
+
+    /**
+     * Load the entity with data.
+     *
+     * @param delroleconstraint contains the ant initialized data entities to be handed off for further processing.
+     */
+    public void addDelroleconstraint( Delroleconstraint delroleconstraint )
+    {
+        this.delroleconstraints.add( delroleconstraint );
+    }
+
+
+    /**
      * @param list
      * @return boolean
      */
@@ -898,6 +922,7 @@ public class FortressAntTask extends Task implements InputHandler
             setContext( addcontexts.get( 0 ).getContexts().get( 0 ) );
         }
 
+        delRoleConstraints();
         delUserRoles();
         delUserAdminRoles();
         deletePermGrants();
@@ -941,6 +966,7 @@ public class FortressAntTask extends Task implements InputHandler
         addPermGrants();
         addUserAdminRoles();
         addUserRoles();
+        addRoleConstraints();
 
         testResults();
 
@@ -1385,6 +1411,70 @@ public class FortressAntTask extends Task implements InputHandler
     /**
      * @throws BuildException An error occurred while building
      */
+    private void addRoleConstraints() throws BuildException
+    {
+        if( addroleconstraints == null )
+        {
+            return;
+        }
+
+        // Loop through the entityclass elements
+        for ( Addroleconstraint addroleconstraint : addroleconstraints )
+        {
+            List<RoleConstraintAnt> roleconstraints = addroleconstraint.getRoleConstraints();
+            for ( RoleConstraintAnt roleConstraint : roleconstraints )
+            {
+                try
+                {
+                    adminMgr.addRoleConstraint( new UserRole( roleConstraint.getUserId(), roleConstraint.getRole() ), roleConstraint );
+                    LOG.info( "addRoleConstraint successfully added: tenant={} type={} userid={} role={} key={} value={}", getTenant(), roleConstraint.getType(), roleConstraint.getUserId(), roleConstraint.getRole(), roleConstraint.getPaSetName(), roleConstraint.getValue() );
+                }
+                catch ( SecurityException se )
+                {
+                    LOG.warn( "addRoleConstraints tenant={} userId={} roleName={} caught SecurityException={}", getTenant(), roleConstraint.getUserId(), roleConstraint.getRole(), se );
+                }
+            }
+        }
+    }
+
+
+
+    /**
+     * @throws BuildException An error occurred while building
+     */
+    private void delRoleConstraints() throws BuildException
+    {
+        if( addroleconstraints == null )
+        {
+            return;
+        }
+
+        // Loop through the entityclass elements
+        for ( Delroleconstraint delroleconstraint : delroleconstraints )
+        {
+            List<RoleConstraintAnt> roleconstraints = delroleconstraint.getRoleConstraints();
+            for ( RoleConstraintAnt roleConstraint : roleconstraints )
+            {
+                try
+                {
+                    adminMgr.removeRoleConstraint( new UserRole( roleConstraint.getUserId(), roleConstraint.getRole()
+                    ), roleConstraint );
+                    LOG.info( "removeRoleConstraint success: tenant={} type={} userid={} role={} key={} value={}",
+                        getTenant(), roleConstraint.getType(), roleConstraint.getUserId(), roleConstraint.getRole(),
+                        roleConstraint.getPaSetName(), roleConstraint.getValue() );
+                }
+                catch ( SecurityException se )
+                {
+                    LOG.warn( "delRoleConstraints tenant={} userId={} roleName={} caught SecurityException={}", getTenant(), roleConstraint.getUserId(), roleConstraint.getRole(), se );
+                }
+            }
+        }
+    }
+
+
+    /**
+     * @throws BuildException An error occurred while building
+     */
     private void addRoles() throws BuildException
     {
         if( addroles == null )

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/ab42f7dd/src/main/java/org/apache/directory/fortress/core/ant/RoleConstraintAnt.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/ant/RoleConstraintAnt.java b/src/main/java/org/apache/directory/fortress/core/ant/RoleConstraintAnt.java
new file mode 100644
index 0000000..ab757b2
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/core/ant/RoleConstraintAnt.java
@@ -0,0 +1,81 @@
+/*
+ *   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.ant;
+
+
+import org.apache.directory.fortress.core.model.RoleConstraint;
+
+
+
+/**
+ * Entity is used by custom Apache Ant task for special handling of collections.
+ * Used when the common entity found in the model doesn't contain necessary attributes to complete the operation via ant admin task.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class RoleConstraintAnt extends RoleConstraint
+{
+    /** Default serialVersionUID */
+    private static final long serialVersionUID = 1L;
+    private String role;
+
+    /**
+     *
+     * @return
+     */
+    public String getUserId()
+    {
+        return userId;
+    }
+
+    /**
+     *
+     * @param userId
+     */
+    public void setUserId(String userId)
+    {
+        this.userId = userId;
+    }
+
+    private String userId;
+
+
+    /**
+     * Return the role as a String.
+     *
+     * @return String contains a comma delimited set of role names assigned to permission.
+     */
+    public String getRole()
+    {
+        return role;
+    }
+
+
+    /**
+     * Accept a comma delimited String containing a list of Roles to be granted to a permission.  This function
+     * will parse the String and call the setter on its parent.
+     *
+     * @param role name targeted for role constraint.
+     */
+    public void setRole( String role )
+    {
+        this.role = role;
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/ab42f7dd/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 390d39f..bd6451c 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
@@ -398,10 +398,19 @@ public final class AdminMgrImpl extends Manageable implements AdminMgr, Serializ
     {        
     	String methodName = "assignUser";
         assertContext( CLS_NM, methodName, uRole, GlobalErrIds.URLE_NULL );
-        AdminUtil.canAssign( uRole.getAdminSession(), new User( uRole.getUserId() ), new Role( uRole.getName() ), contextId );
 
+        // Validate the user-role assignment exists:
+        List<String> assignedRoles = userP.getAssignedRoles( new User( uRole.getUserId() ) );
+        assertContext( CLS_NM, methodName, uRole, GlobalErrIds.URLE_NULL );
+        if ( ! assignedRoles.stream().anyMatch( uRole.getName()::equalsIgnoreCase) )
+        {
+            String error =  methodName + " user [" + uRole.getUserId() + "] not assigned role [" + uRole.getName() + "]";
+            LOG.error( error );
+            throw new SecurityException( GlobalErrIds.URLE_ASSIGN_NOT_EXIST, error, null );
+        }
+        AdminUtil.canAssign( uRole.getAdminSession(), new User( uRole.getUserId() ), new Role( uRole.getName() ),
+            contextId );
         // todo assert roleconstraint here
-        
         userP.assign( uRole, roleConstraint );        
         return roleConstraint;
     }

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/ab42f7dd/src/main/java/org/apache/directory/fortress/core/impl/UserDAO.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/impl/UserDAO.java b/src/main/java/org/apache/directory/fortress/core/impl/UserDAO.java
index c54448f..cd520f1 100755
--- a/src/main/java/org/apache/directory/fortress/core/impl/UserDAO.java
+++ b/src/main/java/org/apache/directory/fortress/core/impl/UserDAO.java
@@ -21,11 +21,11 @@ package org.apache.directory.fortress.core.impl;
 
 
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.TreeMap;
 
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang.ArrayUtils;
@@ -2653,7 +2653,8 @@ final class UserDAO extends LdapDataProvider implements PropUpdater
      */
     private List<UserRole> unloadUserRoles( Entry entry, String userId, String contextId, String roleNameFilter )
     {
-    	Map<String, UserRole> uRoles = new HashMap<String, UserRole>();    	
+    	//Map<String, UserRole> uRoles = new HashMap<String, UserRole>();
+    	Map<String, UserRole> uRoles = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
         List<String> roles = getAttributes( entry, GlobalIds.USER_ROLE_DATA );
 
         if ( roles != null )

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/ab42f7dd/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 f5cc625..7a2a00c 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
@@ -793,19 +793,23 @@ final class UserP
      */
     private void validate( RoleConstraint rc, String contextId ) throws ValidationException
     {
-        if( StringUtils.isEmpty( rc.getPaSetName() ))
+        // TODO: This should be for only one type:
+        if( rc.getType() != RCType.USER)
         {
-        	throw new ValidationException( GlobalErrIds.PERM_ATTRIBUTE_SET_NM_NULL, CLS_NM + ".validate pa set name is NULL" );
-        }
-        try
-        {
-            PermP permP = new PermP();
-            permP.validatePaSet( rc.getPaSetName(), contextId );
-        }
-        catch( SecurityException e )
-        {
-            String error = "validate - paSetName not found with name [" + rc.getPaSetName() + "] caught SecurityException=" + e;
-            throw new ValidationException( GlobalErrIds.PERM_ATTRIBUTE_SET_NOT_FOUND, error );
+            if( StringUtils.isEmpty( rc.getPaSetName() ))
+            {
+                throw new ValidationException( GlobalErrIds.PERM_ATTRIBUTE_SET_NM_NULL, CLS_NM + ".validate pa set name is NULL" );
+            }
+            try
+            {
+                PermP permP = new PermP();
+                permP.validatePaSet( rc.getPaSetName(), contextId );
+            }
+            catch( SecurityException e )
+            {
+                String error = "validate - paSetName not found with name [" + rc.getPaSetName() + "] caught SecurityException=" + e;
+                throw new ValidationException( GlobalErrIds.PERM_ATTRIBUTE_SET_NOT_FOUND, error );
+            }
         }
         if ( rc.getType() == null )
         {

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/ab42f7dd/src/main/java/org/apache/directory/fortress/core/model/Constraint.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/model/Constraint.java b/src/main/java/org/apache/directory/fortress/core/model/Constraint.java
index df47e20..7f6d26d 100755
--- a/src/main/java/org/apache/directory/fortress/core/model/Constraint.java
+++ b/src/main/java/org/apache/directory/fortress/core/model/Constraint.java
@@ -20,6 +20,8 @@
 package org.apache.directory.fortress.core.model;
 
 
+import java.util.List;
+
 /**
  * The Fortress Constraint interface prescribes attributes that are used to store, process and retrieve temporal validation attributes on
  * {@link org.apache.directory.fortress.core.model.User}, {@link org.apache.directory.fortress.core.model.UserRole}, {@link org.apache.directory.fortress.core.model.Role},
@@ -240,5 +242,11 @@ public interface Constraint
      */
     String getName();
 
+    /**
+     * Return a list of role constraints on entity.
+     *
+     * @return
+     */
+    List<RoleConstraint> getConstraints();
 
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/ab42f7dd/src/main/java/org/apache/directory/fortress/core/model/Role.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/model/Role.java b/src/main/java/org/apache/directory/fortress/core/model/Role.java
index e11b79c..5094fa4 100755
--- a/src/main/java/org/apache/directory/fortress/core/model/Role.java
+++ b/src/main/java/org/apache/directory/fortress/core/model/Role.java
@@ -650,8 +650,14 @@ public class Role extends FortEntity implements Constraint, Graphable, java.io.S
     {
         this.timeout = timeout;
     }
-    
-    
+
+
+    @Override
+    public List<RoleConstraint> getConstraints()
+    {
+        throw new java.lang.UnsupportedOperationException();
+    }
+
     /**
      * Get the names of roles that are parents (direct ascendants) of this role.
      * @return Set of parent role names assigned to this role.

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/ab42f7dd/src/main/java/org/apache/directory/fortress/core/model/RoleConstraint.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/model/RoleConstraint.java b/src/main/java/org/apache/directory/fortress/core/model/RoleConstraint.java
index 2c96e67..690261a 100644
--- a/src/main/java/org/apache/directory/fortress/core/model/RoleConstraint.java
+++ b/src/main/java/org/apache/directory/fortress/core/model/RoleConstraint.java
@@ -61,13 +61,15 @@ public class RoleConstraint extends FortEntity implements Serializable
     public enum RCType
     {
         FILTER,
+        USER,
         OTHER
     }
 
     private String id;
     private RCType type;
     private String value;
-    private String paSetName;    
+    private String paSetName;
+    private String typeName;
 
     public RoleConstraint()
     {
@@ -128,19 +130,55 @@ public class RoleConstraint extends FortEntity implements Serializable
         StringBuilder sb = new StringBuilder();
         String delimeter = Config.getInstance().getDelimiter();
 
-        sb.append( uRole.getName() );
+        sb.append( uRole.getName().toLowerCase() );
         sb.append( delimeter );
         sb.append( RC_TYPE_NAME );
         sb.append( delimeter );
         sb.append( type );
         sb.append( delimeter );
+        //sb.append( paSetName.toLowerCase() );
         sb.append( paSetName );
         sb.append( delimeter );
+        //sb.append( value.toLowerCase() );
         sb.append( value );
         sb.append( delimeter );
-        sb.append( id );        
-
+        // ID's not needed for user roleconstraints and complicate deassignment so don't use:
+        if( getType() != RCType.USER)
+        {
+            sb.append( id );
+        }
         return sb.toString();
     }
-    
+
+    /**
+     * Return the type of OU in string format.
+     *
+     * @return String that represents static or dynamic relations.
+     */
+    public String getTypeName()
+    {
+        return typeName;
+    }
+
+    /**
+     * Method accepts a String variable that maps to its parent's set type.
+     *
+     * @param typeName String value represents perm or user ou data sets.
+     */
+    public void setTypeName( String typeName )
+    {
+        this.typeName = typeName;
+        if ( typeName != null && typeName.equalsIgnoreCase( "FILTER" ) )
+        {
+            setType( RCType.FILTER );
+        }
+        else if ( typeName != null && typeName.equalsIgnoreCase( "USER" ) )
+        {
+            setType( RCType.USER );
+        }
+        else
+        {
+            setType( RCType.OTHER );
+        }
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/ab42f7dd/src/main/java/org/apache/directory/fortress/core/model/User.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/model/User.java b/src/main/java/org/apache/directory/fortress/core/model/User.java
index 84f61ef..72aa18a 100755
--- a/src/main/java/org/apache/directory/fortress/core/model/User.java
+++ b/src/main/java/org/apache/directory/fortress/core/model/User.java
@@ -1224,6 +1224,12 @@ public class User extends FortEntity implements Constraint, Serializable
     }
 
 
+    @Override
+    public List<RoleConstraint> getConstraints()
+    {
+        throw new java.lang.UnsupportedOperationException();
+    }
+
     /**
      * If set to true User's password has been reset by administrator.
      * This attribute will be ignored if set by external callers.

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/ab42f7dd/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 ac5cd50..adda11c 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
@@ -590,6 +590,12 @@ public class UserRole extends FortEntity implements Serializable, Constraint
     }
 
 
+    @Override
+    public List<RoleConstraint> getConstraints()
+    {
+        return getRoleConstraints();
+    }
+
     /**
      * Get the names of roles that are parents (direct ascendants) of this role.
      *
@@ -688,9 +694,11 @@ public class UserRole extends FortEntity implements Serializable, Constraint
     }
 
 
-	public List<RoleConstraint> getRoleConstraints() {
-		if(roleConstraints == null){
-			roleConstraints = new ArrayList<RoleConstraint>();
+	public List<RoleConstraint> getRoleConstraints()
+    {
+		if(roleConstraints == null)
+        {
+			roleConstraints = new ArrayList();
 		}
 		return roleConstraints;
 	}

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/ab42f7dd/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 b6ac995..d286101 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
@@ -801,6 +801,12 @@ public final class VUtil implements ConstraintValidator
         public String getName() {
             return group.getName();
         }
+
+        @Override
+        public List getConstraints()
+        {
+            throw new java.lang.UnsupportedOperationException();
+        }
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/ab42f7dd/src/main/java/org/apache/directory/fortress/core/util/time/Discriminant.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/util/time/Discriminant.java b/src/main/java/org/apache/directory/fortress/core/util/time/Discriminant.java
index d364189..de49e04 100644
--- a/src/main/java/org/apache/directory/fortress/core/util/time/Discriminant.java
+++ b/src/main/java/org/apache/directory/fortress/core/util/time/Discriminant.java
@@ -36,6 +36,7 @@ import java.util.TreeSet;
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
+@Deprecated
 public class Discriminant
     implements Validator
 {

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/ab42f7dd/src/main/java/org/apache/directory/fortress/core/util/time/UserRoleConstraint.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/util/time/UserRoleConstraint.java b/src/main/java/org/apache/directory/fortress/core/util/time/UserRoleConstraint.java
new file mode 100644
index 0000000..14afd82
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/core/util/time/UserRoleConstraint.java
@@ -0,0 +1,86 @@
+/*
+ *   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.util.time;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.directory.fortress.core.GlobalErrIds;
+import org.apache.directory.fortress.core.model.Constraint;
+import org.apache.directory.fortress.core.model.RoleConstraint;
+import org.apache.directory.fortress.core.model.Session;
+import org.apache.directory.fortress.core.util.Config;
+import org.apache.directory.fortress.core.util.VUtil;
+
+/**
+ * This class performs dynamic constraint validation on role activation, per FC-235
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class UserRoleConstraint
+    implements Validator
+{
+    /**
+     * This method is called during entity activation, {@link org.apache.directory.fortress.core.util.VUtil#validateConstraints} and ensures role has a
+     * matching constraint value.
+     *
+     * @param session Contains the name and value of discriminator, passed by the caller.  e.g. locale=north
+     * @param role contains the attribute constraint allowed for a given user's role.  e.g. role=tellers, locale=north.
+     * @param time contains the current time stamp, required by the interface, not used here.
+     * @param type used on this validator to prevent it from ever being applied to a user's constraint.
+     * @return '0' if validation succeeds else {@link org.apache.directory.fortress.core.GlobalErrIds#ACTV_FAILED_ABAC} if failed.
+     */
+    @Override
+    public int validate(Session session, Constraint role, Time time, VUtil.ConstraintType type )
+    {
+        int rc = 0;
+        // Doesn't make sense to apply this constraint on a user:
+        if ( type != VUtil.ConstraintType.USER )
+        {
+            // This constraint type requires a global config parameter keyed by the role name:
+            String constraintType = Config.getInstance().getProperty( role.getName() );
+            // Is there a runtime constraint placed on this role activation?
+            if ( StringUtils.isNotEmpty( constraintType ))
+            {
+                String constraintValue = session.getUser().getProperty( constraintType );
+                if( StringUtils.isEmpty( constraintValue ) || role.getConstraints().isEmpty() )
+                {
+                    // This user does not have a corresponding property applied to a role that has a runtime constraint set -OR- Have no applicable role constraint.
+                    rc = GlobalErrIds.ACTV_FAILED_ABAC;
+                }
+                else
+                {
+                    boolean found = false;
+                    for ( RoleConstraint constraint : role.getConstraints() )
+                    {
+                        if( constraint.getType() == RoleConstraint.RCType.USER && constraint.getPaSetName().equalsIgnoreCase( constraintType ) && constraint.getValue().equalsIgnoreCase( constraintValue ) )
+                        {
+                            found = true;
+                            break;
+                        }
+                    }
+                    if( !found)
+                    {
+                        rc = GlobalErrIds.ACTV_FAILED_ABAC;
+                    }
+                }
+            }
+        }
+        return rc;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/ab42f7dd/src/test/java/org/apache/directory/fortress/core/AdminMgrConsole.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/directory/fortress/core/AdminMgrConsole.java b/src/test/java/org/apache/directory/fortress/core/AdminMgrConsole.java
index 5b33658..024a995 100755
--- a/src/test/java/org/apache/directory/fortress/core/AdminMgrConsole.java
+++ b/src/test/java/org/apache/directory/fortress/core/AdminMgrConsole.java
@@ -40,6 +40,7 @@ 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.RoleConstraint;
 import org.apache.directory.fortress.core.model.SDSet;
 import org.apache.directory.fortress.core.model.Session;
 import org.apache.directory.fortress.core.model.User;
@@ -119,7 +120,7 @@ class AdminMgrConsole
             System.out.println("Enter Role's description field");
             re.setDescription(ReaderUtil.readLn());
 
-            Role re2 = am.updateRole(re);
+            Role re2 = am.updateRole( re );
             System.out.println("name [" + re2.getName() + "]");
             System.out.println("internalId [" + re2.getId() + "]");
             System.out.println("name description [" + re2.getDescription() + "]");
@@ -134,6 +135,65 @@ class AdminMgrConsole
     }
 
 
+    void addRoleConstraint()
+    {
+        UserRole uRole = new UserRole();
+        RoleConstraint roleConstraint = new RoleConstraint();
+        try
+        {
+            ReaderUtil.clearScreen();
+            System.out.println("Enter userId:");
+            uRole.setUserId( ReaderUtil.readLn() );
+            System.out.println("Enter role name:");
+            uRole.setName( ReaderUtil.readLn() );
+            System.out.println("Enter constraint type:");
+            roleConstraint.setTypeName( ReaderUtil.readLn() );
+            System.out.println("Enter constraint key:");
+            roleConstraint.setPaSetName( ReaderUtil.readLn() );
+            System.out.println("Enter constraint value:");
+            roleConstraint.setValue( ReaderUtil.readLn() );
+            RoleConstraint re2 = am.addRoleConstraint( uRole, roleConstraint );
+            System.out.println("constraint name [" + re2.getPaSetName() + "]");
+            System.out.println("has been added");
+            System.out.println("ENTER to continue");
+        }
+        catch (SecurityException e)
+        {
+            LOG.error("addRoleConstraint caught SecurityException rc=" + e.getErrorId() + ", msg=" + e.getMessage(), e);
+        }
+        ReaderUtil.readChar();
+    }
+
+
+    void removeRoleConstraint()
+    {
+        UserRole uRole = new UserRole();
+        RoleConstraint roleConstraint = new RoleConstraint();
+        try
+        {
+            ReaderUtil.clearScreen();
+            System.out.println("Enter userId:");
+            uRole.setUserId( ReaderUtil.readLn() );
+            System.out.println("Enter role name:");
+            uRole.setName( ReaderUtil.readLn() );
+            System.out.println("Enter constraint type:");
+            roleConstraint.setTypeName( ReaderUtil.readLn() );
+            System.out.println("Enter constraint key:");
+            roleConstraint.setPaSetName( ReaderUtil.readLn() );
+            System.out.println("Enter constraint value:");
+            roleConstraint.setValue( ReaderUtil.readLn() );
+            am.removeRoleConstraint( uRole, roleConstraint );
+            System.out.println("has been removed");
+            System.out.println("ENTER to continue");
+        }
+        catch (SecurityException e)
+        {
+            LOG.error("addRoleConstraint caught SecurityException rc=" + e.getErrorId() + ", msg=" + e.getMessage(), e);
+        }
+        ReaderUtil.readChar();
+    }
+
+
     void deleteRole()
     {
         Role re = new Role();

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/ab42f7dd/src/test/java/org/apache/directory/fortress/core/ProcessMenuCommand.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/directory/fortress/core/ProcessMenuCommand.java b/src/test/java/org/apache/directory/fortress/core/ProcessMenuCommand.java
index ab2d2e6..9f5c021 100755
--- a/src/test/java/org/apache/directory/fortress/core/ProcessMenuCommand.java
+++ b/src/test/java/org/apache/directory/fortress/core/ProcessMenuCommand.java
@@ -419,19 +419,21 @@ class ProcessMenuCommand
         System.out.println( "C.  Delete Role" );
         System.out.println( "D.  Assign User to Role" );
         System.out.println( "E.  Deassign User from Role" );
-        System.out.println( "F.  Grant Perm to Role" );
-        System.out.println( "G.  Revoke Perm from Role" );
-        System.out.println( "H.  Grant Perm to User" );
-        System.out.println( "I.  Revoke Perm from User" );
-        System.out.println( "J.  Add Role Inheritance" );
-        System.out.println( "K.  Remove Role Inheritance" );
-        System.out.println( "L.  Add Role Ascendant" );
-        System.out.println( "M.  Add Role Descendant" );
-        System.out.println( "N.  Add SSD Data Set" );
-        System.out.println( "O.  Add DSD Data Set" );
-        System.out.println( "X.  Test Annotation" );
-        System.out.println( "Y.  Add Example" );
-        System.out.println( "Z.  Test Config" );
+        System.out.println( "F.  Add User Role Constraint" );
+        System.out.println( "G.  Remove User Role Constraint" );
+        System.out.println( "H.  Grant Perm to Role" );
+        System.out.println( "I.  Revoke Perm from Role" );
+        System.out.println( "J.  Grant Perm to User" );
+        System.out.println( "K.  Revoke Perm from User" );
+        System.out.println( "L.  Add Role Inheritance" );
+        System.out.println( "M.  Remove Role Inheritance" );
+        System.out.println( "N.  Add Role Ascendant" );
+        System.out.println( "O.  Add Role Descendant" );
+        System.out.println( "P.  Add SSD Data Set" );
+        System.out.println( "R.  Add DSD Data Set" );
+        System.out.println( "S.  Test Annotation" );
+        System.out.println( "T.  Add Example" );
+        System.out.println( "U.  Test Config" );
         System.out.println( "Enter q or Q to return to previous menu" );
     }
 
@@ -508,54 +510,62 @@ class ProcessMenuCommand
                         break;
                     case 'f':
                     case 'F':
-                        adminConsole.grantPermission( true );
+                        adminConsole.addRoleConstraint();
                         break;
                     case 'g':
                     case 'G':
-                        adminConsole.revokePermission( true );
+                        adminConsole.removeRoleConstraint();
                         break;
                     case 'h':
                     case 'H':
-                        adminConsole.grantPermission( false );
+                        adminConsole.grantPermission( true );
                         break;
                     case 'i':
                     case 'I':
-                        adminConsole.revokePermission( false );
+                        adminConsole.revokePermission( true );
                         break;
                     case 'j':
                     case 'J':
-                        adminConsole.addRoleInheritance();
+                        adminConsole.grantPermission( false );
                         break;
                     case 'k':
                     case 'K':
-                        adminConsole.removeRoleInheritance();
+                        adminConsole.revokePermission( false );
                         break;
                     case 'l':
                     case 'L':
-                        adminConsole.addRoleAscendant();
+                        adminConsole.addRoleInheritance();
                         break;
                     case 'm':
                     case 'M':
-                        adminConsole.addRoleDescendant();
+                        adminConsole.removeRoleInheritance();
                         break;
                     case 'n':
                     case 'N':
-                        adminConsole.addSsd();
+                        adminConsole.addRoleAscendant();
                         break;
                     case 'o':
                     case 'O':
+                        adminConsole.addRoleDescendant();
+                        break;
+                    case 'p':
+                    case 'P':
+                        adminConsole.addSsd();
+                        break;
+                    case 'r':
+                    case 'R':
                         adminConsole.addDsd();
                         break;
-                    case 'x':
-                    case 'X':
+                    case 's':
+                    case 'S':
                         adminConsole.addAnnotation();
                         break;
-                    case 'y':
-                    case 'Y':
+                    case 't':
+                    case 'T':
                         adminConsole.addExample();
                         break;
-                    case 'z':
-                    case 'Z':
+                    case 'u':
+                    case 'U':
                         adminConsole.testConfig();
                         break;
                     case 'q':

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/ab42f7dd/src/test/java/org/apache/directory/fortress/core/example/Example.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/directory/fortress/core/example/Example.java b/src/test/java/org/apache/directory/fortress/core/example/Example.java
index 7b03727..21fb6b0 100755
--- a/src/test/java/org/apache/directory/fortress/core/example/Example.java
+++ b/src/test/java/org/apache/directory/fortress/core/example/Example.java
@@ -23,6 +23,7 @@ package org.apache.directory.fortress.core.example;
 import org.apache.directory.fortress.core.model.Constraint;
 
 import java.rmi.server.UID;
+import java.util.List;
 
 
 public class Example
@@ -258,4 +259,10 @@ public class Example
     {
         this.timeout = timeout;
     }
+
+    @Override
+    public List getConstraints()
+    {
+        throw new java.lang.UnsupportedOperationException();
+    }
 }