Pull to refresh

Автоматизация легкого управления списками баз 1С

PowerShell *
Sandbox


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

Часто одной из систем, где порядок отсутствует, является система 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=ru" -filter * -Properties SamAccountname | FT SamAccountname

    и поместить данный список на второй лист нашего файла.
  • Далее к полям AccessUser необходимо сделать привязку данного списка. Если не знаете, как, то спросите у Google примерно следующее «How to add a drop-down list to an Excel cell», или просто используйте мой файл.

В итоге, самый, самый главный бухгалтер просто проставит доступы для каждой базы, выбирая пользователей из списка. Список можно предварительно упорядочить средствами самого Excel, например, самые часто встречаемые учетные записи поместить в начало.

3. После заполнения данного файла, его необходимо сохранить и скопировать в директорию, в которой будет запускаться скрипт.

От файла 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-папку или просто папку, например, \\domain.ru\DfsShare\1cconfig\
5. В этой папке будут лежать конфигурационные файлы 1С.
6. К папке \\domain.ru\DfsShare\1cconfig\ дать доступ группе GRRS_1C_ConfigBasesRO только для чтения.

Необходимо, чтобы пользователь, от которого будет запускаться скрипт, имел права на запись в папку с базами и в папку \\domain.ru\DfsShare\1cconfig\.


Требования к запуску скрипта


В скрипте реализовано чтение Excel-файла при помощи Microsoft Access Database Engine 2010 Redistributable
Лучше сразу установить данный продукт на сервер, с которого будет запускаться скрипт.

Движок скачать можно здесь. Важно, чтобы разрядность операционной системы совпадала с разрядностью движка.

Внимание! Если заходите запустить скрипт со своего рабочего клиентского компьютера, то разрядность Microsoft Office должна также совпадать с разрядностью движка.

Рекомендую установить движок на сервер и не мучиться с переустановкой Microsoft Office на своем компьютере. На компьютере для запуска скрипта должен быть установлен powershell версии не ниже 4.0 и оснастки AD с модулями PowerShell.

Также необходимо прописать в скрипте следующие переменные.

#Имя 1с-сервера, где лежат базы
$1CServer = "nn-1cserver"
#Имя папки с общим доступом, где будут лежать базы 1С.
$ShareName = "1cshare"
#OU в Active Directory, где будут лежать группы доступа 1c
$OU = “OU=1C, OU=Resources, DC=domain, DC=ru”
#Имя DFS общей папки, где будут лежать конфигурационные файлы 1С
$1CConfigFolder = "\\domain.ru\DfsShare\1cconfig\"
#Файл со списком баз и пользователей, должен лежать в директории скрипта
$datafile = "BasesBuh.xlsx"
#Имя листа в файле со списком баз и пользователей
$strSheetName = 'Sheet1$'

Примечание: Почему я реализовал чтение Excel, а не csv? Не люблю работу с CSV, так как там необходимо соблюдать кодировку для кириллических символов, также CSV не удобно редактировать. Если есть возможность прочитать Excel-файл, то его можно сразу подсунуть любому скрипту без подготовки его формата.

Этап 3 — Создание политики для пользователей


Sergey-S-Kovalev очень хорошо описал создание политики для работы данной схемы.

1.Реализуем по его статье копирование конфигурационного файла 1CEStart.cfg из общей сетевой папки в папку на компьютере %ProgramData%\1C\1CEStart\ Создаем данную политику для компьютеров.

2.Далее, в политике необходимо обеспечить очистку файла %Appdata%\1C\1CEStart\ibases.v8i для каждого пользователя. Новое его содержимое сформируется при первом запуске 1С из файла 1CEStart.cfg.

Этап 4 — Копирование старых баз в новые папки


После того, как вы запустили скрипт, и он создал все группы, папки и файлы, вам необходимо скопировать старые базы в новое место, то есть распределить их по новым папкам. Здесь вам помогут столбцы OldFolderName,FolderName.

Скрипт здесь
###########################################################
# AUTHOR : Rinat K. Nugaev - http://www.nugaev.net - rinat@nugaev.net
# DATE : 07-02-2016
# EDIT : 07-03-2016
# COMMENT : This script creates folders, groups, and other
# stuff for 1C envinronment.
# Use it for your own risk!
# VERSION : 1.2
###########################################################

# CHANGELOG
# Version 1.2: 07-03-2016 - Changed the code
# - Added DataFilePath checking
# - Added AD modules installing
# - Changed users's array creating
# - Added Russian comments

#Проверка наличия модулей AD PowerShell
Try
{
Import-Module ActiveDirectory -ErrorAction Stop
}
Catch
{
Write-Host "[ERROR]`t Модули ActiveDirectory для Powershell не установлены! Пожалуйста, установите модули!"
Write-Host "[ERROR]`t Для Windows 2008/2008R2 выполните Import-Module ServerManager"
Write-Host "[ERROR]`t Add-WindowsFeature RSAT-AD-PowerShell"
Write-Host "[ERROR]`t Для Windows 2012/2012R2 выполните Add-WindowsFeature RSAT-AD-PowerShell"
Exit 1
}

#---------------------------------------------------------------------------------------
# не ПОСТОЯННЫЕ ПЕРЕМЕННЫЕ - изменяем под свое окружение
#---------------------------------------------------------------------------------------
#Имя файла с базами
$dataFile = "BasesBuh.xlsx"
#Имя 1с-сервера, где лежат базы
$1Cserver = "nn-1cserver"
#Имя папки на 1с сервере с общим доступом, где будут лежать базы 1С.
$ShareName = "1cshare"
#OU в Active Directory, где будут лежать группы доступа 1c
$OU = “OU=1C,OU=Resources,DC=domain,DC=ru”
#Имя DFS общей папки, где будут лежать конфиги 1с
#Необходимо, чтобы пользователь, от которого будет запускаться скрипт,имел права записи в данную папку.
$1CConfigFolder = "\\domain.ru\DfsShare\1cconfig\"
#Файл со списком баз и пользователей
#Имя листа в файле со списком баз и пользователей
$strSheetName = 'Sheet1$' # или Лист1$

#----------------------------------------------------------
#ПОСТОЯННЫЕ ПЕРЕМЕННЫЕ
#----------------------------------------------------------
$dataFilePath = $localPath + "\$dataFile"
$localPath = $PSScriptRoot
#Имя конфигурационного файла 1с
$1CBasesCFG = $1CConfigFolder + “1CEStart.cfg”
#Имя группы с доступом к конфигу
#Даную группу создаем и прописываем ее в ACL к папке с конфигами.
$GRRS_1C_ConfigBasesRO = "GRRS_1C_ConfigBasesRO"
#Имя группы для обеспечения общего доступа к корню общей папки с базами
#Данную группу создаем и прописываем ее в ACL к папке с базами.
$GRRS_1CBases = "GRRS_1CBases"
#Имя группы администраторов 1С
$GR_1CAdmins = "GRUS_1Cadmins"

#Проверяем начилие файла с базами в директории скрипта
If (!(Test-Path -Path $dataFilePath -PathType Any))
{
Write-Host "[ERROR]`t Файл с базами $dataFile не существует! Пожалуйста, скопируйте $dataFile в директорию скрипта!" -ForegroundColor Red
Exit 1
}

# Читаем 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 = $dataFilePath"
$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())
{
#В данных удаляем сразу лишние пробелы (.replace(' ','')), если кто-то ввел при заполнении таблицы.
$BaseName = $DataReader[2].Tostring().replace(' ','')
$FolderName = $DataReader[3].Tostring().replace(' ','')
$GroupName = $DataReader[4].Tostring().replace(' ','')
#Сразу добавляем пользователей в массив $AccessArr
[void] $AccessArr.Add($DataReader[5].Tostring().replace(' ',''))
[void] $AccessArr.Add($DataReader[6].Tostring().replace(' ',''))
[void] $AccessArr.Add($DataReader[7].Tostring().replace(' ',''))
[void] $AccessArr.Add($DataReader[8].Tostring().replace(' ',''))
[void] $AccessArr.Add($DataReader[8].Tostring().replace(' ',''))
[void] $AccessArr.Add($DataReader[10].Tostring().replace(' ',''))
[void] $AccessArr.Add($DataReader[11].Tostring().replace(' ',''))

#Динамические переменные. Переменные не трогаем, все работает автоматически.
#Полный путь к базе. Необходим для создания папок для баз.
$FullPathBase = "\" + "\" + $1Cserver + "\" + $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

#Пробегаем по массиву пользователей и добавляем каждого в группу доступа к базе.
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 для скрипта и так далее, но думаю для этого скрипта все это лишнее. Хотя, некоторые проверки, например, директории с конфигами или общих папок можно будет сделать. Но, думаю, не в этот раз, не такого уровня задача.

#ChangeLog
  1. Поправил неточности, на которые указал Sergey-S-Kovalev;
  2. Изменил способ добавления пользователей в массив, n1nj4p0w3r;
  3. Добавил проверку модулей Active Directory;
  4. Добавил проверку наличия файла с данными в директории.

Спасибо!
Всем добра!
Tags:
Hubs:
Total votes 15: ↑13 and ↓2 +11
Views 17K
Comments Comments 12