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/16 22:19:55 UTC

[directory-fortress-core] 01/01: FC-267 - New Configuration entity, interim

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

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

commit b6809466a061e3154d8e58d7d16142367ed1f4e0
Author: Shawn McKinney <sm...@apache.org>
AuthorDate: Tue Apr 16 17:19:49 2019 -0500

    FC-267 - New Configuration entity, interim
---
 build-config.xml                                   |   1 +
 .../fortress/core/ant/FortressAntTask.java         |  82 +++++---
 .../directory/fortress/core/impl/AdminMgrImpl.java |   3 +-
 .../directory/fortress/core/impl/ConfigDAO.java    | 107 +++++++----
 .../fortress/core/impl/ConfigMgrImpl.java          |  26 ++-
 .../directory/fortress/core/impl/ConfigP.java      |  27 +--
 .../directory/fortress/core/impl/UserDAO.java      |   4 +-
 .../fortress/core/model/Configuration.java         | 213 +++++++++++++++++++++
 .../fortress/core/rest/ConfigMgrRestImpl.java      |  21 ++
 .../directory/fortress/core/util/Config.java       |  35 +++-
 10 files changed, 427 insertions(+), 92 deletions(-)

diff --git a/build-config.xml b/build-config.xml
index 14a2399..eac2f6d 100644
--- a/build-config.xml
+++ b/build-config.xml
@@ -328,6 +328,7 @@
          <replace file="${dst.bootstrap.conf}" token="@TRUST_STORE@" value="${trust.store}"/>
          <replace file="${dst.bootstrap.conf}" token="@TRUST_STORE_PW@" value="${trust.store.password}"/>
          <replace file="${dst.bootstrap.conf}" token="@TRUST_STORE_ONCLASSPATHW@" value="${trust.store.onclasspath}"/>
+         <replace file="${dst.bootstrap.conf}" token="@IS_RFC2307@" value="${rfc2307}"/>
 
        <copy file="${src.remote.conf}" tofile="${dst.remote.conf}"/>
          <!-- These params are bound for config/config.properties file and contain coordinate to the target ldap server (only). -->
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 2b3459c..6abe1a5 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
@@ -44,23 +44,8 @@ import org.apache.directory.fortress.core.PwPolicyMgrFactory;
 import org.apache.directory.fortress.core.SecurityException;
 import org.apache.directory.fortress.core.impl.OrganizationalUnitP;
 import org.apache.directory.fortress.core.impl.SuffixP;
-import org.apache.directory.fortress.core.model.AdminRole;
-import org.apache.directory.fortress.core.model.Context;
-import org.apache.directory.fortress.core.model.Group;
-import org.apache.directory.fortress.core.model.OrgUnit;
-import org.apache.directory.fortress.core.model.OrganizationalUnit;
-import org.apache.directory.fortress.core.model.PermGrant;
-import org.apache.directory.fortress.core.model.PermObj;
-import org.apache.directory.fortress.core.model.Permission;
+import org.apache.directory.fortress.core.model.*;
 import org.apache.directory.fortress.core.util.PropUtil;
-import org.apache.directory.fortress.core.model.PwPolicy;
-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.Suffix;
-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.util.ClassUtil;
 import org.apache.directory.fortress.core.util.Config;
 import org.apache.directory.fortress.core.util.Testable;
@@ -2527,13 +2512,14 @@ public class FortressAntTask extends Task implements InputHandler
      */
     private void addConfig() throws BuildException
     {
+        LOG.info( "addConfig" );
         if( addconfig == null )
         {
             return;
         }
 
         Properties props = new Properties();
-        String configNodeName = "";
+        Configuration configuration = new Configuration();
         // Loop through the entityclass elements
         for ( Addconfig addcfg : addconfig )
         {
@@ -2542,19 +2528,38 @@ public class FortressAntTask extends Task implements InputHandler
                 List<ConfigAnt> cfgs = addcfg.getConfig();
                 for ( ConfigAnt cfg : cfgs )
                 {
-                    LOG.info( "addConfig" );
                     String val = cfg.getProps();
                     int indx = val.indexOf( GlobalIds.PROP_SEP );
                     if ( indx >= 1 )
                     {
                         String name = val.substring( 0, indx );
                         String value = val.substring( indx + 1 );
-                        props.setProperty( name, value );
+
+                        // The config realm property is required on updconfig op and points to the existing node in ldap to update with these new props.
+                        if( name.equalsIgnoreCase( GlobalIds.CONFIG_REALM ))
+                        {
+                            configuration.setName( value );
+                        }
+                        else if( name.equalsIgnoreCase( GlobalIds.CONFIG_UID_NUMBER ))
+                        {
+                            configuration.setUidNumber( value );
+                        }
+                        else if( name.equalsIgnoreCase( GlobalIds.CONFIG_GID_NUMBER ))
+                        {
+                            configuration.setGidNumber( value );
+                        }
+                        else
+                        {
+                            props.setProperty( name, value );
+                            LOG.info( "addConfig name [{}] value [{}]", name, value );
+                        }
                     }
                 }
-                configNodeName = props.getProperty( GlobalIds.CONFIG_REALM );
-                LOG.info( "addConfig realm name [{}]", configNodeName );
-                cfgMgr.add( configNodeName, props );
+                configuration.addProperties( props );
+                LOG.info( "addConfig realm name [{}]", configuration.getName() );
+                LOG.info( "addConfig gid.number [{}]", configuration.getGidNumber() );
+                LOG.info( "addConfig uid.number [{}]", configuration.getUidNumber() );
+                cfgMgr.add( configuration );
             }
             catch ( SecurityException se )
             {
@@ -2562,18 +2567,18 @@ public class FortressAntTask extends Task implements InputHandler
                 {
                     try
                     {
-                        LOG.info( "addConfig realm name={} entry already exists, attempt to update", configNodeName );
-                        cfgMgr.update( configNodeName, props );
-                        LOG.info( "addConfig realm name={} update [{}] successful", configNodeName, configNodeName );
+                        LOG.info( "addConfig realm name={} entry already exists, attempt to update", configuration.getName() );
+                        cfgMgr.update( configuration );
+                        LOG.info( "addConfig realm name={} update [{}] successful", configuration.getName(), configuration.getName() );
                     }
                     catch ( SecurityException se2 )
                     {
-                        LOG.warn( "addConfig realm name={] update failed SecurityException={}", configNodeName, se2 );
+                        LOG.warn( "addConfig realm name={] update failed SecurityException={}", configuration.getName(), se2 );
                     }
                 }
                 else
                 {
-                    LOG.warn( "addConfig realm name={} failed SecurityException={}", configNodeName, se );
+                    LOG.warn( "addConfig realm name={} failed SecurityException={}", configuration.getName(), se );
                 }
             }
         }
@@ -2585,12 +2590,15 @@ public class FortressAntTask extends Task implements InputHandler
      */
     private void updConfig() throws BuildException
     {
+        LOG.info( "updateConfig" );
+
         if( updconfig == null )
         {
             return;
         }
 
         Properties props = new Properties();
+        Configuration configuration = new Configuration();
         String configNodeName = "";
         // Loop through the entityclass elements
         for ( Updconfig updcfg : updconfig )
@@ -2609,26 +2617,38 @@ public class FortressAntTask extends Task implements InputHandler
                     // The config realm property is required on updconfig op and points to the existing node in ldap to update with these new props.
                     if( name.equalsIgnoreCase( GlobalIds.CONFIG_REALM ))
                     {
-                        configNodeName = value;
+                        configuration.setName( value );
+                    }
+                    else if( name.equalsIgnoreCase( GlobalIds.CONFIG_UID_NUMBER ))
+                    {
+                        configuration.setUidNumber( value );
+                    }
+                    else if( name.equalsIgnoreCase( GlobalIds.CONFIG_GID_NUMBER ))
+                    {
+                        configuration.setGidNumber( value );
                     }
                     else
                     {
                         props.setProperty( name, value );
+                        LOG.info( "updateConfig name [{}] value [{}]", name, value );
                     }
                 }
             }
             // Can't go on w/out a name for the config node to update.
-            if ( StringUtils.isEmpty( configNodeName ))
+            if ( StringUtils.isEmpty( configuration.getName() ))
             {
                 LOG.warn( "updConfig realm name not specified, operation aborted." );
                 LOG.warn( "Add entry like this  to input xml: <config props=\"config.realm:DEFAULT\"/>" );
             }
             else
             {
+                configuration.addProperties( props );
+                LOG.info( "updConfig realm name [{}]", configuration.getName() );
+                LOG.info( "updConfig gid.number [{}]", configuration.getGidNumber() );
+                LOG.info( "updConfig uid.number [{}]", configuration.getUidNumber() );
                 try
                 {
-                    LOG.info( "updateConfig realm name [{}]", configNodeName );
-                    cfgMgr.update( configNodeName, props );
+                    cfgMgr.update( configuration );
                 }
                 catch ( SecurityException se )
                 {
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 485f155..b2a820e 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
@@ -418,7 +418,8 @@ 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( realmName, props );
+
+        configP.update( new Configuration(realmName, props) );
         // update in-memory:
         Config.getInstance().setProperty( propKey, propValue );
     }
diff --git a/src/main/java/org/apache/directory/fortress/core/impl/ConfigDAO.java b/src/main/java/org/apache/directory/fortress/core/impl/ConfigDAO.java
index 6edaf5f..73f44ac 100755
--- a/src/main/java/org/apache/directory/fortress/core/impl/ConfigDAO.java
+++ b/src/main/java/org/apache/directory/fortress/core/impl/ConfigDAO.java
@@ -24,12 +24,10 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Properties;
 
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
 import org.apache.directory.api.ldap.model.constants.SchemaConstants;
-import org.apache.directory.api.ldap.model.entry.DefaultEntry;
-import org.apache.directory.api.ldap.model.entry.DefaultModification;
-import org.apache.directory.api.ldap.model.entry.Entry;
-import org.apache.directory.api.ldap.model.entry.Modification;
-import org.apache.directory.api.ldap.model.entry.ModificationOperation;
+import org.apache.directory.api.ldap.model.entry.*;
 import org.apache.directory.api.ldap.model.exception.LdapEntryAlreadyExistsException;
 import org.apache.directory.api.ldap.model.exception.LdapException;
 import org.apache.directory.api.ldap.model.exception.LdapNoSuchObjectException;
@@ -40,12 +38,16 @@ 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.Configuration;
 import org.apache.directory.fortress.core.util.PropUtil;
 import org.apache.directory.fortress.core.util.Config;
 import org.apache.directory.ldap.client.api.LdapConnection;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import static org.apache.directory.fortress.core.GlobalIds.GID_NUMBER;
+import static org.apache.directory.fortress.core.GlobalIds.UID_NUMBER;
+
 
 /**
  * This class provides data access for the standard ldap object device that has been extended to support name/value pairs.
@@ -82,22 +84,21 @@ import org.slf4j.LoggerFactory;
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
 final class ConfigDAO extends LdapDataProvider
-
 {
     private static final String CLS_NM = ConfigDAO.class.getName();
     private static final Logger LOG = LoggerFactory.getLogger( CLS_NM );
     private String CONFIG_ROOT_DN;
 
-    private final String CONFIG_OBJ_CLASS[] =
-        {
-            SchemaConstants.DEVICE_OC, GlobalIds.PROPS_AUX_OBJECT_CLASS_NAME
+    private final String[] CONFIG_OBJ_CLASS =
+    {
+        SchemaConstants.DEVICE_OC, GlobalIds.PROPS_AUX_OBJECT_CLASS_NAME, GlobalIds.FT_RFC2307_AUX_OBJECT_CLASS_NAME
     };
 
     private final String[] CONFIG_ATRS =
-        {
-            SchemaConstants.CN_AT, GlobalIds.PROPS
-    };
+    {
+        SchemaConstants.CN_AT, GlobalIds.PROPS, GID_NUMBER, UID_NUMBER
 
+    };
 
     /**
      * Package private default constructor.
@@ -108,28 +109,44 @@ final class ConfigDAO extends LdapDataProvider
     	CONFIG_ROOT_DN = Config.getInstance().getProperty( GlobalIds.CONFIG_ROOT_PARAM );
     }
 
-
     /**
      * Create a new configuration node and load it with properties.
-     * @param name of the new configuration node to be created in ldap.
-     * @param props each name/value pair becomes an ftprop in this entry.
-     * @return
+     * @param cfg the new configuration node to be created in ldap.
+     * @return what was just added.
      * @throws org.apache.directory.fortress.core.CreateException
      */
-    Properties create( String name, Properties props )
+    Configuration create( Configuration cfg )
         throws CreateException
     {
         LdapConnection ld = null;
-        String dn = getDn( name );
+        String dn = getDn( cfg.getName() );
         LOG.info( "create dn [{}]", dn );
         try
         {
             Entry myEntry = new DefaultEntry( dn );
             myEntry.add( SchemaConstants.OBJECT_CLASS_AT, CONFIG_OBJ_CLASS );
             ld = getAdminConnection();
-            myEntry.add( SchemaConstants.CN_AT, name );
-            loadProperties( props, myEntry, GlobalIds.PROPS );
-            add( ld, myEntry );
+            myEntry.add( SchemaConstants.CN_AT, cfg.getName() );
+            loadProperties( cfg.getProperties(), myEntry, GlobalIds.PROPS );
+            // These attributes hold sequence numbers:
+            if (StringUtils.isNotEmpty(cfg.getUidNumber()))
+            {
+                myEntry.add( GlobalIds.UID_NUMBER, cfg.getUidNumber() );
+            }
+            else
+            {
+                myEntry.add( GlobalIds.UID_NUMBER, "0" );
+            }
+            if (StringUtils.isNotEmpty(cfg.getGidNumber()))
+            {
+                myEntry.add( GlobalIds.GID_NUMBER, cfg.getGidNumber() );
+            }
+            else
+            {
+                myEntry.add( GlobalIds.GID_NUMBER, "0" );
+            }
+
+            add( ld, myEntry, cfg );
         }
         catch ( LdapEntryAlreadyExistsException e )
         {
@@ -148,36 +165,43 @@ final class ConfigDAO extends LdapDataProvider
         {
             closeAdminConnection( ld );
         }
-        return props;
+        return cfg;
     }
 
 
     /**
      * Update existing node with new properties.
-     * @param name contains existing config node name
-     * @param props each property name value will loaded into an attribute (ftprops) under the config node.
-     * @return
+     * @param cfg contains the name and each property name value will loaded into an attribute (ftprops) under the config node.
+     * @return the updated entity.
      * @throws org.apache.directory.fortress.core.UpdateException
      */
-    Properties update( String name, Properties props )
+    Configuration update( Configuration cfg )
         throws UpdateException
     {
         LdapConnection ld = null;
-        String dn = getDn( name );
-        LOG.info( "update dn [{}]", dn );
+        String dn = getDn( cfg.getName() );
+        LOG.debug( "update dn [{}]", dn );
         try
         {
             List<Modification> mods = new ArrayList<>();
-            if ( PropUtil.isNotEmpty( props ) )
+            if ( PropUtil.isNotEmpty( cfg.getProperties() ) )
             {
-                loadProperties( props, mods, GlobalIds.PROPS, false );
+                loadProperties( cfg.getProperties(), mods, GlobalIds.PROPS, false );
+            }
+            if (StringUtils.isNotEmpty(cfg.getUidNumber()))
+            {
+                mods.add(new DefaultModification(ModificationOperation.REPLACE_ATTRIBUTE, GlobalIds.UID_NUMBER,
+                        cfg.getUidNumber()));
+            }
+            if (StringUtils.isNotEmpty(cfg.getGidNumber()))
+            {
+                mods.add(new DefaultModification(ModificationOperation.REPLACE_ATTRIBUTE, GlobalIds.GID_NUMBER,
+                        cfg.getGidNumber()));
             }
-            ld = getAdminConnection();
             if ( mods.size() > 0 )
             {
                 ld = getAdminConnection();
-                // TODO: change to use modify that leaves audit trail:
-                modify( ld, dn, mods );
+                modify( ld, dn, mods, cfg );
             }
         }
         catch ( LdapException e )
@@ -189,7 +213,7 @@ final class ConfigDAO extends LdapDataProvider
         {
             closeAdminConnection( ld );
         }
-        return props;
+        return cfg;
     }
 
 
@@ -203,7 +227,7 @@ final class ConfigDAO extends LdapDataProvider
      * @throws UpdateException in the event the attribute can't be replaced.
      * @throws FinderException in the event the config node and/or property key:value can't be located.
      */
-    void updateProperty( String name, String key, String value, String newValue ) throws UpdateException, FinderException
+    void updateProperty( String name, String key, String value, String newValue ) throws UpdateException
     {
         LdapConnection ld = null;
         String dn = getDn( name );
@@ -297,13 +321,13 @@ final class ConfigDAO extends LdapDataProvider
 
     /**
      * @param name
-     * @return
+     * @return the existing config node.
      * @throws org.apache.directory.fortress.core.FinderException
      */
-    Properties getConfig( String name )
+    Configuration getConfig( String name )
         throws FinderException
     {
-        Properties props = null;
+        Configuration configuration = new Configuration();
         LdapConnection ld = null;
         String dn = getDn( name );
         LOG.debug( "getConfig dn [{}]", dn );
@@ -311,7 +335,10 @@ final class ConfigDAO extends LdapDataProvider
         {
             ld = getAdminConnection();
             Entry findEntry = read( ld, dn, CONFIG_ATRS );
-            props = PropUtil.getProperties( getAttributes( findEntry, GlobalIds.PROPS ) );
+            configuration.setName( name );
+            configuration.addProperties( PropUtil.getProperties( getAttributes( findEntry, GlobalIds.PROPS ) ) );
+            configuration.setUidNumber( getAttribute( findEntry, GlobalIds.UID_NUMBER ) );
+            configuration.setGidNumber( getAttribute( findEntry, GlobalIds.GID_NUMBER ) );
         }
         catch ( LdapNoSuchObjectException e )
         {
@@ -327,7 +354,7 @@ final class ConfigDAO extends LdapDataProvider
         {
             closeAdminConnection( ld );
         }
-        return props;
+        return configuration;
     }
 
 
diff --git a/src/main/java/org/apache/directory/fortress/core/impl/ConfigMgrImpl.java b/src/main/java/org/apache/directory/fortress/core/impl/ConfigMgrImpl.java
index 42dd967..4ba8dfb 100755
--- a/src/main/java/org/apache/directory/fortress/core/impl/ConfigMgrImpl.java
+++ b/src/main/java/org/apache/directory/fortress/core/impl/ConfigMgrImpl.java
@@ -23,7 +23,10 @@ import java.io.Serializable;
 import java.util.Properties;
 
 import org.apache.directory.fortress.core.ConfigMgr;
+import org.apache.directory.fortress.core.GlobalErrIds;
 import org.apache.directory.fortress.core.SecurityException;
+import org.apache.directory.fortress.core.model.Configuration;
+import org.apache.directory.fortress.core.util.VUtil;
 
 
 /**
@@ -39,9 +42,10 @@ import org.apache.directory.fortress.core.SecurityException;
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class ConfigMgrImpl implements ConfigMgr, Serializable
+public class ConfigMgrImpl  extends Manageable implements ConfigMgr, Serializable
 {
     private ConfigP cfgP;
+    private static final String CLS_NM = ConfigMgrImpl.class.getName();
 
     public ConfigMgrImpl() {
     	cfgP = new ConfigP();
@@ -51,9 +55,14 @@ public class ConfigMgrImpl implements ConfigMgr, Serializable
      * {@inheritDoc}
      */
     @Override
-    public Properties add(String name, Properties inProps) throws SecurityException
+    public Configuration add(Configuration cfg) throws SecurityException
     {
-        return cfgP.add(name, inProps);
+        String methodName = "add";
+        setEntitySession( CLS_NM, methodName, cfg );
+        assertContext( CLS_NM, methodName, cfg, GlobalErrIds.FT_CONFIG_NULL );
+        VUtil.assertNotNull( cfg, GlobalErrIds.FT_CONFIG_NULL, CLS_NM + methodName );
+        VUtil.assertNotNull( cfg.getName(), GlobalErrIds.FT_CONFIG_NAME_NULL, CLS_NM + methodName );
+        return cfgP.add(cfg);
     }
 
 
@@ -61,9 +70,14 @@ public class ConfigMgrImpl implements ConfigMgr, Serializable
      * {@inheritDoc}
      */
     @Override
-    public Properties update(String name, Properties inProps) throws SecurityException
+    public Configuration update(Configuration cfg) throws SecurityException
     {
-        return cfgP.update(name, inProps);
+        String methodName = "update";
+        setEntitySession( CLS_NM, methodName, cfg );
+        assertContext( CLS_NM, methodName, cfg, GlobalErrIds.FT_CONFIG_NULL );
+        VUtil.assertNotNull( cfg, GlobalErrIds.FT_CONFIG_NULL, CLS_NM + methodName );
+        VUtil.assertNotNull( cfg.getName(), GlobalErrIds.FT_CONFIG_NAME_NULL, CLS_NM + methodName );
+        return cfgP.update(cfg);
     }
 
     /**
@@ -97,7 +111,7 @@ public class ConfigMgrImpl implements ConfigMgr, Serializable
      * {@inheritDoc}
      */
     @Override
-    public Properties read(String name) throws SecurityException
+    public Configuration read(String name) throws SecurityException
     {
         return cfgP.read(name);
     }
diff --git a/src/main/java/org/apache/directory/fortress/core/impl/ConfigP.java b/src/main/java/org/apache/directory/fortress/core/impl/ConfigP.java
index e566216..efdec90 100755
--- a/src/main/java/org/apache/directory/fortress/core/impl/ConfigP.java
+++ b/src/main/java/org/apache/directory/fortress/core/impl/ConfigP.java
@@ -27,6 +27,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.Configuration;
 import org.apache.directory.fortress.core.util.VUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -70,12 +71,13 @@ final class ConfigP
      * @return {@link Properties} containing the collection of name/value pairs just added.
      * @throws SecurityException in the event entry already present or other system error.
      */
-    Properties add( String name, Properties inProps )
+    //Properties add( String name, Properties inProps )
+    Configuration add(Configuration cfg)
         throws SecurityException
     {
-        validate( name, inProps );
+        validate( cfg.getName(), cfg.getProperties(), false );
         ConfigDAO cfgDao = new ConfigDAO();
-        return cfgDao.create( name, inProps );
+        return cfgDao.create( cfg );
     }
 
 
@@ -88,12 +90,13 @@ final class ConfigP
      * @return {@link Properties} containing the collection of name/value pairs to be added to existing node.
      * @throws org.apache.directory.fortress.core.SecurityException in the event entry not present or other system error.
      */
-    Properties update( String name, Properties inProps )
+    //Properties update( String name, Properties inProps )
+    Configuration update(Configuration cfg)
         throws SecurityException
     {
-        validate( name, inProps );
+        validate( cfg.getName(), cfg.getProperties(), true );
         ConfigDAO cfgDao = new ConfigDAO();
-        return cfgDao.update( name, inProps );
+        return cfgDao.update( cfg );
     }
 
 
@@ -153,7 +156,7 @@ final class ConfigP
     void delete( String name, Properties inProps )
         throws SecurityException
     {
-        validate( name, inProps );
+        validate( name, inProps, false );
         ConfigDAO cfgDao = new ConfigDAO();
         cfgDao.remove( name, inProps );
     }
@@ -167,13 +170,13 @@ final class ConfigP
      * @return {@link Properties} containing the collection of name/value pairs just added. Maps to 'ftProps' attribute in 'ftProperties' object class.
      * @throws org.apache.directory.fortress.core.SecurityException in the event entry doesn't exist or other system error.
      */
-    Properties read( String name )
+    Configuration read( String name )
         throws SecurityException
     {
         Properties outProps;
         ConfigDAO cfgDao = new ConfigDAO();
-        outProps = cfgDao.getConfig( name );
-        return outProps;
+        return cfgDao.getConfig( name );
+        //return outProps;
     }
 
 
@@ -185,7 +188,7 @@ final class ConfigP
      * @param entity contains the name/value properties targeted for operation.
      * @throws org.apache.directory.fortress.core.ValidationException thrown in the event the validations fail.
      */
-    private void validate( String name, Properties entity )
+    private void validate( String name, Properties entity, boolean isUpdate )
         throws ValidationException
     {
         if ( StringUtils.isEmpty( name ) )
@@ -200,7 +203,7 @@ final class ConfigP
             LOG.warn( error );
             throw new ValidationException( GlobalErrIds.FT_CONFIG_NAME_INVLD, error );
         }
-        if ( entity == null || entity.size() == 0 )
+        if ( !isUpdate && ( entity == null || entity.size() == 0 ) )
         {
             String error = "validate name [" + name + "] config props null";
             LOG.warn( error );
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 ba7b513..ce73393 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
@@ -83,6 +83,8 @@ import org.apache.directory.ldap.client.api.LdapConnection;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import static org.apache.directory.fortress.core.impl.RoleDAO.IS_RFC2307;
+
 
 /**
  * Data access class for LDAP User entity.
@@ -195,7 +197,7 @@ final class UserDAO extends LdapDataProvider implements PropUpdater
     // RFC2307bis decls:
     private static final String POSIX_ACCOUNT = "posixAccount";
     private static final String HOME_DIRECTORY =  "homeDirectory";
-    private static final boolean IS_RFC2307 = Config.getInstance().getProperty( GlobalIds.RFC2307_PROP ) != null && Config.getInstance().getProperty( GlobalIds.RFC2307_PROP ).equalsIgnoreCase( "true" ) ? true : false;
+    //private static final boolean IS_RFC2307 = Config.getInstance().getProperty( GlobalIds.RFC2307_PROP ) != null && Config.getInstance().getProperty( GlobalIds.RFC2307_PROP ).equalsIgnoreCase( "true" ) ? true : false;
     /**
      * RF2307bis uses groupOfNames instead of ftRA:
      */
diff --git a/src/main/java/org/apache/directory/fortress/core/model/Configuration.java b/src/main/java/org/apache/directory/fortress/core/model/Configuration.java
new file mode 100644
index 0000000..a2d06e8
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/core/model/Configuration.java
@@ -0,0 +1,213 @@
+/*
+ *   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.model;
+
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Objects;
+import java.util.Properties;
+
+/**
+ * A class for passing configuration information.
+ */
+@XmlRootElement(name = "fortConfiguration")
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "configuration", propOrder =
+{
+        "name",
+        "props",
+        "uidNumber",
+        "gidNumber"
+})
+public class Configuration extends FortEntity
+{
+
+    public Configuration()
+    {
+    }
+
+    public Configuration(String name, Properties props)
+    {
+        this.name = name;
+        addProperties( props );
+    }
+
+    private String name;
+    private Props props = new Props();
+    private String uidNumber;
+    private String gidNumber;
+
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    /**
+     * Gets the value of the Props property.  This method is used by Fortress Core and Rest and should not be called by external programs.
+     *
+     * @return possible object is {@link Props }
+     *
+     */
+    public Props getProps()
+    {
+        return props;
+    }
+
+
+    /**
+     * Sets the value of the Props property.  This method is used by Fortress Core and Rest and should not be called by external programs.
+     *
+     * @param value allowed object is {@link Props }
+     *
+     */
+    public void setProps( Props value )
+    {
+        this.props = value;
+    }
+
+
+    /**
+     * Add name/value pair to list of properties associated with Configuration node.  These values are not constrained by Fortress.
+     * Properties are optional.
+     *
+     * @param key   contains property name and maps to 'ftProps' attribute in 'ftProperties' aux object class.
+     * @param value The property value to add
+     */
+    public void addProperty( String key, String value )
+    {
+        Props.Entry entry = new Props.Entry();
+        entry.setKey( key );
+        entry.setValue( value );
+        props.getEntry().add( entry );
+    }
+
+
+    /**
+     * Get a name/value pair attribute from list of properties associated with Configuration node.  These values are not constrained by Fortress.
+     * Properties are optional.
+     *
+     * @param key contains property name and maps to 'ftProps' attribute in 'ftProperties' aux object class.
+     * @return value containing name/value pair that maps to 'ftProps' attribute in 'ftProperties' aux object class.
+     */
+    public String getProperty( String key )
+    {
+        List<Props.Entry> props = this.props.getEntry();
+        Props.Entry keyObj = new Props.Entry();
+        keyObj.setKey( key );
+
+        String value = null;
+        int indx = props.indexOf( keyObj );
+
+        if ( indx != -1 )
+        {
+            Props.Entry entry = props.get( props.indexOf( keyObj ) );
+            value = entry.getValue();
+        }
+
+        return value;
+    }
+
+
+    /**
+     * Add new collection of name/value pairs to attributes associated with Configuration node.  These values are not constrained by Fortress.
+     * Properties are optional.
+     *
+     * @param props contains collection of name/value pairs and maps to 'ftProps' attribute in 'ftProperties' aux object class.
+     */
+    public void addProperties( Properties props )
+    {
+        if ( props != null )
+        {
+            for (Enumeration<?> e = props.propertyNames(); e.hasMoreElements(); )
+            {
+                // This LDAP attr is stored as a name-value pair separated by a ':'.
+                String key = ( String ) e.nextElement();
+                String val = props.getProperty( key );
+                addProperty( key, val );
+            }
+        }
+    }
+
+
+    /**
+     * Return the collection of name/value pairs to attributes associated with Configuration node.  These values are not constrained by Fortress.
+     * Properties are optional.
+     *
+     * @return Properties contains collection of name/value pairs and maps to 'ftProps' attribute in 'ftProperties' aux object class.
+     */
+    public Properties getProperties()
+    {
+        Properties properties = null;
+        List<Props.Entry> props = this.props.getEntry();
+
+        if ( props.size() > 0 )
+        {
+            properties = new Properties();
+
+            for ( Props.Entry entry : props )
+            {
+                String key = entry.getKey();
+                String val = entry.getValue();
+                properties.setProperty( key, val );
+            }
+        }
+
+        return properties;
+    }
+
+    public String getUidNumber() {
+        return uidNumber;
+    }
+
+    public void setUidNumber(String uidNumber) {
+        this.uidNumber = uidNumber;
+    }
+
+    public String getGidNumber() {
+        return gidNumber;
+    }
+
+    public void setGidNumber(String gidNumber) {
+        this.gidNumber = gidNumber;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        Configuration that = (Configuration) o;
+        return Objects.equals(name, that.name);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(name);
+    }
+}
+
diff --git a/src/main/java/org/apache/directory/fortress/core/rest/ConfigMgrRestImpl.java b/src/main/java/org/apache/directory/fortress/core/rest/ConfigMgrRestImpl.java
index 99011f4..5fe8930 100644
--- a/src/main/java/org/apache/directory/fortress/core/rest/ConfigMgrRestImpl.java
+++ b/src/main/java/org/apache/directory/fortress/core/rest/ConfigMgrRestImpl.java
@@ -24,6 +24,7 @@ import java.util.Properties;
 import org.apache.directory.fortress.core.ConfigMgr;
 import org.apache.directory.fortress.core.GlobalErrIds;
 import org.apache.directory.fortress.core.SecurityException;
+import org.apache.directory.fortress.core.model.Configuration;
 import org.apache.directory.fortress.core.model.FortRequest;
 import org.apache.directory.fortress.core.model.FortResponse;
 import org.apache.directory.fortress.core.model.Props;
@@ -50,6 +51,12 @@ public class ConfigMgrRestImpl implements ConfigMgr
      * {@inheritDoc}
      */
     @Override
+    public Configuration add(Configuration cfg) throws SecurityException
+    {
+        throw new UnsupportedOperationException( "not implemented" );
+    }
+/*
+    @Override
     public Properties add(String name, Properties inProperties) throws SecurityException
     {
         VUtil.assertNotNull(name, GlobalErrIds.FT_CONFIG_NAME_NULL, CLS_NM + ".add");
@@ -73,12 +80,19 @@ public class ConfigMgrRestImpl implements ConfigMgr
         }
         return retProperties;
     }
+*/
 
 
     /**
      * {@inheritDoc}
      */
     @Override
+    public Configuration update(Configuration cfg) throws SecurityException
+    {
+        throw new UnsupportedOperationException( "not implemented" );
+    }
+/*
+    @Override
     public Properties update(String name, Properties inProperties) throws SecurityException
     {
         VUtil.assertNotNull(name, GlobalErrIds.FT_CONFIG_NAME_NULL, CLS_NM + ".update");
@@ -102,6 +116,7 @@ public class ConfigMgrRestImpl implements ConfigMgr
         }
         return retProperties;
     }
+*/
 
 
     /**
@@ -159,6 +174,11 @@ public class ConfigMgrRestImpl implements ConfigMgr
      * {@inheritDoc}
      */
     @Override
+    public Configuration read(String name) throws SecurityException
+    {
+        throw new java.lang.UnsupportedOperationException();
+    }
+/*
     public Properties read(String name) throws SecurityException
     {
         VUtil.assertNotNull(name, GlobalErrIds.FT_CONFIG_NAME_NULL, CLS_NM + ".readRole");
@@ -180,4 +200,5 @@ public class ConfigMgrRestImpl implements ConfigMgr
         }
         return retProps;
     }
+*/
 }
\ No newline at end of file
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 cc70c70..08fd7dc 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
@@ -33,6 +33,7 @@ import org.apache.directory.fortress.core.ConfigMgrFactory;
 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.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -139,6 +140,36 @@ public final class Config
         try
         {
             ConfigMgr cfgMgr = ConfigMgrFactory.createInstance();
+            org.apache.directory.fortress.core.model.Configuration inConfig = cfgMgr.read( name );
+            org.apache.directory.fortress.core.model.Configuration outConfig = new Configuration();
+            outConfig.setName( name );
+            if( key.equals( GlobalIds.UID_NUMBER ))
+            {
+                value = inConfig.getUidNumber();
+                outConfig.setUidNumber( propUpdater.newValue( value ) );
+            }
+            else
+            {
+                value = inConfig.getGidNumber();
+                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 value;
+    }
+
+/*
+    public synchronized String replacePropertyx( String name, String key, PropUpdater propUpdater ) throws CfgException
+    {
+        String value;
+        try
+        {
+            ConfigMgr cfgMgr = ConfigMgrFactory.createInstance();
             Properties props = cfgMgr.read( name );
             // TODO: The key should be scoped to an instance, e.g. FORT104
             value = props.getProperty( key );
@@ -153,6 +184,7 @@ public final class Config
         }
         return value;
     }
+*/
 
     /**
      * Gets the prop attribute as String value from the apache commons cfg component.
@@ -410,7 +442,8 @@ public final class Config
         {
             String configClassName = this.getProperty( GlobalIds.CONFIG_IMPLEMENTATION );
             ConfigMgr cfgMgr = ConfigMgrFactory.createInstance(configClassName, false);
-            props = cfgMgr.read( realmName );
+            Configuration configuration = cfgMgr.read( realmName );
+            props = configuration.getProperties();
         }
         catch ( CfgException ce )
         {