0011814: ActiveDirectory: lazy load domain config
authorPhilipp Schüle <p.schuele@metaways.de>
Thu, 28 Apr 2016 08:56:19 +0000 (10:56 +0200)
committerPhilipp Schüle <p.schuele@metaways.de>
Thu, 28 Apr 2016 09:46:21 +0000 (11:46 +0200)
* adds trait for AD domain config
* this prevents AD binding each time a
 Tinebase_Group_AD object is created

https://forge.tine20.org/view.php?id=11814

Change-Id: I4a8ffd11f13064c8eb77f07e252cca9c7fe20197
Reviewed-on: http://gerrit.tine20.com/customers/3104
Reviewed-by: Philipp Schüle <p.schuele@metaways.de>
Tested-by: Philipp Schüle <p.schuele@metaways.de>
tine20/Calendar/Export/GenericTrait.php
tine20/Tinebase/ActiveDirectory/DomainConfigurationTrait.php [new file with mode: 0644]
tine20/Tinebase/Group/ActiveDirectory.php
tine20/Tinebase/Group/Ldap.php
tine20/Tinebase/Ldap.php
tine20/Tinebase/User/ActiveDirectory.php

index 93bcf43..885e8cb 100644 (file)
@@ -1,6 +1,6 @@
 <?php
 /**
- * abstract calendar export class
+ * calendar export generic trait
  *
  * @package     Calendar
  * @subpackage  Export
@@ -16,6 +16,7 @@
  * @package     Calendar
  * @subpackage  Export
  *
+ * TODO rename trait to hint functionality? GenericTrait is not a good name ;)
  */
 trait Calendar_Export_GenericTrait
 {
@@ -101,6 +102,4 @@ trait Calendar_Export_GenericTrait
             }
         }
     }
-
-
 }
diff --git a/tine20/Tinebase/ActiveDirectory/DomainConfigurationTrait.php b/tine20/Tinebase/ActiveDirectory/DomainConfigurationTrait.php
new file mode 100644 (file)
index 0000000..861e606
--- /dev/null
@@ -0,0 +1,59 @@
+<?php
+/**
+ * ActiveDirectory generic trait
+ *
+ * @package     Tinebase
+ * @subpackage  ActiveDirectory
+ * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
+ * @author      Philipp Schüle <p.schuele@metaways.de>
+ * @copyright   Copyright (c) 2016 Metaways Infosystems GmbH (http://www.metaways.de)
+ *
+ */
+
+/**
+ * ActiveDirectory trait for reading domain configuration
+ * - can be used by User/Group AD controllers
+ *
+ * @package     Tinebase
+ * @subpackage  ActiveDirectory
+ *
+ */
+trait Tinebase_ActiveDirectory_DomainConfigurationTrait
+{
+    /**
+     * AD domain config
+     *
+     * @var array
+     */
+    protected $_domainConfig = null;
+
+    /**
+     * fetch domain config with domain sid and name
+     *
+     * @throws Tinebase_Exception_Backend_Ldap
+     * @throws Zend_Ldap_Exception
+     * @return array
+     *
+     * TODO cache this longer?
+     */
+    public function getDomainConfiguration()
+    {
+        if ($this->_domainConfig === null) {
+            $this->_domainConfig = $this->getLdap()->search(
+                'objectClass=domain',
+                $this->getLdap()->getFirstNamingContext(),
+                Zend_Ldap::SEARCH_SCOPE_BASE
+            )->getFirst();
+
+            $this->_domainConfig['domainSidBinary'] = $this->_domainConfig['objectsid'][0];
+            $this->_domainConfig['domainSidPlain'] = Tinebase_Ldap::decodeSid($this->_domainConfig['objectsid'][0]);
+
+            $domainNameParts = array();
+            $keys = null; // not really needed
+            Zend_Ldap_Dn::explodeDn($this->_domainConfig['distinguishedname'][0], $keys, $domanNameParts);
+            $this->_domainConfig['domainName'] = implode('.', $domainNameParts);
+        }
+
+        return $this->_domainConfig;
+    }
+}
index 87c420a..5bb3024 100644 (file)
@@ -5,7 +5,7 @@
  * @package     Tinebase
  * @subpackage  Group
  * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
- * @copyright   Copyright (c) 2007-2013 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @copyright   Copyright (c) 2007-2016 Metaways Infosystems GmbH (http://www.metaways.de)
  * @author      Lars Kneschke <l.kneschke@metaways.de>
  */
 
@@ -17,6 +17,9 @@
  */
 class Tinebase_Group_ActiveDirectory extends Tinebase_Group_Ldap
 {
+    // TODO move more duplicated (in User/Group AD controllers) code into traits
+    use Tinebase_ActiveDirectory_DomainConfigurationTrait;
+
     /**
      * the ldap backend
      *
@@ -81,7 +84,7 @@ class Tinebase_Group_ActiveDirectory extends Tinebase_Group_Ldap
     protected $_userSearchScope      = Zend_Ldap::SEARCH_SCOPE_SUB;
     
     protected $_isReadOnlyBackend    = false;
-    
+
     /**
      * the constructor
      *
@@ -109,22 +112,8 @@ class Tinebase_Group_ActiveDirectory extends Tinebase_Group_Ldap
         }
         
         parent::__construct($_options);
-        
-        // get domain sid
-        $this->_domainConfig = $this->getLdap()->search(
-            'objectClass=domain',
-            $this->getLdap()->getFirstNamingContext(),
-            Zend_Ldap::SEARCH_SCOPE_BASE
-        )->getFirst();
-        
-        $this->_domainSidBinary = $this->_domainConfig['objectsid'][0];
-        $this->_domainSidPlain  = Tinebase_Ldap::decodeSid($this->_domainConfig['objectsid'][0]);
-        
-        $domainNameParts    = array();
-        Zend_Ldap_Dn::explodeDn($this->_domainConfig['distinguishedname'][0], $unusedPart, $domainNameParts);
-        $this->_domainName = implode('.', $domainNameParts);
     }
-    
+
     /**
      * create a new group in sync backend
      *
@@ -154,8 +143,9 @@ class Tinebase_Group_ActiveDirectory extends Tinebase_Group_Ldap
         if ($this->_options['useRfc2307']) {
             $ldapData['objectclass'][] = 'posixGroup';
             $ldapData['gidnumber']     = $this->_generateGidNumber();
-            
-            $ldapData['msSFU30NisDomain'] = Tinebase_Helper::array_value(0, explode('.', $this->_domainName));
+
+            $domainConfig = $this->getDomainConfiguration();
+            $ldapData['msSFU30NisDomain'] = Tinebase_Helper::array_value(0, explode('.', $domainConfig['domainName']));
         }
         
         if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) 
@@ -218,7 +208,7 @@ class Tinebase_Group_ActiveDirectory extends Tinebase_Group_Ldap
      */
     public function getGroupMembershipsFromSyncBackend($_userId)
     {
-        $userId = $_userId instanceof Tinebase_Model_User ? $_userId->getId() : $_userId; 
+        $userId = $_userId instanceof Tinebase_Model_User ? $_userId->getId() : $_userId;
         
         // find user in AD and retrieve memberOf attribute
         $filter = Zend_Ldap_Filter::andFilter(
@@ -240,10 +230,11 @@ class Tinebase_Group_ActiveDirectory extends Tinebase_Group_Ldap
             return array();
         }
         
-        // resolve primarygrouid to dn
+        // resolve primary group id to dn
+        $domainConfig = $this->getDomainConfiguration();
         $filter = Zend_Ldap_Filter::andFilter(
             Zend_Ldap_Filter::string($this->_groupBaseFilter),
-            Zend_Ldap_Filter::equals('objectsid', Zend_Ldap::filterEscape($this->_domainSidPlain . '-' . $memberOfs['primarygroupid'][0]))
+            Zend_Ldap_Filter::equals('objectsid', Zend_Ldap::filterEscape($domainConfig['domainSidPlain'] . '-' . $memberOfs['primarygroupid'][0]))
         );
         
         $group = $this->getLdap()->search(
@@ -377,8 +368,6 @@ class Tinebase_Group_ActiveDirectory extends Tinebase_Group_Ldap
         if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) 
             Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . " account meta data: " . print_r($accountMetaData, true));
         
-        $memberUidNumbers = $this->getGroupMembers($_groupId);
-        
         $ldapData = array(
             'member' => $accountMetaData['dn']
         );
@@ -406,7 +395,8 @@ class Tinebase_Group_ActiveDirectory extends Tinebase_Group_Ldap
      */
     public function resolveGIdNumberToUUId($rid)
     {
-        $groupSid = $this->_domainSidPlain . '-' .  $rid;
+        $domainConfig = $this->getDomainConfiguration();
+        $groupSid = $domainConfig['domainSidPlain'] . '-' .  $rid;
         
         $filter = Zend_Ldap_Filter::andFilter(
             Zend_Ldap_Filter::string($this->_groupBaseFilter),
@@ -488,7 +478,7 @@ class Tinebase_Group_ActiveDirectory extends Tinebase_Group_Ldap
         if ($this->_isReadOnlyBackend) {
             return;
         }
-        
+
         $groupMetaData = $this->_getMetaData($_groupId);
         
         $membersMetaDatas = $this->_getAccountsMetaData((array)$_groupMembers, FALSE);
@@ -506,12 +496,11 @@ class Tinebase_Group_ActiveDirectory extends Tinebase_Group_Ldap
             Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . '  $group data: ' . print_r($groupMetaData, true));
         if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) 
             Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . '  $memebers: ' . print_r($membersMetaDatas, true));
-        
-        $groupDn = $this->_getDn($_groupId);
-        
+
+        $domainConfig = $this->getDomainConfiguration();
         $memberDn = array();
         foreach ($membersMetaDatas as $memberMetadata) {
-            if ($this->_domainSidPlain . '-' . $memberMetadata['primarygroupid'] == $groupMetaData['objectsid']) {
+            if ($domainConfig['domainSidPlain'] . '-' . $memberMetadata['primarygroupid'] == $groupMetaData['objectsid']) {
                 // skip this user => is already meber because of his primary group
                 continue;
             }
index 9549af4..a33a095 100644 (file)
@@ -245,6 +245,7 @@ class Tinebase_Group_Ldap extends Tinebase_Group_Sql implements Tinebase_Group_I
                 $this->getLdap()->bind();
             } catch (Zend_Ldap_Exception $zle) {
                 // @todo move this to Tinebase_Ldap?
+                Tinebase_Exception::log($zle);
                 throw new Tinebase_Exception_Backend_Ldap('Could not bind to LDAP: ' . $zle->getMessage());
             }
         }
index 167ffb4..ffdeffa 100644 (file)
@@ -48,12 +48,12 @@ class Tinebase_Ldap extends Zend_Ldap
             'optReferrals'              => null,
             'tryUsernameSplit'          => null
         ));
-        
-        $returnValue = parent::__construct($options);
 
         if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__
             . ' LDAP options: ' . print_r($options, true));
-        
+
+        $returnValue = parent::__construct($options);
+
         return $returnValue;
     }
     
index 1e66c9b..2c8ee64 100644 (file)
@@ -5,7 +5,7 @@
  * @package     Tinebase
  * @subpackage  User
  * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
- * @copyright   Copyright (c) 2007-2008 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @copyright   Copyright (c) 2007-2016 Metaways Infosystems GmbH (http://www.metaways.de)
  * @author      Lars Kneschke <l.kneschke@metaways.de>
  */
 
@@ -17,6 +17,9 @@
  */
 class Tinebase_User_ActiveDirectory extends Tinebase_User_Ldap
 {
+    // TODO move more duplicated (in User/Group AD controllers) code into traits
+    use Tinebase_ActiveDirectory_DomainConfigurationTrait;
+
     const ACCOUNTDISABLE = 2;
     const NORMAL_ACCOUNT = 512;
 
@@ -108,21 +111,6 @@ class Tinebase_User_ActiveDirectory extends Tinebase_User_Ldap
             $this->_rowNameMapping['accountHomeDirectory'] = 'unixhomedirectory';
             $this->_rowNameMapping['accountLoginShell']    = 'loginshell';
         }
-        
-        // get domain sid
-        $this->_domainConfig = $this->_ldap->search(
-            'objectClass=domain',
-            $this->_ldap->getFirstNamingContext(),
-            Zend_Ldap::SEARCH_SCOPE_BASE
-        )->getFirst();
-        
-        $this->_domainSidBinary = $this->_domainConfig['objectsid'][0];
-        $this->_domainSidPlain  = Tinebase_Ldap::decodeSid($this->_domainConfig['objectsid'][0]);
-        
-        $domanNameParts    = array();
-        $keys = null; // not really needed
-        Zend_Ldap_Dn::explodeDn($this->_domainConfig['distinguishedname'][0], $keys, $domanNameParts);
-        $this->_domainName = implode('.', $domanNameParts);
     }
     
     /**
@@ -474,7 +462,8 @@ class Tinebase_User_ActiveDirectory extends Tinebase_User_Ldap
         }
         
         /*
-        $maxPasswordAge = abs(bcdiv($this->_domainConfig['maxpwdage'][0], '10000000'));
+        $domainConfig = $this->getDomainConfiguration();
+        $maxPasswordAge = abs(bcdiv($domainConfig['maxpwdage'][0], '10000000'));
         if ($maxPasswordAge > 0 && isset($accountArray['accountLastPasswordChange'])) {
             $accountArray['accountExpires'] = clone $accountArray['accountLastPasswordChange'];
             $accountArray['accountExpires']->addSecond($maxPasswordAge);
@@ -572,9 +561,10 @@ class Tinebase_User_ActiveDirectory extends Tinebase_User_Ldap
                     break;
             }
         }
-        
+
+        $domainConfig = $this->getDomainConfiguration();
         $ldapData['name'] = $ldapData['cn'];
-        $ldapData['userPrincipalName'] =  $_user->accountLoginName . '@' . $this->_domainName;
+        $ldapData['userPrincipalName'] =  $_user->accountLoginName . '@' . $domainConfig['domainName'];
         
         if ($this->_options['useRfc2307']) {
             // homedir is an required attribute
@@ -588,7 +578,7 @@ class Tinebase_User_ActiveDirectory extends Tinebase_User_Ldap
             }
             $ldapData['gidnumber'] = Tinebase_Group::getInstance()->resolveGidNumber($_user->accountPrimaryGroup);
             
-            $ldapData['msSFU30NisDomain'] = Tinebase_Helper::array_value(0, explode('.', $this->_domainName));
+            $ldapData['msSFU30NisDomain'] = Tinebase_Helper::array_value(0, explode('.', $domainConfig['domainName']));
         }
         
         if (isset($_user->sambaSAM) && $_user->sambaSAM instanceof Tinebase_Model_SAMUser) {