📜 ⬆️ ⬇️

Create an AD user through the web interface



Not every web developer will encounter AD at least because a server administrator must first configure a module for working with ldap via php. But sometimes it still happens - the company has a good admin and the need for centralized management of employees.

To put it very simply, this is exactly what AD does - it stores information about employees and gives it to various applications and services as a database, say, MySQL. For setting up and managing AD, there can also be a whole individual employee, but the implementation of access via the web interface will predictably fall on the web programmer. And then there may be some difficulties.

If you understand the general principles of AD and implement, for example, displaying the structure of a company in a browser for a person familiar with databases, it will be quite simple, then organizing input is already more difficult. The fact is that real AD specialists use desktop applications, the console and VBScript (it seems), and manipulate users as objects, and only some functions and the transfer of the user as an array of data are available to the php programmer. Determining which keys to write and in which format the values ​​should be is not a trivial task. Because the network for the function ldap_add () is just one use case .
')
Therefore, it is relevant to create another example - a more detailed one and with all the “body kit”, in order to check the work could be without any significant changes.

We assume that the server is already set up, access is obtained, and our user is granted write access. The first stage - connection - is described in the manuals in sufficient detail:

/* Connection parameters */ $ldap_host = "xxx.local"; # domain controller or ip-address $ldap_port = "389"; # port for connection $ldap_user ="admin@xxx.local"; # AD-user $ldap_pass = "123321";# AD-user's password /* Open connection */ $connect = ldap_connect( $ldap_host, $ldap_port); ldap_set_option($connect, LDAP_OPT_PROTOCOL_VERSION, 3); ldap_set_option($connect, LDAP_OPT_REFERRALS, 0); $bind = ldap_bind($connect, $ldap_user, $ldap_pass); 


Now we’ll check the output and build a hierarchical tree of our company's divisions:

 /* Hierarchical tree */ function build_tree($connect, $ou = '', $base_dn = 'OU=!Users_all,DC=xxx,DC=local') { $specific_dn = $base_dn; if ('' != $ou) {$specific_dn = 'OU='.$ou.','.$base_dn;} $filter = 'ou=*'; $justthese = array("ou"); $sr = ldap_list($connect, $specific_dn, $filter, $justthese); $info = ldap_get_entries($connect, $sr); $result = ''; for ($i=0; $i < $info["count"]; $i++) { $specific_ou = $info[$i]["ou"][0]; $result .= '<ul>'; $result .= '<li><input type="radio" name="dep" value="OU='.$specific_ou.','.$specific_dn.'" title="'.$specific_ou.'" /> '.$specific_ou; $result .= build_tree($connect, $specific_ou, $specific_dn); $result .= '</li>'; $result .= '</ul>'; } return $result; } 


We immediately add form elements to the output, which we will need in the next step. The function calls itself that will allow to pass any level of nesting.
If everything works, we will write a simple form for adding an employee:

 /* Output */ echo ' <form method="POST" action="'.$_SERVER['REQUEST_URI'].'"> <h3></h3> <input type="hidden" name="new_emp" value="1" /> <input type="text" name="family_name" value="" size="20" /> <input type="text" name="first_name" value="" size="20" /> <input type="text" name="fathers_name" value="" size="20" /> <br/> <h3></h3> <input type="text" name="position" value="" size="40" /> <br/> <h3>  </h3> <input type="text" name="tel_num" value="+7(999) 999-9999" size="20" /> <h3></h3> <div class="tree"> '.build_tree($connect).' </div> <br/> <input type="submit" value="" /> </form>'; 


And now - the important part: checking and processing input

 /* Input check */ $errors = ''; /* EXAMPLE OF CORRECT POST new_emp: 1 family_name:  first_name:  fathers_name:  position:  tel_num: +7(999) 999-9999 dep:      */ if(isset($_POST['new_emp'])) { foreach($_POST as $key => $value) { if('' == $value) {$errors .= ' '.$key.'  <br/>'; break;} else {$$key = $value;} } if(!isset($_POST['dep'])) {$errors .= ' «»  <br/>';} /* Creating employee */ if('' == $errors) { $trans_family_name = translit($family_name); $trans_first_name = translit($first_name); $trans_fathers_name = translit($fathers_name); $account = $trans_family_name.substr($trans_first_name, 0, 1).substr($trans_fathers_name, 0, 1); $dn = 'CN='.$family_name.' '.$first_name.' '.$fathers_name.','.$dep; //Getting manager $filter = '(&(objectClass=user)(objectCategory=PERSON))'; $sr = ldap_search($connect, $dep, $filter); $info = ldap_get_entries($connect, $sr); //echo Arratomy($info); $manager = $info[0]['manager'][0]; $department = explode(',', $dep); $department = str_replace('OU=', '', $department[0]); $newuser['cn'] = $family_name.' '.$first_name.' '.$fathers_name; $newuser["objectclass"][0] = "top"; $newuser["objectclass"][1] = "person"; $newuser["objectclass"][2] = "organizationalPerson"; $newuser["objectclass"][3] = "user"; $newuser['displayname'] = $family_name.' '.$first_name.' '.$fathers_name; $newuser['givenname'] = $first_name.' '.$fathers_name; $newuser['name'] = $family_name.' '.$first_name.' '.$fathers_name; $newuser['sn'] = $family_name; $newuser['description'] = $position; $newuser['mobile'] = $tel_num; $newuser['samAccountName'] = $account; $newuser['userPrincipalName'] = $account.'@xxx.local'; $newuser['title'] = $position; $newuser['department'] = $department; $newuser['manager'] = $manager; $newuser['useraccountcontrol'] = 0x0002; // Account disabled $newuser['pwdLastSet'] = 0; // User must change password $newuser['userPassword'] = '123321'; //echo '<h2>New AD user</h2>'.Arratomy($newuser); $result = ldap_add($connect, $dn, $newuser); if($result) {echo '<div class="success"> </div>';} else {$errors = ldap_error($connect);} } if('' != $errors) {echo '<h2 style="color:red;"></h2><div class="errors">'.$errors.'</div>';} } 


Of course, it may happen that you do not need to fill in so many user attributes, or vice versa - that they will need much more. However, such a set already shows much more clearly what will be encountered.
Critical variables are:

  $dn = 'CN=  ,OU=!Users_all,DC=xxx,DC=local'; // Distinguished name $newuser['cn'] = $family_name.' '.$first_name.' '.$fathers_name; $newuser["objectclass"][0] = "top"; $newuser["objectclass"][1] = "person"; $newuser["objectclass"][2] = "organizationalPerson"; $newuser["objectclass"][3] = "user"; $newuser['samAccountName'] = $account; $newuser['userPrincipalName'] = $account.'@xxx.local'; 


Without everything else, as a rule, you can do.

Putting it all together (+ styles and service functions):
 <style> .tree {height:500px; overflow-y:scroll; border:1px solid #ccc;} .tree li:hover {cursor:pointer;} .tree input {display:inline;} .errors {margin:10px 0px; border: 1px dotted red; padding:10px;} .success {margin:10px 0px; border: 1px dotted green; padding:10px;} </style> <?php //ini_set('display_errors','On'); error_reporting(E_ALL | E_STRICT); /* Service functions */ function Arratomy($array) { $result = "\n".'<span>Array (<b>'.sizeof($array).'</b> items)</span>'."\n".'<ol>'."\n"; foreach ($array as $key => $value) { $result .= '<li>'; if(is_array($value)) {$result .= '<b>'.$key.'</b>: '.Arratomy($array[$key]);} else {$result .= '<b>'.$key.'</b>: '.$value.'</br>'."\n";} $result .= '</li>'; } $result .= '</ol>'."\n"; return $result; } function translit($text) { $alphabet_ru = array ( '','','','','','','','', '','','','','','','','', '','','','','','','','', '','','','','','','','','', '','','','','','','','', '','','','','','','','', '','','','','','','','', '','','','','','','','','', ' ' ); $alphabet_eng = array ( 'e','y','ts','u','k','e','n','g', 'sh','sch','z','h','','f','y','v', 'a','p','r','o','l','d','j','e', 'ya','ch','s','m','i','t','','b', 'yu', 'E','Y','Ts','U','K','E','N','G', 'Sh','Sch','Z','H','','F','Y','V', 'A','P','R','O','L','D','J','E', 'Ya','Ch','S','M','I','T','','B', 'Yu', '_' ); return str_replace($alphabet_ru, $alphabet_eng, $text); } /* Connection parameters */ $ldap_host = "xxx.local"; # domain controller or ip-address $ldap_port = "389"; # port for connection // $filter = "ou=*"; # search any department // overridden in the function // $base_dn = "OU=!Users_all,DC=xxx,DC=local"; # specific OU // overridden in the function $ldap_user ="admin@xxx.local"; # AD-user $ldap_pass = "123321";# AD-user's password /* Open connection */ $connect = ldap_connect( $ldap_host, $ldap_port); ldap_set_option($connect, LDAP_OPT_PROTOCOL_VERSION, 3); ldap_set_option($connect, LDAP_OPT_REFERRALS, 0); $bind = ldap_bind($connect, $ldap_user, $ldap_pass); /* Input check */ //echo '<h2>POST</h2>'.Arratomy($_POST); $errors = ''; /* EXAMPLE OF CORRECT POST new_emp: 1 family_name:  first_name:  fathers_name:  position:  tel_num: +7(999) 999-9999 dep:      */ if(isset($_POST['new_emp'])) { foreach($_POST as $key => $value) { if('' == $value) {$errors .= ' '.$key.'  <br/>'; break;} else {$$key = $value;} } if(!isset($_POST['dep'])) {$errors .= ' «»  <br/>';} /* Creating employee */ if('' == $errors) { $trans_family_name = translit($family_name); $trans_first_name = translit($first_name); $trans_fathers_name = translit($fathers_name); $account = $trans_family_name.substr($trans_first_name, 0, 1).substr($trans_fathers_name, 0, 1); $dn = 'CN='.$family_name.' '.$first_name.' '.$fathers_name.','.$dep; //Getting manager $filter = '(&(objectClass=user)(objectCategory=PERSON))'; $sr = ldap_search($connect, $dep, $filter); $info = ldap_get_entries($connect, $sr); //echo Arratomy($info); $manager = $info[0]['manager'][0]; $department = explode(',', $dep); $department = str_replace('OU=', '', $department[0]); $newuser['cn'] = $family_name.' '.$first_name.' '.$fathers_name; $newuser["objectclass"][0] = "top"; $newuser["objectclass"][1] = "person"; $newuser["objectclass"][2] = "organizationalPerson"; $newuser["objectclass"][3] = "user"; $newuser['displayname'] = $family_name.' '.$first_name.' '.$fathers_name; $newuser['givenname'] = $first_name.' '.$fathers_name; $newuser['name'] = $family_name.' '.$first_name.' '.$fathers_name; $newuser['sn'] = $family_name; $newuser['description'] = $position; $newuser['mobile'] = $tel_num; $newuser['samAccountName'] = $account; $newuser['userPrincipalName'] = $account.'@xxx.local'; $newuser['title'] = $position; $newuser['department'] = $department; $newuser['manager'] = $manager; $newuser['useraccountcontrol'] = 0x0002; // Account disabled $newuser['pwdLastSet'] = 0; // User must change password $newuser['userPassword'] = '123321'; //echo '<h2>New AD user</h2>'.Arratomy($newuser); $result = ldap_add($connect, $dn, $newuser); if($result) {echo '<div class="success"> </div>';} else {$errors = ldap_error($connect);} } if('' != $errors) {echo '<h2 style="color:red;"></h2><div class="errors">'.$errors.'</div>';} } /* Hierarchical tree */ function build_tree($connect, $ou = '', $base_dn = 'OU=!Users_all,DC=xxx,DC=local') { $specific_dn = $base_dn; if ('' != $ou) {$specific_dn = 'OU='.$ou.','.$base_dn;} $filter = 'ou=*'; $justthese = array("ou"); $sr = ldap_list($connect, $specific_dn, $filter, $justthese); $info = ldap_get_entries($connect, $sr); $result = ''; for ($i=0; $i < $info["count"]; $i++) { $specific_ou = $info[$i]["ou"][0]; $result .= '<ul>'; $result .= '<li><input type="radio" name="dep" value="OU='.$specific_ou.','.$specific_dn.'" title="'.$specific_ou.'" /> '.$specific_ou; $result .= build_tree($connect, $specific_ou, $specific_dn); $result .= '</li>'; $result .= '</ul>'; } return $result; } /* Output */ echo ' <form method="POST" action="'.$_SERVER['REQUEST_URI'].'"> <h3></h3> <input type="hidden" name="new_emp" value="1" /> <input type="text" name="family_name" value="" size="20" /> <input type="text" name="first_name" value="" size="20" /> <input type="text" name="fathers_name" value="" size="20" /> <br/> <h3></h3> <input type="text" name="position" value="" size="40" /> <br/> <h3>  </h3> <input type="text" name="tel_num" value="+7(999) 999-9999" size="20" /> <h3></h3> <div class="tree"> '.build_tree($connect).' </div> <br/> <input type="submit" value="" /> </form>'; /* Close connection */ ldap_close($connect); ?> 



Source: https://habr.com/ru/post/160681/


All Articles