none
Powershell Создание папок пользователей со структурой из AD RRS feed

  • Вопрос

  • Всем доброго времени суток!

    Нужна помощь в написание скрипта на powershell, требуется создать папки обмена для пользователей AD, но чтобы структура сохранилась т.е. если пользователи находятся здесь "OU=Тест,OU=Базис ,OU=users,DC=holding,DC=ru", то и путь к папке должен быть "\\Host\Holding.ru\Users\Базис\Тест\User" также к папкам пользователей устанавливаются требуемые права (Domain admin, Domain user, user ), есть и юниты которые не должны попадать под поиск (сервисные учетки, те для кого это не требется), т.е. нужен фильтр

    В powershel не селен, сталкивался с простыми скриптами типа импорт экспорт и единичными командлетами.

    С помощью googla  и этого форума кое что нашел:

    1. Это скрипт работает почти так как надо, создает папку и я могу назначить права так как мне нужно, но он создает только папку пользователя "\\Host\User" без структуры "\\Host\Holding.ru\Users\Базис\Тест\User", также не совсем понял как настроить фильтр.

    Import-Module ActiveDirectory
    
    $RootOU = "OU=Лидер,OU=users,DC=holding,DC=ru"
    $RootFolder = "C:\temp"
    $MaxUsers = 10000
    
    # Блок, задающий константы для раздачи прав
    
    # флаги для задания наследования прав (CI, OI, IO)
    $inheritCO = [system.security.accesscontrol.InheritanceFlags]"ContainerInherit, ObjectInherit"
    $propagationIO = [system.security.accesscontrol.PropagationFlags]"InheritOnly"
    $propagationN = [system.security.accesscontrol.PropagationFlags]"None"
    # права для всех пользователей на объекты внутри пользовательских папок
    $colUserRights = [system.security.accesscontrol.FileSystemRights]"ListDirectory, CreateFiles, CreateDirectories, AppendData"
    $colFullRights = [system.security.accesscontrol.FileSystemRights]"FullControl"
    $colListRights = [system.security.accesscontrol.FileSystemRights]"ListDirectory"
    # пользователи
    $system = New-Object System.Security.Principal.NTAccount("NT AUTHORITY\SYSTEM")
    $admins = New-Object System.Security.Principal.NTAccount("Domain Admins")
    $Enginee = New-Object System.Security.Principal.NTAccount("Инженеры ИТ")
    $users = New-Object System.Security.Principal.NTAccount("Domain Users")
    
    
    
    #Скрипт
    
    # Полностью очистить папку обмена
    Set-Location $RootFolder
    Get-ChildItem $RootFolder | Remove-Item -recurse
    
    # выбрать всех пользователей из заданного OU
    $objSearcher = New-Object System.DirectoryServices.DirectorySearcher ([ADSI]"LDAP://$RootOU")
    $objSearcher.Filter = "(&(objectCategory=user)(objectClass=person))"
    $objSearcher.SearchScope = [System.DirectoryServices.SearchScope]::Subtree
    $objSearcher.PageSize = $MaxUsers
    $colResult = $objSearcher.FindAll()
    foreach ($u in $colResult)
    {
    $user = [ADSI]($u.Path)
    if ($user.psbase.invokeget("AccountDisabled") -eq $False)
    {
    # для каждого пользователя, если он не залочен, создаем именную папку
    $user = $u.Properties
    $Folder = "$RootFolder\$($user.name)"
    New-Item -Path "$Folder" -ItemType Directory | Out-Null
    
    # перечень прав доступа к созданной папке
    $acl = Get-Acl $Folder
    
    # убираем наследование прав от родительской папки, при этом чистим все права доступа
    $acl.SetAccessRuleProtection($True, $False)
    
    
    # устанавливаем требуемые права
    $ar = New-Object System.Security.AccessControl.FileSystemAccessRule( $system, $colFullRights, $inheritCO, $propagationN, "Allow")
    $acl.SetAccessRule($ar)
    $ar = New-Object System.Security.AccessControl.FileSystemAccessRule( $admins, $colFullRights, $inheritCO, $propagationN, "Allow")
    $acl.SetAccessRule($ar)
    $ar = New-Object System.Security.AccessControl.FileSystemAccessRule( $Enginee, $colFullRights, $inheritCO, $propagationN, "Allow")
    $acl.SetAccessRule($ar)
    $ar = New-Object System.Security.AccessControl.FileSystemAccessRule( $user.samaccountname, $colFullRights, $inheritCO, $propagationN, "Allow")
    $acl.SetAccessRule($ar)
    $ar = New-Object System.Security.AccessControl.FileSystemAccessRule( $users, $colUserRights, $inheritCO, $propagationN, "Allow")
    $acl.SetAccessRule($ar)
    $acl | Set-Acl $Folder
    
    echo "$folder"
    }
    }

    2.На форуме нашел тему "Создание структуры папок в соответствие с юнитами", сделал из скрипта который там и того что у меня выше вот такой, вроде все как надо, но права на папку пользователя выдаются не правильно, Domain admin, Domain user выдаются так как надо, а вот права User не правильно к своей папки права получает не тот кто должен, а совершенно другой User. И почему то этот скрипт запускается только в ISE просто в powerchell ошибка.

    $domain = "OU=users,DC=holding,DC=ru"
    $RootFolder = "C:\Temp\"
    
    $inheritCO = [system.security.accesscontrol.InheritanceFlags]"ContainerInherit, ObjectInherit"
    $propagationIO = [system.security.accesscontrol.PropagationFlags]"InheritOnly"
    $propagationN = [system.security.accesscontrol.PropagationFlags]"None"
    # права для всех пользователей на объекты внутри пользовательских папок
    $colUserRights = [system.security.accesscontrol.FileSystemRights]"ListDirectory, CreateFiles, CreateDirectories, AppendData"
    $colFullRights = [system.security.accesscontrol.FileSystemRights]"FullControl"
    $colListRights = [system.security.accesscontrol.FileSystemRights]"ListDirectory"
    # пользователи
    #$creator = New-Object System.Security.Principal.NTAccount("CREATOR OWNER")
    $system = New-Object System.Security.Principal.NTAccount("NT AUTHORITY\SYSTEM")
    $admins = New-Object System.Security.Principal.NTAccount("Domain Admins")
    $Enginee = New-Object System.Security.Principal.NTAccount("Инженеры ИТ")
    $users = New-Object System.Security.Principal.NTAccount("Domain Users")
    
    #Структура
    $structure = Get-AdUser -SearchBase $domain -Filter * -prop canonicalname | Where {$_.CanonicalName.Split("/").Count -le 6 -and $_.DistinguishedName -notlike '*OU=Тест,OU=Базис*' -and $_.DistinguishedName -notlike '*OU=Лидер*' -and $_.DistinguishedName -notlike '*OU=DISABLED*'}
    $structure  | Foreach {
    	$RootFolder = md (Join-Path $path $_.CanonicalName)
    $acl = $RootFolder | Get-Acl
    $acl.SetAccessRuleProtection($True, $False)
    $ar = New-Object System.Security.AccessControl.FileSystemAccessRule( $system, $colFullRights, $inheritCO, $propagationN, "Allow")
    $acl.SetAccessRule($ar)
    $ar = New-Object System.Security.AccessControl.FileSystemAccessRule( $admins, $colFullRights, $inheritCO, $propagationN, "Allow")
    $acl.SetAccessRule($ar)
    $ar = New-Object System.Security.AccessControl.FileSystemAccessRule( $Enginee, $colFullRights, $inheritCO, $propagationN, "Allow")
    $acl.SetAccessRule($ar)
    $ar = New-Object System.Security.AccessControl.FileSystemAccessRule( $user.samaccountname, $colFullRights, $inheritCO, $propagationN, "Allow")
    $acl.SetAccessRule($ar)
    $ar = New-Object System.Security.AccessControl.FileSystemAccessRule( $users, $colUserRights, $inheritCO, $propagationN, "Allow")
    $acl.SetAccessRule($ar)
    $acl = Set-Acl -path $RootFolder -AclObject $acl
        }

    Подскажите пожалуйста ка сделать все правильно, думаю я не сильно запутано написал... Буду очень признателен за любую помощь и информацию. 

     
    • Изменено AresRus 20 декабря 2016 г. 10:25
    20 декабря 2016 г. 10:23

Ответы

  • О каких фильтрах идет речь?

    Корень для поиска: ([ADSI]"LDAP://$RootOU")

    LDAP фильтр: "(&(objectCategory=user)(objectClass=person))"

    Первый скрипт поправить на:

    foreach ($u in $colResult)
    {
    	$user = [ADSI]($u.Path)
    	if ($user.psbase.invokeget("AccountDisabled") -eq $False)
    	{
    		# для каждого пользователя, если он не залочен, создаем именную папку
    		$user.GetInfoEx(@("canonicalName"),0)
    		$cn = $user.canonicalName -replace "/","\"
    		$Folder = "$RootFolder\$cn"
    		New-Item -Path "$Folder" -ItemType Directory -Force | Out-Null

    • Помечено в качестве ответа AresRus 21 декабря 2016 г. 6:20
    20 декабря 2016 г. 10:43
    Отвечающий
  • Добавить в начало скрипта:

    $ex = "LDAP://OU=Тест,OU=Базис,OU=users,DC=holding,DC=ru" , "LDAP://OU=Disabled,OU=users,DC=holding,DC=ru"

    И изменить строку на:

    if ($user.psbase.invokeget("AccountDisabled") -eq $False -and ($ex -notcontains $user.Parent))

    • Помечено в качестве ответа AresRus 21 декабря 2016 г. 6:20
    21 декабря 2016 г. 5:59
    Отвечающий
  • Исправить условие:

    !($ex | Where {$user.Parent.Contains($_)})

    • Помечено в качестве ответа AresRus 23 декабря 2016 г. 6:46
    23 декабря 2016 г. 6:06
    Отвечающий

Все ответы

  • О каких фильтрах идет речь?

    Корень для поиска: ([ADSI]"LDAP://$RootOU")

    LDAP фильтр: "(&(objectCategory=user)(objectClass=person))"

    Первый скрипт поправить на:

    foreach ($u in $colResult)
    {
    	$user = [ADSI]($u.Path)
    	if ($user.psbase.invokeget("AccountDisabled") -eq $False)
    	{
    		# для каждого пользователя, если он не залочен, создаем именную папку
    		$user.GetInfoEx(@("canonicalName"),0)
    		$cn = $user.canonicalName -replace "/","\"
    		$Folder = "$RootFolder\$cn"
    		New-Item -Path "$Folder" -ItemType Directory -Force | Out-Null

    • Помечено в качестве ответа AresRus 21 декабря 2016 г. 6:20
    20 декабря 2016 г. 10:43
    Отвечающий
  • Спасибо за ответ и помощь, поправил все заработало!

    LDAP фильтр: "(&(objectCategory=user)(objectClass=person))"

    Нужно к нему добавить исключение некоторых OU, чтоб при поиске по всем "OU=users,DC=holding,DC=ru" исключалась например: "OU=Тест,OU=Базис,OU=users,DC=holding,DC=ru" , "OU=Disabled,OU=users,DC=holding,DC=ru"

    Что то вроде такого фильтра

    Where {$_.DistinguishedName -notlike '*OU=Тест,OU=Базис*}

    Варианты вроде таких которые я нашел для исключения у меня не сработали 

    (!ou:dn:=Тест)

    (&(objectCategory=organizationalUnit)(!ou=Тест))


    • Помечено в качестве ответа AresRus 21 декабря 2016 г. 6:20
    • Снята пометка об ответе AresRus 21 декабря 2016 г. 6:20
    21 декабря 2016 г. 5:02
  • Добавить в начало скрипта:

    $ex = "LDAP://OU=Тест,OU=Базис,OU=users,DC=holding,DC=ru" , "LDAP://OU=Disabled,OU=users,DC=holding,DC=ru"

    И изменить строку на:

    if ($user.psbase.invokeget("AccountDisabled") -eq $False -and ($ex -notcontains $user.Parent))

    • Помечено в качестве ответа AresRus 21 декабря 2016 г. 6:20
    21 декабря 2016 г. 5:59
    Отвечающий
  • Да, все так как надо, спасибо большое за помощь!
    21 декабря 2016 г. 6:22
  • Cтруктура в AD большая и выглядит следующим образом,
    есть OU=users,DC=holding,DC=ru в ней лежат OU=DISABLED,OU=users,DC=holding,DC=ru , OU=ООО Медкон,OU=users,DC=holding,DC=ru , OU=ООО Базис Монолит,OU=users,DC=holding,DC=ru и еще много разных OU, также OU=ООО Базис Монолит,OU=users,DC=holding,DC=ru делится еще на отделы OU=АУП,OU=ООО Базис Монолит,OU=users,DC=holding,DC=ru , OU=Бухгалтерия,OU=ООО Базис Монолит,OU=users,DC=holding,DC=ru и т.д., так же отделы могут делится еще на под отделы, так почти все OU. Если я добавлю в $ex  например OU=Бухгалтерия,OU=ООО Базис Монолит,OU=users,DC=holding,DC=ru то она исключается, но если я добавлю OU=ООО Базис Монолит,OU=users,DC=holding,DC=ru то исключение не работает. 

    Я так понимаю здесь указано то с чем сравнивать $user.Parent а как можно сделать чтоб он смотрел не на юзера а на OU? Чтоб если добавил OU=ООО Базис Монолит,OU=users,DC=holding,DC=ru то он и исключил ее со всеми OU которые в ней есть? Можно конечно и так как есть но просто прописывать каждую OU отдельно накладно... да и много получится

       
    23 декабря 2016 г. 5:19
  • Исправить условие:

    !($ex | Where {$user.Parent.Contains($_)})

    • Помечено в качестве ответа AresRus 23 декабря 2016 г. 6:46
    23 декабря 2016 г. 6:06
    Отвечающий
  • Позовите к компьютеру более обученный персонал, который умеет правильно копировать, а не добавлять свои ошибки.
    23 декабря 2016 г. 6:28
    Отвечающий
  • Не ругайтесь, не буду объяснять как получил ту ошибку, но не из за копирования, уже поправил спасибо) 


    • Изменено AresRus 23 декабря 2016 г. 6:59
    23 декабря 2016 г. 6:46