1

Тема: VBS: Прочитать DACL разрешения у сетевой папки

Добрый день, подскажите пожалуйста.
Задача такая:
Есть файловый сервер с разшаренными сетевыми папками, на каждую папку выставлены NTFS ограничения для доменных пользователей (или изменения или только чтение)
Есть группы в AD названы так же как и папки но с префиксом -R (для чтения) или -W (для записи)
Например если есть папка \\fs01\board, то в AD есть две группы board-R и board-W (группы уже существуют)

Необходимо прочитать NTFS права (DACL) у каждой папки и внести пользователей в соответствующую группу в AD, а так же удалить все NTFS права на папку и добавить группы соответствующие названию папки.
Например если пользователь DOMAIN\I.Ivanov имел доступ на запись в папку board, то он должен стать членом группы board-W в AD, а если пользователь DOMAIN\P.Petrov имел доступ на чтение в папку board, то он должен стать членом группы board-R в AD, так же необходимо удалить все NTFS права на папку board и добавить в NTFS права группу DOMAIN\board-R с правами "чтение" и группу DOMAIN\board-W с правами "запись"

Папок порядка 150 штук, хочется этот процесс автоматизировать

Подскажите алгоритм и если возможно, помогите с кодом. Вот эту тему http://forum.script-coding.com/viewtopic.php?id=5142 видел, но не смог применить для моего случая.

2

Re: VBS: Прочитать DACL разрешения у сетевой папки

Rialto пишет:

... Вот эту тему http://forum.script-coding.com/viewtopic.php?id=5142 видел, но не смог применить для моего случая.

Что именно не получается?

3

Re: VBS: Прочитать DACL разрешения у сетевой папки

Ну для начала я не могу придумать алгоритм, поэтому и прошу помощи.
А по ссылки не могу получить DACL для сетевой папки вида \\fs01\board

4

Re: VBS: Прочитать DACL разрешения у сетевой папки

Rialto пишет:

... не могу получить DACL для сетевой папки вида \\fs01\board

Из моей практики следует, что при использовании UNC-путей в WMI-запросах, действительно, возникают сложности.
Поэтому я предпочитаю добавлять в сценарии (если возможно, конечно) процедуру подключения удалённого ресурса в качестве сетевого диска (с последующим отключением, разумеется).

Rialto пишет:

... не могу придумать алгоритм...

В самом общем виде он может быть таков:
- проверка наличия папки общего доступа и её временное "мапирование";
- создание пары объектов класса Dictionary (один - для списка "читающих" пользователей, второй - "пишущих");
- просмотр всех ACE папки с внесением данных о нужных записях в один из словарей;
- просмотр каждого из сформированных словарей с добавлением данных о пользователях в соответствующую группу;
- вторичный просмотр всех ACE папки с назначением всем исключаемым записям нулевой маски доступа и добавлением записей для групп с соответствующими им масками.

Примечание: нулевые маски доступа записям можно назначить не на последнем, а на третьем шаге.

5

Re: VBS: Прочитать DACL разрешения у сетевой папки

Вот заготовка, которую можете "доводить до ума".
Алгоритм работы этого сценария не вполне соответствует тому, что я предлагал в предыдущем сообщении.
Его достоинство (по сравнению с предыдущим алгоритмом) - отсутствие необходимости подключать сетевую папку как диск.
Недостаток - требуются полномочия локального администратора на том файловом сервере, где находится папка.

Dim objWMI, objCollection, objItem
Dim strSharePath, strShareServer, strShareName, strShareTarget
Dim objSecSettings, objSD, objACE, arrACE
Dim objDict, objUser, arrTemp, strList, strTemp, xRes
Const ACCESS_ALLOWED_ACE_TYPE = 0
Const ACCESS_DENIED_ACE_TYPE = 1
Const SE_DACL_PROTECTED = 4096
Const CREATE_FILE_WRITE_DATA = &H2
Const GENERIC_WRITE = &H40000000

strSharePath = "\\fileserver\Имя_ресурса"
arrTemp = Split(Replace(strSharePath, "\\", ""), "\", -1, vbTextCompare)
strShareServer = arrTemp(0)
strShareName = arrTemp(1)
Erase arrTemp
On Error Resume Next
Set objWMI = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strShareServer & "\root\CIMV2")
If Err.Number = 0 Then
    Set objCollection = objWMI.ExecQuery("SELECT Path FROM Win32_Share WHERE Name='" & strShareName & "'")
    If objCollection.Count > 0 Then
        For Each objItem In objCollection
            'Wscript.Echo "Ресурс " & UCase(strSharePath) & " -> " & objItem.Path
            strShareTarget = objItem.Path
        Next
        Set objItem = Nothing
        Set objSecSettings = objWMI.Get("Win32_LogicalFileSecuritySetting.Path='" & strShareTarget & "'")
        If Err.Number = 0 Then
            If objSecSettings.GetSecurityDescriptor(objSD) = 0 Then
                If Not IsNull(objSD.DACL) Then
                    Set objDict = CreateObject("Scripting.Dictionary")
                    objDict.CompareMode = 1
                    For Each objACE In objSD.DACL
                        strTemp = objACE.Trustee.Domain & "/" & objACE.Trustee.Name
                        If Not objDict.Exists(strTemp) Then
                            If objACE.AceType = ACCESS_ALLOWED_ACE_TYPE Then
                                If CBool(objACE.AccessMask And CREATE_FILE_WRITE_DATA Or _
                                    objACE.AccessMask And GENERIC_WRITE) Then
                                    objDict.Add strTemp, True
                                Else
                                    objDict.Add strTemp, False
                                End If
                            End If
                        End If
                    Next
                    For Each strTemp In objDict.Keys
                        Set objUser = GetObject("WinNT://" & strTemp & ",user")
                        If Err.Number = 0 Then
                            If objDict.Item(strTemp) Then
                                strList = strList & strTemp & " -> пишет" & vbNewLine
                                'Настроить членство пользователя в группе AD
                            Else
                                strList = strList & strTemp & " -> читает" & vbNewLine
                                'Настроить членство пользователя в группе AD
                            End If
                        Else
                            Err.Clear
                            objDict.Remove (strTemp)
                        End If
                    Next
                    Set objUser = Nothing
                    WScript.Echo strList
                    If Not CBool(objSD.ControlFlags And SE_DACL_PROTECTED) Then
                        objSD.ControlFlags = objSD.ControlFlags + SE_DACL_PROTECTED
                        xRes = objSecSettings.SetSecurityDescriptor(objSD)
                    End If
                    If xRes = 0 Then
                        arrACE = objSD.DACL
                        For Each objACE In arrACE
                            strTemp = objACE.Trustee.Domain & "/" & objACE.Trustee.Name
                            If objDict.Exists(strTemp) Then objACE.AccessMask = 0
                            'Убрать (или изменить) проверку условия в вышележащем операторе
                        Next
                        Set objACE = Nothing
                        'Сформировать новые ACE для групп и добавить их в DACL
                        xRes = objSecSettings.SetSecurityDescriptor(objSD)
                        Select Case xRes
                            Case 0: xRes = "Успешное завершение."
                            Case 2: xRes = "Доступ запрещён."
                            Case 5, 9: xRes = "Для выполнения операции недостаточно полномочий."
                            Case 21: xRes = "Заданы недопустимые значения параметров."
                            Case Else: xRes = "Неизвестная ошибка с кодом: " & xRes
                        End Select
                    Else
                        xRes = "Не удалось отключить наследование безопасности для каталога " & UCase(strShareTarget)
                    End If
                    Set objDict = Nothing
                    WScript.Echo xRes
                Else
                    WScript.Echo "Список управления доступом к каталогу " & UCase(strShareTarget) & " пуст."
                End If
            Else
                WScript.Echo "Не удалось прочитать дескриптор безопасности каталога " & UCase(strShareTarget)
            End If
            Set objSD = Nothing
        Else
            WScript.Echo "Ошибка " & CStr(Err.Number) & vbNewLine & Err.Description
            Err.Clear
        End If
        Set objSecSettings = Nothing
    Else
        WScript.Echo "Не найден ресурс " & UCase(strSharePath)
    End If
    Set objCollection = Nothing
Else
    WScript.Echo "Ошибка " & CStr(Err.Number) & vbNewLine & Err.Description
    Err.Clear
End If
Set objWMI = Nothing
WScript.Quit 0