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 8E1BF18651 for ; Tue, 9 Jun 2015 03:15:14 +0000 (UTC) Received: (qmail 12833 invoked by uid 500); 9 Jun 2015 03:15:11 -0000 Delivered-To: apmail-directory-commits-archive@directory.apache.org Received: (qmail 11390 invoked by uid 500); 9 Jun 2015 03:15:09 -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 9840 invoked by uid 99); 9 Jun 2015 03:15:08 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 09 Jun 2015 03:15:08 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 74157E00AA; Tue, 9 Jun 2015 03:15:08 +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: Tue, 09 Jun 2015 03:15:41 -0000 Message-Id: <122766690167448c883d61df28e128e2@git.apache.org> In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [35/75] [abbrv] [partial] directory-fortress-core git commit: FC-109 - rename rbac package to impl http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/ba64d26a/src/main/java/org/apache/directory/fortress/core/impl/UserP.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/directory/fortress/core/impl/UserP.java b/src/main/java/org/apache/directory/fortress/core/impl/UserP.java new file mode 100755 index 0000000..cda04ec --- /dev/null +++ b/src/main/java/org/apache/directory/fortress/core/impl/UserP.java @@ -0,0 +1,869 @@ +/* + * 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.Set; + +import org.apache.commons.lang.StringUtils; +import org.apache.directory.fortress.core.model.AdminRole; +import org.apache.directory.fortress.core.model.OrgUnit; +import org.apache.directory.fortress.core.model.PwPolicy; +import org.apache.directory.fortress.core.model.Role; +import org.apache.directory.fortress.core.model.Session; +import org.apache.directory.fortress.core.model.User; +import org.apache.directory.fortress.core.model.UserAdminRole; +import org.apache.directory.fortress.core.model.UserRole; +import org.apache.directory.fortress.core.util.ObjUtil; +import org.apache.directory.fortress.core.util.attr.AttrHelper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +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.PasswordException; +import org.apache.directory.fortress.core.SecurityException; +import org.apache.directory.fortress.core.ValidationException; +import org.apache.directory.fortress.core.model.VUtil; +import org.apache.directory.fortress.core.util.time.CUtil; + + +/** + * Process module for the User entity. This class performs data validations and error mapping. It is typically called + * by internal Fortress manager classes ({@link AdminMgrImpl}, {@link AccessMgrImpl}, + * {@link ReviewMgrImpl}, ...) and not intended for external non-Fortress clients. This class will accept, + * {@link org.apache.directory.fortress.core.model.User}, validate its contents and forward on to it's corresponding DAO class {@link org.apache.directory.fortress.core.impl.UserDAO}. + *

+ * 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 SecurityException}s with appropriate + * error id from {@link org.apache.directory.fortress.core.GlobalErrIds}. + *

+ * This class is thread safe. + *

+ * + * @author Apache Directory Project + */ +public final class UserP +{ + //private static final boolean IS_SESSION_PROPS_ENABLED = Config.getBoolean( "user.session.props.enabled", false ); + private static final String CLS_NM = UserP.class.getName(); + private static UserDAO uDao = new UserDAO(); + private static final Logger LOG = LoggerFactory.getLogger( CLS_NM ); + private static final PolicyP policyP = new PolicyP(); + private static final AdminRoleP admRoleP = new AdminRoleP(); + private static final OrgUnitP orgUnitP = new OrgUnitP(); + + + /** + * Package private constructor. + */ + UserP() + { + } + + + /** + * Takes a User entity that contains full or partial userId OR a full internal userId for search. + * + * @param user contains all or partial userId or full internal userId. + * @return List of type User containing fully populated matching User entities. If no records found this will be empty. + * @throws SecurityException in the event of DAO search error. + */ + List search( User user ) throws SecurityException + { + return uDao.findUsers( user ); + } + + + List search( OrgUnit ou, boolean limitSize ) throws SecurityException + { + return uDao.findUsers( ou, limitSize ); + } + + + /** + * Search according to full or partial search string that maps to Fortress userid. + * This search is used by RealmMgr for Websphere. + * + * @param user contains full or partial userId. + * @param limit specify the max number of records to return in result set. + * @return List of type String containing userId of all matching User entities. If no records found this will be empty. + * @throws SecurityException in the event of DAO search error. + */ + List search( User user, int limit ) throws SecurityException + { + return uDao.findUsers( user, limit ); + } + + + /** + * Return a list of Users that are authorized the given Role. + * + * @param role contains the role name targeted for search. + * @return List of type User containing fully populated matching User entities. If no records found this will be empty. + * @throws SecurityException in the event of DAO search error. + */ + List getAuthorizedUsers( Role role ) throws SecurityException + { + return uDao.getAuthorizedUsers( role ); + } + + + /** + * Return a list of Users that are authorized the given Role. + * + * @param roles contains the set of role names targeted for search. + * @param contextId maps to sub-tree in DIT, for example ou=contextId, dc=jts, dc = com. + * @return Set of type String containing the userId's for matching User entities. If no records found this will be empty. + * @throws SecurityException in the event of DAO search error. + */ + Set getAssignedUsers( Set roles, String contextId ) throws SecurityException + { + return uDao.getAssignedUsers( roles, contextId ); + } + + + /** + * Return a list of Users that are authorized the given Role. + * In RBAC the word "authorized" implies the hierarchical role relations graph is considered in result set. + * This search is used by RealmMgr for Websphere. + * + * @param role + * @param limit specify the max number of records to return in result set. + * @return list of type String of userIds. If no records found this will be empty. + * @throws SecurityException in the event of DAO search error. + */ + List getAuthorizedUsers( Role role, int limit ) throws SecurityException + { + return uDao.getAuthorizedUsers( role, limit ); + } + + + /** + * Return a list of Users assigned the given RBAC role. + * "Assigned" implies the hierarchical role relation graph will NOT be considered in result set. + * + * @param role contains name of RBAC role used for search. + * @return List of fully populated User entities matching target search. If no records found this will be empty. + * @throws SecurityException in the event of DAO search error. + */ + List getAssignedUsers( Role role ) throws SecurityException + { + return uDao.getAssignedUsers( role ); + } + + + /** + * Return a list of Users assigned the given Administrative role. + * "Assigned" implies the hierarchical role relation graph will NOT be considered in result set. + * + * @param role contains name of Admin role used for search. + * @return List of fully populated User entities matching target search. If no records found this will be empty. + * @throws SecurityException in the event of DAO search error. + */ + List getAssignedUsers( AdminRole role ) throws SecurityException + { + return uDao.getAssignedUsers( role ); + } + + + /** + * Return the list of User's RBAC roles. + * + * @param user contains full userId for target operation. + * @return List of type String containing RBAC role names. If no records found this will be empty. + * @throws SecurityException in the event of DAO search error. + */ + List getAssignedRoles( User user ) throws SecurityException + { + return uDao.getRoles( user ); + } + + + /** + * Return a fully populated User entity for a given userId. If the User entry is not found a SecurityException + * will be thrown. + * + * @param user contains full userId value. + * @param isRoles return user's assigned roles if "true". + * @return User entity containing all attributes associated with User in directory. + * @throws SecurityException in the event of User not found or DAO search error. + */ + User read( User user, boolean isRoles ) throws SecurityException + { + return uDao.getUser( user, isRoles ); + } + + + /** + * Adds a new User entity to directory. The User entity input object will be validated to ensure that: + * userId is present, orgUnitId is valid, roles (optiona) are valid, reasonability checks on all of the + * other populated values. + * + * @param entity User entity contains data targeted for insertion. + * @return User entity copy of input + additional attributes (internalId) that were added by op. + * @throws SecurityException in the event of data validation or DAO system error. + */ + User add( User entity ) throws SecurityException + { + return add( entity, true ); + } + + + /** + * Adds a new User entity to directory. + * The User entity input object will be validated to ensure that: userId is present, orgUnitId is valid, + * roles (optiona) are valid, reasonability checks on all of the other populated values. + * + * @param entity User entity contains data targeted for insertion. + * @param validate if false will skip the validations described above. + * @return User entity copy of input + additional attributes (internalId) + * @throws SecurityException in the event of data validation or DAO system error. + */ + User add( User entity, boolean validate ) throws SecurityException + { + if ( validate ) + { + // Ensure the input data is valid. + validate( entity, false ); + } + + entity = uDao.create( entity ); + + return entity; + } + + + /** + * Update existing user's attributes with the input entity. Null or empty attributes will be ignored. + * This method will ignore userId as input as change userId is not allowed. If password is changed + * OpenLDAP password policy will not be evaluated on behalf of the user. + * Other User entity input data can be changed and will also be validated beforehand to ensure that: + * orgUnitId is valid, roles (optional) are valid, reasonability checks will be performed on all of the populated fields. + * + * @param entity User entity contains data targeted for insertion. + * @return User entity copy of input + * @throws SecurityException in the event of data validation or DAO system error. + */ + User update( User entity ) throws SecurityException + { + return update( entity, true ); + } + + + /** + * Update existing user's attributes with the input entity. Null or empty attributes will be ignored. + * This method will ignore userId or password as input. The former is not allowed and latter is performed by other + * methods in this class. + * Other User entity input data can be changed and will also be validated beforehand to ensure that: + * orgUnitId is valid, roles (optional) are valid, reasonability checks will be performed on all of the populated fields. + * + * @param entity User entity contains data targeted for insertion. + * @param validate if false will skip the validations described above. + * @return User entity copy of input + * @throws SecurityException in the event of data validation or DAO system error. + */ + /** + * Update existing user's attributes with the input entity. Null or empty attributes will be ignored. + * This method will ignore userId or password as input. The former is not allowed and latter is performed by other + * methods in this class. + * Other User entity input data can be changed and will also be validated beforehand to ensure that: + * orgUnitId is valid, roles (optional) are valid, reasonability checks will be performed on all of the populated fields. + * + * @param entity User entity contains data targeted for insertion. + * @param validate if false will skip the validations described above. + * @return User entity copy of input + * @throws SecurityException in the event of data validation or DAO system error. + */ + User update( User entity, boolean validate ) throws SecurityException + { + if ( validate ) + { + // Ensure the input data is valid. + validate( entity, true ); + } + entity = uDao.update( entity ); + return entity; + } + + + /** + * Method performs a "soft" delete. It disables User entity and flags as "deleted". User must exist in directory + * prior to making this call. + * + * @param user Contains the userId of the user targeted for deletion. + * @return String contains user DN + * @throws SecurityException in the event of data validation or DAO system error. + */ + String softDelete( User user ) throws SecurityException + { + // Ensure this user isn't listed in Fortress config as a system user that can't be removed via API. + // Is there a match between this userId and a Fortress system user? + User checkUser = read( user, true ); + if ( ObjUtil.isNotNullOrEmpty( checkUser.isSystem() ) && checkUser.isSystem() ) + { + String warning = "softDelete userId [" + user.getUserId() + + "] can't be removed due to policy violation, rc=" + GlobalErrIds.USER_PLCY_VIOLATION; + throw new SecurityException( GlobalErrIds.USER_PLCY_VIOLATION, warning ); + } + user.setDescription( "DELETED" ); + User outUser = uDao.update( user ); + return outUser.getDn(); + } + + + /** + * This method performs a "hard" delete. It completely removes all data associated with this user from the directory. + * User entity must exist in directory prior to making this call else exception will be thrown. + * + * @param user Contains the userid of the user targeted for deletion. + * @return String contains user DN + * @throws SecurityException in the event of data validation or DAO system error. + */ + String delete( User user ) throws SecurityException + { + // Ensure this user isn't listed in Fortress config as a system user that can't be removed via API. + // Is there a match between this userId and a Fortress system user? + User checkUser = read( user, true ); + if ( ObjUtil.isNotNullOrEmpty( checkUser.isSystem() ) && checkUser.isSystem() ) + { + String warning = "delete userId [" + user.getUserId() + + "] can't be removed due to policy violation, rc=" + GlobalErrIds.USER_PLCY_VIOLATION; + throw new SecurityException( GlobalErrIds.USER_PLCY_VIOLATION, warning ); + } + return uDao.remove( user ); + } + + + /** + * Removes the user's association from OpenLDAP password policy. Once this association is removed, the User + * password policy will default to that which is default for ldap server. + * + * @param user contains the userId for target user. + * @throws SecurityException in the event of DAO error. + */ + void deletePwPolicy( User user ) throws SecurityException + { + uDao.deletePwPolicy( user ); + } + + + /** + * This method performs authentication only. It does not activate RBAC roles in session. It will evaluate + * password policies. + * + * @param user Contains the userid of the user signing on along with password. + * @return Session object will be returned if authentication successful. This will not contain user's roles. + * @throws SecurityException in the event of data validation failure, security policy violation or DAO error. + */ + Session authenticate( User user ) throws SecurityException + { + Session session; + session = uDao.checkPassword( user ); + + if ( !session.isAuthenticated() ) + { + String info = "UserP.authenticate failed for userId [" + user.getUserId() + "] reason code [" + + session.getErrorId() + "] msg [" + session.getMsg() + "]"; + throw new PasswordException( session.getErrorId(), info ); + } + + CUtil.validateConstraints( session, CUtil.ConstraintType.USER, false ); + + return session; + } + + + /** + * CreateSession + *

+ * This method is called by AccessMgr and is not intended for use outside Fortress core. The successful + * result is Session object that contains target user's RBAC and Admin role activations. In addition to checking + * user password validity it will apply configured password policy checks. Method may also store parms passed in for + * audit trail.. + *

    + *
  • authenticate user password + *
  • password policy evaluation with OpenLDAP PwPolicy + *
  • evaluate temporal constraints on User and UserRole entities. + *
  • allow selective role activations into User RBAC Session. + *
  • require valid password if trusted == false. + *
  • will disallow any user who is locked out due to OpenLDAP pw policy, regardless of trusted flag being set as parm on API. + *
  • return User's RBAC Session containing User and UserRole attributes. + *
  • throw a SecurityException for authentication failures, other policy violations, data validation errors or system failure. + *
+ *

+ *

+ * The function is valid if and only if: + *

    + *
  • the user is a member of the USERS data set + *
  • the password is supplied (unless trusted). + *
  • the (optional) active role set is a subset of the roles authorized for that user. + *
+ *

+ *

+ * The User parm contains the following (* indicates required) + *

    + *
  • String userId* + *
  • char[] password + *
  • List userRoles contains a list of RBAC role names authorized for user and targeted for activation within this session. + *
  • List userAdminRoles contains a list of Admin role names authorized for user and targeted for activation. + *
  • Properties logonProps collection of auditable name/value pairs to store. For example hostname:myservername or ip:192.168.1.99 + *
+ *

+ *

+ * Notes: + *

    + *
  • roles that violate Dynamic Separation of Duty Relationships will not be activated into session. + *
  • role activations will proceed in same order as supplied to User entity setter. + *
+ *

+ * + * @param user Contains userId, password (optional if "trusted"), optional User RBAC Roles: List rolesToBeActivated., optional User Admin Roles: List adminRolesToBeActivated. + * @param trusted if true password is not required. + * @return Session object will contain authentication result code, RBAC and Admin role activations, OpenLDAP pw policy output and more. + * @throws SecurityException in the event of data validation failure, security policy violation or DAO error. + */ + Session createSession( User user, boolean trusted ) throws SecurityException + { + Session session; + if ( trusted ) + { + // Create the impl session without authentication of password. + session = createSessionTrusted( user ); + // Check user temporal constraints. This op usually performed during authentication. + CUtil.validateConstraints( session, CUtil.ConstraintType.USER, false ); + } + else + { + // Create the impl session if the user authentication succeeds: + VUtil.assertNotNullOrEmpty( user.getPassword(), GlobalErrIds.USER_PW_NULL, CLS_NM + ".createSession" ); + session = createSession( user ); + } + // Did the caller pass in a set of roles for selective activation? + if ( ObjUtil.isNotNullOrEmpty( user.getRoles() ) ) + { + // Process selective activation of user's RBAC roles into session: + List rlsActual = session.getRoles(); + List rlsFinal = new ArrayList<>(); + session.setRoles( rlsFinal ); + // Activate only the intersection between assigned and roles passed into this method: + for ( UserRole role : user.getRoles() ) + { + int indx = rlsActual.indexOf( role ); + if ( indx != -1 ) + { + UserRole candidateRole = rlsActual.get( indx ); + rlsFinal.add( candidateRole ); + } + } + } + // Check role temporal constraints + activate roles: + CUtil.validateConstraints( session, CUtil.ConstraintType.ROLE, true ); + return session; + } + + + /** + * Called internal to this class only. Will do all of the session activations of the public method + * in addition to the password validation. + * + * @param inUser Contains userId that represents rDn of node in ldap directory. + * @return Session object will contain authentication result code, RBAC and Admin role activations, OpenLDAP pw policy output and more. + * @throws SecurityException in the event of data validation failure, security policy violation or DAO error. + */ + private Session createSession( User inUser ) + throws SecurityException + { + // read user entity: + User user = read( inUser, true ); + user.setContextId( inUser.getContextId() ); + + // authenticate password, check pw policies and validate user temporal constraints: + Session session = authenticate( inUser ); + + // Set the user entity into the session object: + session.setUser( user ); + return session; + } + + + /** + * Trusted session creation method called internal to this class only. Will do all of the session activations of the public method + * + * @param inUser Contains userId that represents rDn of node in ldap directory. + * @return Session object will contain authentication result code, RBAC and Admin role activations, OpenLDAP pw policy output and more. + * @throws SecurityException in the event of data validation failure, security policy violation or DAO error. + */ + private Session createSessionTrusted( User inUser ) + throws SecurityException + { + User user = read( inUser, true ); + user.setContextId( inUser.getContextId() ); + + if ( user.isLocked() ) + { + String warning = "createSession failed for userId [" + inUser.getUserId() + + "] reason user is locked"; + LOG.warn( warning ); + throw new SecurityException( GlobalErrIds.USER_LOCKED_BY_CONST, warning ); + } + + Session session = new ObjectFactory().createSession(); + session.setUserId( inUser.getUserId() ); + // Set this flag to false because user's password was not authenticated. + session.setAuthenticated( false ); + session.setUser( user ); + return session; + } + + + /** + * Method will set the OpenLDAP pwlocked attribute which will lock user from being able to signon to the system. + * + * @param user Contains userId that represents rDn of node in ldap directory. + * @throws SecurityException in the event of DAO error. + */ + void lock( User user ) throws SecurityException + { + uDao.lock( user ); + } + + + /** + * Method will reset the OpenLDAP pwlocked attribute which will unlock user and allow to signon to the system. + * + * @param user Contains userId that represents rDn of node in ldap directory. + * @throws SecurityException in the event of DAO error. + */ + void unlock( User user ) throws SecurityException + { + uDao.unlock( user ); + } + + + /** + * Method will change the user's password and validate user's pw policy in OpenLDAP. + * + * @param entity contains userId and old password. + * @param newPassword contains the new password which must pass the password policy constraints. + * @throws SecurityException in the event of data validation failure, password policy violation or DAO error. + */ + void changePassword( User entity, char[] newPassword ) throws SecurityException + { + String userId = entity.getUserId(); + boolean result = uDao.changePassword( entity, newPassword ); + if ( !result ) + { + LOG.warn( "changePassword failed for user [{}]", userId ); + } + } + + + /** + * Perform password reset on user entity. This will change the User password and set the reset flag + * in OpenLDAP will will force the user to change their password at next logon time. + * + * @param user contains the userId and the new password. + * @throws SecurityException in the event of DAO error. + */ + void resetPassword( User user ) throws SecurityException + { + uDao.resetUserPassword( user ); + } + + + /** + * This command assigns a user to a role. + *

+ *

    + *
  • The command is valid if and only if: + *
  • The user is a member of the USERS data set + *
  • The role is a member of the ROLES data set + *
  • The user is not already assigned to the role + *
  • The SSD constraints are satisfied after assignment. + *
+ *

+ *

+ * Successful completion of this op, the following occurs: + *

+ *
    + *
  • User entity (resides in people container) has role assignment added to aux object class attached to actual user record. + *
  • Role entity (resides in role container) has userId added as role occupant. + *
  • (optional) Temporal constraints may be associated with ftUserAttrs aux object class based on: + *
      + *
    • timeout - number in seconds of session inactivity time allowed. + *
    • beginDate - YYYYMMDD - determines date when role may be activated. + *
    • endDate - YYMMDD - indicates latest date role may be activated. + *
    • beginLockDate - YYYYMMDD - determines beginning of enforced inactive status + *
    • endLockDate - YYMMDD - determines end of enforced inactive status. + *
    • beginTime - HHMM - determines begin hour role may be activated in user's session. + *
    • endTime - HHMM - determines end hour role may be activated in user's session.* + *
    • dayMask - 1234567, 1 = Sunday, 2 = Monday, etc - specifies which day of week role may be activated. + *
    + *
+ * + * @param uRole entity contains userId and role name for targeted assignment. + * @return String containing the user's DN. This value is used to update the "roleOccupant" attribute on associated role entity. + * @throws SecurityException in the event data error in user or role objects or system error. + */ + String assign( UserRole uRole ) throws SecurityException + { + validate( uRole ); + // "assign" custom Fortress role data, i.e. temporal constraints, onto the user node: + return uDao.assign( uRole ); + } + + + /** + * This command deletes the assignment of the User from the Role entities. The command is + * valid if and only if the user is a member of the USERS data set, the role is a member of + * the ROLES data set, and the user is assigned to the role. + * Any sessions that currently have this role activated will not be effected. + * Successful completion includes: + * User entity in USER data set has role assignment removed. + * Role entity in ROLE data set has userId removed as role occupant. + * (optional) Temporal constraints will be removed from user aux object if set prior to call. + * + * @param uRole entity contains userId and RBAC Role name for targeted assignment. + * @return String containing the user's DN. This value is used to remove the "roleOccupant" attribute on associated RBAC Role entity. + * @throws SecurityException - in the event data error in user or role objects or system error. + */ + String deassign( UserRole uRole ) throws SecurityException + { + validate( uRole ); + // "deassign" custom Fortress role data from the user's node: + return uDao.deassign( uRole ); + } + + + /** + * This command assigns a user to an admin role. + * Successful completion of this op, the following occurs: + *

+ *
    + *
  • User entity (resides in people container) has role assignment added to aux object class attached to actual user record. + *
  • AdminRole entity (resides in admin role container) has userId added as role occupant. + *
  • (optional) Temporal constraints may be associated with ftUserAttrs aux object class based on: + *
      + *
    • timeout - number in seconds of session inactivity time allowed. + *
    • beginDate - YYYYMMDD - determines date when role may be activated. + *
    • endDate - YYMMDD - indicates latest date role may be activated. + *
    • beginLockDate - YYYYMMDD - determines beginning of enforced inactive status + *
    • endLockDate - YYMMDD - determines end of enforced inactive status. + *
    • beginTime - HHMM - determines begin hour role may be activated in user's session. + *
    • endTime - HHMM - determines end hour role may be activated in user's session.* + *
    • dayMask - 1234567, 1 = Sunday, 2 = Monday, etc - specifies which day of week role may be activated. + *
    + *
+ * + * @param uRole entity contains userId and Admin Role name for targeted assignment. + * @return String containing the user's DN. This value is used to update the "roleOccupant" attribute on associated Admin Role entity. + * @throws SecurityException in the event data error in user or role objects or system error. + */ + String assign( UserAdminRole uRole ) throws SecurityException + { + validate( uRole ); + // Assign custom Fortress role data, i.e. temporal constraints, onto the user node: + return uDao.assign( uRole ); + } + + + /** + * This method removes assigned admin role from user entity. Both user and admin role entities must exist and have role relationship + * before calling this method. + * Successful completion: + * del Role to User assignment in User data set + * AND + * User to Role assignment in Admin Role data set. + * + * @param uRole entity contains userId and Admin Role name for targeted assignment. + * @return String containing the user's DN. This value is used to remove the "roleOccupant" attribute on associated Admin Role entity. + * @throws SecurityException - in the event data error in user or role objects or system error. + */ + String deassign( UserAdminRole uRole ) throws SecurityException + { + validate( uRole ); + // Deassign custom Fortress role data from the user's node: + return uDao.deassign( uRole ); + } + + + /** + * Ensure that the passed in variable has the correct fields set. + * + * @param uRole - name and userId must be checked. + * @throws ValidationException - if either are null or empty. + */ + private void validate( UserRole uRole ) throws ValidationException + { + if ( !StringUtils.isNotEmpty( uRole.getUserId() ) ) + { + throw new ValidationException( GlobalErrIds.USER_ID_NULL, CLS_NM + ".validate userId is NULL" ); + } + if ( !StringUtils.isNotEmpty( uRole.getName() ) ) + { + throw new ValidationException( GlobalErrIds.ROLE_NM_NULL, CLS_NM + ".validate name is NULL" ); + } + } + + + /** + * Method will perform various validations to ensure the integrity of the User entity targeted for insertion + * or updating in directory. For example the ou attribute will be "read" from the OrgUnit dataset to ensure + * that it is valid. Data reasonability checks will be performed on all non-null attributes. + * This method will also copy the source constraints to target entity iff the target input entity does not have set + * prior to calling. + * + * @param entity User entity contains data targeted for insertion or update. The input role constraints will be accepted. + * @param isUpdate if true update operation is being performed which specifies a different set of targeted attributes. + * @throws SecurityException in the event of data validation error or DAO error on Org validation. + */ + private void validate( User entity, boolean isUpdate ) + throws SecurityException + { + if ( !isUpdate ) + { + // the UserId attribute is required on User: + VUtil.userId( entity.getUserId() ); + + // the cn attribute is optional as input. entity will default to userId if cn not set by caller on add: + if ( StringUtils.isNotEmpty( entity.getCn() ) ) + { + VUtil.safeText( entity.getCn(), GlobalIds.CN_LEN ); + } + // the sn attribute is optional as input. entity will default to userId if sn not set by caller on add: + if ( StringUtils.isNotEmpty( entity.getSn() ) ) + { + VUtil.safeText( entity.getSn(), GlobalIds.SN_LEN ); + } + // password is not required on user object but user cannot execute AccessMgr or DelAccessMgr methods w/out pw. + if ( ObjUtil.isNotNullOrEmpty( entity.getPassword() ) ) + { + VUtil.password( entity.getPassword() ); + } + // the OU attribute is required: + if ( !StringUtils.isNotEmpty( entity.getOu() ) ) + { + String error = "OU validation failed, null or empty value"; + throw new ValidationException( GlobalErrIds.ORG_NULL_USER, error ); + } + VUtil.orgUnit( entity.getOu() ); + // ensure ou exists in the OS-U pool: + OrgUnit ou = new OrgUnit( entity.getOu(), OrgUnit.Type.USER ); + ou.setContextId( entity.getContextId() ); + if ( !orgUnitP.isValid( ou ) ) + { + String error = "validate detected invalid orgUnit name [" + entity.getOu() + + "] adding user with userId [" + entity.getUserId() + "]"; + throw new ValidationException( GlobalErrIds.USER_OU_INVALID, error ); + } + // description attribute is optional: + if ( StringUtils.isNotEmpty( entity.getDescription() ) ) + { + VUtil.description( entity.getDescription() ); + } + } + else + { + // on User update, all attributes are optional: + if ( StringUtils.isNotEmpty( entity.getCn() ) ) + { + VUtil.safeText( entity.getCn(), GlobalIds.CN_LEN ); + } + if ( StringUtils.isNotEmpty( entity.getSn() ) ) + { + VUtil.safeText( entity.getSn(), GlobalIds.SN_LEN ); + } + if ( ObjUtil.isNotNullOrEmpty( entity.getPassword() ) ) + { + VUtil.password( entity.getPassword() ); + } + if ( StringUtils.isNotEmpty( entity.getOu() ) ) + { + VUtil.orgUnit( entity.getOu() ); + // ensure ou exists in the OS-U pool: + OrgUnit ou = new OrgUnit( entity.getOu(), OrgUnit.Type.USER ); + ou.setContextId( entity.getContextId() ); + if ( !orgUnitP.isValid( ou ) ) + { + String error = "validate detected invalid orgUnit name [" + entity.getOu() + + "] updating user wth userId [" + entity.getUserId() + "]"; + throw new ValidationException( GlobalErrIds.USER_OU_INVALID, error ); + } + } + if ( StringUtils.isNotEmpty( entity.getDescription() ) ) + { + VUtil.description( entity.getDescription() ); + } + } + + // 1 OpenLDAP password policy name must be valid if set: + if ( StringUtils.isNotEmpty( entity.getPwPolicy() ) ) + { + PwPolicy policy = new PwPolicy( entity.getPwPolicy() ); + policy.setContextId( entity.getContextId() ); + if ( !policyP.isValid( policy ) ) + { + String error = "validate detected invalid OpenLDAP policy name [" + entity.getPwPolicy() + + "] for userId [" + entity.getUserId() + + "]. Assignment is optional for User but must be valid if specified."; + throw new ValidationException( GlobalErrIds.USER_PW_PLCY_INVALID, error ); + } + } + + // 2 Validate constraints on User object: + CUtil.validate( entity ); + + // 3 Validate or copy constraints on RBAC roles: + if ( ObjUtil.isNotNullOrEmpty( entity.getRoles() ) ) + { + RoleP rp = new RoleP(); + List roles = entity.getRoles(); + for ( UserRole ure : roles ) + { + Role inRole = new Role( ure.getName() ); + inRole.setContextId( entity.getContextId() ); + Role role = rp.read( inRole ); + CUtil.validateOrCopy( role, ure ); + } + } + + // 4 Validate and copy constraints on Administrative roles: + if ( ObjUtil.isNotNullOrEmpty( entity.getAdminRoles() ) ) + { + List uRoles = entity.getAdminRoles(); + for ( UserAdminRole uare : uRoles ) + { + AdminRole inRole = new AdminRole( uare.getName() ); + inRole.setContextId( entity.getContextId() ); + AdminRole outRole = admRoleP.read( inRole ); + CUtil.validateOrCopy( outRole, uare ); + + // copy the ARBAC AdminRole attributes to UserAdminRole: + AttrHelper.copyAdminAttrs( outRole, uare ); + } + } + } +} \ 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/UsoUtil.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/directory/fortress/core/impl/UsoUtil.java b/src/main/java/org/apache/directory/fortress/core/impl/UsoUtil.java new file mode 100755 index 0000000..db42ef8 --- /dev/null +++ b/src/main/java/org/apache/directory/fortress/core/impl/UsoUtil.java @@ -0,0 +1,310 @@ +/* + * 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 java.util.Set; +import java.util.TreeSet; +import java.util.concurrent.locks.ReadWriteLock; + +import org.apache.commons.lang.StringUtils; +import org.apache.directory.fortress.core.model.Graphable; +import org.apache.directory.fortress.core.model.Hier; +import org.apache.directory.fortress.core.model.OrgUnit; +import org.apache.directory.fortress.core.model.Relationship; +import org.apache.directory.fortress.core.util.ObjUtil; +import org.jgrapht.graph.SimpleDirectedGraph; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +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.util.cache.Cache; +import org.apache.directory.fortress.core.util.cache.CacheMgr; + + +/** + * This utility wraps {@link HierUtil} methods to provide hierarchical functionality using the {@link org.apache.directory.fortress.core.model.OrgUnit} data set for User type {@link org.apache.directory.fortress.core.model.OrgUnit.Type#USER}. + * The {@code cn=Hierarchies, ou=OS-U} data contains User OU pools is stored within a data cache, {@link #usoCache}, contained within this class. The parent-child edges are contained in LDAP, + * in {@code ftParents} attribute. The ldap data is retrieved {@link OrgUnitP#getAllDescendants(org.apache.directory.fortress.core.model.OrgUnit)} and loaded into {@code org.jgrapht.graph.SimpleDirectedGraph}. + * The graph... + *
    + *
  1. is stored as singleton in this class with vertices of {@code String}, and edges, as {@link org.apache.directory.fortress.core.model.Relationship}s
  2. + *
  3. utilizes open source library, see JGraphT.
  4. + *
  5. contains a general hierarchical data structure i.e. allows multiple inheritance with parents.
  6. + *
  7. is a simple directed graph thus does not allow cycles.
  8. + *
+ * After update is performed to ldap, the singleton is refreshed with latest info. + *

+ * Static methods on this class are intended for use by other Fortress classes, i.e. {@link DelAdminMgrImpl}. + * and cannot be directly invoked by outside programs. + *

+ * This class contains singleton that can be updated but is thread safe. + *

+ * + * @author Apache Directory Project + */ +public final class UsoUtil +{ + private static final Cache usoCache; + private static final OrgUnitP orgUnitP = new OrgUnitP(); + private static final String CLS_NM = UsoUtil.class.getName(); + private static final Logger LOG = LoggerFactory.getLogger( CLS_NM ); + + /** + * Initialize the User OU hierarchies. This will read the {@link org.apache.directory.fortress.core.model.Hier} data set from ldap and load into + * the JGraphT simple digraph that referenced statically within this class. + */ + static + { + CacheMgr cacheMgr = CacheMgr.getInstance(); + usoCache = cacheMgr.getCache( "fortress.uso" ); + } + + /** + * Private constructor + * + */ + private UsoUtil() + { + } + + /** + * Recursively traverse the {@link org.apache.directory.fortress.core.model.OrgUnit} graph and return all of the descendants of a given parent {@link org.apache.directory.fortress.core.model.OrgUnit#name}. + * + * @param name {@link org.apache.directory.fortress.core.model.OrgUnit#name} on 'ftOrgUnit' object class. + * @return Set of names of descendants {@link org.apache.directory.fortress.core.model.OrgUnit}s of given parent. + */ + static Set getDescendants( String name, String contextId ) + { + return HierUtil.getDescendants( name, getGraph( contextId ) ); + } + + + /** + * Recursively traverse the {@link org.apache.directory.fortress.core.model.OrgUnit.Type#USER} graph and return all of the ascendants of a given child ou. + * + * @param name maps to logical {@link org.apache.directory.fortress.core.model.OrgUnit#name} on 'ftOrgUnit' object class. + * @return Set of ou names that are ascendants of given child. + */ + static Set getAscendants( String name, String contextId ) + { + return HierUtil.getAscendants( name, getGraph( contextId ) ); + } + + + /** + * Traverse one level of the {@link org.apache.directory.fortress.core.model.OrgUnit} graph and return all of the children (direct descendants) of a given parent {@link org.apache.directory.fortress.core.model.OrgUnit#name}. + * + * @param name {@link org.apache.directory.fortress.core.model.OrgUnit#name} maps on 'ftOrgUnit' object class. + * @return Set of names of children {@link org.apache.directory.fortress.core.model.OrgUnit}s of given parent. + */ + public static Set getChildren( String name, String contextId ) + { + return HierUtil.getChildren( name, getGraph( contextId ) ); + } + + + /** + * Traverse one level of the {@link org.apache.directory.fortress.core.model.OrgUnit.Type#USER} graph and return all of the parents (direct ascendants) of a given child ou. + * + * @param name maps to logical {@link org.apache.directory.fortress.core.model.OrgUnit#name} on 'ftOrgUnit' object class. + * @return Set of ou names that are parents of given child. + */ + static Set getParents( String name, String contextId ) + { + return HierUtil.getParents( name, getGraph( contextId ) ); + } + + + /** + * Recursively traverse the {@link org.apache.directory.fortress.core.model.OrgUnit.Type#USER} graph and return number of children a given parent ou has. + * + * @param name maps to logical {@link org.apache.directory.fortress.core.model.OrgUnit#name} on 'ftOrgUnit' object class. + * @return int value contains the number of children of a given parent ou. + */ + static int numChildren( String name, String contextId ) + { + return HierUtil.numChildren( name, getGraph( contextId ) ); + } + + + /** + * Return Set of {@link org.apache.directory.fortress.core.model.OrgUnit#name}s ascendants contained within {@link org.apache.directory.fortress.core.model.OrgUnit.Type#USER}. + * + * @param ous contains list of {@link org.apache.directory.fortress.core.model.OrgUnit}s. + * @return contains Set of all descendants. + */ + static Set getInherited( List ous, String contextId ) + { + // create Set with case insensitive comparator: + Set iOUs = new TreeSet<>( String.CASE_INSENSITIVE_ORDER ); + + if ( ObjUtil.isNotNullOrEmpty( ous ) ) + { + for ( OrgUnit ou : ous ) + { + String name = ou.getName(); + iOUs.add( name ); + Set parents = HierUtil.getAscendants( name, getGraph( contextId ) ); + + if ( ObjUtil.isNotNullOrEmpty( parents ) ) + { + iOUs.addAll( parents ); + } + } + } + + return iOUs; + } + + + /** + * This api is used by {@link DelAdminMgrImpl} to determine parentage for User OU processing. + * It calls {@link HierUtil#validateRelationship(org.jgrapht.graph.SimpleDirectedGraph, String, String, boolean)} to evaluate three OU relationship expressions: + *

    + *
  1. If child equals parent
  2. + *
  3. If mustExist true and parent-child relationship exists
  4. + *
  5. If mustExist false and parent-child relationship does not exist
  6. + *
+ * Method will throw {@link org.apache.directory.fortress.core.ValidationException} if rule check fails meaning caller failed validation + * attempt to add/remove hierarchical relationship failed. + * + * @param child contains {@link org.apache.directory.fortress.core.model.OrgUnit#name} of child. + * @param parent contains {@link org.apache.directory.fortress.core.model.OrgUnit#name} of parent. + * @param mustExist boolean is used to specify if relationship must be true. + * @throws org.apache.directory.fortress.core.ValidationException + * in the event it fails one of the 3 checks. + */ + static void validateRelationship( OrgUnit child, OrgUnit parent, boolean mustExist ) + throws ValidationException + { + HierUtil.validateRelationship( getGraph( child.getContextId() ), child.getName(), parent.getName(), mustExist ); + } + + + /** + * This api allows synchronized access to allow updates to hierarchical relationships. + * Method will update the hierarchical data set and reload the JGraphT simple digraph with latest. + * + * @param contextId maps to sub-tree in DIT, for example ou=contextId, dc=jts, dc = com. + * @param relationship contains parent-child relationship targeted for addition. + * @param op used to pass the ldap op {@link org.apache.directory.fortress.core.model.Hier.Op#ADD}, {@link org.apache.directory.fortress.core.model.Hier.Op#MOD}, {@link org.apache.directory.fortress.core.model.Hier.Op#REM} + * @throws org.apache.directory.fortress.core.SecurityException in the event of a system error. + */ + static void updateHier( String contextId, Relationship relationship, Hier.Op op ) throws SecurityException + { + HierUtil.updateHier( getGraph( contextId ), relationship, op ); + } + + + /** + * Read this ldap record,{@code cn=Hierarchies, ou=OS-P} into this entity, {@link Hier}, before loading into this collection class,{@code org.jgrapht.graph.SimpleDirectedGraph} + * using 3rd party lib, JGraphT. + * + * @param contextId maps to sub-tree in DIT, for example ou=contextId, dc=jts, dc = com. + * @return handle to simple digraph containing user ou hierarchies. + */ + private static SimpleDirectedGraph loadGraph( String contextId ) + { + Hier inHier = new Hier( Hier.Type.ROLE ); + inHier.setContextId( contextId ); + LOG.info( "loadGraph initializing USO context [{}]", inHier.getContextId() ); + + List descendants = null; + try + { + OrgUnit orgUnit = new OrgUnit(); + orgUnit.setType( OrgUnit.Type.USER ); + orgUnit.setContextId( contextId ); + descendants = orgUnitP.getAllDescendants( orgUnit ); + } + catch ( SecurityException se ) + { + LOG.info( "loadGraph caught SecurityException={}", se ); + } + + Hier hier = HierUtil.loadHier( contextId, descendants ); + SimpleDirectedGraph graph; + + graph = HierUtil.buildGraph( hier ); + usoCache.put( getKey( contextId ), graph ); + + return graph; + } + + + /** + * + * @return handle to simple digraph containing user ou hierarchies. + */ + private static SimpleDirectedGraph getGraph( String contextId ) + { + ReadWriteLock hierLock = HierUtil.getLock( contextId, HierUtil.Type.USO ); + String key = getKey( contextId ); + + try + { + hierLock.readLock().lock(); + SimpleDirectedGraph graph = ( SimpleDirectedGraph ) usoCache + .get( key ); + + if ( graph == null ) + { + try + { + hierLock.readLock().unlock(); + hierLock.writeLock().lock(); + + // TODO: determine why this (code that was commented out) creates a deadlock: + //graph = ( SimpleDirectedGraph ) usoCache.get( key ); + + //if ( graph == null ) + //{ + graph = loadGraph( contextId ); + //} + hierLock.readLock().lock(); + } + finally + { + hierLock.writeLock().unlock(); + } + } + + return graph; + } + finally + { + hierLock.readLock().unlock(); + } + } + + + private static String getKey( String contextId ) + { + String key = HierUtil.Type.USO.toString(); + if ( StringUtils.isNotEmpty( contextId ) && !contextId.equalsIgnoreCase( GlobalIds.NULL ) ) + { + key += ":" + contextId; + } + return key; + } +} \ 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/package.html ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/directory/fortress/core/impl/package.html b/src/main/java/org/apache/directory/fortress/core/impl/package.html new file mode 100755 index 0000000..f8b2212 --- /dev/null +++ b/src/main/java/org/apache/directory/fortress/core/impl/package.html @@ -0,0 +1,55 @@ + + + + Package Documentation for org.apache.directory.fortress.core.impl + + +

+

    +
  1. This package provides data entities and apis that adhere to standards like RBAC
  2. +
  3. This package provides data entities and APIs that adhere to ARBAC02 model to provide delegated administration capabilities.
  4. +
  5. This package provides data entities and APIs to interrogate OpenLDAP's slapd access log to obtain fortress audit trail and historical events.
  6. +
  7. This package provides CRUD APIs for storing config data on the ldap server.
  8. +
  9. This package contains APIs to perform create and teardown the ldap group node.
  10. +
  11. This package uses JGraphT to provide hierarchical functionality that is reused within several other packages in the fortress system.
  12. +
+

+

+ The org.apache.directory.fortress.core.impl package data entities may be manipulated by outside + programs but the apis contained within this package are for fortress use only. + The entities include {@link org.apache.directory.fortress.core.model.User User},{@link org.apache.directory.fortress.core.model.Role Role}, {@link org.apache.directory.fortress.core.model.PermObj PermObj}, {@link org.apache.directory.fortress.core.model.Permission Permission}, and more. + See the corresponding javadoc contained with this package for more info. +

+

Fortress Manager APIs implemented in this package

+
    +
  1. AccessMgrImpl - This implements using LDAP the runtime access control operations on objects that are provisioned RBAC entities that reside in LDAP directory.
  2. +
  3. AdminMgrImpl - This implements using LDAP the administrative functions to provision Fortress RBAC entities into the LDAP directory.
  4. +
  5. ReviewMgrImpl - This implements using LDAP the administrative review functions on already provisioned Fortress RBAC entities that reside in LDAP directory.
  6. +
  7. DelegatedAccessMgrImpl - This implements using LDAP the APIs for performing runtime delegated access control operations on objects that are provisioned Fortress ARBAC02 entities that reside in LDAP directory.
  8. +
  9. DelegatedAdminMgrImpl - This implements using LDAP the ARBAC02 DelegatedAdminMgr interface for performing policy administration of Fortress ARBAC entities that reside in LDAP directory.
  10. +
  11. DelegatedReviewMgrImpl - This implements using LDAP the ARBAC02 DelegatedReviewMgr interface for performing policy interrogation of provisioned Fortress ARBAC02 entities that reside in LDAP directory.
  12. +
  13. PwPolicyMgrImpl - Performs CRUD on OpenLDAP password policies stored in directory.
  14. +
  15. AuditMgrImpl - Interrogates Fortress audit data stored in OpenLDAP.
  16. +
  17. ConfigMgrImpl - CRUD for Fortress config objects.
  18. +
  19. GroupMgrImpl - CRUD for LDAP group objects..
  20. +
+ + \ 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/ldap/ApacheDsDataProvider.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/directory/fortress/core/ldap/ApacheDsDataProvider.java b/src/main/java/org/apache/directory/fortress/core/ldap/ApacheDsDataProvider.java index a45995f..148b6a9 100644 --- a/src/main/java/org/apache/directory/fortress/core/ldap/ApacheDsDataProvider.java +++ b/src/main/java/org/apache/directory/fortress/core/ldap/ApacheDsDataProvider.java @@ -88,8 +88,8 @@ import org.slf4j.LoggerFactory; /** * Abstract class contains methods to perform low-level entity to ldap persistence. These methods are called by the - * Fortress DAO's, i.e. {@link org.apache.directory.fortress.core.rbac.UserDAO}. {@link org.apache.directory.fortress.core.rbac.RoleDAO}, - * {@link org.apache.directory.fortress.core.rbac.PermDAO}, .... + * Fortress DAO's, i.e. {@link org.apache.directory.fortress.core.impl.UserDAO}. {@link org.apache.directory.fortress.core.impl.RoleDAO}, + * {@link org.apache.directory.fortress.core.impl.PermDAO}, .... * These are low-level data utilities, very little if any data validations are performed here. *

* This class is thread safe. http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/ba64d26a/src/main/java/org/apache/directory/fortress/core/ldap/group/GroupDAO.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/directory/fortress/core/ldap/group/GroupDAO.java b/src/main/java/org/apache/directory/fortress/core/ldap/group/GroupDAO.java deleted file mode 100755 index 793ed3d..0000000 --- a/src/main/java/org/apache/directory/fortress/core/ldap/group/GroupDAO.java +++ /dev/null @@ -1,508 +0,0 @@ -/* - - * 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.ldap.group; - - -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.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.fortress.core.model.Group; -import org.apache.directory.ldap.client.api.LdapConnection; -import org.apache.directory.fortress.core.FinderException; -import org.apache.directory.fortress.core.model.ObjectFactory; -import org.apache.directory.fortress.core.UpdateException; -import org.apache.directory.fortress.core.util.Config; -import org.apache.directory.fortress.core.ldap.ApacheDsDataProvider; -import org.apache.directory.fortress.core.model.User; -import org.apache.directory.fortress.core.util.attr.AttrHelper; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.apache.directory.fortress.core.CreateException; -import org.apache.directory.fortress.core.GlobalErrIds; -import org.apache.directory.fortress.core.GlobalIds; -import org.apache.directory.fortress.core.RemoveException; - -import java.util.ArrayList; -import java.util.List; - - -/** - * Contains the Group node for LDAP Directory Information Tree. - * This class is thread safe. - * - * @author Apache Directory Project - */ -final class GroupDAO extends ApacheDsDataProvider -{ - private static final String CLS_NM = GroupDAO.class.getName(); - private static final Logger LOG = LoggerFactory.getLogger( CLS_NM ); - private static final String GROUP_OBJECT_CLASS = "group.objectclass"; - private static final String GROUP_OBJECT_CLASS_IMPL = Config.getProperty( GROUP_OBJECT_CLASS ); - private static final String GROUP_PROTOCOL_ATTR = "group.protocol"; - private static final String GROUP_PROTOCOL_ATTR_IMPL = Config.getProperty( GROUP_PROTOCOL_ATTR ); - private static final String GROUP_PROPERTY_ATTR = "group.properties"; - private static final String GROUP_PROPERTY_ATTR_IMPL = Config.getProperty( GROUP_PROPERTY_ATTR ); - private static final String GROUP_OBJ_CLASS[] = - { SchemaConstants.TOP_OC, GROUP_OBJECT_CLASS_IMPL }; - private static final String[] GROUP_ATRS = - { - SchemaConstants.CN_AT, - SchemaConstants.DESCRIPTION_AT, - GROUP_PROTOCOL_ATTR_IMPL, - GROUP_PROPERTY_ATTR_IMPL, - SchemaConstants.MEMBER_AT }; - - - /** - * Package private default constructor. - */ - GroupDAO() - { - } - - - /** - * @param group - * @throws org.apache.directory.fortress.core.CreateException - * - */ - Group create( Group group ) throws CreateException - { - LdapConnection ld = null; - String nodeDn = getDn( group.getName(), group.getContextId() ); - - try - { - LOG.debug( "create group dn [{}]", nodeDn ); - Entry myEntry = new DefaultEntry( nodeDn ); - myEntry.add( SchemaConstants.OBJECT_CLASS_AT, GROUP_OBJ_CLASS ); - myEntry.add( SchemaConstants.CN_AT, group.getName() ); - myEntry.add( GROUP_PROTOCOL_ATTR_IMPL, group.getProtocol() ); - loadAttrs( group.getMembers(), myEntry, SchemaConstants.MEMBER_AT ); - loadProperties( group.getProperties(), myEntry, GROUP_PROPERTY_ATTR_IMPL, '=' ); - - if ( StringUtils.isNotEmpty( group.getDescription() ) ) - { - myEntry.add( SchemaConstants.DESCRIPTION_AT, group.getDescription() ); - } - - ld = getAdminConnection(); - add( ld, myEntry ); - } - catch ( LdapException e ) - { - String error = "create group node dn [" + nodeDn + "] caught LDAPException=" + e.getMessage(); - throw new CreateException( GlobalErrIds.GROUP_ADD_FAILED, error, e ); - } - finally - { - closeAdminConnection( ld ); - } - - return group; - } - - - /** - * @param group - * @return - * @throws org.apache.directory.fortress.core.CreateException - * - */ - Group update( Group group ) throws FinderException, UpdateException - { - LdapConnection ld = null; - String nodeDn = getDn( group.getName(), group.getContextId() ); - - try - { - LOG.debug( "update group dn [{}]", nodeDn ); - List mods = new ArrayList(); - - if ( StringUtils.isNotEmpty( group.getDescription() ) ) - { - mods.add( new DefaultModification( - ModificationOperation.REPLACE_ATTRIBUTE, SchemaConstants.DESCRIPTION_AT, group.getDescription() ) ); - } - - if ( StringUtils.isNotEmpty( group.getProtocol() ) ) - { - mods.add( new DefaultModification( - ModificationOperation.REPLACE_ATTRIBUTE, GROUP_PROTOCOL_ATTR_IMPL, group.getProtocol() ) ); - } - - loadAttrs( group.getMembers(), mods, SchemaConstants.MEMBER_AT ); - loadProperties( group.getProperties(), mods, GROUP_PROPERTY_ATTR_IMPL, true, '=' ); - - if ( mods.size() > 0 ) - { - ld = getAdminConnection(); - modify( ld, nodeDn, mods, group ); - } - } - catch ( LdapException e ) - { - String error = "update group node dn [" + nodeDn + "] caught LDAPException=" + e.getMessage(); - throw new UpdateException( GlobalErrIds.GROUP_UPDATE_FAILED, error, e ); - } - finally - { - closeAdminConnection( ld ); - } - return get( group ); - } - - - Group add( Group group, String key, String value ) throws FinderException, CreateException - { - LdapConnection ld = null; - String nodeDn = getDn( group.getName(), group.getContextId() ); - - try - { - LOG.debug( "add group property dn [{}], key [{}], value [{}]", nodeDn, key, value ); - List mods = new ArrayList(); - mods.add( new DefaultModification( - ModificationOperation.ADD_ATTRIBUTE, GROUP_PROPERTY_ATTR_IMPL, key + "=" + value ) ); - ld = getAdminConnection(); - modify( ld, nodeDn, mods, group ); - } - catch ( LdapException e ) - { - String error = "update group property node dn [" + nodeDn + "] caught LDAPException=" + e.getMessage(); - throw new CreateException( GlobalErrIds.GROUP_ADD_PROPERTY_FAILED, error, e ); - } - finally - { - closeAdminConnection( ld ); - } - - return get( group ); - } - - - Group delete( Group group, String key, String value ) throws FinderException, RemoveException - { - LdapConnection ld = null; - String nodeDn = getDn( group.getName(), group.getContextId() ); - - try - { - LOG.debug( "delete group property dn [{}], key [{}], value [{}]", nodeDn, key, value ); - List mods = new ArrayList(); - mods.add( new DefaultModification( - ModificationOperation.REMOVE_ATTRIBUTE, GROUP_PROPERTY_ATTR_IMPL, key + "=" + value ) ); - ld = getAdminConnection(); - modify( ld, nodeDn, mods, group ); - } - catch ( LdapException e ) - { - String error = "delete group property node dn [" + nodeDn + "] caught LDAPException=" + e.getMessage(); - throw new RemoveException( GlobalErrIds.GROUP_DELETE_PROPERTY_FAILED, error, e ); - } - finally - { - closeAdminConnection( ld ); - } - return get( group ); - } - - - /** - * This method will remove group node from diretory. - * - * @param group - * @throws org.apache.directory.fortress.core.RemoveException - * - */ - Group remove( Group group ) throws RemoveException - { - LdapConnection ld = null; - String nodeDn = getDn( group.getName(), group.getContextId() ); - LOG.debug( "remove group dn [{}]", nodeDn ); - try - { - ld = getAdminConnection(); - deleteRecursive( ld, nodeDn ); - } - catch ( CursorException e ) - { - String error = "remove group node dn [" + nodeDn + "] caught CursorException=" - + e.getMessage(); - throw new RemoveException( GlobalErrIds.GROUP_DELETE_FAILED, error, e ); - } - catch ( LdapException e ) - { - String error = "remove group node dn [" + nodeDn + "] caught LDAPException=" + e.getMessage(); - throw new RemoveException( GlobalErrIds.GROUP_DELETE_FAILED, error, e ); - } - finally - { - closeAdminConnection( ld ); - } - return group; - } - - - /** - * @param entity - * @param userDn - * @return - * @throws org.apache.directory.fortress.core.UpdateException - * - */ - Group assign( Group entity, String userDn ) throws FinderException, UpdateException - { - LdapConnection ld = null; - String dn = getDn( entity.getName(), entity.getContextId() ); - LOG.debug( "assign group property dn [{}], member dn [{}]", dn, userDn ); - try - { - List mods = new ArrayList(); - mods.add( new DefaultModification( - ModificationOperation.ADD_ATTRIBUTE, SchemaConstants.MEMBER_AT, userDn ) ); - ld = getAdminConnection(); - modify( ld, dn, mods, entity ); - } - catch ( LdapException e ) - { - String error = "assign group name [" + entity.getName() + "] user dn [" + userDn + "] caught " + - "LDAPException=" + e.getMessage(); - throw new UpdateException( GlobalErrIds.GROUP_USER_ASSIGN_FAILED, error, e ); - } - finally - { - closeAdminConnection( ld ); - } - return get( entity ); - } - - - /** - * @param entity - * @param userDn - * @return - * @throws org.apache.directory.fortress.core.UpdateException - * - */ - Group deassign( Group entity, String userDn ) throws FinderException, UpdateException - { - LdapConnection ld = null; - String dn = getDn( entity.getName(), entity.getContextId() ); - LOG.debug( "deassign group property dn [{}], member dn [{}]", dn, userDn ); - - try - { - List mods = new ArrayList(); - mods.add( new DefaultModification( - ModificationOperation.REMOVE_ATTRIBUTE, SchemaConstants.MEMBER_AT, userDn ) ); - - ld = getAdminConnection(); - modify( ld, dn, mods, entity ); - } - catch ( LdapException e ) - { - String error = "deassign group name [" + entity.getName() + "] user dn [" + userDn + "] caught " + - "LDAPException=" + e.getMessage(); - throw new UpdateException( GlobalErrIds.GROUP_USER_DEASSIGN_FAILED, error, e ); - } - finally - { - closeAdminConnection( ld ); - } - - return get( entity ); - } - - - /** - * @param group - * @return - * @throws org.apache.directory.fortress.core.FinderException - * - */ - Group get( Group group ) throws FinderException - { - Group entity = null; - LdapConnection ld = null; - String dn = getDn( group.getName(), group.getContextId() ); - - try - { - ld = getAdminConnection(); - Entry findEntry = read( ld, dn, GROUP_ATRS ); - if ( findEntry == null ) - { - String warning = "No Group entry found dn [" + dn + "]"; - throw new FinderException( GlobalErrIds.GROUP_NOT_FOUND, warning ); - } - entity = unloadLdapEntry( findEntry, 0 ); - } - catch ( LdapNoSuchObjectException e ) - { - String warning = "read Obj COULD NOT FIND ENTRY for dn [" + dn + "]"; - throw new FinderException( GlobalErrIds.GROUP_NOT_FOUND, warning, e ); - } - catch ( LdapException e ) - { - String error = "read dn [" + dn + "] LdapException=" + e.getMessage(); - throw new FinderException( GlobalErrIds.GROUP_READ_FAILED, error, e ); - } - finally - { - closeAdminConnection( ld ); - } - return entity; - } - - - /** - * @param group - * @return - * @throws org.apache.directory.fortress.core.FinderException - * - */ - List find( Group group ) throws FinderException - { - List groupList = new ArrayList<>(); - LdapConnection ld = null; - SearchCursor searchResults; - String groupRoot = getRootDn( group.getContextId(), GlobalIds.GROUP_ROOT ); - String filter = null; - - try - { - String searchVal = encodeSafeText( group.getName(), GlobalIds.ROLE_LEN ); - filter = GlobalIds.FILTER_PREFIX + GROUP_OBJECT_CLASS_IMPL + ")(" + SchemaConstants.CN_AT + "=" + searchVal - + "*))"; - ld = getAdminConnection(); - searchResults = search( ld, groupRoot, SearchScope.ONELEVEL, filter, GROUP_ATRS, false, - GlobalIds.BATCH_SIZE ); - long sequence = 0; - while ( searchResults.next() ) - { - groupList.add( unloadLdapEntry( searchResults.getEntry(), sequence++ ) ); - } - } - catch ( CursorException e ) - { - String error = "find filter [" + filter + "] caught CursorException=" + e.getMessage(); - throw new FinderException( GlobalErrIds.GROUP_SEARCH_FAILED, error, e ); - } - catch ( LdapException e ) - { - String error = "find filter [" + filter + "] caught LDAPException=" + e.getMessage(); - throw new FinderException( GlobalErrIds.GROUP_SEARCH_FAILED, error, e ); - } - finally - { - closeAdminConnection( ld ); - } - - return groupList; - } - - - /** - * @param user - * @return - * @throws org.apache.directory.fortress.core.FinderException - * - */ - List find( User user ) throws FinderException - { - List groupList = new ArrayList<>(); - LdapConnection ld = null; - SearchCursor searchResults; - String groupRoot = getRootDn( user.getContextId(), GlobalIds.GROUP_ROOT ); - String filter = null; - - try - { - encodeSafeText( user.getUserId(), GlobalIds.USERID_LEN ); - filter = GlobalIds.FILTER_PREFIX + GROUP_OBJECT_CLASS_IMPL + ")(" + SchemaConstants.MEMBER_AT + "=" - + user.getDn() + "))"; - ld = getAdminConnection(); - searchResults = search( ld, groupRoot, SearchScope.ONELEVEL, filter, GROUP_ATRS, false, - GlobalIds.BATCH_SIZE ); - long sequence = 0; - - while ( searchResults.next() ) - { - groupList.add( unloadLdapEntry( searchResults.getEntry(), sequence++ ) ); - } - } - catch ( CursorException e ) - { - String error = "find filter [" + filter + "] caught CursorException=" + e.getMessage(); - throw new FinderException( GlobalErrIds.GROUP_SEARCH_FAILED, error, e ); - } - catch ( LdapException e ) - { - String error = "find filter [" + filter + "] caught LDAPException=" + e.getMessage(); - throw new FinderException( GlobalErrIds.GROUP_SEARCH_FAILED, error, e ); - } - finally - { - closeAdminConnection( ld ); - } - - return groupList; - } - - - /** - * @param le - * @param sequence - * @return - * @throws LdapException - */ - private Group unloadLdapEntry( Entry le, long sequence ) - throws LdapInvalidAttributeValueException - { - Group entity = new ObjectFactory().createGroup(); - entity.setName( getAttribute( le, SchemaConstants.CN_AT ) ); - entity.setDescription( getAttribute( le, SchemaConstants.DESCRIPTION_AT ) ); - entity.setProtocol( getAttribute( le, GROUP_PROTOCOL_ATTR_IMPL ) ); - entity.setMembers( getAttributes( le, SchemaConstants.MEMBER_AT ) ); - entity.setMemberDn( true ); - entity.setProperties( AttrHelper.getProperties( getAttributes( le, GROUP_PROPERTY_ATTR_IMPL ), '=' ) ); - entity.setSequenceId( sequence ); - - return entity; - } - - - private String getDn( String name, String contextId ) - { - return SchemaConstants.CN_AT + "=" + name + "," + getRootDn( contextId, GlobalIds.GROUP_ROOT ); - } -} \ 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/ldap/group/GroupMgr.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/directory/fortress/core/ldap/group/GroupMgr.java b/src/main/java/org/apache/directory/fortress/core/ldap/group/GroupMgr.java deleted file mode 100755 index b861242..0000000 --- a/src/main/java/org/apache/directory/fortress/core/ldap/group/GroupMgr.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * 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.ldap.group; - - -import org.apache.directory.fortress.core.*; -import org.apache.directory.fortress.core.SecurityException; -import org.apache.directory.fortress.core.model.Group; -import org.apache.directory.fortress.core.model.User; - -import java.util.List; - - -/** - * This interface prescribes CRUD methods used to manage groups stored within the ldap directory. - *

- * This class is thread safe. - *

- * - * @author Apache Directory Project - */ -public interface GroupMgr extends Manageable -{ - /** - * Create a new group node., - * - * @param group contains {@link org.apache.directory.fortress.core.model.Group}. - * @return {@link org.apache.directory.fortress.core.model.Group} containing entity just added. - * @throws org.apache.directory.fortress.core.SecurityException in the event system error. - */ - Group add( Group group ) throws org.apache.directory.fortress.core.SecurityException; - - - /** - * Modify existing group node. The name is required. Does not update members or properties. - * Use {@link GroupMgr#add( Group group, String key, String value )}, {@link GroupMgr#delete( Group group, String key, String value )}, - * {@link GroupMgr#assign( Group group, String member) }, or {@link GroupMgr#deassign( Group group, String member) } for multi-occurring attributes. - * - * @param group contains {@link Group}. - * @return {@link Group} containing entity just modified. - * @throws org.apache.directory.fortress.core.SecurityException in the event system error. - */ - Group update( Group group ) throws SecurityException; - - - /** - * Delete existing group node. The name is required. - * - * @param group contains {@link Group}. - * @return {@link Group} containing entity just removed. - * @throws org.apache.directory.fortress.core.SecurityException in the event system error. - */ - Group delete( Group group ) throws SecurityException; - - - /** - * Add a property to an existing group node. Must have a name and at least one member. - * - * @param group contains {@link Group}. - * @param key contains the property key. - * @param value contains contains the property value. - * @return {@link Group} containing entity just modified. - * @throws org.apache.directory.fortress.core.SecurityException in the event system error. - */ - Group add( Group group, String key, String value ) throws SecurityException; - - - /** - * Delete existing group node. The name is required. - * - * @param group contains {@link Group}. - * @param key contains the property key. - * @param value contains contains the property value. - * @return {@link Group} containing entity just modified. - * @throws org.apache.directory.fortress.core.SecurityException in the event system error. - */ - Group delete( Group group, String key, String value ) throws SecurityException; - - - /** - * Read an existing group node. The name is required. - * - * @param group contains {@link Group} with name field set with an existing group name. - * @return {@link Group} containing entity found. - * @throws org.apache.directory.fortress.core.SecurityException in the event system error. - */ - Group read( Group group ) throws SecurityException; - - - /** - * Search using a full or partial group node. The name is required. - * - * @param group contains {@link Group}. - * @return List of type {@link Group} containing entities found. - * @throws org.apache.directory.fortress.core.SecurityException in the event system error. - */ - List find( Group group ) throws SecurityException; - - - /** - * Search for groups by userId. Member (maps to userId) and is required. - * - * @param user contains userId that maps to Group member attribute. - * @return {@link Group} containing entity just added. - * @throws org.apache.directory.fortress.core.SecurityException in the event system error. - */ - List find( User user ) throws SecurityException; - - - /** - * Assign a user to an existing group node. The group name and member are required. - * - * @param group contains {@link Group}. - * @param member is the relative distinguished name (rdn) of an existing user in ldap. - * @return {@link Group} containing entity to assign. - * @throws org.apache.directory.fortress.core.SecurityException in the event entry already present or other system error. - */ - Group assign( Group group, String member ) throws SecurityException; - - - /** - * Deassign a member from an existing group node. The group name and member are required. - * - * @param group contains {@link Group}. - * @param member is the relative distinguished name (rdn) of an existing user in ldap. - * @return {@link Group} containing entity to deassign - * @throws org.apache.directory.fortress.core.SecurityException in the event entry already present or other system error. - */ - Group deassign( Group group, String member ) throws SecurityException; -} \ No newline at end of file