directory-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From smckin...@apache.org
Subject [45/75] [abbrv] [partial] directory-fortress-core git commit: FC-109 - rename rbac package to impl
Date Tue, 09 Jun 2015 03:15:51 GMT
http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/ba64d26a/src/main/java/org/apache/directory/fortress/core/impl/AuditDAO.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/impl/AuditDAO.java b/src/main/java/org/apache/directory/fortress/core/impl/AuditDAO.java
new file mode 100755
index 0000000..e5c2aea
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/core/impl/AuditDAO.java
@@ -0,0 +1,787 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.fortress.core.impl;
+
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.directory.api.ldap.model.constants.SchemaConstants;
+import org.apache.directory.api.ldap.model.cursor.CursorException;
+import org.apache.directory.api.ldap.model.cursor.SearchCursor;
+import org.apache.directory.api.ldap.model.entry.Entry;
+import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException;
+import org.apache.directory.api.ldap.model.message.SearchScope;
+import org.apache.directory.fortress.core.model.AuthZ;
+import org.apache.directory.fortress.core.model.Bind;
+import org.apache.directory.fortress.core.model.Mod;
+import org.apache.directory.fortress.core.model.UserAudit;
+import org.apache.directory.fortress.core.util.attr.AttrHelper;
+import org.apache.directory.ldap.client.api.LdapConnection;
+import org.apache.directory.fortress.core.FinderException;
+import org.apache.directory.fortress.core.GlobalErrIds;
+import org.apache.directory.fortress.core.GlobalIds;
+import org.apache.directory.fortress.core.model.ObjectFactory;
+import org.apache.directory.fortress.core.util.Config;
+import org.apache.directory.fortress.core.ldap.ApacheDsDataProvider;
+
+
+/**
+ * This class performs data access for OpenLDAP synch repl log data
+ * <p/>
+ * <h3>1. Binds</h3>
+ * <p/>
+ * The auditBind Structural object class is used to store authentication events that can later be queried via ldap API.<br />
+ * <code># The Bind class includes the reqVersion attribute which contains the LDAP</code>
+ * <code># protocol version specified in the Bind as well as the reqMethod attribute</code>
+ * <code># which contains the Bind Method used in the Bind. This will be the string</code>
+ * <code># SIMPLE for LDAP Simple Binds or SASL(mech) for SASL Binds. Note that unless</code>
+ * <code># configured as a global overlay, only Simple Binds using DNs that reside in</code>
+ * <code># the current database will be logged:</code>
+ * <ul>
+ * <li>  ------------------------------------------
+ * <li> <code>objectclass (  1.3.6.1.4.1.4203.666.11.5.2.6 NAME 'auditBind'</code>
+ * <li> <code>DESC 'Bind operation'</code>
+ * <li> <code>SUP auditObject STRUCTURAL</code>
+ * <li> <code>MUST ( reqVersion $ reqMethod ) )</code>
+ * <li> ------------------------------------------
+ * </ul>
+ * <h3>2. Authorizations</h3>
+ * <code>For  the  Search class the reqScope attribute contains the scope of the</code><br />
+ * <code>original search request, using the values specified for  the  LDAP  URL</code><br />
+ * <code>format. I.e.  base, one, sub, or subord.  The reqDerefAliases attribute</code><br />
+ * <code>is one of never, finding, searching, or always,  denoting  how  aliases</code><br />
+ * <code>will  be  processed during the search.  The reqAttrsOnly attribute is a</code><br />
+ * <code>Boolean value showing TRUE if only attribute names were  requested,  or</code><br />
+ * <code>FALSE  if  attributes  and  their values were requested.  The reqFilter</code><br />
+ * <code>attribute carries the filter used in the search request.   The  reqAttr</code><br />
+ * <code>attribute  lists  the  requested attributes if specific attributes were</code><br />
+ * <code>requested.  The reqEntries attribute is the integer count of  how  many</code><br />
+ * <code>entries  were  returned  by  this search request.  The reqSizeLimit and</code><br />
+ * <code>reqTimeLimit attributes indicate what  limits  were  requested  on  the</code><br />
+ * <code>search operation.</code><br />
+ * <ul>
+ * <li>  ------------------------------------------
+ * <li> <code>objectclass  (  1.3.6.1.4.1.4203.666.11.5.2.11</code>
+ * <li> <code>NAME 'auditSearch'</code>
+ * <li> <code>DESC 'Search operation'</code>
+ * <li> <code>SUP auditReadObject STRUCTURAL</code>
+ * <li> <code>MUST ( reqScope $ reqDerefAliases $ reqAttrsOnly )</code>
+ * <li> <code>MAY ( reqFilter $ reqAttr $ reqEntries $ reqSizeLimit $</code>
+ * <li> <code>reqTimeLimit ) )</code>
+ * <li> ------------------------------------------
+ * </ul>
+ * <p/>
+ * <p/>
+ * <h3>3. Modifications</h3>
+ * The auditModify Structural object class is used to store Fortress update and delete events that can later be queried via ldap API.<br />
+ * The deletions can be recorded in this manner and associated with Fortress context because deletions will perform a modification first
+ * if audit is enabled.
+ * <p/>
+ * <code>The Modify operation contains a description  of  modifications  in  the</code><br />
+ * <code>reqMod  attribute,  which  was  already  described  above  in  the  Add</code><br />
+ * <code>operation. It may optionally  contain  the  previous  contents  of  any</code><br />
+ * <code>modified  attributes  in the reqOld attribute, using the same format as</code><br />
+ * <code>described above for the Delete operation.  The reqOld attribute is only</code><br />
+ * <code>populated  if  the  entry  being modified matches the configured logold</code><br />
+ * <code>filter.</code><br />
+ * <ul>
+ * <li>  ------------------------------------------
+ * <li> <code>objectclass (  1.3.6.1.4.1.4203.666.11.5.2.9</code>
+ * <li> <code>NAME 'auditModify'</code>
+ * <li> <code>DESC 'Modify operation'</code>
+ * <li> <code>SUP auditWriteObject STRUCTURAL</code>
+ * <li> <code>MAY reqOld MUST reqMod )</code>
+ * <li> ------------------------------------------
+ * </ul>
+ * <p/>
+ * Note this class used descriptions pulled from man pages on slapd access log.
+ * <p/>
+ * This class is thread safe.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+final class AuditDAO extends ApacheDsDataProvider
+{
+    private static final String CREATETIMESTAMP = "createTimestamp";
+    private static final String CREATORSNAME = "creatorsName";
+    private static final String ENTRYCSN = "entryCSN";
+    private static final String ENTRYDN = "entryDN";
+    private static final String ENTRYUUID = "entryUUID";
+    private static final String HASSUBORDINATES = "hasSubordinates";
+    private static final String MODIFIERSNAME = "modifiersName";
+    private static final String MODIFYTIMESTAMP = "modifyTimestamp";
+    private static final String OBJECTCLASS = "objectClass";
+    private static final String REQUAUTHZID = "reqAuthzID";
+    private static final String REQCONTROLS = "reqControls";
+    private static final String REQDN = "reqDN";
+    private static final String REQEND = "reqEnd";
+    private static final String REQMETHOD = "reqMethod";
+    private static final String REQRESULT = "reqResult";
+    private static final String REQSESSION = "reqSession";
+    private static final String REQSTART = "reqStart";
+    private static final String REQTYPE = "reqType";
+    private static final String REQVERSION = "reqVersion";
+    private static final String REQMOD = "reqMod";
+    private static final String STRUCTURALOBJECTCLASS = "structuralObjectClass";
+    private static final String SUBSCHEMAENTRY = "subschemaSubentry";
+    private static final String REQATTR = "reqAttr";
+    private static final String REQATTRSONLY = "reqAttrsOnly";
+    private static final String REQDREFALIASES = "reqDerefAliases";
+    private static final String REQENTRIES = "reqEntries";
+    private static final String REQFILTER = "reqFilter";
+    private static final String REQSCOPE = "reqScope";
+    private static final String REQSIZELIMIT = "reqSizeLimit";
+    private static final String REQTIMELIMIT = "reqTimeLimit";
+    private static final String REQASSERTION = "reqAssertion";
+    private static final String ACCESS_BIND_CLASS_NM = "auditBind";
+    //private static final String ACCESS_AUTHZ_CLASS_NM = "auditSearch";
+    private static final String ACCESS_AUTHZ_CLASS_NM = "auditCompare";
+    private static final String ACCESS_MOD_CLASS_NM = "auditModify";
+    private static final String ACCESS_ADD_CLASS_NM = "auditAdd";
+    private static final String AUDIT_ROOT = "audit.root";
+
+    private static final String[] AUDIT_AUTHZ_ATRS =
+        {
+            CREATETIMESTAMP, CREATORSNAME, ENTRYCSN, ENTRYDN, ENTRYUUID, HASSUBORDINATES, MODIFIERSNAME,
+            MODIFYTIMESTAMP, OBJECTCLASS, REQATTR, REQATTRSONLY, REQUAUTHZID, REQCONTROLS, REQDN, REQDREFALIASES,
+            REQEND, REQENTRIES, REQFILTER, REQRESULT, REQSCOPE, REQSESSION, REQSIZELIMIT, REQSTART, REQTIMELIMIT,
+            REQTYPE, STRUCTURALOBJECTCLASS, SUBSCHEMAENTRY
+    };
+
+    private static final String[] AUDIT_BIND_ATRS =
+        {
+            CREATETIMESTAMP, CREATORSNAME, ENTRYCSN, ENTRYDN, ENTRYUUID, HASSUBORDINATES, MODIFIERSNAME,
+            MODIFYTIMESTAMP, OBJECTCLASS, REQUAUTHZID, REQCONTROLS, REQDN, REQEND, REQMETHOD, REQRESULT,
+            REQSESSION, REQSTART, REQTYPE, REQVERSION, STRUCTURALOBJECTCLASS, SUBSCHEMAENTRY
+    };
+
+    private static final String[] AUDIT_MOD_ATRS =
+        {
+            OBJECTCLASS, REQUAUTHZID, REQDN, REQEND, REQRESULT, REQSESSION, REQSTART, REQTYPE, REQMOD
+    };
+
+
+    /**
+     * This method returns failed authentications where the userid is not present in the directory.  This
+     * is possible because Fortress performs read on user before the bind.
+     * User:
+     * dn: reqStart=20101014235402.000000Z, cn=log
+     * reqStart: 20101014235402.000000Z
+     * reqEnd: 20101014235402.000001Z
+     * reqAuthzID: cn=Manager,dc=jts,dc=com
+     * reqDerefAliases: never
+     * reqSession: 84
+     * reqAttrsOnly: FALSE
+     * reqSizeLimit: -1
+     * objectClass: auditSearch
+     * reqResult: 32
+     * reqAttr: ftId
+     * reqAttr: uid
+     * reqAttr: userpassword
+     * reqAttr: description
+     * reqAttr: ou
+     * reqAttr: cn
+     * reqAttr: sn
+     * reqAttr: ftRoleCstr
+     * reqAttr: ftCstr
+     * reqAttr: ftRoleAsgn
+     * reqAttr: pwdReset
+     * reqAttr: pwdAccountLockedTime
+     * reqAttr: ftProps
+     * reqEntries: 0
+     * reqFilter: (|(objectClass=*)(?objectClass=ldapSubentry))
+     * reqType: search
+     * reqDN: uid=foo,ou=People,dc=jts,dc=com        /cal/cal2.jsp
+     * reqTimeLimit: -1
+     * reqScope: base
+     *
+     * @param audit
+     * @return
+     * @throws org.apache.directory.fortress.core.FinderException
+     *
+     */
+    List<AuthZ> searchInvalidAuthNs( UserAudit audit ) throws FinderException
+    {
+        List<AuthZ> auditList = new ArrayList<>();
+        LdapConnection ld = null;
+        String auditRoot = Config.getProperty( AUDIT_ROOT );
+        String userRoot = Config.getProperty( GlobalIds.USER_ROOT );
+
+        try
+        {
+            // use wildcard for user if not passed in:
+            //reqDN: uid=foo,ou=People,dc=jts,dc=com
+            //(&
+            //  (objectclass=auditSearch)
+            //      (reqDN=uid=*,ou=People,dc=jts,dc=com)
+            //      (reqAuthzID=cn=Manager,dc=jts,dc=com)
+            //      (reqEntries=0)
+            // )
+
+            String filter = GlobalIds.FILTER_PREFIX + ACCESS_AUTHZ_CLASS_NM + ")(";
+            String userId;
+
+            if ( StringUtils.isNotEmpty( audit.getUserId() ) )
+            {
+                userId = audit.getUserId();
+                filter += REQDN + "=" + SchemaConstants.UID_AT + "=" + userId + "," + userRoot + ")(" +
+                    REQUAUTHZID + "=" + "cn=Manager," + Config.getProperty( GlobalIds.SUFFIX ) + ")";
+            }
+            else
+            {
+                // pull back all failed authN attempts for all users:
+                filter += REQATTR + "=" + SchemaConstants.UID_AT + ")(" +
+                    REQUAUTHZID + "=" + "cn=Manager," + Config.getProperty( GlobalIds.SUFFIX ) + ")";
+            }
+
+            if ( audit.isFailedOnly() )
+            {
+                filter += "(" + REQENTRIES + "=" + 0 + ")";
+            }
+
+            if ( audit.getBeginDate() != null )
+            {
+                String szTime = AttrHelper.encodeGeneralizedTime( audit.getBeginDate() );
+                filter += "(" + REQEND + ">=" + szTime + ")";
+            }
+
+            filter += ")";
+
+            //log.warn("filter=" + filter);
+            ld = getLogConnection();
+            SearchCursor searchResults = search( ld, auditRoot,
+                SearchScope.ONELEVEL, filter, AUDIT_AUTHZ_ATRS, false, GlobalIds.BATCH_SIZE );
+            long sequence = 0;
+
+            while ( searchResults.next() )
+            {
+                AuthZ authZ = getAuthzEntityFromLdapEntry( searchResults.getEntry(), sequence++ );
+                // todo: fix this workaround. This search will return failed role assign searches as well.  
+                // Work around is to remove the ou=People failed searches from user failed searches on authN.
+                if ( !AttrHelper.getAuthZId( authZ.getReqDN() ).equalsIgnoreCase( "People" ) )
+                {
+                    auditList.add( authZ );
+                }
+            }
+        }
+        catch ( LdapException e )
+        {
+            String error = "LdapException in AuditDAO.searchAuthZs id=" + e.getMessage();
+            throw new FinderException( GlobalErrIds.AUDT_AUTHN_INVALID_FAILED, error, e );
+        }
+        catch ( CursorException e )
+        {
+            String error = "CursorException in AuditDAO.searchAuthZs id=" + e.getMessage();
+            throw new FinderException( GlobalErrIds.AUDT_AUTHN_INVALID_FAILED, error, e );
+        }
+        finally
+        {
+            closeLogConnection( ld );
+        }
+
+        return auditList;
+    }
+
+
+    /**
+     * @param audit
+     * @return
+     * @throws org.apache.directory.fortress.core.FinderException
+     *
+     */
+    List<AuthZ> searchAuthZs( UserAudit audit ) throws FinderException
+    {
+        List<AuthZ> auditList = new ArrayList<>();
+        LdapConnection ld = null;
+        String auditRoot = Config.getProperty( AUDIT_ROOT );
+        String permRoot = getRootDn( audit.isAdmin(), audit.getContextId() );
+        String userRoot = getRootDn( audit.getContextId(), GlobalIds.USER_ROOT );
+
+        try
+        {
+            String reqDn = PermDAO.getOpRdn( audit.getOpName(), audit.getObjId() ) + "," + GlobalIds.POBJ_NAME + "="
+                + audit.getObjName() + "," + permRoot;
+            String filter = GlobalIds.FILTER_PREFIX + ACCESS_AUTHZ_CLASS_NM + ")(" + REQDN + "=" +
+                reqDn + ")(" + REQUAUTHZID + "=" + SchemaConstants.UID_AT + "=" + audit.getUserId() + "," + userRoot
+                + ")";
+
+            if ( audit.isFailedOnly() )
+            {
+                filter += "(" + REQRESULT + "=" + GlobalIds.AUTHZ_COMPARE_FAILURE_FLAG + ")";
+            }
+
+            if ( audit.getBeginDate() != null )
+            {
+                String szTime = AttrHelper.encodeGeneralizedTime( audit.getBeginDate() );
+                filter += "(" + REQEND + ">=" + szTime + ")";
+            }
+
+            filter += ")";
+
+            //System.out.println("filter=" + filter);
+            ld = getLogConnection();
+            SearchCursor searchResults = search( ld, auditRoot,
+                SearchScope.ONELEVEL, filter, AUDIT_AUTHZ_ATRS, false, GlobalIds.BATCH_SIZE );
+            long sequence = 0;
+
+            while ( searchResults.next() )
+            {
+                auditList.add( getAuthzEntityFromLdapEntry( searchResults.getEntry(), sequence++ ) );
+            }
+        }
+        catch ( LdapException e )
+        {
+            String error = "LdapException in AuditDAO.searchAuthZs id=" + e.getMessage();
+            throw new FinderException( GlobalErrIds.AUDT_AUTHZ_SEARCH_FAILED, error, e );
+        }
+        catch ( CursorException e )
+        {
+            String error = "CursorException in AuditDAO.searchAuthZs id=" + e.getMessage();
+            throw new FinderException( GlobalErrIds.AUDT_AUTHZ_SEARCH_FAILED, error, e );
+        }
+        finally
+        {
+            closeLogConnection( ld );
+        }
+
+        return auditList;
+    }
+
+
+    private String getRootDn( boolean isAdmin, String contextId )
+    {
+        String dn;
+
+        if ( isAdmin )
+        {
+            dn = getRootDn( contextId, GlobalIds.ADMIN_PERM_ROOT );
+        }
+        else
+        {
+            dn = getRootDn( contextId, GlobalIds.PERM_ROOT );
+        }
+
+        return dn;
+    }
+
+
+    /**
+     * @param audit
+     * @return
+     * @throws org.apache.directory.fortress.core.FinderException
+     *
+     */
+    List<AuthZ> getAllAuthZs( UserAudit audit ) throws FinderException
+    {
+        List<AuthZ> auditList = new ArrayList<>();
+        LdapConnection ld = null;
+        String auditRoot = Config.getProperty( AUDIT_ROOT );
+        String userRoot = getRootDn( audit.getContextId(), GlobalIds.USER_ROOT );
+
+        try
+        {
+            String filter = GlobalIds.FILTER_PREFIX + ACCESS_AUTHZ_CLASS_NM + ")(";
+
+            if ( audit.getUserId() != null && audit.getUserId().length() > 0 )
+            {
+                filter += REQUAUTHZID + "=" + SchemaConstants.UID_AT + "=" + audit.getUserId() + "," + userRoot + ")";
+            }
+            else
+            {
+                // have to limit the query to only authorization entries.
+                // TODO: determine why the cn=Manager user is showing up in this search:
+                filter += REQUAUTHZID + "=*)(!(" + REQUAUTHZID + "=cn=Manager," + Config.getProperty( GlobalIds.SUFFIX )
+                    + "))";
+
+                // TODO: fix this so filter by only the Fortress AuthZ entries and not the others:
+                if ( audit.isFailedOnly() )
+                {
+                    filter += "(" + REQRESULT + "=" + GlobalIds.AUTHZ_COMPARE_FAILURE_FLAG + ")";
+                }
+            }
+
+            if ( audit.getBeginDate() != null )
+            {
+                String szTime = AttrHelper.encodeGeneralizedTime( audit.getBeginDate() );
+                filter += "(" + REQEND + ">=" + szTime + ")";
+            }
+
+            filter += ")";
+
+            //log.warn("filter=" + filter);
+            ld = getLogConnection();
+            SearchCursor searchResults = search( ld, auditRoot,
+                SearchScope.ONELEVEL, filter, AUDIT_AUTHZ_ATRS, false, GlobalIds.BATCH_SIZE );
+            long sequence = 0;
+
+            while ( searchResults.next() )
+            {
+                auditList.add( getAuthzEntityFromLdapEntry( searchResults.getEntry(), sequence++ ) );
+            }
+        }
+        catch ( LdapException e )
+        {
+            String error = "LdapException in AuditDAO.getAllAuthZs id=" + e.getMessage();
+            throw new FinderException( GlobalErrIds.AUDT_AUTHZ_SEARCH_FAILED, error, e );
+        }
+        catch ( CursorException e )
+        {
+            String error = "CursorException in AuditDAO.getAllAuthZs id=" + e.getMessage();
+            throw new FinderException( GlobalErrIds.AUDT_AUTHZ_SEARCH_FAILED, error, e );
+        }
+        finally
+        {
+            closeLogConnection( ld );
+        }
+
+        return auditList;
+    }
+
+
+    /**
+     * @param audit
+     * @return
+     * @throws org.apache.directory.fortress.core.FinderException
+     *
+     */
+    List<Bind> searchBinds( UserAudit audit ) throws FinderException
+    {
+        List<Bind> auditList = new ArrayList<>();
+        LdapConnection ld = null;
+        String auditRoot = Config.getProperty( AUDIT_ROOT );
+        String userRoot = getRootDn( audit.getContextId(), GlobalIds.USER_ROOT );
+
+        try
+        {
+            String filter;
+
+            if ( audit.getUserId() != null && audit.getUserId().length() > 0 )
+            {
+                filter = GlobalIds.FILTER_PREFIX + ACCESS_BIND_CLASS_NM + ")(" +
+                    REQDN + "=" + SchemaConstants.UID_AT + "=" + audit.getUserId() + "," + userRoot + ")";
+
+                if ( audit.isFailedOnly() )
+                {
+                    filter += "(" + REQRESULT + ">=" + 1 + ")";
+                }
+
+                if ( audit.getBeginDate() != null )
+                {
+                    String szTime = AttrHelper.encodeGeneralizedTime( audit.getBeginDate() );
+                    filter += "(" + REQEND + ">=" + szTime + ")";
+                }
+
+                filter += ")";
+            }
+            else
+            {
+                filter = GlobalIds.FILTER_PREFIX + ACCESS_BIND_CLASS_NM + ")";
+
+                if ( audit.isFailedOnly() )
+                {
+                    filter += "(" + REQRESULT + ">=" + 1 + ")";
+                }
+
+                if ( audit.getBeginDate() != null )
+                {
+                    String szTime = AttrHelper.encodeGeneralizedTime( audit.getBeginDate() );
+                    filter += "(" + REQEND + ">=" + szTime + ")";
+                }
+
+                filter += ")";
+            }
+
+            //log.warn("filter=" + filter);
+            ld = getLogConnection();
+            SearchCursor searchResults = search( ld, auditRoot,
+                SearchScope.ONELEVEL, filter, AUDIT_BIND_ATRS, false, GlobalIds.BATCH_SIZE );
+            long sequence = 0;
+
+            while ( searchResults.next() )
+            {
+                auditList.add( getBindEntityFromLdapEntry( searchResults.getEntry(), sequence++ ) );
+            }
+        }
+        catch ( LdapException e )
+        {
+            String error = "LdapException in AuditDAO.searchBinds id=" + e.getMessage();
+            throw new FinderException( GlobalErrIds.AUDT_BIND_SEARCH_FAILED, error, e );
+        }
+        catch ( CursorException e )
+        {
+            String error = "CursorException in AuditDAO.searchBinds id=" + e.getMessage();
+            throw new FinderException( GlobalErrIds.AUDT_BIND_SEARCH_FAILED, error, e );
+        }
+        finally
+        {
+            closeLogConnection( ld );
+        }
+
+        return auditList;
+    }
+
+
+    /**
+     * @param audit
+     * @return
+     * @throws org.apache.directory.fortress.core.FinderException
+     *
+     */
+    List<Mod> searchUserMods( UserAudit audit ) throws FinderException
+    {
+        List<Mod> modList = new ArrayList<>();
+        LdapConnection ld = null;
+        String auditRoot = Config.getProperty( AUDIT_ROOT );
+
+        String userRoot = getRootDn( audit.getContextId(), GlobalIds.USER_ROOT );
+
+        try
+        {
+            String filter = GlobalIds.FILTER_PREFIX + ACCESS_MOD_CLASS_NM + ")(" +
+                REQDN + "=" + SchemaConstants.UID_AT + "=" + audit.getUserId() + "," + userRoot + ")";
+
+            if ( audit.getBeginDate() != null )
+            {
+                String szTime = AttrHelper.encodeGeneralizedTime( audit.getBeginDate() );
+                filter += "(" + REQEND + ">=" + szTime + ")";
+            }
+
+            filter += ")";
+            //log.warn("filter=" + filter);
+            ld = getLogConnection();
+            SearchCursor searchResults = search( ld, auditRoot,
+                SearchScope.ONELEVEL, filter, AUDIT_MOD_ATRS, false, GlobalIds.BATCH_SIZE );
+            long sequence = 0;
+
+            while ( searchResults.next() )
+            {
+                modList.add( getModEntityFromLdapEntry( searchResults.getEntry(), sequence++ ) );
+            }
+        }
+        catch ( LdapException e )
+        {
+            String error = "searchUserMods caught LdapException id=" + e.getMessage();
+            throw new FinderException( GlobalErrIds.AUDT_MOD_SEARCH_FAILED, error, e );
+        }
+        catch ( CursorException e )
+        {
+            String error = "searchUserMods caught CursorException id=" + e.getMessage();
+            throw new FinderException( GlobalErrIds.AUDT_MOD_SEARCH_FAILED, error, e );
+        }
+        finally
+        {
+            closeLogConnection( ld );
+        }
+
+        return modList;
+    }
+
+
+    /**
+     * @param audit
+     * @return
+     * @throws FinderException
+     */
+    List<Mod> searchAdminMods( UserAudit audit ) throws FinderException
+    {
+        List<Mod> modList = new ArrayList<>();
+        LdapConnection ld = null;
+        String auditRoot = Config.getProperty( AUDIT_ROOT );
+
+        try
+        {
+            String filter = "(&(|(objectclass=" + ACCESS_MOD_CLASS_NM + ")";
+            filter += "(objectclass=" + ACCESS_ADD_CLASS_NM + "))";
+
+            if ( StringUtils.isNotEmpty( audit.getDn() ) )
+            {
+                filter += "(" + REQDN + "=" + audit.getDn() + ")";
+            }
+
+            if ( StringUtils.isNotEmpty( audit.getObjName() ) )
+            {
+                filter += "(|(" + REQMOD + "=" + GlobalIds.FT_MODIFIER_CODE + ":= " + audit.getObjName() + ".";
+
+                if ( StringUtils.isNotEmpty( audit.getOpName() ) )
+                {
+                    filter += audit.getOpName();
+                }
+
+                filter += "*)";
+                filter += "(" + REQMOD + "=" + GlobalIds.FT_MODIFIER_CODE + ":+ " + audit.getObjName() + ".";
+
+                if ( StringUtils.isNotEmpty( audit.getOpName() ) )
+                {
+                    filter += audit.getOpName();
+                }
+
+                filter += "*))";
+            }
+
+            if ( StringUtils.isNotEmpty( audit.getInternalUserId() ) )
+            {
+                filter += "(|(" + REQMOD + "=" + GlobalIds.FT_MODIFIER + ":= " + audit.getInternalUserId() + ")";
+                filter += "(" + REQMOD + "=" + GlobalIds.FT_MODIFIER + ":+ " + audit.getInternalUserId() + "))";
+            }
+
+            if ( audit.getBeginDate() != null )
+            {
+                String szTime = AttrHelper.encodeGeneralizedTime( audit.getBeginDate() );
+                filter += "(" + REQEND + ">=" + szTime + ")";
+            }
+
+            if ( audit.getEndDate() != null )
+            {
+                String szTime = AttrHelper.encodeGeneralizedTime( audit.getEndDate() );
+                filter += "(" + REQEND + "<=" + szTime + ")";
+            }
+
+            filter += ")";
+            //log.warn("filter=" + filter);
+            ld = getLogConnection();
+            SearchCursor searchResults = search( ld, auditRoot,
+                SearchScope.ONELEVEL, filter, AUDIT_MOD_ATRS, false, GlobalIds.BATCH_SIZE );
+            long sequence = 0;
+
+            while ( searchResults.next() )
+            {
+                modList.add( getModEntityFromLdapEntry( searchResults.getEntry(), sequence++ ) );
+            }
+        }
+        catch ( LdapException e )
+        {
+            String error = "searchAdminMods caught LdapException id=" + e.getMessage();
+            throw new FinderException( GlobalErrIds.AUDT_MOD_ADMIN_SEARCH_FAILED, error, e );
+        }
+        catch ( CursorException e )
+        {
+            String error = "searchAdminMods caught CursorException id=" + e.getMessage();
+            throw new FinderException( GlobalErrIds.AUDT_MOD_ADMIN_SEARCH_FAILED, error, e );
+        }
+        finally
+        {
+            closeLogConnection( ld );
+        }
+
+        return modList;
+    }
+
+
+    /**
+     * @param le
+     * @return
+     * @throws LdapInvalidAttributeValueException 
+     * @throws LdapException
+     */
+    private Bind getBindEntityFromLdapEntry( Entry le, long sequence ) throws LdapInvalidAttributeValueException
+    {
+
+        Bind auditBind = new ObjectFactory().createBind();
+        auditBind.setSequenceId( sequence );
+        auditBind.setCreateTimestamp( getAttribute( le, CREATETIMESTAMP ) );
+        auditBind.setCreatorsName( getAttribute( le, CREATORSNAME ) );
+        auditBind.setEntryCSN( getAttribute( le, ENTRYCSN ) );
+        auditBind.setEntryDN( getAttribute( le, ENTRYDN ) );
+        auditBind.setEntryUUID( getAttribute( le, ENTRYUUID ) );
+        auditBind.setHasSubordinates( getAttribute( le, HASSUBORDINATES ) );
+        auditBind.setModifiersName( getAttribute( le, MODIFIERSNAME ) );
+        auditBind.setModifyTimestamp( getAttribute( le, MODIFYTIMESTAMP ) );
+        auditBind.setObjectClass( getAttribute( le, OBJECTCLASS ) );
+        auditBind.setReqAuthzID( getAttribute( le, REQUAUTHZID ) );
+        auditBind.setReqControls( getAttribute( le, REQCONTROLS ) );
+        auditBind.setReqDN( getAttribute( le, REQDN ) );
+        auditBind.setReqEnd( getAttribute( le, REQEND ) );
+        auditBind.setReqMethod( getAttribute( le, REQMETHOD ) );
+        auditBind.setReqResult( getAttribute( le, REQRESULT ) );
+        auditBind.setReqSession( getAttribute( le, REQSESSION ) );
+        auditBind.setReqStart( getAttribute( le, REQSTART ) );
+        auditBind.setReqType( getAttribute( le, REQTYPE ) );
+        auditBind.setReqVersion( getAttribute( le, REQVERSION ) );
+        auditBind.setStructuralObjectClass( getAttribute( le, STRUCTURALOBJECTCLASS ) );
+
+        return auditBind;
+    }
+
+
+    /**
+     * @param le
+     * @return
+     * @throws LdapInvalidAttributeValueException 
+     * @throws LdapException
+     */
+    private AuthZ getAuthzEntityFromLdapEntry( Entry le, long sequence ) throws LdapInvalidAttributeValueException
+    {
+
+        // these attrs also on audit bind OC:
+        AuthZ authZ = new ObjectFactory().createAuthZ();
+        authZ.setSequenceId( sequence );
+        authZ.setCreateTimestamp( getAttribute( le, CREATETIMESTAMP ) );
+        authZ.setCreatorsName( getAttribute( le, CREATORSNAME ) );
+        authZ.setEntryCSN( getAttribute( le, ENTRYCSN ) );
+        authZ.setEntryDN( getAttribute( le, ENTRYDN ) );
+        authZ.setEntryUUID( getAttribute( le, ENTRYUUID ) );
+        authZ.setHasSubordinates( getAttribute( le, HASSUBORDINATES ) );
+        authZ.setModifiersName( getAttribute( le, MODIFIERSNAME ) );
+        authZ.setModifyTimestamp( getAttribute( le, MODIFYTIMESTAMP ) );
+        authZ.setObjectClass( getAttribute( le, OBJECTCLASS ) );
+        authZ.setReqAuthzID( getAttribute( le, REQUAUTHZID ) );
+        authZ.setReqControls( getAttribute( le, REQCONTROLS ) );
+        authZ.setReqDN( getAttribute( le, REQDN ) );
+        authZ.setReqEnd( getAttribute( le, REQEND ) );
+        authZ.setReqResult( getAttribute( le, REQRESULT ) );
+        authZ.setReqSession( getAttribute( le, REQSESSION ) );
+        authZ.setReqStart( getAttribute( le, REQSTART ) );
+        authZ.setReqType( getAttribute( le, REQTYPE ) );
+        authZ.setStructuralObjectClass( getAttribute( le, STRUCTURALOBJECTCLASS ) );
+
+        // these attrs only on audit search OC:
+        authZ.setReqAttr( getAttribute( le, REQATTR ) );
+        authZ.setReqAttrsOnly( getAttribute( le, REQATTRSONLY ) );
+        authZ.setReqDerefAliases( getAttribute( le, REQDREFALIASES ) );
+        authZ.setReqEntries( getAttribute( le, REQENTRIES ) );
+        authZ.setReqFilter( getAttribute( le, REQFILTER ) );
+        authZ.setReqScope( getAttribute( le, REQSCOPE ) );
+        authZ.setReqSizeLimit( getAttribute( le, REQSIZELIMIT ) );
+        authZ.setReqTimeLimit( getAttribute( le, REQTIMELIMIT ) );
+
+        return authZ;
+    }
+
+
+    private Mod getModEntityFromLdapEntry( Entry le, long sequence ) throws LdapInvalidAttributeValueException
+    {
+        Mod mod = new ObjectFactory().createMod();
+        mod.setSequenceId( sequence );
+        mod.setObjectClass( getAttribute( le, OBJECTCLASS ) );
+        mod.setReqAuthzID( getAttribute( le, REQUAUTHZID ) );
+        mod.setReqDN( getAttribute( le, REQDN ) );
+        mod.setReqEnd( getAttribute( le, REQEND ) );
+        mod.setReqResult( getAttribute( le, REQRESULT ) );
+        mod.setReqSession( getAttribute( le, REQSESSION ) );
+        mod.setReqStart( getAttribute( le, REQSTART ) );
+        mod.setReqType( getAttribute( le, REQTYPE ) );
+        mod.setReqMod( getAttributes( le, REQMOD ) );
+
+        return mod;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/ba64d26a/src/main/java/org/apache/directory/fortress/core/impl/AuditMgrImpl.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/impl/AuditMgrImpl.java b/src/main/java/org/apache/directory/fortress/core/impl/AuditMgrImpl.java
new file mode 100755
index 0000000..27ae1cc
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/core/impl/AuditMgrImpl.java
@@ -0,0 +1,261 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.fortress.core.impl;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.directory.fortress.core.AuditMgr;
+import org.apache.directory.fortress.core.GlobalErrIds;
+import org.apache.directory.fortress.core.ReviewMgrFactory;
+import org.apache.directory.fortress.core.SecurityException;
+import org.apache.directory.fortress.core.ReviewMgr;
+import org.apache.directory.fortress.core.model.AuthZ;
+import org.apache.directory.fortress.core.model.Bind;
+import org.apache.directory.fortress.core.model.Mod;
+import org.apache.directory.fortress.core.model.User;
+import org.apache.directory.fortress.core.model.UserAudit;
+
+import java.util.List;
+
+/**
+ * This object performs searches across <a href="http://www.openldap.org/">OpenLDAP</a>'s slapd access log.  The access log events are
+ * persisted in <a href="http://www.oracle.com/technetwork/database/berkeleydb/overview/index.html">BDB</a> and available for inquiry via common LDAP protocols.
+ * Audit entries stored on behalf of Fortress operations correspond to runtime authentication {@link org.apache.directory.fortress.core.model.Bind}, authorization {@link org.apache.directory.fortress.core.model.AuthZ} and modification {@link org.apache.directory.fortress.core.model.Mod}
+ * events as they occur automatically on the server when audit is enabled.
+ * <h4>Audit Interrogator</h4>
+ * Provides an OpenLDAP access log retrieval mechanism that enables security event monitoring.
+ * <ol>
+ * <li>Authentication events:
+ * <li>Session enablement events
+ * <li>Authorization events
+ * <li>Entity mods and deletes
+ * </li>
+ * </ol>
+ * <img src="../doc-files/Audit.png">
+ * <p/>
+ * All events include Fortress context, see {@link org.apache.directory.fortress.core.model.FortEntity}.
+ * <p/>
+ * <h4>
+ * The following APIs generate events subsequently stored in this access log:
+ * </h4>
+ * <ul>
+ * <li> {@link org.apache.directory.fortress.core.AccessMgr}
+ * <li> {@link org.apache.directory.fortress.core.AdminMgr}
+ * <li> {@link org.apache.directory.fortress.core.AdminMgr}
+ * <li> {@link org.apache.directory.fortress.core.DelAdminMgr}
+ * <li> {@link org.apache.directory.fortress.core.ConfigMgr}
+ * <li> {@link org.apache.directory.fortress.core.PwPolicyMgr}
+ * </ul>
+ * <h4>
+ * The following reports are supported using search input: {@link org.apache.directory.fortress.core.model.UserAudit}
+ * </h4>
+ * <ul>
+ * <li>User Authentications:     <code>List<{@link org.apache.directory.fortress.core.model.Bind}>  {@link org.apache.directory.fortress.core.AuditMgr#searchBinds(org.apache.directory.fortress.core.model.UserAudit)}</code>
+ * <li>Invalid Users AuthN:      <code>List<{@link org.apache.directory.fortress.core.model.Bind}>  {@link org.apache.directory.fortress.core.AuditMgr#searchInvalidUsers(org.apache.directory.fortress.core.model.UserAudit)} </code>
+ * <li>User Authorizations 1:    <code>List<{@link org.apache.directory.fortress.core.model.AuthZ}> {@link org.apache.directory.fortress.core.AuditMgr#getUserAuthZs(org.apache.directory.fortress.core.model.UserAudit)} </code>
+ * <li>User Authorizations 2:    <code>List<{@link org.apache.directory.fortress.core.model.AuthZ}> {@link org.apache.directory.fortress.core.AuditMgr#searchAuthZs(org.apache.directory.fortress.core.model.UserAudit)} </code>
+ * <li>User Session Activations: <code>List<{@link org.apache.directory.fortress.core.model.Mod}>   {@link org.apache.directory.fortress.core.AuditMgr#searchUserSessions(org.apache.directory.fortress.core.model.UserAudit)} </code>
+ * <li>Entity Modifications:     <code>List<{@link org.apache.directory.fortress.core.model.Mod}>   {@link org.apache.directory.fortress.core.AuditMgr#searchAdminMods(org.apache.directory.fortress.core.model.UserAudit)} </code>
+ *
+ * </ul>
+ * <p/>
+ * This class is NOT thread safe if parent instance variables ({@link #contextId} or {@link #adminSess}) are set.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class AuditMgrImpl extends Manageable implements AuditMgr
+{
+    private static final String CLS_NM = AuditMgrImpl.class.getName();
+    private static final AuditP auditP = new AuditP();
+
+    /**
+     * This method returns a list of authorization events for a particular user {@link org.apache.directory.fortress.core.model.UserAudit#userId}
+     * and given timestamp field {@link org.apache.directory.fortress.core.model.UserAudit#beginDate}.<BR>
+     * Method also can discriminate between all events or failed only by setting {@link org.apache.directory.fortress.core.model.UserAudit#failedOnly}.
+     * <h4>optional parameters</h4>
+     * <ul>
+     * <li>{@link org.apache.directory.fortress.core.model.UserAudit#userId} - contains the target userId</li>
+     * <li>{@link org.apache.directory.fortress.core.model.UserAudit#beginDate} - contains the date in which to begin search</li>
+     * <li>{@link org.apache.directory.fortress.core.model.UserAudit#failedOnly} - if set to 'true', return only failed authorization events</li>
+     * </ul>
+     *
+     * @param uAudit This entity is instantiated and populated before invocation.
+     * @return a List of objects of type AuthZ.  Each AuthZ object contains one authorization event.
+     * @throws org.apache.directory.fortress.core.SecurityException
+     *          if a runtime system error occurs.
+     */
+    @Override
+    public List<AuthZ> getUserAuthZs(UserAudit uAudit)
+        throws SecurityException
+    {
+        String methodName = "getUserAuthZs";
+        assertContext(CLS_NM, methodName, uAudit, GlobalErrIds.AUDT_INPUT_NULL);
+        checkAccess(CLS_NM, methodName);
+        return auditP.getAuthZs(uAudit);
+    }
+
+
+    /**
+     * This method returns a list of authorization events for a particular user {@link UserAudit#userId},
+     * object {@link UserAudit#objName}, and given timestamp field {@link UserAudit#beginDate}.<BR>
+     * Method also can discriminate between all events or failed only by setting flag {@link UserAudit#failedOnly}..
+     * <h4>required parameters</h4>
+     * <ul>
+     * <li>{@link UserAudit#userId} - contains the target userId<</li>
+     * <li>{@link UserAudit#objName} - contains the object (authorization resource) name</li>
+     * </ul>
+     * <h4>optional parameters</h4>
+     * <ul>
+     * <li>{@link UserAudit#beginDate} - contains the date in which to begin search</li>
+     * <li>{@link UserAudit#failedOnly} - if set to 'true', return only failed authorization events</li>
+     * </ul>
+     *
+     * @param uAudit This entity is instantiated and populated before invocation.
+     * @return a List of objects of type AuthZ.  Each AuthZ object contains one authorization event.
+     * @throws SecurityException if a runtime system error occurs.
+     */
+    @Override
+    public List<AuthZ> searchAuthZs(UserAudit uAudit)
+        throws SecurityException
+    {
+        String methodName = "searchAuthZs";
+        assertContext(CLS_NM, methodName, uAudit, GlobalErrIds.AUDT_INPUT_NULL);
+        checkAccess(CLS_NM, methodName);
+        return auditP.searchAuthZs(uAudit);
+    }
+
+
+    /**
+     * This method returns a list of authentication audit events for a particular user {@link UserAudit#userId},
+     * and given timestamp field {@link UserAudit#beginDate}.<BR>
+     * <h4>optional parameters</h4>
+     * <ul>
+     * <li>{@link UserAudit#userId} - contains the target userId<</li>
+     * <li>{@link UserAudit#beginDate} - contains the date in which to begin search</li>
+     * <li>{@link UserAudit#failedOnly} - if set to 'true', return only failed authorization events</li>
+     * </ul>
+     *
+     * @param uAudit This entity is instantiated and populated before invocation.
+     * @return a List of objects of type Bind.  Each Bind object contains one bind event.
+     * @throws org.apache.directory.fortress.core.SecurityException
+     *          if a runtime system error occurs.
+     */
+    @Override
+    public List<Bind> searchBinds(UserAudit uAudit)
+        throws SecurityException
+    {
+        String methodName = "searchBinds";
+        assertContext(CLS_NM, methodName, uAudit, GlobalErrIds.AUDT_INPUT_NULL);
+        checkAccess(CLS_NM, methodName);
+        return auditP.searchBinds(uAudit);
+    }
+
+    /**
+     * This method returns a list of sessions created for a given user {@link UserAudit#userId},
+     * and timestamp {@link UserAudit#beginDate}.<BR>
+     * <h4>required parameters</h4>
+     * <ul>
+     * <li>{@link UserAudit#userId} - contains the target userId<</li>
+     * </ul>
+     * <h4>optional parameters</h4>
+     * <ul>
+     * <li>{@link UserAudit#beginDate} - contains the date in which to begin search</li>
+     * </ul>
+     *
+     * @param uAudit This entity is instantiated and populated before invocation.
+     * @return a List of objects of type Mod.  Each Mod object in list corresponds to one update or delete event on directory.
+     * @throws org.apache.directory.fortress.core.SecurityException
+     *          if a runtime system error occurs.
+     */
+    @Override
+    public List<Mod> searchUserSessions(UserAudit uAudit)
+        throws SecurityException
+    {
+        String methodName = "searchUserSessions";
+        assertContext(CLS_NM, methodName, uAudit, GlobalErrIds.AUDT_INPUT_NULL);
+        checkAccess(CLS_NM, methodName);
+        return auditP.searchUserMods(uAudit);
+    }
+
+    /**
+     * This method returns a list of admin operations events for a particular entity {@link UserAudit#dn},
+     * object {@link UserAudit#objName} and timestamp {@link UserAudit#beginDate}.  If the internal
+     * userId {@link UserAudit#internalUserId} is set it will limit search by that field.
+     * <h4>optional parameters</h4>
+     * <ul>
+     * <li>{@link UserAudit#dn} - contains the LDAP distinguished name for the updated object.  For example if caller
+     * wants to find out what changes were made to John Doe's user object this would be 'uid=jdoe,ou=People,dc=example,dc=com'</li>
+     * <li>{@link UserAudit#objName} - contains the object (authorization resource) name corresponding to the event.  For example if caller
+     * wants to return events where User object was modified, this would be 'updateUser'</li>
+     * <li>{@link UserAudit#internalUserId} - maps to the internalUserId of user who changed the record in LDAP.  This maps to {@link org.apache.directory.fortress.core.model.User#internalId}.</li>
+     * <li>{@link UserAudit#beginDate} - contains the date in which to begin search</li>
+     * <li>{@link UserAudit#endDate} - contains the date in which to end search</li>
+     * </ul>
+     *
+     * @param uAudit This entity is instantiated and populated before invocation.
+     * @return a List of objects of type Mod.  Each Mod object in list corresponds to one update or delete event on directory.
+     * @throws org.apache.directory.fortress.core.SecurityException
+     *          if a runtime system error occurs.
+     */
+    @Override
+    public List<Mod> searchAdminMods(UserAudit uAudit)
+        throws SecurityException
+    {
+        String methodName = "searchAdminMods";
+        assertContext(CLS_NM, methodName, uAudit, GlobalErrIds.AUDT_INPUT_NULL);
+        checkAccess(CLS_NM, methodName);
+        if ( StringUtils.isNotEmpty( uAudit.getUserId() ))
+        {
+            ReviewMgr rMgr = ReviewMgrFactory.createInstance(this.contextId);
+            User user = rMgr.readUser(new User(uAudit.getUserId()));
+            uAudit.setInternalUserId(user.getInternalId());
+        }
+        return auditP.searchAdminMods(uAudit);
+    }
+
+
+    /**
+     * This method returns a list of failed authentication events for a particular invalid user {@link UserAudit#userId},
+     * and given timestamp {@link UserAudit#beginDate}.  If the {@link UserAudit#failedOnly} is true it will
+     * return only authentication attempts made with invalid userId.
+     * </p>
+     * This is possible because Fortress performs read on user before the bind.
+     * </p>
+     * <h4>optional parameters</h4>
+     * <ul>
+     * <li>{@link UserAudit#userId} - contains the target userId</li>
+     * <li>{@link UserAudit#beginDate} - contains the date in which to begin search</li>
+     * <li>{@link UserAudit#failedOnly} - if set to 'true', return only failed authorization events</li>
+     * </ul>
+     *
+     * @param uAudit This entity is instantiated and populated before invocation.
+     * @return a List of objects of type AuthZ.  Each AuthZ object contains one failed authentication event.
+     * @throws org.apache.directory.fortress.core.SecurityException
+     *          if a runtime system error occurs.
+     */
+    @Override
+    public List<AuthZ> searchInvalidUsers(UserAudit uAudit)
+        throws SecurityException
+    {
+        String methodName = "searchInvalidUsers";
+        assertContext(CLS_NM, methodName, uAudit, GlobalErrIds.AUDT_INPUT_NULL);
+        checkAccess(CLS_NM, methodName);
+        return auditP.searchInvalidAuthNs(uAudit);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/ba64d26a/src/main/java/org/apache/directory/fortress/core/impl/AuditP.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/impl/AuditP.java b/src/main/java/org/apache/directory/fortress/core/impl/AuditP.java
new file mode 100755
index 0000000..631badc
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/core/impl/AuditP.java
@@ -0,0 +1,153 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.fortress.core.impl;
+
+
+import java.util.List;
+
+import org.apache.directory.fortress.core.SecurityException;
+import org.apache.directory.fortress.core.model.AuthZ;
+import org.apache.directory.fortress.core.model.Bind;
+import org.apache.directory.fortress.core.model.Mod;
+import org.apache.directory.fortress.core.model.UserAudit;
+
+
+/**
+ * This class is process layer for Fortress audit data.  It performs data validation
+ * and data mapping functions.
+ * Process module for the for Fortress audit data.  It performs data validation and data mapping functions.
+ * The audit data is passed using {@link org.apache.directory.fortress.core.model.AuthZ} class.  This class does perform simple data validations to ensure data reasonability and
+ * the required fields are present..<BR>
+ * The methods in this class are called by {@link AuditMgrImpl} methods during audit log interrogations.
+ * <p/>
+ * Class will throw {@link SecurityException} to caller in the event of security policy, data constraint violation or system
+ * error internal to DAO object. This class will forward DAO exception {@link org.apache.directory.fortress.core.FinderException},
+ * or {@link org.apache.directory.fortress.core.ValidationException} as {@link SecurityException}s with appropriate
+ * error id from {@link org.apache.directory.fortress.core.GlobalErrIds}.
+ * <p/>
+ * This class performs simple data validations.
+ * <p/>
+ * This class is thread safe.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public final class AuditP
+{
+    private static final AuditDAO aDao = new AuditDAO();
+
+
+    /**
+     * Package private constructor
+     */
+    AuditP()
+    {
+    }
+
+
+    /**
+     * This method returns a list of authorization events for a particular user {@link org.apache.directory.fortress.core.model.UserAudit#userId}
+     * and given timestamp field {@link org.apache.directory.fortress.core.model.UserAudit#beginDate}.<BR>
+     * Method also can discriminate between all events or failed only by setting {@link org.apache.directory.fortress.core.model.UserAudit#failedOnly}.
+     *
+     * @param uAudit This entity is instantiated and populated before invocation.
+     * @return a List of objects of type AuthZ.  Each AuthZ object contains one authorization event.
+     * @throws SecurityException if a runtime system error occurs.
+     */
+    List<AuthZ> getAuthZs( UserAudit uAudit ) throws SecurityException
+    {
+        return aDao.getAllAuthZs( uAudit );
+    }
+
+
+    /**
+     * This method returns a list of authorization events for a particular user {@link UserAudit#userId},
+     * object {@link UserAudit#objName}, and given timestamp field {@link UserAudit#beginDate}.<BR>
+     * Method also can discriminate between all events or failed only by setting flag {@link UserAudit#failedOnly}..
+     *
+     * @param uAudit This entity is instantiated and populated before invocation.
+     * @return a List of objects of type AuthZ.  Each AuthZ object contains one authorization event.
+     * @throws SecurityException if a runtime system error occurs.
+     */
+    List<AuthZ> searchAuthZs( UserAudit uAudit ) throws SecurityException
+    {
+        return aDao.searchAuthZs( uAudit );
+    }
+
+
+    /**
+     * This method returns a list of authentication audit events for a particular user {@link UserAudit#userId},
+     * and given timestamp field {@link UserAudit#beginDate}.<BR>
+     *
+     * @param uAudit This entity is instantiated and populated before invocation.
+     * @return a List of objects of type Bind.  Each Bind object contains one bind event.
+     * @throws SecurityException if a runtime system error occurs.
+     */
+    List<Bind> searchBinds( UserAudit uAudit ) throws SecurityException
+    {
+        return aDao.searchBinds( uAudit );
+    }
+
+
+    /**
+     * This method returns a list of sessions created for a given user {@link UserAudit#userId},
+     * and timestamp {@link UserAudit#beginDate}.<BR>
+     *
+     * @param uAudit This entity is instantiated and populated before invocation.
+     * @return a List of objects of type AuthZ.  Each AuthZ object contains one authorization event.
+     * @throws SecurityException if a runtime system error occurs.
+     */
+    List<Mod> searchUserMods( UserAudit uAudit ) throws SecurityException
+    {
+        return aDao.searchUserMods( uAudit );
+    }
+
+
+    /**
+     * This method returns a list of admin operations events for a particular entity {@link UserAudit#dn},
+     * object {@link UserAudit#objName} and timestamp {@link UserAudit#beginDate}.  If the internal
+     * userId {@link UserAudit#internalUserId} is set it will limit search by that field.
+     *
+     * @param uAudit This entity is instantiated and populated before invocation.
+     * @return a List of objects of type AuthZ.  Each AuthZ object contains one authorization event.
+     * @throws SecurityException if a runtime system error occurs.
+     */
+    List<Mod> searchAdminMods( UserAudit uAudit ) throws SecurityException
+    {
+        return aDao.searchAdminMods( uAudit );
+    }
+
+
+    /**
+     * This method returns a list of failed authentication events for a particular invalid user {@link UserAudit#userId},
+     * and given timestamp {@link UserAudit#beginDate}.  If the {@link UserAudit#failedOnly} is true it will
+     * return only authentication attempts made with invalid userId.
+     * </p>
+     * This is possible because Fortress performs read on user before the bind.
+     * </p>
+     *
+     * @param uAudit This entity is instantiated and populated before invocation.
+     * @return a List of objects of type AuthZ.  Each AuthZ object contains one failed authentication event.
+     * @throws SecurityException if a runtime system error occurs.
+     */
+    List<AuthZ> searchInvalidAuthNs( UserAudit uAudit ) throws SecurityException
+    {
+        return aDao.searchInvalidAuthNs( uAudit );
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/ba64d26a/src/main/java/org/apache/directory/fortress/core/impl/ConfigDAO.java
----------------------------------------------------------------------
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
new file mode 100755
index 0000000..45807e8
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/core/impl/ConfigDAO.java
@@ -0,0 +1,302 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.fortress.core.impl;
+
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+
+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.Entry;
+import org.apache.directory.api.ldap.model.entry.Modification;
+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;
+import org.apache.directory.fortress.core.CreateException;
+import org.apache.directory.fortress.core.util.Config;
+import org.apache.directory.fortress.core.util.ObjUtil;
+import org.apache.directory.ldap.client.api.LdapConnection;
+import org.apache.directory.fortress.core.ldap.ApacheDsDataProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.directory.fortress.core.FinderException;
+import org.apache.directory.fortress.core.GlobalErrIds;
+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.util.attr.AttrHelper;
+
+
+/**
+ * This class provides data access for the standard ldap object device that has been extended to support name/value pairs.
+ * Fortress uses this data structure to store its remote cfg parameters.
+ * <p/>
+ * The Fortress Config node is a combination of:
+ * <p/>
+ * 'device' Structural Object Class is used to store basic attributes like cn which will be used for config node name.
+ * <ul>
+ * <li>  ------------------------------------------
+ * <li> <code>objectclass ( 2.5.6.14 NAME 'device'</code>
+ * <li> <code>DESC 'RFC2256: a device''</code>
+ * <li> <code>SUP top STRUCTURAL</code>
+ * <li> <code>MUST cn</code>
+ * <li> <code>MAY ( serialNumber $ seeAlso $ owner $ ou $ o $ l $ description ) )</code>
+ * <li>  ------------------------------------------
+ * </ul>
+ * <p/>
+ * 'ftProperties' AUXILIARY Object Class is used to store name/value pairs on target node.<br />
+ * <code>This aux object class can be used to store custom attributes.</code><br />
+ * <code>The properties collections consist of name/value pairs and are not constrainted by Fortress.</code><br />
+ * <ul>
+ * <li>  ------------------------------------------
+ * <li> <code>objectclass ( 1.3.6.1.4.1.38088.3.2</code>
+ * <li> <code>NAME 'ftProperties'</code>
+ * <li> <code>DESC 'Fortress Properties AUX Object Class'</code>
+ * <li> <code>AUXILIARY</code>
+ * <li> <code>MAY ( ftProps ) ) </code>
+ * <li>  ------------------------------------------
+ * </ul>
+ * <p/>
+ * <p/>
+ * This class is thread safe.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+final class ConfigDAO extends ApacheDsDataProvider
+
+{
+    private static final String CLS_NM = ConfigDAO.class.getName();
+    private static final Logger LOG = LoggerFactory.getLogger( CLS_NM );
+    private static final String CONFIG_ROOT_PARAM = "config.root";
+    private static final String CONFIG_ROOT_DN = Config.getProperty( CONFIG_ROOT_PARAM );
+
+    private static final String CONFIG_OBJ_CLASS[] =
+        {
+            SchemaConstants.DEVICE_OC, GlobalIds.PROPS_AUX_OBJECT_CLASS_NAME
+    };
+
+    private static final String[] CONFIG_ATRS =
+        {
+            SchemaConstants.CN_AT, GlobalIds.PROPS
+    };
+
+
+    /**
+     * Package private default constructor.
+     */
+    ConfigDAO()
+    {
+    }
+
+
+    /**
+     * @param name
+     * @param props
+     * @return
+     * @throws org.apache.directory.fortress.core.CreateException
+     */
+    Properties create( String name, Properties props )
+        throws CreateException
+    {
+        LdapConnection ld = null;
+        String dn = getDn( name );
+        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 );
+        }
+        catch ( LdapEntryAlreadyExistsException e )
+        {
+            String warning = "create config dn [" + dn + "] caught LdapEntryAlreadyExistsException="
+                + e.getMessage() + " msg=" + e.getMessage();
+            throw new CreateException( GlobalErrIds.FT_CONFIG_ALREADY_EXISTS, warning, e );
+        }
+        catch ( LdapException e )
+        {
+            String error;
+            error = "create config dn [" + dn + "] caught LDAPException=" + e.getMessage();
+            LOG.error( error, e );
+            throw new CreateException( GlobalErrIds.FT_CONFIG_CREATE_FAILED, error, e );
+        }
+        finally
+        {
+            closeAdminConnection( ld );
+        }
+        return props;
+    }
+
+
+    /**
+     * @param name
+     * @param props
+     * @return
+     * @throws org.apache.directory.fortress.core.UpdateException
+     */
+    Properties update( String name, Properties props )
+        throws UpdateException
+    {
+        LdapConnection ld = null;
+        String dn = getDn( name );
+        LOG.info( "update dn [{}]", dn );
+        try
+        {
+            List<Modification> mods = new ArrayList<Modification>();
+            if ( ObjUtil.isNotNullOrEmpty( props ) )
+            {
+                loadProperties( props, mods, GlobalIds.PROPS, true );
+            }
+            ld = getAdminConnection();
+            if ( mods.size() > 0 )
+            {
+                ld = getAdminConnection();
+                modify( ld, dn, mods );
+            }
+        }
+        catch ( LdapException e )
+        {
+            String error = "update dn [" + dn + "] caught LDAPException=" + e.getMessage();
+            throw new UpdateException( GlobalErrIds.FT_CONFIG_UPDATE_FAILED, error, e );
+        }
+        finally
+        {
+            closeAdminConnection( ld );
+        }
+        return props;
+    }
+
+
+    /**
+     * @param name
+     * @throws org.apache.directory.fortress.core.RemoveException
+     */
+    void remove( String name )
+        throws RemoveException
+    {
+        LdapConnection ld = null;
+        String dn = getDn( name );
+        LOG.info( "remove dn [{}]", dn );
+        try
+        {
+            ld = getAdminConnection();
+            delete( ld, dn );
+        }
+        catch ( LdapException e )
+        {
+            String error = "remove dn [" + dn + "] LDAPException=" + e.getMessage();
+            throw new RemoveException( GlobalErrIds.FT_CONFIG_DELETE_FAILED, error, e );
+        }
+        finally
+        {
+            closeAdminConnection( ld );
+        }
+    }
+
+
+    /**
+     * @param name
+     * @param props
+     * @return
+     * @throws org.apache.directory.fortress.core.UpdateException
+     */
+    Properties remove( String name, Properties props )
+        throws UpdateException
+    {
+        LdapConnection ld = null;
+        String dn = getDn( name );
+        LOG.info( "remove props dn [{}]", dn );
+        try
+        {
+            List<Modification> mods = new ArrayList<Modification>();
+            if ( ObjUtil.isNotNullOrEmpty( props ) )
+            {
+                removeProperties( props, mods, GlobalIds.PROPS );
+            }
+            if ( mods.size() > 0 )
+            {
+                ld = getAdminConnection();
+                modify( ld, dn, mods );
+            }
+        }
+        catch ( LdapException e )
+        {
+            String error = "remove props dn [" + dn + "] caught LDAPException=" + e.getMessage();
+            throw new UpdateException( GlobalErrIds.FT_CONFIG_DELETE_PROPS_FAILED, error, e );
+        }
+        finally
+        {
+            closeAdminConnection( ld );
+        }
+        return props;
+    }
+
+
+    /**
+     * @param name
+     * @return
+     * @throws org.apache.directory.fortress.core.FinderException
+     */
+    Properties getConfig( String name )
+        throws FinderException
+    {
+        Properties props = null;
+        LdapConnection ld = null;
+        String dn = getDn( name );
+        LOG.info( "getConfig dn [{}]", dn );
+        try
+        {
+            ld = getAdminConnection();
+            Entry findEntry = read( ld, dn, CONFIG_ATRS );
+            props = AttrHelper.getProperties( getAttributes( findEntry, GlobalIds.PROPS ) );
+        }
+        catch ( LdapNoSuchObjectException e )
+        {
+            String warning = "getConfig COULD NOT FIND ENTRY for dn [" + dn + "]";
+            throw new FinderException( GlobalErrIds.USER_NOT_FOUND, warning, e );
+        }
+        catch ( LdapException e )
+        {
+            String error = "getConfig dn [" + dn + "] caught LdapException=" + e.getMessage();
+            throw new FinderException( GlobalErrIds.FT_CONFIG_READ_FAILED, error, e );
+        }
+        finally
+        {
+            closeAdminConnection( ld );
+        }
+        return props;
+    }
+
+
+    /**
+     *
+     * @param name
+     * @return
+     */
+    private String getDn( String name )
+    {
+        return SchemaConstants.CN_AT + "=" + name + "," + CONFIG_ROOT_DN;
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/ba64d26a/src/main/java/org/apache/directory/fortress/core/impl/ConfigMgrImpl.java
----------------------------------------------------------------------
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
new file mode 100755
index 0000000..4ce5710
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/core/impl/ConfigMgrImpl.java
@@ -0,0 +1,115 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.fortress.core.impl;
+
+import org.apache.directory.fortress.core.ConfigMgr;
+import org.apache.directory.fortress.core.SecurityException;
+
+import java.util.Properties;
+
+
+/**
+ * This Manager impl supplies CRUD methods used to manage properties stored within the ldap directory.
+ * The Fortress config nodes are used to remotely share Fortress client specific properties between processes.
+ * Fortress places no limits on the number of unique configurations that can be present at one time in the directory.
+ * The Fortress client will specify the preferred cfg node by name via a property named, {@link org.apache.directory.fortress.core.GlobalIds#CONFIG_REALM}.
+ * Each process using Fortress client is free to share an existing node with other processes or create its own unique config
+ * instance using the methods within this class.<BR>
+ * <p/>
+ * This class is thread safe.
+ * <p/>
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class ConfigMgrImpl implements ConfigMgr
+{
+    private static final ConfigP cfgP = new ConfigP();
+
+    /**
+     * Create a new cfg node with given name and properties.  The name is required.  If node already exists,
+     * a {@link org.apache.directory.fortress.core.SecurityException} with error {@link org.apache.directory.fortress.core.GlobalErrIds#FT_CONFIG_ALREADY_EXISTS} will be thrown.
+     *
+     * @param name    attribute is required and maps to 'cn' attribute in 'device' object class.
+     * @param inProps contains {@link Properties} with list of name/value pairs to add to existing config node.
+     * @return {@link Properties} containing the collection of name/value pairs just added.
+     * @throws org.apache.directory.fortress.core.SecurityException in the event entry already present or other system error.
+     */
+    @Override
+    public Properties add(String name, Properties inProps) throws SecurityException
+    {
+        return cfgP.add(name, inProps);
+    }
+
+
+    /**
+     * Update existing cfg node with additional properties, or, replace existing properties.  The name is required.  If node does not exist,
+     * a {@link org.apache.directory.fortress.core.SecurityException} with error {@link org.apache.directory.fortress.core.GlobalErrIds#FT_CONFIG_NOT_FOUND} will be thrown.
+     *
+     * @param name    attribute is required and maps to 'cn' attribute in 'device' object class.
+     * @param inProps contains {@link Properties} with list of name/value pairs to add or update from existing config node.
+     * @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.
+     */
+    @Override
+    public Properties update(String name, Properties inProps) throws SecurityException
+    {
+        return cfgP.update(name, inProps);
+    }
+
+    /**
+     * Removes named cfg node from the directory.  The name is required.  If node does not exist,
+     * a {@link org.apache.directory.fortress.core.SecurityException} with error {@link org.apache.directory.fortress.core.GlobalErrIds#FT_CONFIG_NOT_FOUND} will be thrown.
+     *
+     * @param name is required and maps to 'cn' attribute on 'device' object class of node targeted for operation.
+     * @throws org.apache.directory.fortress.core.SecurityException in the event of system error.
+     */
+    @Override
+    public void delete(String name) throws SecurityException
+    {
+        cfgP.delete(name);
+    }
+
+    /**
+     * Delete properties from existing cfg node.  The name is required.  If node does not exist,
+     * a {@link org.apache.directory.fortress.core.SecurityException} with error {@link org.apache.directory.fortress.core.GlobalErrIds#FT_CONFIG_NOT_FOUND} will be thrown.
+     *
+     * @param name attribute is required and maps to 'cn' attribute in 'device' object class.
+     * @throws org.apache.directory.fortress.core.SecurityException in the event entry not present or other system error.
+     */
+    @Override
+    public void delete(String name, Properties inProps) throws SecurityException
+    {
+        cfgP.delete(name, inProps);
+    }
+
+    /**
+     * Read an existing cfg node with given name and return to caller.  The name is required.  If node doesn't exist,
+     * a {@link org.apache.directory.fortress.core.SecurityException} with error {@link org.apache.directory.fortress.core.GlobalErrIds#FT_CONFIG_NOT_FOUND} will be thrown.
+     *
+     * @param name attribute is required and maps to 'cn' attribute in 'device' object class.
+     * @return {@link Properties} containing the collection of name/value pairs just added. Maps to 'ftProps' attribute in 'ftProperties' object class.
+     * @throws SecurityException in the event entry doesn't exist or other system error.
+     */
+    @Override
+    public Properties read(String name) throws SecurityException
+    {
+        return cfgP.read(name);
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/ba64d26a/src/main/java/org/apache/directory/fortress/core/impl/ConfigP.java
----------------------------------------------------------------------
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
new file mode 100755
index 0000000..bfdb861
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/core/impl/ConfigP.java
@@ -0,0 +1,202 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.fortress.core.impl;
+
+
+import java.util.Properties;
+
+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.SecurityException;
+import org.apache.directory.fortress.core.ValidationException;
+import org.apache.directory.fortress.core.model.VUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * Process module for the configurations node used for remotely storing Fortress specific properties.
+ * Fortress places no limits on the number of unique configurations that can be present.  The Fortress client will specify
+ * the preferred cfg node by name via a property named, {@link org.apache.directory.fortress.core.GlobalIds#CONFIG_REALM}.  Each
+ * process using Fortress client is free to share existing node with other processes or create its own unique config
+ * instance using the methods within this class.<BR>
+ * This class does perform simple data validations to ensure data reasonability and the required fields are present.<BR>
+ * The {@link org.apache.directory.fortress.core.ant.FortressAntTask#addConfig()} method calls the {@link #add} from this class during initial base loads.
+ * Removal {@link org.apache.directory.fortress.core.ant.FortressAntTask#deleteConfig()} is performed when removal of properties is the aim.<BR>
+ * This class will accept {@link Properties}, and forward on to it's corresponding DAO class {@link ConfigDAO} for updating properties stored on behalf of Fortress.
+ * <p>
+ * Class will throw {@link SecurityException} to caller in the event of security policy, data constraint violation or system
+ * error internal to DAO object. This class will forward DAO exceptions ({@link org.apache.directory.fortress.core.FinderException},
+ * {@link org.apache.directory.fortress.core.CreateException},{@link org.apache.directory.fortress.core.UpdateException},{@link org.apache.directory.fortress.core.RemoveException}),
+ *  or {@link org.apache.directory.fortress.core.ValidationException} as {@link org.apache.directory.fortress.core.SecurityException}s with appropriate
+ *  error id from {@link org.apache.directory.fortress.core.GlobalErrIds}.
+ * <p>
+ * This class performs simple data validation on properties to ensure length does not exceed 100 and contents are safe text.
+ * <p/>
+
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+final class ConfigP
+{
+    private static final String CLS_NM = ConfigP.class.getName();
+    private static final Logger LOG = LoggerFactory.getLogger( CLS_NM );
+
+
+    /**
+     * Package private constructor
+     */
+    ConfigP()
+    {
+    }
+
+
+    /**
+     * Create a new cfg node with given name and properties.  The name is required.  If node already exists,
+     * a {@link org.apache.directory.fortress.core.SecurityException} with error {@link GlobalErrIds#FT_CONFIG_ALREADY_EXISTS} will be thrown.
+     *
+     * @param name    attribute is required and maps to 'cn' attribute in 'device' object class.
+     * @param inProps contains {@link Properties} with list of name/value pairs to remove from existing config node.
+     * @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 )
+        throws SecurityException
+    {
+        validate( name, inProps );
+        ConfigDAO cfgDao = new ConfigDAO();
+        return cfgDao.create( name, inProps );
+    }
+
+
+    /**
+     * Update existing cfg node with additional properties, or, replace existing properties.  The name is required.  If node does not exist,
+     * a {@link SecurityException} with error {@link org.apache.directory.fortress.core.GlobalErrIds#FT_CONFIG_NOT_FOUND} will be thrown.
+     *
+     * @param name    attribute is required and maps to 'cn' attribute in 'device' object class.
+     * @param inProps contains {@link Properties} with list of name/value pairs to add or udpate from existing config node.
+     * @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 )
+        throws SecurityException
+    {
+        validate( name, inProps );
+        ConfigDAO cfgDao = new ConfigDAO();
+        return cfgDao.update( name, inProps );
+    }
+
+
+    /**
+     * Delete existing cfg node which will remove all properties associated with that node.
+     * The name is required.  If node does not exist, a {@link SecurityException} with error
+     * {@link GlobalErrIds#FT_CONFIG_NOT_FOUND} will be thrown.
+     * <p/>
+     * <font size="2" color="red">
+     * This method is destructive and will remove the cfg node completely from directory.<BR>
+     * Care should be taken during execution to ensure target name is correct and permanent removal of all parameters located
+     * there is intended.  There is no 'undo' for this operation.
+     * </font>
+     * <p/>
+     * @param name attribute is required and maps to 'cn' attribute in 'device' object class.
+     * @return {@link Properties} containing the collection of name/value pairs to be added to existing node.
+     * @throws SecurityException in the event entry not present or other system error.
+     */
+    void delete( String name )
+        throws SecurityException
+    {
+        if ( !StringUtils.isNotEmpty( name ) )
+        {
+            String error = "delete detected null config realm name";
+            LOG.warn( error );
+            throw new ValidationException( GlobalErrIds.FT_CONFIG_NAME_NULL, error );
+        }
+        ConfigDAO cfgDao = new ConfigDAO();
+        cfgDao.remove( name );
+    }
+
+
+    /**
+     * Delete existing cfg node with additional properties, or, replace existing properties.  The name is required.  If node does not exist,
+     * a {@link SecurityException} with error {@link org.apache.directory.fortress.core.GlobalErrIds#FT_CONFIG_NOT_FOUND} will be thrown.
+     *
+     * @param name attribute is required and maps to 'cn' attribute in 'device' object class.
+     * @throws org.apache.directory.fortress.core.SecurityException in the event entry not present or other system error.
+     */
+    void delete( String name, Properties inProps )
+        throws SecurityException
+    {
+        validate( name, inProps );
+        ConfigDAO cfgDao = new ConfigDAO();
+        cfgDao.remove( name, inProps );
+    }
+
+
+    /**
+     * Read an existing cfg node with given name and return to caller.  The name is required.  If node doesn't exist,
+     * a {@link SecurityException} with error {@link org.apache.directory.fortress.core.GlobalErrIds#FT_CONFIG_NOT_FOUND} will be thrown.
+     *
+     * @param name attribute is required and maps to 'cn' attribute in 'device' object class.
+     * @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 )
+        throws SecurityException
+    {
+        Properties outProps;
+        ConfigDAO cfgDao = new ConfigDAO();
+        outProps = cfgDao.getConfig( name );
+        return outProps;
+    }
+
+
+    /**
+     * Method will perform simple validations to ensure the integrity of the {@link Properties} entity targeted for insertion
+     * or deletion in directory.
+     *
+     * @param name contains the name of the cfg node.
+     * @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 )
+        throws ValidationException
+    {
+        if ( !StringUtils.isNotEmpty( name ) )
+        {
+            String error = "validate detected null config realm name";
+            LOG.warn( error );
+            throw new ValidationException( GlobalErrIds.FT_CONFIG_NAME_NULL, error );
+        }
+        if ( name.length() > GlobalIds.OU_LEN )
+        {
+            String error = "validate name [" + name + "] invalid length [" + name.length() + "]";
+            LOG.warn( error );
+            throw new ValidationException( GlobalErrIds.FT_CONFIG_NAME_INVLD, error );
+        }
+        if ( entity == null || entity.size() == 0 )
+        {
+            String error = "validate name [" + name + "] config props null";
+            LOG.warn( error );
+            throw new ValidationException( GlobalErrIds.FT_CONFIG_PROPS_NULL, error );
+        }
+        VUtil.properties( entity );
+    }
+}


Mime
View raw message