[Из песочницы] Автоматизация легкого управления списками баз 1С
Наверное, вам в работе, как и мне, часто приходится заниматься ИТ-системами компаний, которые до тебя непонятно кем и как обслуживались. Прежде чем полноценно поставить компанию на обслуживание необходимо обязательно сделать ИТ-Аудит и привести все системы в порядок.
Часто дной из систем, где порядок отсутствует, является система 1С. Например, можно встретить базы с названием папок «new_copybase1_old» или «База1КомпанияЗП», или вообще вложенные друг в друга папки.
Кто и какой имеет к данным базам доступ определить порой крайне сложно. Списки баз на клиентских компьютерах, в самом приложении 1С, тоже могут быть названы непонятно. В общем, не очень радостная картина.
Если у вас пришло время привести все базы к одному общему стандарту и автоматизировать подключение пользователей, то прошу под кат.
Привести все базы к общему стандарту, навести порядок — все это хорошо! Но как это сделать наиболее быстро и эффективно?
Поиск готового решения
Поиск в Сети показал, что лучшие статьи на эту тему есть на «Хабре»:
1. «Управление списками баз 1С 8.2»;
2. «Как приготовить сотни баз 1С и не сойти с ума»;
3. «Управление списком баз 1С 8.2 с помощью Active Directory»;
4. «Легкое управление списками баз 1С».
Статья «Легкое управление списками баз 1С» пользователя Sergey-S-Kovalev показалась самой полезной, она начинается со знаменитой цитаты:
«Лучше день потерять, а потом за пять минут долететь» © м/ф Крылья, ноги и хвосты.
Но не все так быстро и просто.
Итак, настройка по статье пользователя Sergey-S-Kovalev заключается в выполнении шагов, которые разбиты на 6 этапов.
Этап 1 — Инвентаризация;
Этап 2 — Группы AD для баз 1С;
Этап 3 — Файлы конфигураций 1С;
Этап 4 — Файловый или DFS ресурс;
Этап 5 — Групповые политики;
Этап 6 — Пользователь.
Шаги в этапах 1, 5 реализуются один раз для каждой из компаний, в них нет никакой рутины, легко можно сделать руками.
Схема настройки, которую предлагает Sergey-S-Kovalev, великолепная! Никаких скриптов, все работает просто и понятно. Но придётся потерять не день, а намного больше, если вам необходимо настроить данную схему работы, например, в 10 компаниях, в которых в совокупности может быть около 200 баз 1С.
То есть первоначальная настройка в большой компании может быть очень долгой и нудной.
Я предлагаю автоматизировать часть шагов и сократить количество этапов.
Чтобы лучше понять о чем я, рекомендую сначала ознакомится «Легкое управление списками баз 1С».
Этап 1 — Инвентаризация
1. Создаем на общем для бухгалтерии ресурсе Excel файл, как показано на рисунке.
Обязательно вносим в данный файл названия старых баз и папок, OldBaseName, OldFolderName. В итоговом файле мы данные колонки удалим, но на первом этапе они нам будут полезны, чтобы понимать, откуда и куда копировать базы. Файл можно взять здесь.
2. Вместе с самым-самым главным бухгалтером компании заполняем поля:
BaseName, FolderName, GroupName, AccessUser(1-7)
- Колонка
BaseName
заполняется вручную на русском языке согласно стандарту, например, ИП-Иванов_БУХ. - Колонка
FolderName
заполняется вручную на латинице согласно стандарту, в нашем случае IP-IVANOV_BUH. - Имя группы AD уже генерируется на основании колонки
FolderName
, в нашем случае GRRS_IP-IVANOV_BUH, думаю, знаете, как в Excel можно дополнить содержимое ячеек на основе информации из других ячеек. - Проставить доступы к базам в полях AccessUser можно попросить самого, самого главного бухгалтера, но и ему тоже можно облегчить работу. Для этого необходимо взять список бухгалтерских учеток из AD, например, при помощи команды
Get-Aduser -searchbase "OU=Accountants, DC=domain, DC=com" -filter * -Properties SamAccountname | FT SamAccountname
и поместить данный список на второй лист нашего файла. - Далее к полям AccessUser необходимо сделать привязку данного списка. Если не знаете, как, то спросите у Google примерно следующее «How to add a drop-down list to an Excel cell», или просто используйте мой файл.
В итоге, самый, самый главный бухгалтер просто проставит доступы для каждой базы, выбирая пользователей из списка. Список можно предварительно упорядочить средствами самого Excel, например, самые часто встречаемые учетные записи поместить в начало.
3. После заполнения данного файла, его необходимо сохранить и сделать копию.
В его копии необходимо удалить колонки OldBaseName, OldFolderName
. Получится следующий файл.
От файла Sergey-S-Kovalev, он отличается тем, что в нем сразу проставлены доступы для пользователей, нет описания, имен серверов и кластеров. В моем окружении данная информация лишняя и я ее не стал включать в файл.
Этап 2 — Запуск скрипта
Наверное, вам уже понятно, что файлом, который получился в результате первого этапа, мы накормим скрипт. Скрипт выполнит все действия, которые Sergey-S-Kovalev описал в этапах 2,3,4,6.
Что же сделает скрипт:
1.Создаст группы в AD для каждой базы.
2.Добавит в поле description каждой группы путь к папке с базой.
3.В поле notes каждой группы, добавит название базы и путь к папке с базой.
4.Добавит в группы доступа пользователей согласно списку.
5.Сгенерирует общий файл 1CEStart.cfg со списком всех баз, и разместит данный файл в сетевой папке с конфигурационными файлами 1С.
6.Сгенерирует v8i-файлы для каждой базы и разместит данные файлы в сетевой папке с конфигурационными файлами 1С.
7.Пропишет для каждого v8i-файла в списках доступа соответствующую группу.
8.Создаст папки для баз и пропишет в списках доступа к папке соответствующую группу.
В общем скрипт сделает почти все, что Sergey-S-Kovalev в своей статье делал вручную.
Перед запуском скрипта необходимо следующее.
(Автоматизация этих действий пока только в планах)
Создать группы AD
1. Создать в домене OU для хранения групп с доступом к базам 1C. В моем примере это будет $OU = «OU=1C, OU=Resources, DC=domain, DC=ru»
2. Создать в данной OU группу GRRS_1C_ConfigBasesRO. Добавить в группу GRRS_1C_ConfigBasesRO группу «Domain computers»
3. Создать в данной OU группу GRRS_1CBases.
4. Создать в данной OU группу GRUS_1Cadmins и добавить в нее админов 1С (опционально)
Создать папки
1. Создать на сервере 1С папку для хранения баз. В нашем случае это будет 1cshare
2. К папке 1cshare необходимо дать доступ группе GRRS_1CBases на запись, в разрешениях на вкладке Share.
3. На вкладке Security удалить группу Users и прописать разрешения на чтение для группы GRRS_1CBases.
4. Создать в домене общую DFS-папку или просто папку, например, \\DfsShare\1cconfig\
5. В этой папке будут лежать конфигурационные файлы 1С.
6. К папке \\DfsShare\1cconfig\ дать доступ группе GRRS_1C_ConfigBasesRO только для чтения.
Необходимо, чтобы пользователь, от которого будет запускаться скрипт, имел права записи в папку \\DfsShare\1cconfig\.
Требования к запуску скрипта
В скрипте реализовано чтение Excel-файла при помощи Microsoft Access Database Engine 2010 Redistributable
Лучше сразу установить данный продукт на сервер, с которого будет запускаться скрипт.
Движок скачать можно здесь. Важно, чтобы разрядность платформы компьютера совпадала с разрядностью движка.
Внимание! Если заходите запустить скрипт со своего рабочего клиентского компьютера, то разрядность Microsoft Office должна совпадать с разрядностью движка, иначе он не будет работать.
Советую установить движок на сервер и не мучиться с переустановкой Microsoft Office на своем компьютере. На компьютере для запуска скрипта должен быть установлен powershell версии не ниже 4.0 и оснастки AD с модулями PowerShell.
Также необходимо прописать в скрипте следующие переменные.
#Имя 1с-сервера, где лежат базы
$NameFileServer = "\\nn-1cserver"
#Имя папки с общим доступом, где будут лежать базы 1С.
$ShareName = "1cshare"
#OU в Active Directory, где будут лежать группы доступа 1c
$OU = "OU=1C, OU=Resources, DC=domain, DC=ru”
#Имя DFS общей папки, где будут лежать конфигурационные файлы 1С
$1CConfigFolder = "\\DfsShare\1cconfig\"
#Файл со списком баз и пользователей
$datafile = "c:\PathToFile\BasesBuh.xlsx"
#Имя листа в файле со списком баз и пользователей
$strSheetName = 'Sheet1$'
Примечание: Почему я реализовал чтение Excel, а не csv? Не люблю работу с CSV, так как там необходимо соблюдать кодировку для кириллических символов, также CSV не удобно редактировать.
Этап 3 — Создание политики для пользователей
Sergey-S-Kovalev очень хорошо описал создание политики для работы данной схемы.
1.Реализуем по его статье копирование конфигурационного файла 1CEStart.cfg из общей сетевой папки в папку на компьютере %ProgramData%\1C\1CEStart\ Создаем данную политику для компьютеров.
2.Далее, в политике необходимо обеспечить очистку файла %Appdata%\1C\1CEStart\ibases.v8i для каждого пользователя. Новое его содержимое сформируется при первом запуске 1С из файла 1CEStart.cfg.
Этап 4 — Копирование старых баз в новые папки
После того, как вы запустили скрипт, и он создал все группы, папки и файлы, вам необходимо скопировать старые базы в новое место, то есть распределить их по новым папкам.
Данную процедуру можно также автоматизировать, ведь у нас осталась копия файла со столбцами OldFolderName, FolderName. Но это уже вы сможете сделать сами.
#Здесь задаем переменные под свое окружение
#Имя 1с-сервера, где лежат базы
$NameFileserver = "\\nn-1cserver"
#Имя папки с общим доступом, где будут лежать базы 1С.
$ShareName = "1cshare"
#OU в Active Directory, где будут лежать группы доступа 1c
$OU = "OU=1C,OU=Resources,DC=domain,DC=ru”
#Имя DFS общей папки, где будут лежать конфиги 1с
#Необходимо, чтобы пользователь, от которого будет запускаться скрипт,имел права записи в данную папку.
$1CConfigFolder = "\\DfsShare\1cconfig\"
#Файл со списком баз и пользователей
$datafile = "c:\PathToFile\BasesBuh.xlsx"
#Имя листа в файле со списком баз и пользователей
$strSheetName = 'Sheet1$' # или Лист1$
#Далее никакие переменные не изменяем, все генерируется автоматически
#Имя конфигурационного файла 1с
$1CBasesCFG = $1CConfigFolder + "1CEStart.cfg”
#Имя группы с доступом к конфигу
#Даную группу создаем и прописываем ее в ACL к папке с конфигами.
$GRRS_1C_ConfigBasesRO = "GRRS_1C_ConfigBasesRO"
#Имя группы для обеспечения общего доступа к корню общей папки с базами
#Данную группу создаем и прописываем ее в ACL к папке с базами.
$GRRS_1CBases = "GRRS_1CBases"
#Имя группы администраторов 1С
$GR_1CAdmins = "GRUS_1Cadmins"
# Читаем Excel-файл и сохраняем его, как временную таблицу SQLDB
# Для этого на компьютере должен быть установлен Microsoft Access Database Engine 2010 Redistributable
# Скачать можно здесь www.microsoft.com/en-us/download/details.aspx?id=13255
# Необходимо, чтобы разрядность системы совпадала с разрядностью движка. Если на компьютере установлен Office
# То разрядность офиса должна тоже совпадать. Лучше все ставить на сервер, где нет офиса.
$strProvider = "Provider=microsoft.ace.oledb.12.0"
$strDataSource = "Data Source = $datafile"
$strExtend = "Extended Properties=Excel 8.0"
$strQuery = "Select * from [$strSheetName]"
$objConn = New-Object System.Data.OleDb.OleDbConnection("$strProvider;$strDataSource;$strExtend")
$sqlCommand = New-Object System.Data.OleDb.OleDbCommand($strQuery)
$sqlCommand.Connection = $objConn
$objConn.open()
$DataReader = $sqlCommand.ExecuteReader()
#Создаем массив для хранения пользователей
$AccessArr = New-Object System.Collections.ArrayList
#Читаем нашу таблицу и сохраняем значения ячеек в переменные
While($DataReader.Read())
{
$BaseName = $DataReader[0].Tostring().replace(' ','')
$FolderName = $DataReader[1].Tostring().replace(' ','')
$GroupName = $DataReader[2].Tostring().replace(' ','')
$AccessUser1 = $DataReader[3].Tostring().replace(' ','')
$AccessUser2 = $DataReader[4].Tostring().replace(' ','')
$AccessUser3 = $DataReader[5].Tostring().replace(' ','')
$AccessUser4 = $DataReader[6].Tostring().replace(' ','')
$AccessUser5 = $DataReader[7].Tostring().replace(' ','')
$AccessUser6 = $DataReader[8].Tostring().replace(' ','')
$AccessUser7 = $DataReader[9].Tostring().replace(' ','')
#Динамические переменные. Переменные не трогаем, все работает автоматически.
#Полный путь к базе. Необходим для создания папок для баз.
$FullPathBase = $NameFileserver + "\" + $Sharename + "\" + $FolderName
#Создаем комментарии для добавления в описание групп AD
$CommentBase = "База” + " ” + $BaseName + " ”
$CommentPath = $FullPathBase
$Comment = $CommentBase + $CommentPath
#Создаем имя файла конфига, для каждой базы
$ConfigBaseFile = $1cConfigFolder + $FolderName + ".v8i”
#Создаем содержимое для каждого файла v8i
#У нас файловая 1с, поэтому Connect=File
$ConfigBaseFileContent ="[$BaseName]
Connect=File=$FullPathBase
ClientConnectionSpeed=Normal
App=Auto
WA=1
Version=8.3
"
#Создание v8i-файлов и файла 1CEStart.cfg
#Создаем сам v8i-файл для каждой базы
$ConfigBaseFileContent | Set-Content $ConfigBaseFile -Encoding UTF8
#Создаем строчку с путем к v8i-файлу для файла 1CEStart.cfg
$1CBasesCFGContent = "CommonInfoBases=$ConfigBaseFile"
#Добавляем путь к каждому v8i-файлу в файл 1CEStart.cfg
$1CBasesCFGContent | Add-Content $1CBasesCFG -Encoding UTF8
#Создаем группу для каждой базы, добавляем к каждой группе ее описание и путь к базе.
New-ADGroup -GroupScope DomainLocal -GroupCategory Security `
-name $GroupName -Path $OU -Description $CommentPath -OtherAttributes @{info="$Comment"}
#Добавляем данную группу в группу с доступом к папке с конфигами
Add-ADGroupMember -Identity $GRRS_1C_ConfigBasesRO $GroupName
#Добавляем данную группу в группу с доступом к папке с базами
Add-ADGroupMember -Identity $GRRS_1CBases $GroupName
#Добавляем пользователей в массив $AccessArr, чтобы потом добавить каждого в группу доступа к базе.
[void] $AccessArr.Add($AccessUser1)
[void] $AccessArr.Add($AccessUser2)
[void] $AccessArr.Add($AccessUser3)
[void] $AccessArr.Add($AccessUser4)
[void] $AccessArr.Add($AccessUser5)
[void] $AccessArr.Add($AccessUser6)
[void] $AccessArr.Add($AccessUser7)
#Пробегаем по массиву пользователей и добавляем каждого в группу доступа к базе.
foreach ($i in $AccessArr)
{
if ($i)
{
Add-ADGroupMember -Identity $GroupName $i
}
}
#Создаем папку с базой
New-item -Path $FullPathBase -ItemType directory
#Создаем и применяем списки доступа к папке с базой
$acl = Get-Acl $FullPathBase
$GroupOwner = New-Object System.Security.Principal.NTAccount("Builtin", "Administrators")
$acl.SetOwner($GroupOwner)
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule("Administrators”,”Modify,FullControl, Synchronize”, "ContainerInherit, ObjectInherit”, "None”, "Allow”)
$acl.AddAccessRule($rule)
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule("Domain admins”,”Modify,FullControl, Synchronize”, "ContainerInherit, ObjectInherit”, "None”, "Allow”)
$acl.AddAccessRule($rule)
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule("$GroupName”,”Modify, Synchronize”, "ContainerInherit, ObjectInherit”, "None”, "Allow”)
$acl.AddAccessRule($rule)
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule("$GR_1CAdmins”,”Modify, Synchronize”, "ContainerInherit, ObjectInherit”, "None”, "Allow”)
$acl.AddAccessRule($rule)
$acl.SetAccessRuleProtection($True, $False)
Set-Acl $FullPathBase $acl
#Создаем и применяем списки доступа к v8i-файлу
$aclfl = Get-Acl $ConfigBaseFile
$GroupOwner = New-Object System.Security.Principal.NTAccount("Builtin", "Administrators")
$aclfl.SetOwner($GroupOwner)
$rulefl = New-Object System.Security.AccessControl.FileSystemAccessRule("Administrators”,”Modify,FullControl, Synchronize”, "Allow”)
$aclfl.AddAccessRule($rulefl)
$rulefl = New-Object System.Security.AccessControl.FileSystemAccessRule("Domain admins”,”Modify,FullControl, Synchronize”, "Allow”)
$aclfl.AddAccessRule($rulefl)
$rulefl = New-Object System.Security.AccessControl.FileSystemAccessRule("$GroupName”,”ReadAndExecute, Synchronize”, "Allow”)
$aclfl.AddAccessRule($rulefl)
$rulefl = New-Object System.Security.AccessControl.FileSystemAccessRule("$GR_1CAdmins”,”ReadAndExecute, Synchronize”, "Allow”)
$aclfl.AddAccessRule($rulefl)
Set-Acl $ConfigBaseFile $aclfl
#Создаем и применяем списки доступа к 1CEStart.cfg
$aclcf = Get-Acl $1CBasesCFG
$GroupOwner = New-Object System.Security.Principal.NTAccount("Builtin", "Administrators")
$aclcf.SetOwner($GroupOwner)
$rulecf = New-Object System.Security.AccessControl.FileSystemAccessRule("Administrators”,”Modify,FullControl, Synchronize”, "Allow”)
$aclcf.AddAccessRule($rulecf)
$rulecf = New-Object System.Security.AccessControl.FileSystemAccessRule("Domain admins”,”Modify,FullControl, Synchronize”, "Allow”)
$aclcf.AddAccessRule($rulecf)
$rulecf = New-Object System.Security.AccessControl.FileSystemAccessRule("$GRRS_1C_ConfigBasesRO”,”ReadAndExecute, Synchronize”, "Allow”)
$aclcf.AddAccessRule($rulecf)
$rulecf = New-Object System.Security.AccessControl.FileSystemAccessRule("$GR_1CAdmins”,”ReadAndExecute, Synchronize”, "Allow”)
$aclcf.AddAccessRule($rulecf)
Set-Acl $1CBasesCFG $aclcf
}
#Закрываем файл со списком баз и пользователей
$dataReader.close()
$objConn.close()
Возможные сложности
Не понял по каким причинам, но у меня почему-то на некоторые папки с базами не включилась опция «replace all child object permissions with inheritable permissions from this object», хотя в скрипте все прописано. И поэтому после копирования баз на новое место, проверьте, унаследовались ли права на скопированные файлы от родительской папки.
Заключение
Коллеги, скрипт довольно хорошо документирован, но написан на коленке, примерно за час. Вся ответственность за его использование лежит только на НЛО.
Я знаю, как правильно писать функции в PowerShell, делать запросы и проверку параметров, реализовывать логирование, писать help для скрипта и так далее, но думаю для этого скрипта все это лишнее. Хотя, некоторые проверки, например, директории с конфигами или общих папок можно будет сделать. Но, думаю, не в этот раз, не такого уровня задача.
Спасибо!
Всем добра!