This article introduce a script to Script to convert SVN-based permission file (authz) to Windows-based permission file (authz-windows) in VisualSVN server.
VisualSVN Server is a good SVN server for Windows-based. By default, authentication in VisualSVN server is based on 2 files: authorization file (password is encoded with htpassword) and permission file. If later, we intend to use Windows/AD-based authentication for SVN server, then how can we keep all granted permission for users along all SVN repositories?
An example of authz file is as follows
[/] user1=rw [RD:/] user2=rw [RD:/analytics] user2=rw user3=rw user4=rw
An exmple of authz.windows is as follows:
[/] S-1-5-21-3028427551-2588925682-1401053627-1114=rw [RD:/] S-1-5-21-3028427551-2588925682-1401053627-1734=rw [RD:/analytics] S-1-5-21-3028427551-2588925682-1401053627-1734=rw S-1-5-21-3028427551-2588925682-1401053627-1868=rw S-1-5-21-3028427551-2588925682-1401053627-1855=rw
We can write a PHP script to convert authz -> authz-windows by generating Windows SID from current username:
<?php define('SVN_REPOSITORY_ROOT_FOLDER','/data/www/test'); define('SOURCE_AUTHZ_FILE', 'authz'); define('DEST_AUTHZ_WINDOWS_FILE', 'authz-windows'); doProcess(); /** * Convert a username to an AD-based SID. * NOTE: Stupid processing method, since we establish 1 connection per username. But who cares when the amount of users is not too large :D/ */ function convertUsernameToSID($bind_username_to_search = "BIND_USER_NAME") { $suffix ="@YOURDOMAIN.com"; $base_dn = "ou=YOUR_OU_Users,dc=YOURDOMAIN,dc=com"; $server = "ldaps://www.YOUR_WEBSITE.com:636"; $bind_username = "binduser"; $bind_password = "bindpassword"; $ds = ldap_connect($server); ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3); ldap_set_option($ds, LDAP_OPT_REFERRALS, 0); $r = ldap_bind($ds, $bind_username.$suffix, $bind_password); $sr = ldap_search($ds, $base_dn, "(samaccountname=".$bind_username_to_search.")"); @$entries = ldap_get_entries($ds, $sr); if (empty($entries)) return '';//-- find nothing T__T // All SID's begin with S- $sid = "S-"; // Convert Bin to Hex and split into byte chunks @$sidinhex = str_split(bin2hex($entries[0]['objectsid'][0]), 2); // Byte 0 = Revision Level @$sid = $sid.hexdec($sidinhex[0])."-"; // Byte 1-7 = 48 Bit Authority @$sid = $sid.hexdec($sidinhex[6].$sidinhex[5].$sidinhex[4].$sidinhex[3].$sidinhex[2].$sidinhex[1]); // Byte 8 count of sub authorities - Get number of sub-authorities @$subauths = hexdec($sidinhex[7]); //Loop through Sub Authorities for($i = 0; $i < $subauths; $i++) { $start = 8 + (4 * $i); // X amount of 32Bit (4 Byte) Sub Authorities @$sid = $sid."-".hexdec($sidinhex[$start+3].$sidinhex[$start+2].$sidinhex[$start+1].$sidinhex[$start]); } return $sid; } /** * Main process: Read each lines of file, do covert if needed, and write to the target file */ function doProcess() { $filearray = file(SVN_REPOSITORY_ROOT_FOLDER . DIRECTORY_SEPARATOR . SOURCE_AUTHZ_FILE); if (!($filearray)) { echo "Cannot read file!!!!"; return; } $group_name_mapping = array ( '@group1custom' => 'GROUP-NAME-1', '@group2custom' => 'GROUP-NAME-2', ); //-- map pre-defined groups in SVN server to AD-based group name $permission_pattern = '/(@?[0-9a-zA-Z]+)s?=s?([a-z]*)/'; $prev_mapped_username = array(); $str_output_to_write = ''; while (list(,$oneline) = each($filearray)) { if (preg_match_all($permission_pattern, $oneline, $matches)) { if (isset($matches[1]) && isset($matches[2])) { $object_name = $matches[1][0]; $permission = $matches[2][0]; //-- If it is a pre-defined group: (1) retrieved according group in AD (2) convert the name to SID if (substr($object_name, 0, 1) == '@') { if (isset($prev_mapped_username[$object_name])) { $group_sid = $prev_mapped_username[$object_name]; } else { if (isset($group_name_mapping[$object_name])) { $group_sid = convertUsernameToSID($group_name_mapping[$object_name]); $prev_mapped_username[$object_name] = $user_sid; } } if (!empty($group_sid)) { $str_output_to_write .= $group_sid . '=' . $permission . PHP_EOL; } } else { if (isset($prev_mapped_username[$object_name])) { $user_sid = $prev_mapped_username[$object_name]; } else { $user_sid = convertUsernameToSID($object_name); $prev_mapped_username[$object_name] = $user_sid; } if (!empty($user_sid) && @strlen($user_sid) >= 20) //-- TRICK: Remove non-valid SIDs { $str_output_to_write .= $user_sid . '=' . $permission . PHP_EOL; } } } else { $str_output_to_write .= $oneline; } } else { if (substr($oneline, 0, 1) == '*') { continue; //-- Remove ALL * access. To be improved: Might replace with Everyone? } else { $str_output_to_write .= $oneline; } } //echo $oneline . '<br />'; } if (!empty($str_output_to_write)) { $fp = fopen(SVN_REPOSITORY_ROOT_FOLDER . DIRECTORY_SEPARATOR . DEST_AUTHZ_WINDOWS_FILE, 'w'); if (!empty($fp)) { fwrite($fp, $str_output_to_write); fclose($fp); echo 'DONE!!'; } else { echo 'Cannot open ' . SVN_REPOSITORY_ROOT_FOLDER . DIRECTORY_SEPARATOR . DEST_AUTHZ_WINDOWS_FILE; } } }