(495) 925-0049, ITShop интернет-магазин 229-0436, Учебный Центр 925-0049
  Главная страница Карта сайта Контакты
Поиск
Вход
Регистрация
Рассылки сайта
 
 
 
 
 

Автоматизация миграции базы данных DocsVision

Источник: habrahabr
Namelles_One

Преамбула

Казалось бы - если система закрытая, то должны быть удобные инструменты? Ну, или хотя бы API для возможности написания этих удобных инструментов самостоятельно.

К сожалению, обычно все плохо: инструменты есть, но настолько неудобные, что от их наличия - никакого счастья. Приходится выкручиваться.

Итак, дано - система DocsVision (далее DV) версии 4.5 SR1. И, стоит задача переместить базу с одного сервера на другой (скажем, клиенты купили новый). Проблема, которая при этом возникает - ровно одна.

Права на объекты для локальных учетных записей при переносе базы на новое место превратятся в тыкву. А так как стандартные группы DV являются именно локальными - то проблем не избежать.

Кто заинтересован - прошу пожаловать под кат.

Стандартные инструменты

Для начала рассмотрим тот инструмент, что нам предлагает для этих целей компания DocsVision.
Он описан по ссылке dvprofessionals.blogspot.com/2010/03/blog-post_22.html

Казалось бы - это то, что нам нужно, но - только на первый взгляд.

image

Как видно из скриншота - только по одной записи за раз, что даже в случае пары десятков локальных учеток - ну очень неудобно. А, исходя из реального опыта - клиенты без домена встречаются не реже, чем клиенты с доменом. И в этом случае - все пользователи заведены на сервере локально. И руками обрабатывать сотню-другую учеток - ничуть не улыбается.

Поэтому и было принято решение - написать нечто свое.

Исследование структуры БД

DocsVision - платформа закрытая и документирована только в рамках предоставленных разработчикам API. Но, кое-какая информация все-таки по интернету гуляет, и ее оказалось достаточно.

Основными интересующими нас таблицами являются dvsys_instances и dvsys_security. Первая содержит информацию обо всех объектах системы (карточки, папки, справочники, файлы и т.д.), вторая же. не мудрствуя лукаво, хранит описатели безопасности. Структура таблиц приведена ниже.

image
 
image
 

Связь таблиц осуществляется по полям dvsys_instances.SDID и dvsys_security.ID. Также, необходимо отметить, что количество записей в этих таблицах различается очень сильно, спасибо наследованию прав. Например, у одного из клиентов эти значения составляют 277571 и 6639 соответственно.

Итак, задача поставлена - необходимо пройтись по всем строкам второй таблицы, раскодировать описатели безопасности, заменить старые SID для необходимых записей на новые и, предварительно закодировав, записать обратно. Что ж, приступим.

Реализация задуманного

В качестве языка разработки был выбран PowerShell, так как большую часть необходимых задач с его помощью можно решить легко и непринужденно.

Для удобства использования все настройки были вынесены в отдельный файл. К таковым можно отнести таблицу соответствия аккаунтов и настройки доступа к БД.

$SIDReplacement = @{ "S-1-5-21-2179127525-659978549-3108502893-1019" = "a31003\akushsky"; #akushsky "S-1-5-21-2179127525-659978549-3108502893-1016" = "a31003\ASPNET"; #ASPNET "S-1-5-21-2179127525-659978549-3108502893-1008" = "a31003\DocsVision Administrators"; #DV Administrators "S-1-5-21-2179127525-659978549-3108502893-1010" = "a31003\DocsVision Power Users"; #DV Power Users "S-1-5-21-2179127525-659978549-3108502893-1012" = "a31003\DocsVision Users"; #DV Users "S-1-5-21-2179127525-659978549-3108502893-1026" = "a31003\dobriy"; #DV Editors } $SQLServerName = "a31003" $SQLDatabaseName = "DV-BASE"

Мне показалось логичнее запускать скрипт на целевом сервере, поэтому старые учетные записи присутствуют в виде SID-ов (для их получение также можно использовать PowerShell, об этом знает Гугл). А новые - укажем в виде учеток и их SID-ы получим в процессе работы скрипта.

Также, как выяснилось в процессе разработки, PowerShell не умеет создавать экземпляры объектов generic-ков, поэтому из недр Гугла для этого пришлось достать функцию New-GenericObject. Ее код приводить не буду, в конце статьи будет ссылка на репозитарий - все там.

Для удобства, при работе скрипта, в консоль выводится лог, поэтому было решено создать структуру для более удобного накапливания информации.

# Struct for log add-type @" public struct DVObject { public string ID; public string Description; public string Accounts; } "@

Для наиболее полного логирования запрос, конечно же, возвращает гораздо больше информации, чем мог бы, но - красота требует жертв.

SELECT I.InstanceID, I.Description, S.ID, S.SecurityDesc FROM [DV-BASE].[dbo].[dvsys_security] S LEFT JOIN [DV-BASE].[dbo].[dvsys_instances] I ON I.SDID = S.ID

Поэтому, чтобы не обрабатывать один и тот же описатель много раз - идентификаторы записываются.

# Replace SDDL in each row only once $IDList = New-Object System.Collections.Generic.HashSet[Guid] ... # We need only one SQL-request for each ID if ($IDList.Contains($row["ID"])) {continue} else {$isOk = $IDList.Add($row["ID"])}

А далее начинается самое интересное:

  1. Полученный SecurityDesc представляет собой бинарную последовательность символов, закодированную Base64. А, для подмены SID-ов нам необходимо получить SDDL-строку. Описание формата есть на MSDN. А теперь то же самое, только кодом:

    # Convert SDDL from Base64 to binary form $ObjectWithSDDL = ([wmiclass]"Win32_SecurityDescriptorHelper") .BinarySDToSDDL([System.Convert]::FromBase64String($row["SecurityDesc"])) $sddl = $ObjectWithSDDL.SDDL

  2. Далее, вычленяя при помощи регулярки SID-ы из SDDL-строки, проверяем их по таблице соответствия и, в случае совпадения, подменяем.

    # Match all SIDs and replace [regex]::Matches($sddl,"(S(-\d+){2,8})") / sort index -desc / % { if ($SIDReplacement.ContainsKey($_.ToString())) { # Translate NT account name to SID $objUser = New-Object System.Security.Principal.NTAccount($SIDReplacement[$_.ToString()]) $strSID = $objUser.Translate([System.Security.Principal.SecurityIdentifier]) # Replace it in SDDL $sddl = $sddl.Remove($_.index,$_.length) $sddl = $sddl.Insert($_.index,$strSID.Value) # Add to list of current object accounts $dvobject.Accounts += $SIDReplacement[$_.ToString()] $dvobject.Accounts += "`n" # Set replace completed $replaceComplete = $true } }

  3. Если замена была произведена, то тогда необходимо произвести обратные действия и записать данное изменение в БД:
    if ($replaceComplete) { # Add current info object to list $DVObjectList.Add($dvobject) $binarySDDL = ([wmiclass]"Win32_SecurityDescriptorHelper").SDDLToBinarySD($sddl).BinarySD $ret = [System.Convert]::ToBase64String($binarySDDL) ##### Update database ##### # Update query for currently replaced SDDL $SqlQuery = "UPDATE [dbo].[dvsys_security] SET Hash = '" + $binarySDDL.GetHashCode() + "', SecurityDesc = '" + $ret + "' WHERE ID = CONVERT(uniqueidentifier, '" + $row["ID"] + "')" # Attach query to command $UpdateSqlCmd.CommandText = $SqlQuery # Execute update query if ($UpdateSqlCmd.ExecuteNonQuery()) { Write-host "Update true for ID: " $row["ID"] } else { Write-host "Update false for ID: " $row["ID"] } }

Таким образом, получен универсальный механизм для любой миграции - между серверами заказчика, между сервером разработки и заказчиком, да мало ли еще как.

В конце, как и было обещано: ссылка на репозитарий с описанным кодом.

Ссылки по теме


 Распечатать »
 Правила публикации »
  Написать редактору 
 Рекомендовать » Дата публикации: 30.01.2014 
 

Магазин программного обеспечения   WWW.ITSHOP.RU
VMware Workstation 14 Player for Linux and Windows, ESD
VMware Fusion 10 Pro, ESD
ABViewer Professional пользовательская
IBM Domino Messaging Server Processor Value Unit (PVU) License + SW Subscription & Support 12 Months
The BAT! Professional - 1 компьютер
 
Другие предложения...
 
Курсы обучения   WWW.ITSHOP.RU
 
Другие предложения...
 
Магазин сертификационных экзаменов   WWW.ITSHOP.RU
 
Другие предложения...
 
3D Принтеры | 3D Печать   WWW.ITSHOP.RU
 
Другие предложения...
 
Новости по теме
 
Рассылки Subscribe.ru
Информационные технологии: CASE, RAD, ERP, OLAP
Новости ITShop.ru - ПО, книги, документация, курсы обучения
Программирование на Microsoft Access
CASE-технологии
СУБД Oracle "с нуля"
Утиль - лучший бесплатный софт для Windows
Мастерская программиста
 
Статьи по теме
 
Новинки каталога Download
 
Исходники
 
Документация
 
 



    
rambler's top100 Rambler's Top100