Return-Path: X-Original-To: apmail-directory-commits-archive@www.apache.org Delivered-To: apmail-directory-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 2DB0717F0C for ; Wed, 22 Oct 2014 15:44:22 +0000 (UTC) Received: (qmail 17436 invoked by uid 500); 22 Oct 2014 15:44:22 -0000 Delivered-To: apmail-directory-commits-archive@directory.apache.org Received: (qmail 17330 invoked by uid 500); 22 Oct 2014 15:44:22 -0000 Mailing-List: contact commits-help@directory.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@directory.apache.org Delivered-To: mailing list commits@directory.apache.org Received: (qmail 16728 invoked by uid 99); 22 Oct 2014 15:44:21 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 22 Oct 2014 15:44:21 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 6203D9B24AB; Wed, 22 Oct 2014 15:44:21 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: smckinney@apache.org To: commits@directory.apache.org Date: Wed, 22 Oct 2014 15:44:34 -0000 Message-Id: <96d0ae9ec2a540b19dbf271986526c48@git.apache.org> In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [15/51] [partial] Rename packages from org.openldap.fortress to org.apache.directory.fortress.core. Change default suffix to org.apache. Switch default ldap api from unbound to apache ldap. http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/687ee1ad/src/main/java/org/apache/directory/fortress/core/rbac/dao/apache/RoleDAO.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/directory/fortress/core/rbac/dao/apache/RoleDAO.java b/src/main/java/org/apache/directory/fortress/core/rbac/dao/apache/RoleDAO.java new file mode 100755 index 0000000..6aa4900 --- /dev/null +++ b/src/main/java/org/apache/directory/fortress/core/rbac/dao/apache/RoleDAO.java @@ -0,0 +1,657 @@ +/* + * 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.rbac.dao.apache; + + +import java.util.ArrayList; +import java.util.List; + +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.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.exception.LdapException; +import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException; +import org.apache.directory.api.ldap.model.exception.LdapNoSuchObjectException; +import org.apache.directory.api.ldap.model.message.SearchScope; +import org.apache.directory.ldap.client.api.LdapConnection; + +import org.apache.directory.fortress.core.CreateException; +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.ObjectFactory; +import org.apache.directory.fortress.core.RemoveException; +import org.apache.directory.fortress.core.UpdateException; +import org.apache.directory.fortress.core.ldap.ApacheDsDataProvider; +import org.apache.directory.fortress.core.rbac.Graphable; +import org.apache.directory.fortress.core.rbac.Role; +import org.apache.directory.fortress.core.rbac.RoleUtil; +import org.apache.directory.fortress.core.util.attr.VUtil; +import org.apache.directory.fortress.core.util.time.CUtil; + + +/** + * This class perform data access for Fortress Role entity. + *

+ * The Fortress Role entity is a composite of the following other Fortress structural and aux object classes: + *

1. ftRls Structural objectclass is used to store the Role information like name and temporal constraint attributes

+ *
    + *
  • ------------------------------------------ + *
  • objectclass ( 1.3.6.1.4.1.38088.2.1 + *
  • NAME 'ftRls' + *
  • DESC 'Fortress Role Object Class' + *
  • SUP organizationalrole + *
  • STRUCTURAL + *
  • MUST ( ftId $ ftRoleName ) + *
  • MAY ( description $ ftCstr ) ) + *
  • ------------------------------------------ + *
+ *

2. ftProperties AUXILIARY Object Class is used to store client specific name/value pairs on target entity

+ * # This aux object class can be used to store custom attributes.
+ * # The properties collections consist of name/value pairs and are not constrainted by Fortress.
+ *
    + *
  • ------------------------------------------ + *
  • objectclass ( 1.3.6.1.4.1.38088.3.2 + *
  • NAME 'ftProperties' + *
  • DESC 'Fortress Properties AUX Object Class' + *
  • AUXILIARY + *
  • MAY ( ftProps ) ) + *
  • ------------------------------------------ + *
+ *

3. ftMods AUXILIARY Object Class is used to store Fortress audit variables on target entity

+ *
    + *
  • objectclass ( 1.3.6.1.4.1.38088.3.4 + *
  • NAME 'ftMods' + *
  • DESC 'Fortress Modifiers AUX Object Class' + *
  • AUXILIARY + *
  • MAY ( + *
  • ftModifier $ + *
  • ftModCode $ + *
  • ftModId ) ) + *
  • ------------------------------------------ + *
+ *

+ * This class is thread safe. + * + * @author Kevin McKinney + */ +public final class RoleDAO extends ApacheDsDataProvider implements org.apache.directory.fortress.core.rbac.dao.RoleDAO +{ + /* + * ************************************************************************* + * ** OpenAccessMgr ROLE STATICS + * ************************************************************************ + */ + private static final String ROLE_OCCUPANT = "roleOccupant"; + private static final String ROLE_NM = "ftRoleName"; + + private static final String[] ROLE_NM_ATR = + { + ROLE_NM + }; + + private static final String[] ROLE_ATRS = + { + GlobalIds.FT_IID, ROLE_NM, GlobalIds.DESC, GlobalIds.CONSTRAINT, ROLE_OCCUPANT, GlobalIds.PARENT_NODES + }; + + + /** + * @param entity + * @return + * @throws CreateException + */ + public final Role create( Role entity ) throws CreateException + { + LdapConnection ld = null; + String dn = getDn( entity.getName(), entity.getContextId() ); + + try + { + Entry entry = new DefaultEntry( dn ); + entry.add( GlobalIds.OBJECT_CLASS, GlobalIds.ROLE_OBJ_CLASS ); + entity.setId(); + entry.add( GlobalIds.FT_IID, entity.getId() ); + entry.add( ROLE_NM, entity.getName() ); + + // description field is optional on this object class: + if ( VUtil.isNotNullOrEmpty( entity.getDescription() ) ) + { + entry.add( GlobalIds.DESC, entity.getDescription() ); + } + + // CN attribute is required for this object class: + entry.add( GlobalIds.CN, entity.getName() ); + entry.add( GlobalIds.CONSTRAINT, CUtil.setConstraint( entity ) ); + + // These multi-valued attributes are optional. The utility function will return quietly if items are not loaded into collection: + loadAttrs( entity.getParents(), entry, GlobalIds.PARENT_NODES ); + + ld = getAdminConnection(); + add( ld, entry, entity ); + } + catch ( LdapException e ) + { + String error = "create role [" + entity.getName() + "] caught LdapException=" + e.getMessage(); + throw new CreateException( GlobalErrIds.ROLE_ADD_FAILED, error, e ); + } + finally + { + closeAdminConnection( ld ); + } + + return entity; + } + + + /** + * @param entity + * @return + * @throws org.apache.directory.fortress.core.UpdateException + * + */ + public final Role update( Role entity ) throws UpdateException + { + LdapConnection ld = null; + String dn = getDn( entity.getName(), entity.getContextId() ); + + try + { + List mods = new ArrayList(); + + if ( VUtil.isNotNullOrEmpty( entity.getDescription() ) ) + { + mods.add( new DefaultModification( ModificationOperation.REPLACE_ATTRIBUTE, + GlobalIds.DESC, entity.getDescription() ) ); + } + + if ( VUtil.isNotNullOrEmpty( entity.getOccupants() ) ) + { + for ( String name : entity.getOccupants() ) + { + mods.add( new DefaultModification( ModificationOperation.REPLACE_ATTRIBUTE, + ROLE_OCCUPANT, entity.getOccupants().toArray( new String[] + {} ) ) ); + } + } + + if ( entity.isTemporalSet() ) + { + String szRawData = CUtil.setConstraint( entity ); + + if ( VUtil.isNotNullOrEmpty( szRawData ) ) + { + mods.add( new DefaultModification( ModificationOperation.REPLACE_ATTRIBUTE, + GlobalIds.CONSTRAINT, szRawData ) ); + } + } + + loadAttrs( entity.getParents(), mods, GlobalIds.PARENT_NODES ); + + if ( mods.size() > 0 ) + { + ld = getAdminConnection(); + modify( ld, dn, mods, entity ); + } + } + catch ( LdapException e ) + { + String error = "update name [" + entity.getName() + "] caught LdapException=" + e.getMessage(); + throw new UpdateException( GlobalErrIds.ROLE_UPDATE_FAILED, error, e ); + } + catch ( Exception e ) + { + String error = "update name [" + entity.getName() + "] caught LdapException=" + e.getMessage(); + throw new UpdateException( GlobalErrIds.ROLE_UPDATE_FAILED, error, e ); + } + finally + { + try + { + closeAdminConnection( ld ); + } + catch ( Exception e ) + { + String error = "update name [" + entity.getName() + "] caught LdapException=" + e.getMessage(); + throw new UpdateException( GlobalErrIds.ROLE_UPDATE_FAILED, error, e ); + } + } + + return entity; + } + + + /** + * + * @param entity + * @throws UpdateException + */ + public final void deleteParent( Role entity ) throws UpdateException + { + LdapConnection ld = null; + String dn = getDn( entity.getName(), entity.getContextId() ); + try + { + List mods = new ArrayList(); + mods.add( new DefaultModification( ModificationOperation.REMOVE_ATTRIBUTE, + GlobalIds.PARENT_NODES ) ); + ld = getAdminConnection(); + modify( ld, dn, mods, entity ); + } + catch ( LdapException e ) + { + String error = "deleteParent name [" + entity.getName() + "] caught LdapException=" + e.getMessage(); + throw new UpdateException( GlobalErrIds.ROLE_REMOVE_PARENT_FAILED, error, e ); + } + finally + { + closeAdminConnection( ld ); + } + } + + + /** + * @param entity + * @param userDn + * @return + * @throws org.apache.directory.fortress.core.UpdateException + * + */ + public final Role assign( Role entity, String userDn ) throws UpdateException + { + LdapConnection ld = null; + String dn = getDn( entity.getName(), entity.getContextId() ); + + try + { + //ld = getAdminConnection(); + List mods = new ArrayList(); + mods.add( new DefaultModification( ModificationOperation.ADD_ATTRIBUTE, ROLE_OCCUPANT, userDn ) ); + ld = getAdminConnection(); + modify( ld, dn, mods, entity ); + } + catch ( LdapException e ) + { + String error = "assign role name [" + entity.getName() + "] user dn [" + userDn + "] caught LdapException=" + + e.getMessage(); + throw new UpdateException( GlobalErrIds.ROLE_USER_ASSIGN_FAILED, error, e ); + } + finally + { + closeAdminConnection( ld ); + } + + return entity; + } + + + /** + * @param entity + * @param userDn + * @return + * @throws org.apache.directory.fortress.core.UpdateException + * + */ + public final Role deassign( Role entity, String userDn ) throws UpdateException + { + LdapConnection ld = null; + String dn = getDn( entity.getName(), entity.getContextId() ); + try + { + List mods = new ArrayList(); + mods.add( new DefaultModification( ModificationOperation.REMOVE_ATTRIBUTE, ROLE_OCCUPANT, userDn ) ); + ld = getAdminConnection(); + modify( ld, dn, mods, entity ); + } + catch ( LdapException e ) + { + String error = "deassign role name [" + entity.getName() + "] user dn [" + userDn + + "] caught LdapException=" + e.getMessage(); + throw new UpdateException( GlobalErrIds.ROLE_USER_DEASSIGN_FAILED, error, e ); + } + finally + { + closeAdminConnection( ld ); + } + + return entity; + } + + + /** + * @param role + * @throws RemoveException + */ + public final void remove( Role role ) + throws RemoveException + { + LdapConnection ld = null; + String dn = getDn( role.getName(), role.getContextId() ); + + try + { + ld = getAdminConnection(); + delete( ld, dn, role ); + } + catch ( LdapException e ) + { + String error = "remove role name=" + role.getName() + " LdapException=" + e.getMessage(); + throw new RemoveException( GlobalErrIds.ROLE_DELETE_FAILED, error, e ); + } + finally + { + closeAdminConnection( ld ); + } + } + + + /** + * @param role + * @return + * @throws org.apache.directory.fortress.core.FinderException + * + */ + public final Role getRole( Role role ) + throws FinderException + { + Role entity = null; + LdapConnection ld = null; + String dn = getDn( role.getName(), role.getContextId() ); + + try + { + ld = getAdminConnection(); + Entry findEntry = read( ld, dn, ROLE_ATRS ); + if(findEntry != null) + { + entity = unloadLdapEntry( findEntry, 0, role.getContextId() ); + } + if ( entity == null ) + { + String warning = "getRole no entry found dn [" + dn + "]"; + throw new FinderException( GlobalErrIds.ROLE_NOT_FOUND, warning ); + } + } + catch ( LdapNoSuchObjectException e ) + { + String warning = "getRole Obj COULD NOT FIND ENTRY for dn [" + dn + "]"; + throw new FinderException( GlobalErrIds.ROLE_NOT_FOUND, warning ); + } + catch ( LdapException e ) + { + String error = "getRole dn [" + dn + "] LEXCD=" + e; + throw new FinderException( GlobalErrIds.ROLE_READ_FAILED, error, e ); + } + finally + { + closeAdminConnection( ld ); + } + + return entity; + } + + + /** + * @param role + * @return + * @throws org.apache.directory.fortress.core.FinderException + * + */ + public final List findRoles( Role role ) + throws FinderException + { + List roleList = new ArrayList<>(); + LdapConnection ld = null; + String roleRoot = getRootDn( role.getContextId(), GlobalIds.ROLE_ROOT ); + String filter = null; + + try + { + String searchVal = encodeSafeText( role.getName(), GlobalIds.ROLE_LEN ); + filter = GlobalIds.FILTER_PREFIX + GlobalIds.ROLE_OBJECT_CLASS_NM + ")(" + + ROLE_NM + "=" + searchVal + "*))"; + ld = getAdminConnection(); + SearchCursor searchResults = search( ld, roleRoot, + SearchScope.ONELEVEL, filter, ROLE_ATRS, false, GlobalIds.BATCH_SIZE ); + long sequence = 0; + + while ( searchResults.next() ) + { + roleList.add( unloadLdapEntry( searchResults.getEntry(), sequence++, role.getContextId() ) ); + } + } + catch ( LdapException e ) + { + String error = "findRoles filter [" + filter + "] caught LdapException=" + e.getMessage(); + throw new FinderException( GlobalErrIds.ROLE_SEARCH_FAILED, error, e ); + } + catch ( CursorException e ) + { + String error = "findRoles filter [" + filter + "] caught LdapException=" + e.getMessage(); + throw new FinderException( GlobalErrIds.ROLE_SEARCH_FAILED, error, e ); + } + finally + { + closeAdminConnection( ld ); + } + + return roleList; + } + + + /** + * @param role + * @param limit + * @return + * @throws org.apache.directory.fortress.core.FinderException + * + */ + public final List findRoles( Role role, int limit ) + throws FinderException + { + List roleList = new ArrayList<>(); + LdapConnection ld = null; + String roleRoot = getRootDn( role.getContextId(), GlobalIds.ROLE_ROOT ); + String filter = null; + + try + { + String searchVal = encodeSafeText( role.getName(), GlobalIds.ROLE_LEN ); + filter = GlobalIds.FILTER_PREFIX + GlobalIds.ROLE_OBJECT_CLASS_NM + ")(" + + ROLE_NM + "=" + searchVal + "*))"; + ld = getAdminConnection(); + SearchCursor searchResults = search( ld, roleRoot, + SearchScope.ONELEVEL, filter, ROLE_NM_ATR, false, GlobalIds.BATCH_SIZE, limit ); + + while ( searchResults.next() ) + { + Entry entry = searchResults.getEntry(); + roleList.add( getAttribute( entry, ROLE_NM ) ); + } + } + catch ( LdapException e ) + { + String error = "findRoles filter [" + filter + "] caught LdapException=" + e.getMessage(); + throw new FinderException( GlobalErrIds.ROLE_SEARCH_FAILED, error, e ); + } + catch ( CursorException e ) + { + String error = "findRoles filter [" + filter + "] caught LdapException=" + e.getMessage(); + throw new FinderException( GlobalErrIds.ROLE_SEARCH_FAILED, error, e ); + } + finally + { + closeAdminConnection( ld ); + } + + return roleList; + } + + + /** + * + * @param userDn + * @param contextId + * @return + * @throws FinderException + */ + public final List findAssignedRoles( String userDn, String contextId ) + throws FinderException + { + List roleNameList = new ArrayList<>(); + LdapConnection ld = null; + String roleRoot = getRootDn( contextId, GlobalIds.ROLE_ROOT ); + + try + { + String filter = GlobalIds.FILTER_PREFIX + GlobalIds.ROLE_OBJECT_CLASS_NM + ")"; + filter += "(" + ROLE_OCCUPANT + "=" + userDn + "))"; + ld = getAdminConnection(); + SearchCursor searchResults = search( ld, roleRoot, + SearchScope.ONELEVEL, filter, ROLE_NM_ATR, false, GlobalIds.BATCH_SIZE ); + + while ( searchResults.next() ) + { + roleNameList.add( getAttribute( searchResults.getEntry(), ROLE_NM ) ); + } + } + catch ( LdapException e ) + { + String error = "findAssignedRoles userDn [" + userDn + "] caught LdapException=" + e.getMessage(); + throw new FinderException( GlobalErrIds.ROLE_OCCUPANT_SEARCH_FAILED, error, e ); + } + catch ( CursorException e ) + { + String error = "findAssignedRoles userDn [" + userDn + "] caught LdapException=" + e.getMessage(); + throw new FinderException( GlobalErrIds.ROLE_OCCUPANT_SEARCH_FAILED, error, e ); + } + finally + { + closeAdminConnection( ld ); + } + + return roleNameList; + } + + + /** + * + * @param contextId + * @return + * @throws FinderException + */ + public final List getAllDescendants( String contextId ) + throws FinderException + { + String[] DESC_ATRS = + { ROLE_NM, GlobalIds.PARENT_NODES }; + List descendants = new ArrayList<>(); + LdapConnection ld = null; + String roleRoot = getRootDn( contextId, GlobalIds.ROLE_ROOT ); + String filter = null; + + try + { + filter = GlobalIds.FILTER_PREFIX + GlobalIds.ROLE_OBJECT_CLASS_NM + ")(" + + GlobalIds.PARENT_NODES + "=*))"; + ld = getAdminConnection(); + SearchCursor searchResults = search( ld, roleRoot, + SearchScope.ONELEVEL, filter, DESC_ATRS, false, GlobalIds.BATCH_SIZE ); + long sequence = 0; + + while ( searchResults.next() ) + { + descendants.add( unloadDescendants( searchResults.getEntry(), sequence++, contextId ) ); + } + } + catch ( LdapException e ) + { + String error = "getAllDescendants filter [" + filter + "] caught LdapException=" + e.getMessage(); + throw new FinderException( GlobalErrIds.ROLE_SEARCH_FAILED, error, e ); + } + catch ( CursorException e ) + { + String error = "getAllDescendants filter [" + filter + "] caught LdapException=" + e.getMessage(); + throw new FinderException( GlobalErrIds.ROLE_SEARCH_FAILED, error, e ); + } + finally + { + closeAdminConnection( ld ); + } + + return descendants; + } + + + /** + * + * @param le + * @param sequence + * @param contextId + * @return + * @throws LdapInvalidAttributeValueException + * @throws LdapException + */ + private Graphable unloadDescendants( Entry le, long sequence, String contextId ) + throws LdapInvalidAttributeValueException + { + Role entity = new ObjectFactory().createRole(); + entity.setSequenceId( sequence ); + entity.setName( getAttribute( le, ROLE_NM ) ); + entity.setParents( getAttributeSet( le, GlobalIds.PARENT_NODES ) ); + return entity; + } + + + /** + * + * @param le + * @param sequence + * @param contextId + * @return + * @throws LdapInvalidAttributeValueException + * @throws LdapException + */ + private Role unloadLdapEntry( Entry le, long sequence, String contextId ) throws LdapInvalidAttributeValueException + { + Role entity = new ObjectFactory().createRole(); + entity.setSequenceId( sequence ); + entity.setId( getAttribute( le, GlobalIds.FT_IID ) ); + entity.setName( getAttribute( le, ROLE_NM ) ); + entity.setDescription( getAttribute( le, GlobalIds.DESC ) ); + entity.setOccupants( getAttributes( le, ROLE_OCCUPANT ) ); + //entity.setParents(RoleUtil.getParents(entity.getName().toUpperCase(), contextId)); + entity.setChildren( RoleUtil.getChildren( entity.getName().toUpperCase(), contextId ) ); + entity.setParents( getAttributeSet( le, GlobalIds.PARENT_NODES ) ); + unloadTemporal( le, entity ); + + return entity; + } + + + private String getDn( String name, String contextId ) + { + return GlobalIds.CN + "=" + name + "," + getRootDn( contextId, GlobalIds.ROLE_ROOT ); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/687ee1ad/src/main/java/org/apache/directory/fortress/core/rbac/dao/apache/SdDAO.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/directory/fortress/core/rbac/dao/apache/SdDAO.java b/src/main/java/org/apache/directory/fortress/core/rbac/dao/apache/SdDAO.java new file mode 100755 index 0000000..f4d25b6 --- /dev/null +++ b/src/main/java/org/apache/directory/fortress/core/rbac/dao/apache/SdDAO.java @@ -0,0 +1,633 @@ +/* + * 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.rbac.dao.apache; + + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +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.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.exception.LdapException; +import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException; +import org.apache.directory.api.ldap.model.exception.LdapNoSuchObjectException; +import org.apache.directory.api.ldap.model.message.SearchScope; +import org.apache.directory.ldap.client.api.LdapConnection; + +import org.apache.directory.fortress.core.CreateException; +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.ObjectFactory; +import org.apache.directory.fortress.core.RemoveException; +import org.apache.directory.fortress.core.UpdateException; +import org.apache.directory.fortress.core.ldap.ApacheDsDataProvider; +import org.apache.directory.fortress.core.rbac.Role; +import org.apache.directory.fortress.core.rbac.RoleUtil; +import org.apache.directory.fortress.core.rbac.SDSet; +import org.apache.directory.fortress.core.util.attr.VUtil; + + +/** + * This class performs persistence on the RBAC Static Separation of Duties and Dynamic Separation of Duties data sets. + *

+ * The Fortress SDSet entity is a composite of the following other Fortress structural and aux object classes: + *

1. organizationalRole Structural Object Class is used to store basic attributes like cn and description

+ *
    + *
  • ------------------------------------------ + *
  • objectclass ( 2.5.6.8 NAME 'organizationalRole' + *
  • DESC 'RFC2256: an organizational role' + *
  • SUP top STRUCTURAL + *
  • MUST cn + *
  • MAY ( x121Address $ registeredAddress $ destinationIndicator $ + *
  • preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $ + *
  • telephoneNumber $ internationaliSDNNumber $ facsimileTelephoneNumber $ + *
  • seeAlso $ roleOccupant $ preferredDeliveryMethod $ street $ + *
  • postOfficeBox $ postalCode $ postalAddress $ + *
  • physicalDeliveryOfficeName $ ou $ st $ l $ description ) ) + *
  • ------------------------------------------ + *
+ *

2. The RBAC Separation of Duties

+ *
    + *
  • ---Static Separation of Duties Set------- + *
  • objectclass ( 1.3.6.1.4.1.38088.2.4 + *
  • NAME 'ftSSDSet' + *
  • DESC 'Fortress Role Static Separation of Duty Set Object Class' + *
  • SUP organizationalrole + *
  • STRUCTURAL + *
  • MUST ( ftId $ ftSetName $ ftSetCardinality ) + *
  • MAY ( ftRoles $ description ) ) + *
  • ------------------------------------------ + *
+ *

+ * OR + *

Dynamic Separation of Duties Set

+ *
    + *
  • + *
  • objectclass ( 1.3.6.1.4.1.38088.2.5 + *
  • NAME 'ftDSDSet' + *
  • DESC 'Fortress Role Dynamic Separation of Duty Set Object Class' + *
  • SUP organizationalrole + *
  • STRUCTURAL + *
  • MUST ( ftId $ ftSetName $ ftSetCardinality ) + *
  • MAY ( ftRoles $ description ) ) + *
  • ------------------------------------------ + *
+ *

3. ftMods AUXILIARY Object Class is used to store Fortress audit variables on target entity

+ *
    + *
  • objectclass ( 1.3.6.1.4.1.38088.3.4 + *
  • NAME 'ftMods' + *
  • DESC 'Fortress Modifiers AUX Object Class' + *
  • AUXILIARY + *
  • MAY ( + *
  • ftModifier $ + *
  • ftModCode $ + *
  • ftModId ) ) + *
  • ------------------------------------------ + *
+ *

+ * This class is thread safe. + *

+ * + * @author Shawn McKinney + */ +public final class SdDAO extends ApacheDsDataProvider implements org.apache.directory.fortress.core.rbac.dao.SdDAO +{ + private static final String SD_SET_NM = "ftSetName"; + private static final String ROLES = "ftRoles"; + private static final String SD_SET_CARDINALITY = "ftSetCardinality"; + + private static final String SSD_OBJECT_CLASS_NM = "ftSSDSet"; + private static final String SSD_OBJ_CLASS[] = + { + GlobalIds.TOP, SSD_OBJECT_CLASS_NM, GlobalIds.FT_MODIFIER_AUX_OBJECT_CLASS_NAME + }; + + private static final String DSD_OBJECT_CLASS_NM = "ftDSDSet"; + private static final String DSD_OBJ_CLASS[] = + { + GlobalIds.TOP, DSD_OBJECT_CLASS_NM, GlobalIds.FT_MODIFIER_AUX_OBJECT_CLASS_NAME + }; + + private static final String[] SD_SET_ATRS = + { + GlobalIds.FT_IID, SD_SET_NM, GlobalIds.DESC, ROLES, SD_SET_CARDINALITY + }; + + + /** + * @param entity + * @return + * @throws org.apache.directory.fortress.core.CreateException + */ + public final SDSet create( SDSet entity ) throws CreateException + { + LdapConnection ld = null; + String dn = getDn( entity.getName(), entity.getContextId() ); + String[] objectClass = SSD_OBJ_CLASS; + + if ( entity.getType() == SDSet.SDType.DYNAMIC ) + { + objectClass = DSD_OBJ_CLASS; + } + + try + { + Entry entry = new DefaultEntry( dn ); + entry.add( createAttributes( GlobalIds.OBJECT_CLASS, objectClass ) ); + entity.setId(); + entry.add( GlobalIds.FT_IID, entity.getId() ); + entry.add( SD_SET_NM, entity.getName() ); + + // description field is optional on this object class: + if ( VUtil.isNotNullOrEmpty( entity.getDescription() ) ) + { + entry.add( GlobalIds.DESC, entity.getDescription() ); + } + + // CN attribute is required for this object class: + entry.add( GlobalIds.CN, entity.getName() ); + loadAttrs( entity.getMembers(), entry, ROLES ); + entry.add( SD_SET_CARDINALITY, "" + entity.getCardinality() ); + + ld = getAdminConnection(); + add( ld, entry, entity ); + } + catch ( LdapException e ) + { + String error = "create SD set name [" + entity.getName() + "] type [" + entity.getType() + + "] caught LdapException=" + e.getMessage(); + int errCode; + if ( entity.getType() == SDSet.SDType.DYNAMIC ) + { + errCode = GlobalErrIds.DSD_ADD_FAILED; + } + else + { + errCode = GlobalErrIds.SSD_ADD_FAILED; + } + + throw new CreateException( errCode, error, e ); + } + finally + { + closeAdminConnection( ld ); + } + return entity; + } + + + /** + * @param entity + * @return + * @throws org.apache.directory.fortress.core.UpdateException + */ + public final SDSet update( SDSet entity ) throws UpdateException + { + LdapConnection ld = null; + String dn = getDn( entity.getName(), entity.getContextId() ); + + try + { + List mods = new ArrayList(); + + if ( VUtil.isNotNullOrEmpty( entity.getDescription() ) ) + { + mods.add( new DefaultModification( + ModificationOperation.REPLACE_ATTRIBUTE, GlobalIds.DESC, entity.getDescription() ) ); + } + + if ( entity.getCardinality() != null ) + { + mods.add( new DefaultModification( + ModificationOperation.REPLACE_ATTRIBUTE, SD_SET_CARDINALITY, entity.getCardinality().toString() ) ); + } + + loadAttrs( entity.getMembers(), mods, ROLES ); + + if ( mods.size() > 0 ) + { + ld = getAdminConnection(); + modify( ld, dn, mods, entity ); + } + } + catch ( LdapException e ) + { + String error = "update name [" + entity.getName() + "] type [" + entity.getType() + + "] caught LdapException=" + e.getMessage(); + int errCode; + if ( entity.getType() == SDSet.SDType.DYNAMIC ) + { + errCode = GlobalErrIds.DSD_UPDATE_FAILED; + } + else + { + errCode = GlobalErrIds.SSD_UPDATE_FAILED; + } + + throw new UpdateException( errCode, error, e ); + } + finally + { + closeAdminConnection( ld ); + } + + return entity; + } + + + /** + * @param entity + * @throws org.apache.directory.fortress.core.RemoveException + */ + public final SDSet remove( SDSet entity ) throws RemoveException + { + LdapConnection ld = null; + String dn = getDn( entity.getName(), entity.getContextId() ); + + try + { + ld = getAdminConnection(); + delete( ld, dn, entity ); + } + catch ( LdapException e ) + { + String error = "remove SD name=" + entity.getName() + " type [" + entity.getType() + "] LdapException=" + + e.getMessage(); + int errCode; + if ( entity.getType() == SDSet.SDType.DYNAMIC ) + { + errCode = GlobalErrIds.DSD_DELETE_FAILED; + } + else + { + errCode = GlobalErrIds.SSD_DELETE_FAILED; + } + + throw new RemoveException( errCode, error, e ); + } + finally + { + closeAdminConnection( ld ); + } + + return entity; + } + + + /** + * @param sdSet + * @return + * @throws FinderException + */ + public final SDSet getSD( SDSet sdSet ) throws FinderException + { + SDSet entity = null; + LdapConnection ld = null; + String dn = getDn( sdSet.getName(), sdSet.getContextId() ); + + try + { + ld = getAdminConnection(); + Entry findEntry = read( ld, dn, SD_SET_ATRS ); + entity = unloadLdapEntry( findEntry, 0 ); + + if ( entity == null ) + { + String warning = "getSD no entry found dn [" + dn + "]"; + throw new FinderException( GlobalErrIds.SSD_NOT_FOUND, warning ); + } + } + catch ( LdapNoSuchObjectException e ) + { + String warning = "getSD Obj COULD NOT FIND ENTRY for dn [" + dn + "]"; + throw new FinderException( GlobalErrIds.SSD_NOT_FOUND, warning ); + } + catch ( LdapException e ) + { + String error = "getSSD dn [" + dn + "] LEXCD=" + e; + int errCode; + + if ( sdSet.getType() == SDSet.SDType.DYNAMIC ) + { + errCode = GlobalErrIds.DSD_READ_FAILED; + } + else + { + errCode = GlobalErrIds.SSD_READ_FAILED; + } + + throw new FinderException( errCode, error, e ); + } + finally + { + closeAdminConnection( ld ); + } + + return entity; + } + + + /** + * Given an SSD name and type, find matching object in the directory. + * @param sdset requires name and type. + * @return List of matching SDSets. + * @throws org.apache.directory.fortress.core.FinderException + */ + public final List search( SDSet sdset ) throws FinderException + { + List sdList = new ArrayList<>(); + LdapConnection ld = null; + String ssdRoot = getSdRoot( sdset.getContextId() ); + String objectClass = SSD_OBJECT_CLASS_NM; + + if ( sdset.getType() == SDSet.SDType.DYNAMIC ) + { + objectClass = DSD_OBJECT_CLASS_NM; + } + + try + { + String searchVal = encodeSafeText( sdset.getName(), GlobalIds.ROLE_LEN ); + String filter = GlobalIds.FILTER_PREFIX + objectClass + ")(" + SD_SET_NM + "=" + searchVal + "*))"; + ld = getAdminConnection(); + SearchCursor searchResults = search( ld, ssdRoot, + SearchScope.SUBTREE, filter, SD_SET_ATRS, false, GlobalIds.BATCH_SIZE ); + long sequence = 0; + + while ( searchResults.next() ) + { + sdList.add( unloadLdapEntry( searchResults.getEntry(), sequence++ ) ); + } + } + catch ( LdapException e ) + { + String error = "search sdset name [" + sdset.getName() + "] type [" + sdset.getType() + + "] caught LdapException=" + e.getMessage(); + int errCode; + + if ( sdset.getType() == SDSet.SDType.DYNAMIC ) + { + errCode = GlobalErrIds.DSD_SEARCH_FAILED; + } + else + { + errCode = GlobalErrIds.SSD_SEARCH_FAILED; + } + + throw new FinderException( errCode, error, e ); + } + catch ( CursorException e ) + { + String error = "search sdset name [" + sdset.getName() + "] type [" + sdset.getType() + + "] caught LdapException=" + e.getMessage(); + int errCode; + + if ( sdset.getType() == SDSet.SDType.DYNAMIC ) + { + errCode = GlobalErrIds.DSD_SEARCH_FAILED; + } + else + { + errCode = GlobalErrIds.SSD_SEARCH_FAILED; + } + + throw new FinderException( errCode, error, e ); + } + finally + { + closeAdminConnection( ld ); + } + return sdList; + } + + + /** + * @param role + * @return + * @throws org.apache.directory.fortress.core.FinderException + */ + public final List search( Role role, SDSet.SDType type ) throws FinderException + { + List sdList = new ArrayList<>(); + LdapConnection ld = null; + String ssdRoot = getSdRoot( role.getContextId() ); + String objectClass = SSD_OBJECT_CLASS_NM; + + if ( type == SDSet.SDType.DYNAMIC ) + { + objectClass = DSD_OBJECT_CLASS_NM; + } + + try + { + String roleVal = encodeSafeText( role.getName(), GlobalIds.ROLE_LEN ); + //String filter = GlobalIds.FILTER_PREFIX + SSD_OBJECT_CLASS_NM + ")(" + ROLES + "=" + roleVal + "))"; + String filter = GlobalIds.FILTER_PREFIX + objectClass + ")("; + // Include any parents target role may have: + Set roles = RoleUtil.getAscendants( role.getName(), role.getContextId() ); + + if ( VUtil.isNotNullOrEmpty( roles ) ) + { + filter += "|(" + ROLES + "=" + roleVal + ")"; + + for ( String uRole : roles ) + { + filter += "(" + ROLES + "=" + uRole + ")"; + } + filter += ")"; + } + else + { + filter += ROLES + "=" + roleVal + ")"; + } + + filter += ")"; + ld = getAdminConnection(); + SearchCursor searchResults = search( ld, ssdRoot, + SearchScope.SUBTREE, filter, SD_SET_ATRS, false, GlobalIds.BATCH_SIZE ); + + long sequence = 0; + + while ( searchResults.next() ) + { + sdList.add( unloadLdapEntry( searchResults.getEntry(), sequence++ ) ); + } + } + catch ( LdapException e ) + { + String error = "search role [" + role.getName() + "] type [" + type + "] caught LdapException=" + + e.getMessage(); + int errCode; + + if ( type == SDSet.SDType.DYNAMIC ) + { + errCode = GlobalErrIds.DSD_SEARCH_FAILED; + } + else + { + errCode = GlobalErrIds.SSD_SEARCH_FAILED; + } + + throw new FinderException( errCode, error, e ); + } + catch ( CursorException e ) + { + String error = "search role [" + role.getName() + "] type [" + type + "] caught LdapException=" + + e.getMessage(); + int errCode; + + if ( type == SDSet.SDType.DYNAMIC ) + { + errCode = GlobalErrIds.DSD_SEARCH_FAILED; + } + else + { + errCode = GlobalErrIds.SSD_SEARCH_FAILED; + } + + throw new FinderException( errCode, error, e ); + } + finally + { + closeAdminConnection( ld ); + } + + return sdList; + } + + + /** + * @param roles + * @param sdSet + * @return + * @throws org.apache.directory.fortress.core.FinderException + */ + public final Set search( Set roles, SDSet sdSet ) throws FinderException + { + Set sdList = new HashSet<>(); + LdapConnection ld = null; + String ssdRoot = getSdRoot( sdSet.getContextId() ); + String objectClass = SSD_OBJECT_CLASS_NM; + + if ( sdSet.getType() == SDSet.SDType.DYNAMIC ) + { + objectClass = DSD_OBJECT_CLASS_NM; + } + + try + { + if ( VUtil.isNotNullOrEmpty( roles ) ) + { + String filter = GlobalIds.FILTER_PREFIX + objectClass + ")(|"; + for ( String rle : roles ) + { + filter += "(" + ROLES + "=" + rle + ")"; + } + filter += "))"; + ld = getAdminConnection(); + SearchCursor searchResults = search( ld, ssdRoot, + SearchScope.SUBTREE, filter, SD_SET_ATRS, false, GlobalIds.BATCH_SIZE ); + long sequence = 0; + + while ( searchResults.next() ) + { + sdList.add( unloadLdapEntry( searchResults.getEntry(), sequence++ ) ); + } + } + } + catch ( LdapException e ) + { + String error = "search type [" + sdSet.getType() + "] caught LdapException=" + e.getMessage(); + int errCode; + + if ( sdSet.getType() == SDSet.SDType.DYNAMIC ) + { + errCode = GlobalErrIds.DSD_SEARCH_FAILED; + } + else + { + errCode = GlobalErrIds.SSD_SEARCH_FAILED; + } + throw new FinderException( errCode, error, e ); + } + catch ( CursorException e ) + { + String error = "search type [" + sdSet.getType() + "] caught LdapException=" + e.getMessage(); + int errCode; + + if ( sdSet.getType() == SDSet.SDType.DYNAMIC ) + { + errCode = GlobalErrIds.DSD_SEARCH_FAILED; + } + else + { + errCode = GlobalErrIds.SSD_SEARCH_FAILED; + } + throw new FinderException( errCode, error, e ); + } + finally + { + closeAdminConnection( ld ); + } + + return sdList; + } + + + /** + * @param le + * @return + * @throws LdapInvalidAttributeValueException + * @throws LdapException + */ + private SDSet unloadLdapEntry( Entry le, long sequence ) throws LdapInvalidAttributeValueException + { + SDSet entity = new ObjectFactory().createSDset(); + entity.setSequenceId( sequence ); + entity.setId( getAttribute( le, GlobalIds.FT_IID ) ); + entity.setName( getAttribute( le, SD_SET_NM ) ); + entity.setDescription( getAttribute( le, GlobalIds.DESC ) ); + entity.setMembers( getAttributeSet( le, ROLES ) ); + String szCard = getAttribute( le, SD_SET_CARDINALITY ); + entity.setCardinality( new Integer( szCard ) ); + + return entity; + } + + + private String getDn( String name, String contextId ) + { + return GlobalIds.CN + "=" + name + "," + getSdRoot( contextId ); + } + + + private String getSdRoot( String contextId ) + { + return getRootDn( contextId, GlobalIds.SD_ROOT ); + } +}