Package org.wso2.carbon.user.core.tenant

Source Code of org.wso2.carbon.user.core.tenant.CommonHybridLDAPTenantManager

/*
*  Copyright (c) 2005-2010, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
*  WSO2 Inc. 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.wso2.carbon.user.core.tenant;

import org.apache.axiom.om.OMElement;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.user.api.TenantMgtConfiguration;
import org.wso2.carbon.user.core.UserCoreConstants;
import org.wso2.carbon.user.core.UserStoreException;
import org.wso2.carbon.user.api.RealmConfiguration;
import org.wso2.carbon.user.core.ldap.LDAPConnectionContext;
import org.wso2.carbon.user.core.ldap.LDAPConstants;

import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.DirContext;
import javax.sql.DataSource;
import java.util.Map;

/**
* This class is the tenant manager for any external LDAP and based on the "ou" partitioning
* per tenant under one DIT.
*/
public class CommonHybridLDAPTenantManager extends JDBCTenantManager {
    private static Log logger = LogFactory.getLog(CommonHybridLDAPTenantManager.class);
    private DirContext initialDirContext;
    //TODO move the following configurations and constants to relevant files.

    private TenantMgtConfiguration tenantMgtConfig = null;
    private RealmConfiguration realmConfig = null;
    //constants
    private static final String USER_PASSWORD_ATTRIBUTE_NAME = "userPassword";
    private static final String EMAIL_ATTRIBUTE_NAME = "mail";
    private static final String SN_ATTRIBUTE_NAME = "sn";
    private static final String CN_ATTRIBUTE_NAME = "cn";

    public CommonHybridLDAPTenantManager(OMElement omElement, Map<String, Object> properties)
            throws Exception {
        super(omElement, properties);
        LDAPConnectionContext ldapConnectionSource = (LDAPConnectionContext) properties.get(
                UserCoreConstants.LDAP_CONNECTION_SOURCE);
        initialDirContext = ldapConnectionSource.getContext();
        tenantMgtConfig = (TenantMgtConfiguration) properties.get(
                UserCoreConstants.TENANT_MGT_CONFIGURATION);

        realmConfig = (RealmConfiguration) properties.get(UserCoreConstants.REALM_CONFIGURATION);
    }

    public CommonHybridLDAPTenantManager(DataSource dataSource, String superTenantDomain) {
        super(dataSource, superTenantDomain);

    }

    /**
     * Do necessary things in LDAP when adding a tenant.
     *
     * @param tenant
     * @return
     * @throws UserStoreException
     */
    @Override
    public int addTenant(org.wso2.carbon.user.api.Tenant tenant) throws UserStoreException {
        int tenantID = super.addTenant(tenant);
        tenant.setId(tenantID);

        //create per tenant context and its user store and group store with admin related entries.
        createOrganizationalUnit(tenant.getDomain(), (Tenant) tenant);

        return tenantID;
    }

    /**
     * Create a space for tenant in LDAP.
     *
     * @param orgName
     * @param tenant
     * @throws UserStoreException
     */
    private void createOrganizationalUnit(String orgName, Tenant tenant)
            throws UserStoreException {
        if (initialDirContext != null) {
            //e.g: ou=wso2.com
            String partitionDN = tenantMgtConfig.getTenantStoreProperties().get(
                    UserCoreConstants.TenantMgtConfig.PROPERTY_ROOT_PARTITION);
            createOrganizationalContext(partitionDN, orgName);

            //create user store
            String organizationNameAttribute = tenantMgtConfig.getTenantStoreProperties().get(
                    UserCoreConstants.TenantMgtConfig.PROPERTY_ORG_SUB_CONTEXT_ATTRIBUTE);
            //eg:o=cse.org,dc=wso2,dc=com
            String dnOfOrganizationalContext = organizationNameAttribute + "=" + orgName + "," +
                                               partitionDN;
            createOrganizationalSubContext(dnOfOrganizationalContext,
                                           LDAPConstants.USER_CONTEXT_NAME);

            //create group store
            createOrganizationalSubContext(dnOfOrganizationalContext,
                                           LDAPConstants.GROUP_CONTEXT_NAME);

            //create admin entry
            String orgSubContextAttribute = tenantMgtConfig.getTenantStoreProperties().get(
                    UserCoreConstants.TenantMgtConfig.PROPERTY_ORG_SUB_CONTEXT_ATTRIBUTE);
            //eg: ou=users,o=cse.org,dc=wso2,dc=com
            String dnOfUserContext = orgSubContextAttribute + "=" + LDAPConstants.USER_CONTEXT_NAME
                                     + "," + dnOfOrganizationalContext;
            String dnOfUserEntry = createAdminEntry(dnOfUserContext, tenant);

            //create admin group if write ldap group is enabled
            if (("true").equals(realmConfig.getUserStoreProperty(
                    LDAPConstants.WRITE_EXTERNAL_ROLES))) {
                //construct dn of group context: eg:ou=groups,o=cse.org,dc=wso2,dc=com
                String dnOfGroupContext = orgSubContextAttribute + "=" +
                                          LDAPConstants.GROUP_CONTEXT_NAME + "," +
                                          dnOfOrganizationalContext;
                createAdminGroup(dnOfGroupContext, dnOfUserEntry);
            }

        }

    }

    /**
     * Create main context corresponding to tenant.
     *
     * @param rootDN
     * @param orgName
     * @throws UserStoreException
     */
    private void createOrganizationalContext(String rootDN, String orgName)
            throws UserStoreException {
        if (initialDirContext != null) {
            try {
                //get the connection context for rootDN
                DirContext subContext = (DirContext) initialDirContext.lookup(rootDN);

                Attributes contextAttributes = new BasicAttributes(true);
                //create organizational object class attribute
                Attribute objectClass = new BasicAttribute(LDAPConstants.OBJECT_CLASS_NAME);
                objectClass.add(
                        tenantMgtConfig.getTenantStoreProperties().get(
                                UserCoreConstants.TenantMgtConfig.PROPERTY_ORGANIZATIONAL_OBJECT_CLASS));
                contextAttributes.put(objectClass);
                //create organizational name attribute
                String organizationalNameAttribute = tenantMgtConfig.getTenantStoreProperties().get(
                        UserCoreConstants.TenantMgtConfig.PROPERTY_ORGANIZATIONAL_ATTRIBUTE);
                Attribute organization =
                        new BasicAttribute(organizationalNameAttribute);
                organization.add(orgName);
                contextAttributes.put(organization);
                //construct organization rdn.
                String rdnOfOrganizationalContext = organizationalNameAttribute + "=" + orgName;
                if (logger.isDebugEnabled()) {
                    logger.debug("Adding sub context: " + rdnOfOrganizationalContext + " under " +
                                 rootDN + " ...");
                }
                //create organization sub context
                subContext.createSubcontext(rdnOfOrganizationalContext, contextAttributes);
                if (logger.isDebugEnabled()) {
                    logger.debug("Sub context: " + rdnOfOrganizationalContext + " was added under "
                                 + rootDN + " successfully.");
                }

            } catch (NamingException e) {
                String errorMsg = "Error occurred while adding the organizational unit " +
                                  "sub context.";
                logger.error(errorMsg, e);
                throw new UserStoreException(errorMsg, e);
            }
        }
    }

    /**
     * Create sub contexts under the tenant's main context.
     *
     * @param dnOfParentContext
     * @param nameOfCurrentContext
     * @throws UserStoreException
     */
    private void createOrganizationalSubContext(String dnOfParentContext,
                                                String nameOfCurrentContext)
            throws UserStoreException {
        if (initialDirContext != null) {
            try {
                //get the connection for tenant's main context
                DirContext subContext = (DirContext) initialDirContext.lookup(dnOfParentContext);

                Attributes contextAttributes = new BasicAttributes(true);
                //create sub unit object class attribute
                Attribute objectClass = new BasicAttribute(LDAPConstants.OBJECT_CLASS_NAME);
                objectClass.add(tenantMgtConfig.getTenantStoreProperties().get(
                        UserCoreConstants.TenantMgtConfig.PROPERTY_ORG_SUB_CONTEXT_OBJ_CLASS));
                contextAttributes.put(objectClass);

                //create org sub unit name attribute
                String orgSubUnitAttributeName = tenantMgtConfig.getTenantStoreProperties().get(
                        UserCoreConstants.TenantMgtConfig.PROPERTY_ORG_SUB_CONTEXT_ATTRIBUTE);
                Attribute organizationSubUnit = new BasicAttribute(orgSubUnitAttributeName);
                organizationSubUnit.add(nameOfCurrentContext);
                contextAttributes.put(organizationSubUnit);

                //construct the rdn of org sub context
                String rdnOfOrganizationalContext = orgSubUnitAttributeName + "=" +
                                                    nameOfCurrentContext;
                if (logger.isDebugEnabled()) {
                    logger.debug("Adding sub context: " + rdnOfOrganizationalContext + " under " +
                                 dnOfParentContext + " ...");
                }
                //create sub context
                subContext.createSubcontext(rdnOfOrganizationalContext, contextAttributes);
                if (logger.isDebugEnabled()) {
                    logger.debug("Sub context: " + rdnOfOrganizationalContext + " was added under "
                                 + dnOfParentContext + " successfully.");
                }

            } catch (NamingException e) {
                String errorMsg = "Error occurred while adding the organizational unit " +
                                  "sub context.";
                logger.error(errorMsg, e);
                throw new UserStoreException(errorMsg, e);
            }
        }

    }

    private String createAdminEntry(String dnOfUserContext, Tenant tenant)
            throws UserStoreException {
        String userDN = null;
        if (initialDirContext != null) {
            try {
                //get connection to tenant's user context
                DirContext organizationalUsersContext = (DirContext) initialDirContext.lookup(
                        dnOfUserContext);
                Attributes userAttributes = new BasicAttributes(true);

                //create person object class attribute
                Attribute objClass = new BasicAttribute(LDAPConstants.OBJECT_CLASS_NAME);
                objClass.add(realmConfig.getUserStoreProperty(LDAPConstants.USER_ENTRY_OBJECT_CLASS));
                userAttributes.put(objClass);

                //create user password attribute
                Attribute password = new BasicAttribute(USER_PASSWORD_ATTRIBUTE_NAME);
                password.add(tenant.getAdminPassword());
                userAttributes.put(password);

                //create mail attribute
                Attribute adminEmail = new BasicAttribute(EMAIL_ATTRIBUTE_NAME);
                adminEmail.add(tenant.getEmail());
                userAttributes.put(adminEmail);

                //create compulsory attribute: sn-last name
                Attribute lastName = new BasicAttribute(SN_ATTRIBUTE_NAME);
                lastName.add(tenant.getAdminLastName());
                userAttributes.put(lastName);

                //read user name attribute in user-mgt.xml
                String userNameAttribute = realmConfig.getUserStoreProperty(
                        LDAPConstants.USER_NAME_ATTRIBUTE_NAME);

                //if user name attribute is not cn, add it to attribute list
                if (!(CN_ATTRIBUTE_NAME.equals(userNameAttribute))) {
                    Attribute firstName = new BasicAttribute(CN_ATTRIBUTE_NAME);
                    firstName.add(tenant.getAdminFirstName());
                    userAttributes.put(firstName);
                }
                String userRDN = userNameAttribute + "=" + tenant.getAdminName();
                organizationalUsersContext.bind(userRDN, null, userAttributes);
                userDN = userRDN + "," + dnOfUserContext;
                //return (userRDN + dnOfUserContext);
            } catch (NamingException e) {
                String errorMsg = "Error occurred while creating Admin entry";
                logger.error(errorMsg, e);
                throw new UserStoreException(errorMsg, e);
            }

        }
        return userDN;
    }

    private void createAdminGroup(String dnOfGroupContext, String adminUserDN)
            throws UserStoreException {
        if (initialDirContext != null) {
            //create set of attributes required to create admin group
            Attributes adminGroupAttributes = new BasicAttributes(true);
            //admin entry object class
            Attribute objectClassAttribute = new BasicAttribute(LDAPConstants.OBJECT_CLASS_NAME);
            objectClassAttribute.add(realmConfig.getUserStoreProperty(
                    LDAPConstants.GROUP_ENTRY_OBJECT_CLASS));
            adminGroupAttributes.put(objectClassAttribute);

            //group name attribute
            String groupNameAttributeName = realmConfig.getUserStoreProperty(
                    LDAPConstants.ROLE_NAME_ATTRIBUTE_NAME);
            Attribute groupNameAttribute = new BasicAttribute(groupNameAttributeName);
            String adminRoleName = realmConfig.getAdminRoleName();
            groupNameAttribute.add(adminRoleName);
            adminGroupAttributes.put(groupNameAttribute);

            //membership attribute
            Attribute membershipAttribute = new BasicAttribute(realmConfig.getUserStoreProperty(
                    LDAPConstants.MEMBERSHIP_ATTRIBUTE));
            membershipAttribute.add(adminUserDN);
            adminGroupAttributes.put(membershipAttribute);

            try {
                DirContext groupContext = (DirContext) initialDirContext.lookup(dnOfGroupContext);
                String rdnOfAdminGroup = groupNameAttributeName + "=" + adminRoleName;
                groupContext.bind(rdnOfAdminGroup, null, adminGroupAttributes);

            } catch (NamingException e) {
                String errorMessage = "Error occurred while creating the admin group.";
                logger.error(errorMessage);
                throw new UserStoreException(errorMessage, e);
            }
        }


    }

}
TOP

Related Classes of org.wso2.carbon.user.core.tenant.CommonHybridLDAPTenantManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.