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 2019/04/22 19:08:19 UTC

[directory-fortress-core] branch master updated: FC-269 - Make Fortress ABAC Role Constraint multi tenant

This is an automated email from the ASF dual-hosted git repository.

smckinney pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/directory-fortress-core.git


The following commit(s) were added to refs/heads/master by this push:
     new 3c61efa  FC-269 - Make Fortress ABAC Role Constraint multi tenant
3c61efa is described below

commit 3c61efa4bf17c33d151b83a683dc26b4f9fc562d
Author: Shawn McKinney <sm...@apache.org>
AuthorDate: Mon Apr 22 14:08:13 2019 -0500

    FC-269 - Make Fortress ABAC Role Constraint multi tenant
---
 .../apache/directory/fortress/core/GlobalIds.java  |  2 +-
 .../directory/fortress/core/impl/AdminMgrImpl.java | 11 +--
 .../directory/fortress/core/util/Config.java       | 97 +++++++++++++---------
 .../core/util/time/UserRoleConstraint.java         |  7 +-
 4 files changed, 65 insertions(+), 52 deletions(-)

diff --git a/src/main/java/org/apache/directory/fortress/core/GlobalIds.java b/src/main/java/org/apache/directory/fortress/core/GlobalIds.java
index e5e4a87..74baf01 100755
--- a/src/main/java/org/apache/directory/fortress/core/GlobalIds.java
+++ b/src/main/java/org/apache/directory/fortress/core/GlobalIds.java
@@ -43,7 +43,7 @@ public final class GlobalIds
     public static final String TENANT = "tenant";
     public static final String DISABLE_AUDIT = "disable.audit";
     public static final String ENABLE_REST = "enable.mgr.impl.rest";
-    public static final String CONSTRAINT_KEY_PREFIX = "RC-";
+    public static final String CONSTRAINT_KEY_PREFIX = "RC";
 
     /**
      * The following constants are used within the factory classes:
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 b2a820e..6467b10 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
@@ -406,10 +406,8 @@ public final class AdminMgrImpl extends Manageable implements AdminMgr, Serializ
         VUtil.assertNotNull( roleConstraint, GlobalErrIds.ROLE_CONSTRAINT_NULL, CLS_NM + methodName );
         VUtil.assertNotNull( role.getName(), GlobalErrIds.ROLE_NM_NULL, CLS_NM + methodName );
         setEntitySession( CLS_NM, methodName, role );
-        // The name:value pair is bound as fortress property, using prefix 'RC-'.
-        // It's for convenient and efficient lookup during the runtime checks.
-        // We will cache as java.util.properties, require case insensitivity, convention is use lower case keys:
-        String propKey = GlobalIds.CONSTRAINT_KEY_PREFIX + role.getName().toLowerCase();
+        // This constraint type requires a global config parameter keyed by RC$tenant$role:constraint:
+        String propKey = Config.getInstance().getConstraintKey( role.getName(), contextId );
         String propValue = roleConstraint.getKey();
         VUtil.assertNotNull( propValue, GlobalErrIds.ROLE_CONSTRAINT_KEY_NULL, CLS_NM + methodName );
         // Verify the role exists:
@@ -418,7 +416,6 @@ public final class AdminMgrImpl extends Manageable implements AdminMgr, Serializ
         props.setProperty( propKey, propValue );
         // Retrieve parameters from the config node stored in target LDAP DIT:
         String realmName = Config.getInstance().getProperty( GlobalIds.CONFIG_REALM, "DEFAULT" );
-
         configP.update( new Configuration(realmName, props) );
         // update in-memory:
         Config.getInstance().setProperty( propKey, propValue );
@@ -437,8 +434,8 @@ public final class AdminMgrImpl extends Manageable implements AdminMgr, Serializ
         VUtil.assertNotNull( roleConstraint, GlobalErrIds.ROLE_CONSTRAINT_NULL, CLS_NM + methodName );
         VUtil.assertNotNull( role.getName(), GlobalErrIds.ROLE_NM_NULL, CLS_NM + methodName );
         setEntitySession( CLS_NM, methodName, role );
-        // We want case insensitive on java.util.propp, convention is use lower case key:
-        String propKey = GlobalIds.CONSTRAINT_KEY_PREFIX + role.getName().toLowerCase();
+        // This constraint type requires a global config parameter keyed by RC$tenant$role:constraint:
+        String propKey = Config.getInstance().getConstraintKey( role.getName(), contextId );
         String propValue = roleConstraint.getKey();
         VUtil.assertNotNull( propValue, GlobalErrIds.ROLE_CONSTRAINT_KEY_NULL, CLS_NM + methodName );
         Properties props = new Properties();
diff --git a/src/main/java/org/apache/directory/fortress/core/util/Config.java b/src/main/java/org/apache/directory/fortress/core/util/Config.java
index 3bed01c..c754eaf 100755
--- a/src/main/java/org/apache/directory/fortress/core/util/Config.java
+++ b/src/main/java/org/apache/directory/fortress/core/util/Config.java
@@ -35,7 +35,6 @@ 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.Configuration;
-import org.apache.directory.fortress.core.model.Props;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -128,46 +127,6 @@ public final class Config
     }
 
     /**
-     * Performs auto-increment on a list of key names that map to integer values stored on the current config node of the runtime.
-     * Unfortunately, it's synchronized to prevent a race condition of multiple threads trying to update the same id.
-     * Worse, it doesn't lock meaning not synched across processes and so a temporary workaround until the Apache LDAP API supports RFC 4525 (Modify Increment attribute).
-     *
-     * @param props list of attribute names to update on config node.
-     * @param propUpdater reference to object that updates to new value.
-     * @return Configuration entity containing the old values.
-     */
-    public synchronized Configuration getIncrementReplacePosixIds(List<String> props, PropUpdater propUpdater ) throws CfgException
-    {
-        String cfgName = Config.getInstance().getProperty( GlobalIds.CONFIG_REALM );
-        org.apache.directory.fortress.core.model.Configuration inConfig;
-        try
-        {
-            ConfigMgr cfgMgr = ConfigMgrFactory.createInstance();
-            inConfig = cfgMgr.getIds( cfgName );
-            org.apache.directory.fortress.core.model.Configuration outConfig = new Configuration();
-            outConfig.setName( cfgName );
-            for( String name : props )
-            {
-                if( name.equals( GlobalIds.UID_NUMBER ) )
-                {
-                    outConfig.setUidNumber( propUpdater.newValue( inConfig.getUidNumber() ) );
-                }
-                if( name.equals( GlobalIds.GID_NUMBER ) )
-                {
-                    outConfig.setGidNumber( propUpdater.newValue( inConfig.getGidNumber() ) );
-                }
-            }
-            cfgMgr.update( outConfig );
-        }
-        catch ( SecurityException se )
-        {
-            String error = "replaceProperty failed, exception=" + se.getMessage();
-            throw new CfgRuntimeException( GlobalErrIds.FT_CONFIG_UPDATE_FAILED, error, se );
-        }
-        return inConfig;
-    }
-
-    /**
      * Gets the prop attribute as String value from the apache commons cfg component.
      *
      * @param name contains the name of the property.
@@ -794,4 +753,60 @@ public final class Config
             throw new CfgRuntimeException( GlobalErrIds.FT_CONFIG_INITIALIZE_FAILED, error, se );
         }
     }
+
+    /**
+     * Constructs a key used to store dynamic role constraints inside the properties, as name:value.
+     * The format is: RC$tenant$role:constraint
+     * @param role contains the name of the role being constrained.
+     * @param contextId contains the tenant name.
+     * @return String containing the key name used to lookup the value of the role constraint.
+     */
+    public String getConstraintKey( String role, String contextId )
+    {
+        return GlobalIds.CONSTRAINT_KEY_PREFIX +
+                getDelimiter() +
+                contextId +
+                getDelimiter()
+                + role.toLowerCase();
+    }
+
+    /**
+     * Performs auto-increment on a list of key names that map to integer values stored on the current config node of the runtime.
+     * Unfortunately, it's synchronized to prevent a race condition of multiple threads trying to update the same id.
+     * Worse, it doesn't lock meaning not synched across processes and so a temporary workaround until the pending Apache LDAP API/Directory support for RFC 4525 (Modify Increment attribute).
+     *
+     * @param props list of attribute names to update on config node.
+     * @param propUpdater reference to object that updates to new value.
+     * @return Configuration entity containing the old values.
+     */
+    public synchronized Configuration getIncrementReplacePosixIds(List<String> props, PropUpdater propUpdater ) throws CfgException
+    {
+        String cfgName = Config.getInstance().getProperty( GlobalIds.CONFIG_REALM, "DEFAULT" );
+        org.apache.directory.fortress.core.model.Configuration inConfig;
+        try
+        {
+            ConfigMgr cfgMgr = ConfigMgrFactory.createInstance();
+            inConfig = cfgMgr.getIds( cfgName );
+            org.apache.directory.fortress.core.model.Configuration outConfig = new Configuration();
+            outConfig.setName( cfgName );
+            for( String name : props )
+            {
+                if( name.equals( GlobalIds.UID_NUMBER ) )
+                {
+                    outConfig.setUidNumber( propUpdater.newValue( inConfig.getUidNumber() ) );
+                }
+                if( name.equals( GlobalIds.GID_NUMBER ) )
+                {
+                    outConfig.setGidNumber( propUpdater.newValue( inConfig.getGidNumber() ) );
+                }
+            }
+            cfgMgr.update( outConfig );
+        }
+        catch ( SecurityException se )
+        {
+            String error = "replaceProperty failed, exception=" + se.getMessage();
+            throw new CfgRuntimeException( GlobalErrIds.FT_CONFIG_UPDATE_FAILED, error, se );
+        }
+        return inConfig;
+    }
 }
\ No newline at end of file
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
index 2c71e2e..6edfec8 100644
--- 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
@@ -21,7 +21,6 @@ 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.GlobalIds;
 import org.apache.directory.fortress.core.model.Constraint;
 import org.apache.directory.fortress.core.model.RoleConstraint;
 import org.apache.directory.fortress.core.model.Session;
@@ -58,8 +57,10 @@ public class UserRoleConstraint
         // 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( GlobalIds.CONSTRAINT_KEY_PREFIX + role.getName().toLowerCase() );
+            // This constraint type requires a global config parameter keyed by RC$tenant$role:constraint:
+            String constraintKey = Config.getInstance().getConstraintKey( role.getName(), session.getContextId() );
+            String constraintType = Config.getInstance().getProperty( constraintKey );
+
             // Is there a runtime constraint placed on this role activation?
             if ( StringUtils.isNotEmpty( constraintType ))
             {