Предупреждение.
Всё нижеследующее вы можете использовать на свой страх и риск! Автор не несёт никакой ответственности за возможные риски: утерю информации, некорректное функционирование программного обеспечения и т.п.
Постановка задачи.
Имеется веб-портал SharePoint Services 3.0, аутентификация пользователей в котором происходит по локальным учётным записям на самом сервере. Требуется ввести сервер в домен Active Directory и использовать для аутентификации на портале учётные записи из домена.
1. Получение информации об имеющихся на портале учётных записях
Запускаем MS SQL Enterprise Manager, открываем базу данных WSS_Content. Информация о пользователях находится в таблице UserInfo. Запускаем из Enterprise Manager'а инструмент SQL Query Analyzer, в которм выполняем следующий запрос:
select tp_SystemID, tp_Login, tp_Title
from UserInfo;
Полученную информацию копируем в таблицу Excel. В выбранных колонках находятся: SID пользователя, логин пользователя вместе с доменом в виде "ДОМЕН\Логин", строка описания пользователя. SID пользователя в базе данных хранится в двоичном виде, а Query Analyzer выводит его в шестнадцатеричном виде.
После этого в таблице должны иметься следующие столбцы:
A - шестнадцатеричный SID локальной учётной записи,
B - логин локальной учётной записи,
C - описание локальной учётной записи.
2. Добавляем в полученный список столбец с учётными записями пользователей из домена
Каждой учётной записи, используемой для входа на портал, нужно сопоставить учётную запись из домена. Возможно, на этом этапе понадобится завести в домене учётные записи недостающих пользователей.
После этого в таблице должны иметься следующие столбцы:
A - шестнадцатеричный SID локальной учётной записи,
B - логин локальной учётной записи,
C - описание локальной учётной записи,
D - логин доменной учётной записи.
3. Получение SID пользователей из домена
Берём программу user2sid Евгения Рудного по ссылке
http://evgenii.rudnyi.ru/programming.html#sid2user. Копируем столбец D в текстовый файл, а в начале каждой строки добавляем команду user2sid. Копируем получившийся bat-файл в каталог с программой. Запускаем bat-файл, перенаправив вывод из него в другой текстовый файл. В полученном текстовом файле убираем всё, кроме SID'ов, так чтобы в каждой строчке файла было по одному SID'у. Информацию из текстового файла добавляем в столбец E файла Excel.
После этого в таблице должны иметься следующие столбцы:
A - шестнадцатеричный SID локальной учётной записи,
B - логин локальной учётной записи,
C - описание локальной учётной записи,
D - логин доменной учётной записи,
E - SID доменной учётной записи.
Будьте внимательны! В списке должны присутствовать ровно столько SID'ов пользователей, сколько их имелось в первоначальном столбце. Также они должны следовать точно в таком же порядке, как в Excel-файле. Если что-то идёт не так, нужно поправить Excel-таблицу и bat-файл и повторить этот этап снова.
4. Конвертирование доменных SID в шестнадцатеричный вид
Для понимания того, каким образом SID хранится в двоичном виде в системе, можно воспользоваться следующей статьёй:
Microsoft Security Descriptor(SID)Attributes.
Пишем на PHP сценарий для конвертирования SID:
<?
function swap($hexdword)
{
$res = "";
for($i = 6; $i >= 0 ; $i -= 2)
$res .= $hexdword[$i] . $hexdword[$i+1];
return $res;
}
function sid2hex($sid)
{
$sidl = explode("-", $sid);
$hex_sid = "0x" .
sprintf("%02X", $sidl[1]+0) .
sprintf("%02X", $sidl[2]+0) .
"000000000005";
for($i = 0; $i < $sidl[2]; $i++)
$hex_sid .= swap(sprintf("%08X", $sidl[3+$i]+0));
return $hex_sid;
}
function hex2sid($hex_sid)
{
$hex_sid = trim($hex_sid);
$sidl[0] = "S";
$sidl[1] = hexdec(substr($hex_sid, 2, 2));
$sidl[2] = hexdec(substr($hex_sid, 4, 2));
for($i = 0; $i < $sidl[2]; $i++)
$sidl[3+$i] = hexdec(swap(substr($hex_sid, 18+$i*8, 8)));
$sid = implode("-", $sidl);
return $sid;
}
$sids = "S-1-5-21-583367659-4273102991-479599032-4176
S-1-5-21-583367659-4273102991-479599032-4450";
$sidsl = explode("\n", $sids);
foreach ($sidsl as $sid)
echo sid2hex($sid) . "<br>";
?>
Для того, чтобы быть уверенным в правильности написанных функций, я написал их пару. Проверив, что преобразование SID в шестнадцатеричный вид и обратно, не искажает его, я удостоверился, что функции написаны правильно.
В вышеприведённом сценарии я оставил только пару SID'ов. Вам следует вставить на место этих двух SID'ов содержимое столбца E. Полученный после выполнения сценария результат нужно скопировать в столбец F.
После этого в таблице должны иметься следующие столбцы:
A - шестнадцатеричный SID локальной учётной записи,
B - логин локальной учётной записи,
C - описание локальной учётной записи,
D - логин доменной учётной записи,
E - SID доменной учётной записи,
F - шестнадцатеричный SID доменной учётной записи.
5. Получение SQL-запросов для миграции портала на доменные учётные записи
Забегая вперёд, я хочу сказать, что обнаружил в базе данных ещё одну таблицу, в которой упоминаются логины пользователей. Эти логины не используются для проверки входа пользователей, они используются лишь для вывода информации о пользователе. Можно не менять их - в конце концов мы занимаемся не вполне чистым делом, а грязным хаком, а можно поменять, чтобы несоответствие реального логина и информации о логине не бросалось в глаза. итак, эта информация находилась в таблице AllUserData в поле nvarchar3.
Теперь мы можем написать в Excel'е формулы, которые сгенерируют нам SQL-запросы, необходимые для внесения необходимых изменений в БД SharePoint Services.
G ="update UserInfo set tp_Login = '" & D2 &"', tp_SystemID = " & F2 & " where tp_Login = '" & B2 &"' "
H ="update AllUserData set nvarchar3 = '" & D2 &"' where nvarchar3 = '" & B2 &"' "
Чтобы не бросаться голой задницей на амбразуру, подготовим SQL-запросы для отката навороченного:
I ="update UserInfo set tp_Login = '" & B2 &"', tp_SystemID = " & A2 & " where tp_Login = '" & D2 &"' "
J ="update AllUserData set nvarchar3 = '" & B2 &"' where nvarchar3 = '" & D2 &"' "
После этого в таблице должны иметься следующие столбцы:
A - шестнадцатеричный SID локальной учётной записи,
B - логин локальной учётной записи,
C - описание локальной учётной записи,
D - логин доменной учётной записи,
E - SID доменной учётной записи,
F - шестнадцатеричный SID доменной учётной записи,
G - SQL-запрос для обновления информации в таблице UserInfo,
H - SQL-запрос для обновления информации в таблице AllUserData,
I - SQL-запрос для отката обновления таблицы UserInfo,
J - SQL-запрос для отката обновления таблицы AllUserData.
Создаём два текстовых файла - update.txt и rollback.txt. В первый копируем столбцы G и H, а во второй - I и J.
6. Миграция
Для миграции нужно выделить перерыв обслуживания примерно в 15 минут. За это время можно будет выполнить SQL-запросы из файла update.txt и ввести компьютер в домен. На случай если что-то пойдёт не так, лучше увеличить паузу до 30 минут, чтобы вывести компьютер из домена и выполнить SQL-запросы из файла rollback.txt.
На случай же если же что-то пойдёт совсем не так, следует заготовить резервную копию базы данных. Перед снятием резервной копии нужно перевести базу данных портала в режим "Только чтение" через "Центр администрирования" SharePoint Services, вкладку "Управление приложениями", пункт "Квоты и блокировки семейства узлов", а затем снять резервную копию средствами MS SQL Enterprise Manager. После восстановления следует не забыть восстановить режим "Нет блокировки".
Я выполнял обновление из дома, глубоким вечером, разумеется проработав в рабочее время сценарий миграции и текстовые файлы с SQL-запросами.
7. Кое-что ещё
Дополнительно, я поменял учётную запись администратора SharePoint Services в "Центре администрирования" на доменную. Поменял я её в базе данных SharePoint_Admincontent_многобукв в таблицах AllUserData и UserInfo. Это уже не столь критично и не столь сложно. Администраторов мало и они, в отличие от пользователей, могут выдержать и больший перерыв в обслуживании.