Skip to content

Instantly share code, notes, and snippets.

@strike
Created April 16, 2015 16:05
Show Gist options
  • Save strike/89e31bd4d92c93b0f6a9 to your computer and use it in GitHub Desktop.
Save strike/89e31bd4d92c93b0f6a9 to your computer and use it in GitHub Desktop.
SyncADWith1C
<#
.DESCRIPTION
This script sync AD (tree and users) with csv files (exported from 1c)
.AUTHOR Zubarev Alexander aka Strike ([email protected])
.LINK
http://...
#>
#config file
Set-Location ($MyInvocation.MyCommand.Definition | split-path -parent) #move to cur dir
[xml]$CF = Get-Content "Config.xml"
$Patch = $CF.cfg.patch
Import-Module ActiveDirectory
$PatchFolder = Get-ChildItem -Path "$Patch" | Select-Object Name
$date = Get-Date -Format 'dd.MM.yyyy'
$date = '07.04.2015'
#create temp dir
$TempDir = [System.Guid]::NewGuid().ToString()
Set-Location $env:temp
New-Item -Type Directory -Name $TempDir
Set-Location $TempDir
#create header for file
echo "UserLogin`tLastUserLogin`tAccountId" > "DuplicateLogin.csv"
echo "Detailedname`tUserLogin`tPassword`tDepartament`tOU" > "Login.csv"
echo "OU`tUserLogin`tPassword" > "Error.csv"
echo "" > "Log.txt"
#пути в AD
$root = "OU=Staff,DC=ad,DC=guu,DC=ru"
$group = "OU=Группы,$root"
$dismissed = "OU=Уволенные,$root"
$withOutGUID = "OU=Без подразделения,$root"
#Настройка SMTP
$smtp = New-Object System.Net.Mail.SmtpClient($CF.cfg.smtp.server, $CF.cfg.smtp.port);
$smtp.EnableSSL = $true
$smtp.Credentials = New-Object System.Net.NetworkCredential($CF.cfg.smtp.username, $CF.cfg.smtp.password);
$message = New-Object System.Net.Mail.MailMessage
$message.subject = "AD Sync script ($date)"
$message.from = $CF.cfg.message.from
foreach ($mailTo in $CF.cfg.message.to.ChildNodes ){
$message.to.add($mailTo.InnerText)
}
$messageBody = ""
function log {
$txt = $args[0]
$timestamp = (Get-Date).ToString()
echo "$txt"
echo "${timestamp}: $txt" >> Log.txt
}
Function Get-Seed{ $RandomBytes = New-Object -TypeName 'System.Byte[]' 4 $Random = New-Object -TypeName 'System.Security.Cryptography.RNGCryptoServiceProvider' $Random.GetBytes($RandomBytes) [BitConverter]::ToInt32($RandomBytes, 0)
}
function genPassword {
$MinPasswordLength = 8
$MaxPasswordLength = 10
$InputStrings = @('abcdefghijkmnpqrstuvwxyz', 'abcdefghijkmnpqrstuvwxyz', 'ABCDEFGHIJKMNPQRSTUVWXYZ', 'ABCDEFGHIJKMNPQRSTUVWXYZ', '23456789', '23456789', '!@#$')
$Count = 1
[char[][]]$CharGroups = $InputStrings
[int[]]$UsedGroups = for($i=0;$i -lt $CharGroups.Count;$i++){0}
if($MinPasswordLength -eq $MaxPasswordLength) { $password = New-Object -TypeName 'System.Char[]' $MinPasswordLength } else { $password = New-Object -TypeName 'System.Char[]' (Get-Random -SetSeed $(Get-Seed) -Minimum $MinPasswordLength -Maximum $($MaxPasswordLength+1)) }
for($i=0;$i -lt $password.Length;$i++){
if($i -ge ($password.Length - ($UsedGroups | Where-Object {$_ -eq 0}).Count)) {
$CharGroupIndex = 0
while(($UsedGroups[$CharGroupIndex] -ne 0) -and ($CharGroupIndex -lt $CharGroups.Length)) { $CharGroupIndex++ } } else { $CharGroupIndex = Get-Random -SetSeed $(Get-Seed) -Minimum 0 -Maximum $CharGroups.Length } $password[$i] = Get-Random -SetSeed $(Get-Seed) -InputObject $CharGroups[$CharGroupIndex]
$UsedGroups[$CharGroupIndex] = $UsedGroups[$CharGroupIndex] + 1
}
$script:Password = $password -join ''}
log("Init sync")
$isErrors = $false
$isDuplicateLogin = $false
try { $FileTree = ($PatchFolder | Select-String -pattern "\bOU_$date.*" | % { $_.Matches } | % { $_.Value }).Replace("}","") } catch {}
try { $FileStaffs = ($PatchFolder | Select-String -pattern "\b$date.*" | % { $_.Matches } | % { $_.Value }).Replace("}","") } catch {}
try {
$Tree = Import-Csv -Delimiter "`t" -Path "$Patch\\$FileTree"
} catch {
log("Tree file not found!")
$message.subject = "AD Sync script ($date) file ERROR"
$message.body = "Tree file not found!"
$smtp.send($message)
exit
}
try {
$Staffs = Import-Csv -Delimiter "`t" -Path "$Patch\\$FileStaffs"
} catch {
log("Staffs file not found!")
$message.subject = "AD Sync script ($date) file ERROR"
$message.body = "Staffs file not found!"
$smtp.send($message)
exit
}
#Create new OU
log("Check and creating new OU..")
$someAdd = $true
$OUAddCount = 0;
for ($i=0; $i -le 10; $i++){
if (!$someAdd){
break;
}
$someAdd = $false
$allOU = Get-ADOrganizationalUnit -Filter * -SearchBase "$root" -Properties Description
foreach ($ou in $Tree)
{
echo $ou
if (![bool]::Parse($ou.NotRelevant)){
$thisOU = $allOU | Where {$_.Description -cmatch $ou.OUGUID}
if ($thisOU){
continue
}
$normalOU=$ou.OU.Replace(",","\,").Replace("""","")
if($normalOU.Length -ge 60){
$normalOU = $normalOU.Substring(0,60);
}
$normalOU = $normalOU.Trim();
if ($ou.OUParrent -eq ""){
$addOU = "OU=" + $normalOU + ",$root"
} else {
$allOU = Get-ADOrganizationalUnit -Filter * -SearchBase "$root" -Properties Description
$pOu = $allOU | Where {$_.Description -cmatch $ou.OUParrentGUID}
if ($pOu){
$addOU = "OU=" + $normalOU + "," + $pOu.DistinguishedName + ""
$allOU = Get-ADOrganizationalUnit -Filter * -SearchBase "$root" -Properties Description
$addDuplicateOU = $allOU | Where {$_.DistinguishedName -eq $addOU}
if ($addDuplicateOU){
$desc = $addDuplicateOU.Description + "," + $ou.OUGUID
Set-ADObject -Identity $addDuplicateOU.DistinguishedName -Description "$desc"
log("!DuplucateOU (with one GUID): $addDuplicateOU.DistinguishedName")
continue
}
} else {
continue
}
}
log("Added OU: $addOU")
$OUAddCount++
dsadd ou "$addOU" -desc $ou.OUGUID
$someAdd = $true
}
}
}
log("Check, add, activate and deactivate USERS")
$UserAddCount = 0; $UserUpdCount = 0; $UserDisableCount = 0;
$allou = Get-ADOrganizationalUnit -Filter * -SearchBase "$root" -Properties Description
foreach ($User in $Staffs) {
if (![bool]::Parse($User.MainJob)){
continue
}
if ( ([bool]::Parse($User.MainJob)) -and (![bool]::Parse($User.Enabled)) ){
continue
}
$AccountId = $User.Id
$UserLogin = $User.Login
$OUGUID = $User.OUGUID
$Enabled = [bool]::Parse($User.Enabled)
$Detailedname = $User.LastName + " " + $User.FirstName + " " + $User.MiddleName
$UserFirstname = $User.FirstName.Trim();
$UserLastName = $User.LastName.Trim();
$Title = $User.JobTitle.Trim();
$Password = "" #use genPassword
$Department = $User.OU
if($Department.Length -ge 60){
$Department = $Department.Substring(0,60);
}
$Department = $Department.Trim();
#search manager
$ManagerGUID = $User.ManagerGUID
$Manager = (Get-ADUser -Filter 'EmployeeNumber -eq $ManagerGUID').SamAccountName
$Company = "ФГБОУ ВПО «Государственный университет управления»"
$UserGroup = $User.GroupType
#preambule end
#if user alryedy exist in AD
$ExistUser = Get-ADUser -Filter 'EmployeeNumber -eq $AccountId' -Properties DisplayName, Surname, Title, Department, Manager, Company, EmployeeNumber
echo $AccountId
echo $ExistUser
echo $Detailedname
if ($ExistUser){
$upd = $false
$UserLogin = $ExistUser.SamAccountName
#check OU
$OU = ($ExistUser | select *,@{l='Parent';e={([adsi]"LDAP://$($_.DistinguishedName)").Parent}}).Parent.Replace("LDAP://","")
$OU = Get-ADOrganizationalUnit $OU -Properties Description
if (!($OU.Description -cmatch $User.OUGUID)){
$upd = $true
log("$UserLogin change OU: $($OU.Description) -> $($User.OUGUID) ($($OU.Name) -> $($User.OU))" )
$ou = $allou | Where {$_.Description -cmatch $User.OUGUID}
if ($ou) {
$OU = $ou.DistinguishedName
} else {
$OU = $withOutGUID
}
$ExistUser | Move-ADObject -TargetPath "$OU"
}
#check Name (CN)
if ($ExistUser.Name -ne $Detailedname){
$upd = $true
log("$UserLogin change Name (CN): $($ExistUser.Name) -> $Detailedname" )
$ExistUser | Rename-ADObject -NewName "$Detailedname"
}
#check DisplayName
if ($ExistUser.DisplayName -ne $Detailedname){
$upd = $true
log("$UserLogin change DisplayName: $($ExistUser.DisplayName) -> $Detailedname" )
Set-ADUser -Identity $ExistUser.SamAccountName -DisplayName $Detailedname
}
#check GivenName
if ($ExistUser.GivenName -ne $UserFirstName){
$upd = $true
log("$UserLogin change GivenName: $($ExistUser.GivenName) -> $UserFirstName")
Set-ADUser -Identity $ExistUser.SamAccountName -GivenName "$UserFirstName"
}
#check Surname
if ($ExistUser.Surname -ne $UserLastName){
$upd = $true
log("$UserLogin change Surname: $($ExistUser.Surname) -> $UserLastName")
Set-ADUser -Identity $ExistUser.SamAccountName -Surname $UserLastName
}
#check Title
if ($ExistUser.Title -ne $Title){
$upd = $true
log("$UserLogin change Title: $($ExistUser.Title) -> $Title")
Set-ADUser -Identity $ExistUser.SamAccountName -Title $Title
}
#check Department
if ($ExistUser.Department -ne $Department){
$upd = $true
log("$UserLogin change Department: $($ExistUser.Department) -> $Department")
Set-ADUser -Identity $ExistUser.SamAccountName -Department $Department
}
#check manager
if ($Manager){
$DNManager = (Get-ADUser $Manager).DistinguishedName
if ($ExistUser.Manager -ne $DNManager){
$upd = $true
log("$UserLogin change Manager: $($ExistUser.Manager) -> $Manager")
Set-ADUser -Identity $ExistUser.SamAccountName -Manager $Manager
}
}
#check organisation
if ($ExistUser.Company -ne $Company){
$upd = $true
log("$UserLogin change Company: $($ExistUser.Company) -> $Company")
Set-ADUser -Identity $ExistUser.SamAccountName -Company $Company
}
#check enable
if($ExistUser.Enabled -ne $Enabled) {
log("$UserLogin change Enable (status): $($ExistUser.Enabled) -> $Enabled")
if ($Enabled) {
Enable-ADAccount -Identity "$UserLogin"
} else {
$UserDisableCount++
Disable-ADAccount -Identity "$UserLogin"
}
}
if ($upd){
$UserUpdCount++
}
} else {
# add new user
if ($Enabled){
$ou = $allou | Where {$_.Description -cmatch $User.OUGUID}
if ($ou) {
$OU = $ou.DistinguishedName
} else {
$OU = $withOutGUID
}
} else {
continue # didnt add inactive users
#$OU = $dismissed
}
# personal rules (for long name)
if($UserLogin.Length -gt 20){
$UserLogin = "$UserLogin" -replace "^(\w+)_(\w+)", '$2'
}
if($UserLogin.Length -gt 20){
$UserLogin = $UserLogin.Replace("-","")
}
if($UserLogin.Length -gt 20){
$UserLogin = $UserLogin.Substring(0, 20)
}
$uniqueLogin = $false
try {get-aduser "$UserLogin"}
catch {
$uniqueLogin = $true
echo "Unique"
}
if(!$uniqueLogin){
$isDuplicateLogin = $true;
$LastUserLogin = $UserLogin
$UserLogin = "$UserLogin" -replace "^(\w+)_(\w+)", '$2_$1'
echo "$UserLogin`t$LastUserLogin`t$AccountId" >> "DuplicateLogin.csv"
$uniqueLogin = $false
try {get-aduser "$UserLogin"}
catch {
$uniqueLogin = $true
echo "Unique after replace"
}
if(!$uniqueLogin){
echo "Duble Duplicate login"
$LastUserLogin = $UserLogin
echo "$UserLogin`t$AccountId" >> "DuplicateLogin.csv"
$UserLogin = "$UserLogin" -replace "^(\w+)_(\w+)", '$2_$1'
$UserLogin = $UserLogin.Replace("_",".")
echo "$UserLogin`t$LastUserLogin`t$AccountId" >> "DuplicateLogin.csv"
}
}
log("Create user: $UserLogin ($Detailedname, $Title, $Department)")
$SAM= $UserLogin + "@guu.ru"
genPassword
echo "$Detailedname`t$UserLogin`t$Password`t$Department`t$OU" >> "Login.csv"
try{
if ($manager){
New-ADUser -Manager $Manager -Name "$Detailedname" -SamAccountName "$UserLogin" -UserPrincipalName "$SAM" -EmailAddres "$SAM" -DisplayName "$Detailedname" -GivenName "$UserFirstName" -Surname "$UserLastName" -Title "$Title" -EmployeeNumber $AccountId -Path "$OU" -ChangePasswordAtLogon $false -Department "$Department" -Company $Company -PasswordNeverExpires $true
} else {
New-ADUser -Name "$Detailedname" -SamAccountName "$UserLogin" -UserPrincipalName "$SAM" -EmailAddres "$SAM" -DisplayName "$Detailedname" -GivenName "$UserFirstName" -Surname "$UserLastName" -Title "$Title" -EmployeeNumber $AccountId -Path "$OU" -ChangePasswordAtLogon $false -Department "$Department" -Company $Company -PasswordNeverExpires $true
}
$UserAddCount++
} catch {
echo "$OU`t$UserLogin`t$Password" >> "Error.csv"
$isErrors = $true
log("ERROR: Can't add user: $UserLogin")
$message.subject = "AD Sync script ($date) ERROR"
#read-host "Press Enter for continue"
}
Set-ADAccountPassword -Identity "$UserLogin" -NewPassword (ConvertTo-SecureString -AsPlainText "$Password" -Force)
if($Enabled) {
Enable-ADAccount -Identity "$UserLogin"
} else {
Disable-ADAccount -Identity "$UserLogin"
}
}
echo $UserGroup
if ($UserGroup -ne ""){
try {get-adgroup $UserGroup
} catch {
New-ADGroup -Name $UserGroup -SamAccountName $UserGroup -GroupScope Global -GroupCategory Security -Path "$group"
}
Add-ADGroupMember -Identity $UserGroup -Member "$UserLogin"
}
}
log("End working with users")
#add files and send mail
$message.attachments.add((Resolve-Path Log.txt).Path)
if ($UserAddCount -ne 0){
$message.attachments.add((Resolve-Path Login.csv).Path)
}
if ($isDuplicateLogin){
$message.attachments.add((Resolve-Path DuplicateLogin.csv).Path)
}
if ($isErrors){
$message.attachments.add((Resolve-Path Error.csv).Path)
}
$message.body = "Added users:`t$UserAddCount`nDisabled users:`t$UserDisableCount`nUpdated users:`t$UserUpdCount`nAdded OU:`t$OUAddCount`n`n"
$smtp.send($message)
$message.Dispose()
#remove temp dir
Remove-Item *.* -Force
Set-Location ..
Remove-Item $TempDir
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment