PS: SH-SOFT GAL Sync - ADDS (<)-> ADDS
This script version is designed to synchronize AD users / contscts with AD Power Shell commandlets between two active directory domains / forests. It can also be used to do a one way synchronization from a sour ce to a target environment.
It has some included filters to limit the number of accounts to be synchronised by the script:
- Multiple OUs for source mail enabled users in the source and in the target organisation
- It only synchronises visible users (so users hidden from the address list are not processes)
The password required to access the target environment can be stored using Power Shell please use the helper script provided >> here.
Content to be syncronised
The following attributes are synchronised:
- Display Name
- Name
- Lastname
- Firstname
- Department
- Title
- Company
- Office
- Phone
- Fax
- MobilePhone
- City
- PostalCode
- StreetAddress
- StateOrProvince
- CountryOrRegion
- PrimarySMTPAddress
- Legacy ExchangeDN (as X500 Address) (it is only written once and not kept up to date)
- Alias (with prefix is required)
The script populates the AD extension attributes 14 and 15 with sha1 hashed GUIDs either of the source user or of the scripts GUID to allow multiple instances of the script to coexist.
SETUP
This in short describes how to configure the script for a first time use:
After Download you should verify the integrity of the script downloaded with the included hashes. After this the following variables inside the script have to be configured:
- TargetDCList
A list to domaincontrollers to be used on target side. - TargetDomainNetBiosName
This represents the NetBIOS name of the target environment. It is used to determine if the connection to the target DC is possible. - TargetSearchScopes
Comma separated list of OUs to search for mail enabled users in the target organisation. - TargetContactOU
OU in which the contacts should be created (this one needs to be writable for the Sync account in the target organisation). - DoNotSearchWithinTarget
If set to true the script runs in one way mode and does not write anything to the source environment. - TargetCredentialPasswordFileName
Filename for the password file that should be created. - TargetCredentialUserName
Username for the remote access. - TargetAliasPrefix
A prefix that is placed in front of the alias to avoid duplicate aliases. - TargetObjectClass
Can be used to define an object class to search for in the target environemnt. - SourceDCList
A list to domaincontrollers to be used on target side. - SourceDomainNetBiosName
This represents the NetBIOS name of the source environment. It is used to determine if the connection to the source DC is possible. - SourceSearchScopes
Comma separated list of OUs to search for mail enabled users in the source organisation. - SourceContactOU
OU in which the contacts should be created (this one needs to be writable for the Sync account in the source organisation). - SourceAliasPrefix
A prefix that is placed in front of the alias to avoid duplicate aliases. - SourceObjectClass
Can be used to define an object class to search for in the target environemnt. - LogFilePath
By default this points to the script execution directory. But it can be changed to a different location if this is required. - LogFileBaseName
Basic file name of the log file. The current Date is prepended to that filename. - LogFileDateTime
Date and time syntax inside the log file. - DebugLogging
It is recommended to keep this active until a full check has verified the script operates in a normal way… - DebugToScreen
This is only required if you need to see the debug output in the shell window. This should be disabled to increase overall script performance. - ThisScriptGUIDFileBaseName
Filename to the script GUI hash. The hash itself is being created automatically if no guid file is found at startup. Then it will result in problems because all contacts loose sync. If the file or the content of the file is lost take a look to extensionAttribut14 of already created contacts and store that string to the file specified here. - UpdateDeleteContactsOnlyCreatedByThisScript
A very important switch please always use it set to true! It ensures the script only updates and deletes contacts created by itself. If this switch is not set the script WILL DELTE contacts in the Contacts OU if they do not match to a source mail enabled user!
You need to set up the environment:
- Open firewall from the Computer / Server running the script to the source and target Exchange and directory services.
- Add an account in the target environment with appropriate permissions in the target environment.
- Add an account in the source environment with appropriate permissions (Also the logon as Batch Job right is required on the machine running the script as a scheduled task).
- Store the target accounts password as encrypted password file with the account the script is running as.
Version History
- 1.0.0: Initial release
- 1.0.1: Bug fixes: New contacts in Target environment have not been created
Download the script:
>> Version 1.0.1 (current)
(MD5: b0ad80f86334b0fe503f3ee8946e2d13)
(SHA1: 62e0d7e027a17f607469bad62bf3c430080dc86c)
Script code:
##------------------------------------------------------------------------------------------------
##
## SH-SOFT-GALSync-ADDSADDS.ps1
##
## Version 1.0.1
##
##
## Copyright (c) 2016 Martin Mueller - www.sh-soft.com
##
## Permission is hereby granted, free of charge, to any person obtaining a copy of this software
## and associated documentation files (the "Software"), to deal in the Software without
## restriction, including without limitation the rights to use, copy, modify, merge, publish,
## distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
## Software is furnished to do so, subject to the following conditions:
##
## The above copyright notice and this permission notice shall be included in all copies or
## substantial portions of the Software.
##
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
## BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
## NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
## DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
## FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
## (The MIT License (MIT))
##
##------------------------------------------------------------------------------------------------
<#
.SYNOPSIS
please visit https://www.sh-soft.com/en/scripting/ps/sh-galsync/ps-sh-soft-gal-sync-adds-adds.html for instructions about the script. Thanks.
This script version can synchronize users between two Active Directory forests.
You can find a complete list of available versions here:
https://www.sh-soft.com/en/scripting/ps/sh-galsync
Otherwise please contact me to see if there are possible inofficial versions available for your special purpose :-)
#>
##------------------------------------------------------------------------------------------------
## Configuration parameters for the script
##------------------------------------------------------------------------------------------------
#------------------------------------------------------------------------------------------------
## Target environment
#
# this variables contain connection information to your partners ADDS server
#
#------------------------------------------------------------------------------------------------
# FQDN server name of the partners exchange environment
$TargetDCList = @("TDC1.sh-soft.com", "TDC2.sh-soft.com")
#Domain name is used verify connectivity to target domaincontroller should be: "(Get-ADDomain -Server (Read-Host -Prompt "Enter server name") -Credential (Get-Credential)).NetBIOSName"
$TargetDomainNetBiosName = "SH-SOFT"
# Search scopes to look for mail enabled users
$TargetSearchScopes = @("OU=SomeUsers,dc=sh-soft,dc=com", "OU=SomeMoreUsers,dc=sh-soft,dc=com")
# if you enable the following setting ist will do a one way sync from local to target environment
$DoNotSearchWithinTarget = $false
# You have to verfiy this one is not within the SearchScopes!
$TargetContactOU = "OU=Contacts,DC=sh-soft,dc=com"
# Alias prefix that is attached infront of the original alias when they get created / updated in the source directory
$TargetAliasPrefix = ""
# Username to connect to the target environment (use NetBiosDomainName\SAMaccountName)
$TargetCredentialUserName = "SH-SOFT\service_addssync"
# Password for the above account stored encrypted
# see https://www.sh-soft.com/en/scripting/ps/ps-store-credential.html
$TargetCredentialPasswordFileName = "service_addssync.cred"
# Target object class (used in the query to find objects to be created on the source side)
$TargetObjectClass = "(ObjectClass -eq 'user')"
#------------------------------------------------------------------------------------------------
## Source environment
#
# this variables contain connection infromation of your ADDS Environment
#
#------------------------------------------------------------------------------------------------
# FQDN server name of the local exchange environment
$SourceDCList = @("sdc1.schnitzelbroetchen.info", "sdc2.schnitzelbroetchen.info")
#Domain name is used verify connectivity to target domaincontroller should be: "(Get-ADDomain -Server (Read-Host -Prompt "Enter server name")).NetBIOSName"
$SourceDomainNetBiosName = "SB"
# Search scopes to look for mail enabled users
$SourceSearchScopes = @("OU=MyUsers,DC=schnitzelbroetchen,DC=info")
# You have to verfiy this one is not within the SearchScopes!
$SourceContactOU = "OU=SH-Contacts,dc=schnitzelbroetchen,dc=info"
# Alias prefix that is attached infront of the original alias when they get created / updated in the target directory
$SourceAliasPrefix = ""
# Source object class (used in the query to find objects to be created on the target side)
$SourceObjectClass = "(ObjectClass -eq 'User')"
#------------------------------------------------------------------------------------------------
# Logging
#------------------------------------------------------------------------------------------------
$LogFilePath = (Split-Path -Parent -Path $MyInvocation.MyCommand.Definition) #default points to the script directory
$LogFileBaseName = "_SH-SOFT-GALSync-ADDSADDS.log"
$LogFileDateTime = "yyyyMMdd.HHmmss"
# Enable or disable debug (detailed) logging
$DebugLogging = $true
# Enable or disable debugging to screen -> Should be set to $false in production because it reduces the script performance.
$DebugToScreen = $false
#Monitoring files (Not yet implemented in a perfect way... )
$CreateMonitoringFiles = $false
$OverallStatusFileName = "somefilenaemewithpath"
#------------------------------------------------------------------------------------------------
# GUID file of the script
#------------------------------------------------------------------------------------------------
$ThisScriptGUIDFileBaseName = "ThisScript.guid"
#------------------------------------------------------------------------------------------------
# To process only contacts created by this script leave this option enabled ($true)
#
# This ensures no otherwise created contacts get updated or removed!
# The script creates a GUID if none exists. The GUID is stored as sha1 hash in a file defined in the variable $ThisScriptGUIDFileBaseName
# the default name is ThisScript.guid
# Every contact created by the script gets ExtensionAttribute14 provisioned with this hashed GUID (regardless if this option is enabled or not)
#------------------------------------------------------------------------------------------------
$UpdateDeleteContactsOnlyCreatedByThisScript = $true
###================================================================================================###
### ###
### MAIN SCRIPT PART - no change should be required from here on... ###
### ###
###================================================================================================###
##------------------------------------------------------------------------------------------------
## Internal variables
##------------------------------------------------------------------------------------------------
# Logfile DateTime prefix
$Date = Get-Date -Format $LogFileDateTime
#Hashing algorithm (sha1 as default)
$CProvider = New-Object System.Security.Cryptography.SHA1CryptoServiceProvider
#Overall status variable
$ScriptOverallStatus = "OK"
#GUID filename handling
$ThisScriptGUIDFileName = ""
$ThisScriptGUIDFileName = Join-Path -Path (Split-Path -Parent -Path $MyInvocation.MyCommand.Definition) -ChildPath ($ThisScriptGUIDFileBaseName) -WarningAction SilentlyContinue -ErrorAction SilentlyContinue
$ThisScriptGUID = $null
#Password filename hdanling
$TargetCredentialPasswordFile = ""
$TargetCredentialPasswordFile = Join-Path -Path (Split-Path -Parent -Path $MyInvocation.MyCommand.Definition) -ChildPath ($TargetCredentialPasswordFileName) -WarningAction SilentlyContinue -ErrorAction SilentlyContinue
$TargetCredentialPasswordFileName = $null
##------------------------------------------------------------------------------------------------
## Internal functions
##------------------------------------------------------------------------------------------------
#------------------------------------------------------------------------------------------------
# Log writer
function Write-Log ($Entry, $DebugEntry) {
$DateTime = Get-Date -Format "yyyyMMdd;HHmmss;"
$FileName = Join-Path -Path $LogFilePath -ChildPath ($Date + $LogFileBaseName)
## USER INTERFACE
if ($DebugToScreen) {
if ($Entry) {
Write-Host -ForegroundColor Cyan ($DateTime+$Entry)
}
if ($DebugEntry) {
Write-Host -ForegroundColor DarkMagenta ($DateTime+"[DEBUG]") -nonewline
Write-Host -ForegroundColor Cyan $DebugEntry
}
}
if ($LogFilePath.Length -eq $null) {
$FileName = ($Date + "-" + $LogFileBaseName)
}
if ($Entry) {
Add-Content -Path $FileName -Value ($DateTime + $Entry)
}
if ($DebugLogging -and $DebugEntry) {
Add-Content -Path $FileName -Value ($DateTime +" [DEBUG] "+ $DebugEntry)
}
}
#------------------------------------------------------------------------------------------------
# Create hashes for strings
function Create-SHAHash ([string]$Value) {
if ($Value.Length -gt 0) {
$encoding = [system.Text.Encoding]::UTF8
$ByteValue = $encoding.GetBytes($value)
$HASH = ([System.BitConverter]::ToString($CProvider.ComputeHash($ByteValue))).Replace("-", "").ToLower()
Write-Log -DebugEntry ("[CREATE-SHAHASH] Input: `""+$Value+"`" -- Output: `""+$HASH+"`"")
return ($HASH)
}
else {
return "[ERROR-SOURCEWASEMPTY]"
}
}
#------------------------------------------------------------------------------------------------
# Verify hashes
function Verfiy-SHAHash ([string]$Value, [string]$Hash) {
$InnerHash = Create-SHAHash -Value $Value
Write-Log -DebugEntry ("[VERIFY-SHAHASH] Value: `""+$Value+"`" (`""+$InnerHash+"`") -- Hash: `""+$Hash+"`"")
if ($InnerHash -eq $Hash) {
Write-Log -DebugEntry ("[VERIFY-SHAHASH] - Match")
return $true
}
else {
Write-Log -DebugEntry ("[VERIFY-SHAHASH] - No Match")
return $false
}
}
#------------------------------------------------------------------------------------------------
# Update Status File
function Update-StatusFiles ($OverallStatusFile) {
if ($CreateMonitoringFiles) {
Write-Log -DebugEntry "[UPDATE-STATUSFILES]"
if ($OverallStatusFile.Length -gt 0) {
$ScriptOverallStatus = $OverallStatusFile
}
try {
# Overall file
Set-Content -Path $OverallStatusFileName -Value $ScriptOverallStatus
Add-Content -Path $OverallStatusFileName -Value (Get-Date -Format "yyyyMMdd-HHmmss")
}
catch {
Write-Log -Entry "[ERROR] failed updating status file!"
}
}
}
##------------------------------------------------------------------------------------------------
## early initialization
##------------------------------------------------------------------------------------------------
#------------------------------------------------------------------------------------------------
# GUID handling
if ($ThisScriptGUIDFileName.Length -eq 0) {
$ThisScriptGUIDFileName = $ThisScriptGUIDFileBaseName
}
#Verify file exists then load
if (Test-Path $ThisScriptGUIDFileName) {
try {
$ThisScriptGUID = Get-Content -Path $ThisScriptGUIDFileName
Write-Log -DebugEntry "Reading GUID from file: $ThisScriptGUIDFileName - successfull"
}
catch {
Write-Log -Entry "[ERROR] while reading GUID file" -DebugEntry "$ThisScriptGUIDFileName"
}
}
#Otherwise create guid and save it to file
else {
Write-Log -Entry "Creating new GUID for this script"
$ThisScriptGUID = ([guid]::NewGuid()) | Select-Object -ExpandProperty GUID
Write-Log -DebugEntry "Creating hash for new GUID: $ThisScriptGUID"
$ThisScriptGUID = Create-SHAHash -Value $ThisScriptGUID
Write-Log -DebugEntry "Hash for GUID is: $ThisScriptGUID"
try {
Set-Content -Path $ThisScriptGUIDFileName -Value $ThisScriptGUID -Encoding UTF8
}
catch {
Write-Log -Entry "[ERROR] while writing GUID to file" -DebugEntry $ThisScriptGUIDFileName
}
}
#------------------------------------------------------------------------------------------------
# Log file initialize
Write-Log -DebugEntry ("[LOGGING] `""+$LogFilePath+"`"")
Write-Log -DebugEntry ("[LOGGING] `""+$LogFileBaseName+"`"")
Write-Log -DebugEntry ("[LOGGING] `""+$LogFileDateTime+"`"")
Write-Log -DebugEntry ("[STATUSFILE] `""+$OverallStatusFileName+"`"")
#Status monitoring
Update-StatusFiles
Write-log -Entry "Starting script execution"
#------------------------------------------------------------------------------------------------
# Build target credential
$TargetCredential = $null
if (Test-Path -Path $TargetCredentialPasswordFile) {
try {
$Password = Get-Content "$TargetCredentialPasswordFile" | ConvertTo-SecureString
$TargetCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "$TargetCredentialUserName",$Password
$Password = $null
}
catch {
Write-Log -Entry "ERROR while reading target credential file" -DebugEntry $TargetCredentialPasswordFile
$ScriptOverallStatus = "ERROR"
$Password = $null
exit
}
}
else {
Write-Log -Entry "ERROR target credential file not found please check whether file exists or not." -DebugEntry $TargetCredentialPasswordFile
$ScriptOverallStatus = "ERROR"
exit
}
#------------------------------------------------------------------------------------------------
#Load ADDS Power Shell module if this one is not already loaded...
if (-Not (Get-Module -Name ActiveDirectory)) {
try {
Write-Log -Entry "Importing ADDS module for powershell"
Import-Module ActiveDirectory -ErrorAction SilentlyContinue -WarningAction SilentlyContinue
Write-Log -DebugEntry "done"
}
catch {
Write-Log -Entry "[ERROR] failed to load AD module for power shell. please ensure it is installed."
exit
}
}
#------------------------------------------------------------------------------------------------
# establish connection to target side (Test credential and connection)
$TargetDC = $null
foreach ($testDC in $TargetDCList) {
if ((Get-ADDomain -Server $testDC -Credential $TargetCredential -ErrorAction SilentlyContinue -WarningAction SilentlyContinue).NetBIOSName -eq $TargetDomainNetBiosName) {
Write-Log -Entry "[TESTCONNECTION] Connection to target DC: $testDC has been verified"
$TargetDC = $testDC
break
}
else {
Write-Log -Entry "[TESTCONNECTION] A connection to a target domaincontroller in the server list could not be established. The server used was: $testDC"
}
}
if ($TargetDC -eq $null) {
Write-Log -Entry "[ERROR] None of the servers in the target server list was accessible or the credentials used did not match!"
exit
}
#------------------------------------------------------------------------------------------------
# establish connection to source side (Test credential and connection)
$SourceDC = $null
foreach ($testDC in $SourceDCList) {
if ((Get-ADDomain -Server $testDC -ErrorAction SilentlyContinue -WarningAction SilentlyContinue).NetBIOSName -eq $SourceDomainNetBiosName) {
Write-Log -Entry "[TESTCONNECTION] Connection to source DC: $testDC has been verified"
$SourceDC = $testDC
break
}
else {
Write-Log -Entry "[TESTCONNECTION] A connection to a source domaincontroller in the server list could not be established. The server used was: $testDC"
}
}
if ($SourceDC -eq $null) {
Write-Log -Entry "[ERROR] None of the servers in the source server list was accessible or the credentials used did not match!"
exit
}
##------------------------------------------------------------------------------------------------
## Get source elements
##------------------------------------------------------------------------------------------------
##Status monitoring
Update-StatusFiles
#------------------------------------------------------------------------------------------------
# Get source real users
#------------------------------------------------------------------------------------------------
$SourceElements = @()
$SourceFilter = 'mail -like "*" -and {0}' -f "$SourceObjectClass"
foreach ($OU in $SourceSearchScopes) {
$SourceElements += Get-ADObject -SearchBase "$OU" -Filter "$SourceFilter" -Server $SourceDC -Properties DisplayName, Name, sn, givenName,msExchHideFromAddressLists, `
department, title, company, physicalDeliveryOfficeName, `
telephoneNumber, facsimileTelephoneNumber, mobile, `
l, postalCode, streetAddress, st, co, `
mail, legacyExchangeDN, mailNickname, `
extensionAttribute14, extensionAttribute15, DistinguishedName, objectGUID | `
Where-Object {$_.msExchHideFromAddressLists -ne $true } | `
Select-Object -Property SHElementID, SHHashedGUID, SHStatus, SHSourceContactElementID, `
DisplayName, Name, sn, givenName,msExchHideFromAddressLists, `
department, title, company, physicalDeliveryOfficeName, `
telephoneNumber, facsimileTelephoneNumber, mobile, `
l, postalCode, streetAddress, st, co, `
mail, legacyExchangeDN, mailNickname, `
extensionAttribute14, extensionAttribute15, DistinguishedName, objectGUID
}
# Create Hashed GUID foreach recipient and collect additional attributes
$ElementID = 0
foreach ($SourceElement in $SourceElements) {
$CurrentDN = $SourceElement.DistinguishedName
Write-Log -DebugEntry ("[SOURCEUSERATTRIBUTE-COLLECTION] $CurrentDN")
#Update new values to existing object
$SourceElement.SHElementID = $ElementID
$SourceElement.SHHashedGUID = Create-SHAHash -Value $SourceElement.objectGUID.ToString()
#Set Alias Prefix
$SourceElement.mailNickname = $SourceAliasPrefix+$SourceElement.mailNickname
$ElementID++
}
#------------------------------------------------------------------------------------------------
# Get Contacts in SourceContacts OU (Partners Addresses in Source directory)
#------------------------------------------------------------------------------------------------
if (-not $DoNotSearchWithinTarget) {
$TargetContactElements = @()
$TargetContactElements = Get-ADObject -SearchBase "$SourceContactOU" -Filter "ObjectClass -eq 'Contact'" -Server $SourceDC -Properties DisplayName, Name, sn, givenName,msExchHideFromAddressLists, `
department, title, company, physicalDeliveryOfficeName, `
telephoneNumber, facsimileTelephoneNumber, mobile, `
l, postalCode, streetAddress, st, co, `
mail, legacyExchangeDN, mailNickname, `
extensionAttribute14, extensionAttribute15, DistinguishedName, objectGUID | `
Select-Object -Property SHElementID, SHHashedGUID, SHStatus, SHTargetElementID, `
DisplayName, Name, sn, givenName,msExchHideFromAddressLists, `
department, title, company, physicalDeliveryOfficeName, `
telephoneNumber, facsimileTelephoneNumber, mobile, `
l, postalCode, streetAddress, st, co, `
mail, legacyExchangeDN, mailNickname, `
extensionAttribute14, extensionAttribute15, DistinguishedName, objectGUID
$ElementID = 0
if ($TargetContactElements.Count -gt 0) {
foreach ($TargetContactElement in $TargetContactElements) {
$CurrentDN = $TargetContactElement.DistinguishedName
Write-Log -DebugEntry ("[TARGETCONTACTATTRIBUTE-COLLECTION] $CurrentDN")
$TargetContactElement.SHElementID = $ElementID
$ElementID++
}
}
}
##------------------------------------------------------------------------------------------------
## Get target elements
##------------------------------------------------------------------------------------------------
##Status monitoring
Update-StatusFiles
#------------------------------------------------------------------------------------------------
# Get Elements from Target Domain
#------------------------------------------------------------------------------------------------
if (-not $DoNotSearchWithinTarget) {
$TargetElements = @()
$TargetFilter = 'mail -like "*" -and {0}' -f "$TargetObjectClass"
foreach ($OU in $TargetSearchScopes) {
$TargetElements += Get-ADObject -SearchBase "$OU" -Filter "$TargetFilter" -Server $TargetDC -Credential $TargetCredential -Properties DisplayName, Name, sn, givenName,msExchHideFromAddressLists, `
department, title, company, physicalDeliveryOfficeName, `
telephoneNumber, facsimileTelephoneNumber, mobile, `
l, postalCode, streetAddress, st, co, `
mail, legacyExchangeDN, mailNickname, `
extensionAttribute14, extensionAttribute15, DistinguishedName, objectGUID | `
Where-Object {$_.msExchHideFromAddressLists -ne $true } | `
Select-Object -Property SHElementID, SHHashedGUID, SHStatus, SHSourceContactElementID, `
DisplayName, Name, sn, givenName,msExchHideFromAddressLists, `
department, title, company, physicalDeliveryOfficeName, `
telephoneNumber, facsimileTelephoneNumber, mobile, `
l, postalCode, streetAddress, st, co, `
mail, legacyExchangeDN, mailNickname, `
extensionAttribute14, extensionAttribute15, DistinguishedName, objectGUID
}
# Create Hased GUID foreach recipient
$ElementID = 0
foreach ($TargetElement in $TargetElements) {
$CurrentDN = $TargetElement.DistinguishedName
Write-Log -DebugEntry ("[TARGETUSERATTRIBUTE-COLLECTION] $CurrentDN")
#Update new values to existing object
$TargetElement.SHElementID = $ElementID
$TargetElement.SHHashedGUID = Create-SHAHash -Value $TargetElement.objectGUID.ToString()
#Set Alias Prefix
$TargetElement.mailNickname = $TargetAliasPrefix+$TargetElement.mailNickname
$ElementID++
}
}
#------------------------------------------------------------------------------------------------
# Get Contacts in TargetContacts OU (Your Addresses in target directory)
#------------------------------------------------------------------------------------------------
$SourceContactElements = @()
$SourceContactElements = Get-ADObject -SearchBase "$TargetContactOU" -Filter "ObjectClass -eq 'Contact'" -Server $TargetDC -Credential $TargetCredential -Properties DisplayName, Name, sn, givenName,msExchHideFromAddressLists, `
department, title, company, physicalDeliveryOfficeName, `
telephoneNumber, facsimileTelephoneNumber, mobile, `
l, postalCode, streetAddress, st, co, `
mail, legacyExchangeDN, mailNickname, `
extensionAttribute14, extensionAttribute15, DistinguishedName, objectGUID | `
Select-Object -Property SHElementID, SHHashedGUID, SHStatus, SHSourceElementID, `
DisplayName, Name, sn, givenName,msExchHideFromAddressLists, `
department, title, company, physicalDeliveryOfficeName, `
telephoneNumber, facsimileTelephoneNumber, mobile, `
l, postalCode, streetAddress, st, co, `
mail, legacyExchangeDN, mailNickname, `
extensionAttribute14, extensionAttribute15, DistinguishedName, objectGUID
$ElementID = 0
if ($SourceContactElements.Count -gt 0) {
foreach ($SourceContactElement in $SourceContactElements) {
$CurrentDN = $SourceContactElement.DistinguishedName
Write-Log -DebugEntry ("[SOURCECONTACTATTRIBUTE-COLLECTION] $CurrentDN")
$SourceContactElement.SHElementID = $ElementID
$ElementID++
}
}
##------------------------------------------------------------------------------------------------
## compare
##------------------------------------------------------------------------------------------------
##Status monitoring
Update-StatusFiles
#------------------------------------------------------------------------------------------------
# Check Source Elements (Compare your source elements with the contacts in your partners directory)
#------------------------------------------------------------------------------------------------
Write-Log -Entry "[COMPAREOBJECTS] SourceUser::RemoteContact"
if ($SourceElements.Count -ne 0 -or $SourceContactElements.count -ne 0) {
# Check for updates an new created users in source system
foreach ($SourceElement in $SourceElements) {
$CurrentSourceElementHashGUID = $SourceElement.SHHashedGUID
$SourceElement.SHStatus = "userNotFound"
if ($SourceContactElements.Count -gt 0) {
foreach ($SourceContactElement in $SourceContactElements) {
if ($SourceContactElement.extensionAttribute15 -eq $CurrentSourceElementHashGUID) {
$SourceElement.SHStatus = "userFound"
$SourceElement.SHSourceContactElementID = $SourceContactElement.SHElementID
$SourceContactElement.SHSourceElementID = $SourceElement.SHElementID
break
}
}
if ($SourceElement.SHStatus -eq "userFound") {
$SourceContactID = $SourceElement.SHSourceContactElementID
# Name
if ($SourceElement.DisplayName -ne $SourceContactElements[$SourceContactID].DisplayName) {
$SourceElement.SHStatus = "userUpdated"
Write-Log -DebugEntry ("[DisplayName.Updated]"+$CurrentSourceElementHashGUID+";Old: "+ $SourceContactElements[$SourceContactID].DisplayName +";New: "+$SourceElement.DisplayName)
}
if ($SourceElement.Name -ne $SourceContactElements[$SourceContactID].Name) {
$SourceElement.SHStatus = "userUpdated"
Write-Log -DebugEntry ("[Name.Updated]"+$CurrentSourceElementHashGUID+";Old: "+ $SourceContactElements[$SourceContactID].Name +";New: "+$SourceElement.Name)
}
if ($SourceElement.sn -ne $SourceContactElements[$SourceContactID].sn) {
$SourceElement.SHStatus = "userUpdated"
Write-Log -DebugEntry ("[sn.Updated]"+$CurrentSourceElementHashGUID+";Old: "+ $SourceContactElements[$SourceContactID].sn +";New: "+$SourceElement.sn)
}
if ($SourceElement.GivenName -ne $SourceContactElements[$SourceContactID].GivenName) {
$SourceElement.SHStatus = "userUpdated"
Write-Log -DebugEntry ("[GivenName.Updated]"+$CurrentSourceElementHashGUID+";Old: "+ $SourceContactElements[$SourceContactID].GivenName +";New: "+$SourceElement.GivenName)
}
# Company
if ($SourceElement.Department -ne $SourceContactElements[$SourceContactID].Department) {
$SourceElement.SHStatus = "userUpdated"
Write-Log -DebugEntry ("[Department.Updated]"+$CurrentSourceElementHashGUID+";Old: "+ $SourceContactElements[$SourceContactID].Department +";New: "+$SourceElement.Department)
}
if ($SourceElement.Title -ne $SourceContactElements[$SourceContactID].Title) {
$SourceElement.SHStatus = "userUpdated"
Write-Log -DebugEntry ("[Title.Updated]"+$CurrentSourceElementHashGUID+";Old: "+ $SourceContactElements[$SourceContactID].Title +";New: "+$SourceElement.Title)
}
if ($SourceElement.Company -ne $SourceContactElements[$SourceContactID].Company) {
$SourceElement.SHStatus = "userUpdated"
Write-Log -DebugEntry ("[Company.Updated]"+$CurrentSourceElementHashGUID+";Old: "+ $SourceContactElements[$SourceContactID].Company +";New: "+$SourceElement.Company)
}
if ($SourceElement.physicalDeliveryOfficeName -ne $SourceContactElements[$SourceContactID].physicalDeliveryOfficeName) {
$SourceElement.SHStatus = "userUpdated"
Write-Log -DebugEntry ("[physicalDeliveryOfficeName.Updated]"+$CurrentSourceElementHashGUID+";Old: "+ $SourceContactElements[$SourceContactID].physicalDeliveryOfficeName +";New: "+$SourceElement.physicalDeliveryOfficeName)
}
# telephoneNumber
if ($SourceElement.telephoneNumber -ne $SourceContactElements[$SourceContactID].telephoneNumber) {
$SourceElement.SHStatus = "userUpdated"
Write-Log -DebugEntry ("[telephoneNumber.Updated]"+$CurrentSourceElementHashGUID+";Old: "+ $SourceContactElements[$SourceContactID].telephoneNumber +";New: "+$SourceElement.telephoneNumber)
}
if ($SourceElement.facsimileTelephoneNumber -ne $SourceContactElements[$SourceContactID].facsimileTelephoneNumber) {
$SourceElement.SHStatus = "userUpdated"
Write-Log -DebugEntry ("[facsimileTelephoneNumber.Updated]"+$CurrentSourceElementHashGUID+";Old: "+ $SourceContactElements[$SourceContactID].facsimileTelephoneNumber +";New: "+$SourceElement.facsimileTelephoneNumber)
}
if ($SourceElement.mobile -ne $SourceContactElements[$SourceContactID].mobile) {
$SourceElement.SHStatus = "userUpdated"
Write-Log -DebugEntry ("[mobile.Updated]"+$CurrentSourceElementHashGUID+";Old: "+ $SourceContactElements[$SourceContactID].mobile +";New: "+$SourceElement.mobile)
}
# Address
if ($SourceElement.l -ne $SourceContactElements[$SourceContactID].l) {
$SourceElement.SHStatus = "userUpdated"
Write-Log -DebugEntry ("[l.Updated]"+$CurrentSourceElementHashGUID+";Old: "+ $SourceContactElements[$SourceContactID].l +";New: "+$SourceElement.l)
}
if ($SourceElement.PostalCode -ne $SourceContactElements[$SourceContactID].PostalCode) {
$SourceElement.SHStatus = "userUpdated"
Write-Log -DebugEntry ("[PostalCode.Updated]"+$CurrentSourceElementHashGUID+";Old: "+ $SourceContactElements[$SourceContactID].PostalCode +";New: "+$SourceElement.PostalCode)
}
if ($SourceElement.StreetAddress -ne $SourceContactElements[$SourceContactID].StreetAddress) {
$SourceElement.SHStatus = "userUpdated"
Write-Log -DebugEntry ("[StreetAddress.Updated]"+$CurrentSourceElementHashGUID+";Old: "+ $SourceContactElements[$SourceContactID].StreetAddress +";New: "+$SourceElement.StreetAddress)
}
if ($SourceElement.st -ne $SourceContactElements[$SourceContactID].st) {
$SourceElement.SHStatus = "userUpdated"
Write-Log -DebugEntry ("[StateOrPrivonce.Updated]"+$CurrentSourceElementHashGUID+";Old: "+ $SourceContactElements[$SourceContactID].st +";New: "+$SourceElement.st)
}
if ($SourceElement.co -ne $SourceContactElements[$SourceContactID].co) {
$SourceElement.SHStatus = "userUpdated"
Write-Log -DebugEntry ("[co.Updated]"+$CurrentSourceElementHashGUID+";Old: "+ $SourceContactElements[$SourceContactID].co +";New: "+$SourceElement.co)
}
# Mail
if ($SourceElement.mail -ne $SourceContactElements[$SourceContactID].mail) {
$SourceElement.SHStatus = "userUpdated"
Write-Log -DebugEntry ("[mail.Updated]"+$CurrentSourceElementHashGUID+";Old: "+ $SourceContactElements[$SourceContactID].mail +";New: "+$SourceElement.mail)
}
#NOTE: LegacyExchangeDN can be implemented but is at the moment not required to check for updates because source field is more or less a constant.
if ($SourceElement.mailNickname -ne ($SourceContactElements[$SourceContactID].mailNickname)) {
$SourceElement.SHStatus = "userUpdated"
Write-Log -DebugEntry ("[mailNickname.Updated]"+$CurrentSourceElementHashGUID+";Old: "+ $SourceContactElements[$SourceContactID].mailNickname +";New: "+$SourceElement.mailNickname)
}
}
}
}
# Check for deleted users in source system
if ($SourceContactElements.Count -gt 0) {
foreach ($SourceContactElement in $SourceContactElements) {
foreach ($SourceElement in $SourceElements) {
$SourceContactElement.SHStatus = "userRemoved"
if ($SourceContactElement.extensionAttribute15 -eq $SourceElement.SHHashedGUID) {
$SourceContactElement.SHStatus = "userExists"
break
}
}
}
}
}
#------------------------------------------------------------------------------------------------
# Check Target Elements (Compare your partners elements with the contacts created in your directory)
#------------------------------------------------------------------------------------------------
if (-not $DoNotSearchWithinTarget) {
Write-Log -Entry "[COMPAREOBJECTS] RemoteUser::TargetContact"
if ($TargetElements.Count -ne 0 -or $TargetContactElements.count -ne 0) {
# Check for updates an new created users in source system
foreach ($TargetElement in $TargetElements) {
$CurrentTargetElementHashGUID = $TargetElement.SHHashedGUID
$TargetElement.SHStatus = "userNotFound"
if ($TargetContactElements.Count -gt 0) {
foreach ($TargetContactElement in $TargetContactElements) {
if ($TargetContactElement.extensionAttribute15 -eq $CurrentTargetElementHashGUID) {
$TargetElement.SHStatus = "userFound"
$TargetElement.SHTargetContactElementID = $TargetContactElement.SHElementID
$TargetContactElement.SHTargetElementID = $TargetElement.SHElementID
break
}
}
if ($TargetElement.SHStatus -eq "userFound") {
$TargetContactID = $TargetElement.SHTargetContactElementID
# Name
if ($TargetElement.DisplayName -ne $TargetContactElements[$TargetContactID].DisplayName) {
$TargetElement.SHStatus = "userUpdated"
Write-Log -DebugEntry ("[DisplayName.Updated]"+$CurrentTargetElementHashGUID+";Old: "+ $TargetContactElements[$TargetContactID].DisplayName +";New: "+$TargetElement.DisplayName)
}
if ($TargetElement.Name -ne $TargetContactElements[$TargetContactID].Name) {
$TargetElement.SHStatus = "userUpdated"
Write-Log -DebugEntry ("[Name.Updated]"+$CurrentTargetElementHashGUID+";Old: "+ $TargetContactElements[$TargetContactID].Name +";New: "+$TargetElement.Name)
}
if ($TargetElement.sn -ne $TargetContactElements[$TargetContactID].sn) {
$TargetElement.SHStatus = "userUpdated"
Write-Log -DebugEntry ("[sn.Updated]"+$CurrentTargetElementHashGUID+";Old: "+ $TargetContactElements[$TargetContactID].sn +";New: "+$TargetElement.sn)
}
if ($TargetElement.GivenName -ne $TargetContactElements[$TargetContactID].GivenName) {
$TargetElement.SHStatus = "userUpdated"
Write-Log -DebugEntry ("[GivenName.Updated]"+$CurrentTargetElementHashGUID+";Old: "+ $TargetContactElements[$TargetContactID].GivenName +";New: "+$TargetElement.GivenName)
}
# Company
if ($TargetElement.Department -ne $TargetContactElements[$TargetContactID].Department) {
$TargetElement.SHStatus = "userUpdated"
Write-Log -DebugEntry ("[Department.Updated]"+$CurrentTargetElementHashGUID+";Old: "+ $TargetContactElements[$TargetContactID].Department +";New: "+$TargetElement.Department)
}
if ($TargetElement.Title -ne $TargetContactElements[$TargetContactID].Title) {
$TargetElement.SHStatus = "userUpdated"
Write-Log -DebugEntry ("[Title.Updated]"+$CurrentTargetElementHashGUID+";Old: "+ $TargetContactElements[$TargetContactID].Title +";New: "+$TargetElement.Title)
}
if ($TargetElement.Company -ne $TargetContactElements[$TargetContactID].Company) {
$TargetElement.SHStatus = "userUpdated"
Write-Log -DebugEntry ("[Company.Updated]"+$CurrentTargetElementHashGUID+";Old: "+ $TargetContactElements[$TargetContactID].Company +";New: "+$TargetElement.Company)
}
if ($TargetElement.physicalDeliveryOfficeName -ne $TargetContactElements[$TargetContactID].physicalDeliveryOfficeName) {
$TargetElement.SHStatus = "userUpdated"
Write-Log -DebugEntry ("[physicalDeliveryOfficeName.Updated]"+$CurrentTargetElementHashGUID+";Old: "+ $TargetContactElements[$TargetContactID].physicalDeliveryOfficeName +";New: "+$TargetElement.physicalDeliveryOfficeName)
}
# telephoneNumber
if ($TargetElement.telephoneNumber -ne $TargetContactElements[$TargetContactID].telephoneNumber) {
$TargetElement.SHStatus = "userUpdated"
Write-Log -DebugEntry ("[telephoneNumber.Updated]"+$CurrentTargetElementHashGUID+";Old: "+ $TargetContactElements[$TargetContactID].telephoneNumber +";New: "+$TargetElement.telephoneNumber)
}
if ($TargetElement.facsimileTelephoneNumber -ne $TargetContactElements[$TargetContactID].facsimileTelephoneNumber) {
$TargetElement.SHStatus = "userUpdated"
Write-Log -DebugEntry ("[facsimileTelephoneNumber.Updated]"+$CurrentTargetElementHashGUID+";Old: "+ $TargetContactElements[$TargetContactID].facsimileTelephoneNumber +";New: "+$TargetElement.facsimileTelephoneNumber)
}
if ($TargetElement.mobile -ne $TargetContactElements[$TargetContactID].mobile) {
$TargetElement.SHStatus = "userUpdated"
Write-Log -DebugEntry ("[mobile.Updated]"+$CurrentTargetElementHashGUID+";Old: "+ $TargetContactElements[$TargetContactID].mobile +";New: "+$TargetElement.mobile)
}
# Address
if ($TargetElement.l -ne $TargetContactElements[$TargetContactID].l) {
$TargetElement.SHStatus = "userUpdated"
Write-Log -DebugEntry ("[l.Updated]"+$CurrentTargetElementHashGUID+";Old: "+ $TargetContactElements[$TargetContactID].l +";New: "+$TargetElement.l)
}
if ($TargetElement.PostalCode -ne $TargetContactElements[$TargetContactID].PostalCode) {
$TargetElement.SHStatus = "userUpdated"
Write-Log -DebugEntry ("[PostalCode.Updated]"+$CurrentTargetElementHashGUID+";Old: "+ $TargetContactElements[$TargetContactID].PostalCode +";New: "+$TargetElement.PostalCode)
}
if ($TargetElement.StreetAddress -ne $TargetContactElements[$TargetContactID].StreetAddress) {
$TargetElement.SHStatus = "userUpdated"
Write-Log -DebugEntry ("[StreetAddress.Updated]"+$CurrentTargetElementHashGUID+";Old: "+ $TargetContactElements[$TargetContactID].StreetAddress +";New: "+$TargetElement.StreetAddress)
}
if ($TargetElement.st -ne $TargetContactElements[$TargetContactID].st) {
$TargetElement.SHStatus = "userUpdated"
Write-Log -DebugEntry ("[StateOrPrivonce.Updated]"+$CurrentTargetElementHashGUID+";Old: "+ $TargetContactElements[$TargetContactID].st +";New: "+$TargetElement.st)
}
if ($TargetElement.co -ne $TargetContactElements[$TargetContactID].co) {
$TargetElement.SHStatus = "userUpdated"
Write-Log -DebugEntry ("[co.Updated]"+$CurrentTargetElementHashGUID+";Old: "+ $TargetContactElements[$TargetContactID].co +";New: "+$TargetElement.co)
}
# Mail
if ($TargetElement.mail -ne $TargetContactElements[$TargetContactID].mail) {
$TargetElement.SHStatus = "userUpdated"
Write-Log -DebugEntry ("[mail.Updated]"+$CurrentTargetElementHashGUID+";Old: "+ $TargetContactElements[$TargetContactID].mail +";New: "+$TargetElement.mail)
}
#NOTE: LegacyExchangeDN can be implemented but is at the moment not required to check for updates because source field is more or less a constant.
if ($TargetElement.mailNickname -ne ($TargetContactElements[$TargetContactID].mailNickname)) {
$TargetElement.SHStatus = "userUpdated"
Write-Log -DebugEntry ("[mailNickname.Updated]"+$CurrentTargetElementHashGUID+";Old: "+ $TargetContactElements[$TargetContactID].mailNickname +";New: "+$TargetElement.mailNickname)
}
}
}
}
# Check for deleted users in source system
if ($TargetContactElements.Count -gt 0) {
foreach ($TargetContactElement in $TargetContactElements) {
foreach ($TargetElement in $TargetElements) {
$TargetContactElement.SHStatus = "userRemoved"
if ($TargetContactElement.extensionAttribute15 -eq $TargetElement.SHHashedGUID) {
$TargetContactElement.SHStatus = "userExists"
break
}
}
}
}
}
}
##------------------------------------------------------------------------------------------------
## Create, update / delete source elements (Your partners elements in your directory)
##------------------------------------------------------------------------------------------------
##Status monitoring
Update-StatusFiles
#------------------------------------------------------------------------------------------------
# delete elements (Your partners users as your contacts)
#------------------------------------------------------------------------------------------------
if (-not $DoNotSearchWithinTarget) {
$DeleteSourceContacts = @()
$DeleteSourceContacts = $TargetContactElements | Where-Object {$_.SHStatus -eq "userRemoved"} | Select-Object -Property DistinguishedName, extensionAttribute14
if ($DeleteSourceContacts) {
foreach ($DeleteContact in $DeleteSourceContacts) {
$doNotDelete = $true
#Switch update only contacts created by script...
if ($UpdateDeleteContactsOnlyCreatedByThisScript) {
if ($DeleteContact.extensionAttribute14 -eq $ThisScriptGUID) {
$doNotDelete = $false
}
}
else {
$doNotDelete = $false
}
if (-not $doNotDelete) {
$DeleteContactDN = $DeleteContact.DistinguishedName
Write-Log -DebugEntry ("[DELETE-SourceCONTACT] $DeleteContactDN")
Remove-ADObject -Identity "$DeleteContactDN" -Confirm:$false -Server $SourceDC
}
}
}
else {
Write-Log -DebugEntry ("[DELETE-SOURCECONTACT] no contact to delete")
}
}
#------------------------------------------------------------------------------------------------
# update elements (Your partners users as your contacts)
#------------------------------------------------------------------------------------------------
if (-not $DoNotSearchWithinTarget) {
$UpdateSourceElements = @()
$UpdateSourceElements = $TargetElements | Where-Object {$_.SHStatus -eq "userUpdated"} | Select-Object -ExpandProperty SHTargetContactElementID
if ($UpdateSourceElements) {
foreach ($UpdateContactID in $UpdateElements) {
$ContactDN = $TargetContactElements[$UpdateContactID].DistinguishedName
$TargetElementID = $TargetContactElements[$UpdateContactID].SHTargetElementID
$extensionAttribute14 = $TargetContactElements[$UpdateContactID].extensionAttribute14
$doNotUpdate = $true
#Switch update only contacts created by script...
if ($UpdateDeleteContactsOnlyCreatedByThisScript) {
if ($extensionAttribute14 -eq $ThisScriptGUID) {
$doNotUpdate = $false
}
}
else {
$doNotUpdate = $false
}
if (-not $doNotUpdate) {
Write-Log -DebugEntry ("[UPDATE-TARGETCONTACT] $ContactDN")
$DisplayName = ($TargetElements[$TargetElementID]).DisplayName
$Name = ($TargetElements[$TargetElementID]).Name
$sn = ($TargetElements[$TargetElementID]).sn
$GivenName = ($TargetElements[$TargetElementID]).GivenName
$department = ($TargetElements[$TargetElementID]).department
$title = ($TargetElements[$TargetElementID]).title
$company = ($TargetElements[$TargetElementID]).company
$physicalDeliveryOfficeName = ($TargetElements[$TargetElementID]).physicalDeliveryOfficeName
$telephoneNumber = ($TargetElements[$TargetElementID]).telephoneNumber
$facsimileTelephoneNumber = ($TargetElements[$TargetElementID]).facsimileTelephoneNumber
$mobile = ($TargetElements[$TargetElementID]).mobile
$l = ($TargetElements[$TargetElementID]).l
$postalCode = ($TargetElements[$TargetElementID]).postalCode
$streetAddress = ($TargetElements[$TargetElementID]).streetAddress
$st = ($TargetElements[$TargetElementID]).st
$co = ($TargetElements[$TargetElementID]).co
$mail = ($TargetElements[$TargetElementID]).mail
$mailNickname = ($TargetElements[$TargetElementID]).mailNickname
$ChangeAttributes = @{"field" = "value"}
$ClearAttributes = @()
$renameObject = $false
# name
if ($Name -ne $TargetContactElements[$UpdateContactID].Name) { $renameObject = $true }
# sn
if ($sn -ne $null) { $ChangeAttributes.Add('sn' , "$sn") }
else { $ClearAttributes += "sn" }
# GivenName
if ($GivenName -ne $null) { $ChangeAttributes.Add('GivenName' , "$GivenName") }
else { $ClearAttributes += "GivenName" }
# department
if ($department -ne $null) { $ChangeAttributes.Add('department' , "$department") }
else { $ClearAttributes += "department" }
# title
if ($title -ne $null) { $ChangeAttributes.Add('title' , "$title") }
else { $ClearAttributes += "title" }
# company
if ($company -ne $null) { $ChangeAttributes.Add('company' , "$company") }
else { $ClearAttributes += "company" }
# physicalDeliveryOfficeName
if ($physicalDeliveryOfficeName -ne $null) { $ChangeAttributes.Add('physicalDeliveryOfficeName' , "$physicalDeliveryOfficeName") }
else { $ClearAttributes += "physicalDeliveryOfficeName" }
# telephoneNumber
if ($telephoneNumber -ne $null) { $ChangeAttributes.Add('telephoneNumber' , "$telephoneNumber") }
else { $ClearAttributes += "telephoneNumber" }
# facsimileTelephoneNumber
if ($facsimileTelephoneNumber -ne $null) { $ChangeAttributes.Add('facsimileTelephoneNumber' , "$facsimileTelephoneNumber") }
else { $ClearAttributes += "facsimileTelephoneNumber" }
# mobile
if ($mobile -ne $null) { $ChangeAttributes.Add('mobile' , "$mobile") }
else { $ClearAttributes += "mobile" }
# l
if ($l -ne $null) { $ChangeAttributes.Add('l' , "$l") }
else { $ClearAttributes += "l" }
# postalCode
if ($postalCode -ne $null) { $ChangeAttributes.Add('postalCode' , "$postalCode") }
else { $ClearAttributes += "postalCode" }
# streetAddress
if ($streetAddress -ne $null) { $ChangeAttributes.Add('streetAddress' , "$streetAddress") }
else { $ClearAttributes += "streetAddress" }
# st
if ($st -ne $null) { $ChangeAttributes.Add('st' , "$st") }
else { $ClearAttributes += "st" }
# co
if ($co -ne $null) { $ChangeAttributes.Add('co' , "$co") }
else { $ClearAttributes += "co" }
# mail
if ($mail -ne $null) { $ChangeAttributes.Add('mail' , "$mail"); $OtherAttributes.Add('targetAddress', $mail) }
else { $ClearAttributes += "mail" }
# mailNickname
if ($mailNickname -ne $null) { $ChangeAttributes.Add('mailNickname' , "$mailNickname") }
else { $ClearAttributes += "mailNickname" }
$ChangeAttributes.Remove('field')
#
if ($ChangeAttributes.Count -gt 0) {
Write-Log -Entry "[UPDATE-SOURCECONTACT]REPLACEATTRIBUTE $ContactDN"
Set-ADObject -Identity "$ContactDN" -Server $SourceDC -DisplayName $DisplayName -Replace $ChangeAttributes -Confirm:$false
}
if ($ClearAttributes.Count -gt 0) {
Write-Log -Entry "[UPDATE-SOURCECONTACT]CLEARATTRIBUTE $ContactDN"
Set-ADObject -Identity "$ContactDN" -Server $SourceDC -DisplayName $DisplayName -Clear $ClearAttributes -Confirm:$false
}
if ($renameObject) {
Write-Log -Entry "[UPDATE-SOURCECONTACT]CLEARATTRIBUTE $ContactDN"
Rename-ADObject -Identity "$ContactDN" -NewName $Name -Server $SourceDC -Credential $TargetCredential
}
}
}
}
else {
Write-Log -DebugEntry ("[UPDATE-SOURCECONTACT] no contact to update")
}
}
#------------------------------------------------------------------------------------------------
# create elements (Your partners users as your contacts)
#------------------------------------------------------------------------------------------------
if (-not $DoNotSearchWithinTarget) {
$NewSourceElements = @()
$NewSourceElements = $TargetElements | Where-Object {$_.SHStatus -eq "userNotFound"} | Select-Object -ExpandProperty SHElementID
if ($NewSourceElements) {
foreach ($SourceElementID in $NewElements) {
$NewMailContactWarning = $null
$SetMailContactWarning = $null
$SetContactWarning = $null
Write-Log -DebugEntry ("[CREATE-SOURCECONTACT] "+($TargetElements[$TargetElementID]).DisplayName)
$DisplayName = ($TargetElements[$TargetElementID]).DisplayName
$Name = ($TargetElements[$TargetElementID]).Name
$sn = ($TargetElements[$TargetElementID]).sn
$GivenName = ($TargetElements[$TargetElementID]).GivenName
$department = ($TargetElements[$TargetElementID]).department
$title = ($TargetElements[$TargetElementID]).title
$company = ($TargetElements[$TargetElementID]).company
$physicalDeliveryOfficeName = ($TargetElements[$TargetElementID]).physicalDeliveryOfficeName
$telephoneNumber = ($TargetElements[$TargetElementID]).telephoneNumber
$facsimileTelephoneNumber = ($TargetElements[$TargetElementID]).facsimileTelephoneNumber
$mobile = ($TargetElements[$TargetElementID]).mobile
$l = ($TargetElements[$TargetElementID]).l
$postalCode = ($TargetElements[$TargetElementID]).postalCode
$streetAddress = ($TargetElements[$TargetElementID]).streetAddress
$st = ($TargetElements[$TargetElementID]).st
$co = ($TargetElements[$TargetElementID]).co
$mail = ($TargetElements[$TargetElementID]).mail
$legacyExchangeDN = ($SourceElements[$SourceElementID]).legacyExchangeDN
$mailNickname = ($TargetElements[$TargetElementID]).mailNickname
$extensionAttribute15=($TargetElements[$TargetElementID]).SHHashedGUID
$proxyaddresses=@()
$proxyaddresses += ("SMTP:$mail")
$proxyaddresses += e("X500:$legacyExchangeDN")
$OtherAttributes = @{"field" = "value"}
# sn
if ($sn -ne $null) { $OtherAttributes.Add('sn' , "$sn") }
# GivenName
if ($GivenName -ne $null) { $OtherAttributes.Add('GivenName' , "$GivenName") }
# department
if ($department -ne $null) { $OtherAttributes.Add('department' , "$department") }
# title
if ($title -ne $null) { $OtherAttributes.Add('title' , "$title") }
# company
if ($company -ne $null) { $OtherAttributes.Add('company' , "$company") }
# physicalDeliveryOfficeName
if ($physicalDeliveryOfficeName -ne $null) { $OtherAttributes.Add('physicalDeliveryOfficeName' , "$physicalDeliveryOfficeName") }
# telephoneNumber
if ($telephoneNumber -ne $null) { $OtherAttributes.Add('telephoneNumber' , "$telephoneNumber") }
# facsimileTelephoneNumber
if ($facsimileTelephoneNumber -ne $null) { $OtherAttributes.Add('facsimileTelephoneNumber' , "$facsimileTelephoneNumber") }
# mobile
if ($mobile -ne $null) { $OtherAttributes.Add('mobile' , "$mobile") }
# l
if ($l -ne $null) { $OtherAttributes.Add('l' , "$l") }
# postalCode
if ($postalCode -ne $null) { $OtherAttributes.Add('postalCode' , "$postalCode") }
# streetAddress
if ($streetAddress -ne $null) { $OtherAttributes.Add('streetAddress' , "$streetAddress") }
# st
if ($st -ne $null) { $OtherAttributes.Add('st' , "$st") }
# co
if ($co -ne $null) { $OtherAttributes.Add('co' , "$co") }
# mail
if ($mail -ne $null) { $OtherAttributes.Add('mail' , "$mail"); $OtherAttributes.Add('proxyaddresses', $proxyaddresses); $OtherAttributes.Add('targetAddress', $mail) }
# mailNickname
if ($mailNickname -ne $null) { $OtherAttributes.Add('mailNickname' , "$mailNickname") }
# User GUID
$OtherAttributes.Add('extensionAttribute15', "$extensionAttribute15")
# Script GUID
$OtherAttributes.Add('extensionAttribute14', "$ThisScriptGUID")
$OtherAttributes.Remove('field')
$null = New-ADObject -server $SourceDC -Name "$Name" -path "$SourceContactOU" -Type contact -OtherAttributes $OtherAttributes -confirm:$false
#Write possible errors to DEBUGLOG
if ($NewMailContactWarning -or $SetMailContactWarning -or $SetContactWarning) {
Write-Log -DebugEntry ("[CREATE-SOURCECONTACT] NewMailContactWarning: "+$NewMailContactWarning)
Write-Log -DebugEntry ("[CREATE-SOURCECONTACT] SetMailContactWarning: "+$NewMailContactWarning)
Write-Log -DebugEntry ("[CREATE-SOURCECONTACT] SetContactWarning: "+$NewMailContactWarning)
}
}
}
else {
Write-Log -DebugEntry ("[CREATE-SOURCECONTACT] no contact to create")
}
}
##------------------------------------------------------------------------------------------------
## Create, update / delete target elements (Your elements in your partners directory)
##------------------------------------------------------------------------------------------------
##Status monitoring
Update-StatusFiles
#------------------------------------------------------------------------------------------------
# delete elements (Your Users as your Partners Contacts)
#------------------------------------------------------------------------------------------------
$DeleteTargetContacts = @()
$DeleteTargetContacts = $SourceContactElements | Where-Object {$_.SHStatus -eq "userRemoved"} | Select-Object -Property DistinguishedName, extensionAttribute14
if ($DeleteTargetContacts) {
foreach ($DeleteContact in $DeleteTargetContacts) {
$doNotDelete = $true
#Switch update only contacts created by script...
if ($UpdateDeleteContactsOnlyCreatedByThisScript) {
if ($DeleteContact.extensionAttribute14 -eq $ThisScriptGUID) {
$doNotDelete = $false
}
}
else {
$doNotDelete = $false
}
if (-not $doNotDelete) {
$DeleteContactDN = $DeleteContact.DistinguishedName
Write-Log -DebugEntry ("[DELETE-TARGETCONTACT] $DeleteContactDN")
Remove-ADObject -Identity "$DeleteContactDN" -Confirm:$false -Server $TargetDC -Credential $TargetCredential
}
}
}
else {
Write-Log -DebugEntry ("[DELETE-TARGETCONTACT] no contact to delete")
}
#------------------------------------------------------------------------------------------------
# update elements (Your Users as your Partners Contacts)
#------------------------------------------------------------------------------------------------
$UpdateElements = @()
$UpdateElements = $SourceElements | Where-Object {$_.SHStatus -eq "userUpdated"} | Select-Object -ExpandProperty SHSourceContactElementID
if ($UpdateElements) {
foreach ($UpdateContactID in $UpdateElements) {
$ContactDN = $SourceContactElements[$UpdateContactID].DistinguishedName
$SourceElementID = $SourceContactElements[$UpdateContactID].SHSourceElementID
$extensionAttribute14 = $SourceContactElements[$UpdateContactID].extensionAttribute14
$doNotUpdate = $true
#Switch update only contacts created by script...
if ($UpdateDeleteContactsOnlyCreatedByThisScript) {
if ($extensionAttribute14 -eq $ThisScriptGUID) {
$doNotUpdate = $false
}
}
else {
$doNotUpdate = $false
}
if (-not $doNotUpdate) {
Write-Log -DebugEntry ("[UPDATE-TARGETCONTACT] $ContactDN")
$DisplayName = ($SourceElements[$SourceElementID]).DisplayName
$Name = ($SourceElements[$SourceElementID]).Name
$sn = ($SourceElements[$SourceElementID]).sn
$GivenName = ($SourceElements[$SourceElementID]).GivenName
$department = ($SourceElements[$SourceElementID]).department
$title = ($SourceElements[$SourceElementID]).title
$company = ($SourceElements[$SourceElementID]).company
$physicalDeliveryOfficeName = ($SourceElements[$SourceElementID]).physicalDeliveryOfficeName
$telephoneNumber = ($SourceElements[$SourceElementID]).telephoneNumber
$facsimileTelephoneNumber = ($SourceElements[$SourceElementID]).facsimileTelephoneNumber
$mobile = ($SourceElements[$SourceElementID]).mobile
$l = ($SourceElements[$SourceElementID]).l
$postalCode = ($SourceElements[$SourceElementID]).postalCode
$streetAddress = ($SourceElements[$SourceElementID]).streetAddress
$st = ($SourceElements[$SourceElementID]).st
$co = ($SourceElements[$SourceElementID]).co
$mail = ($SourceElements[$SourceElementID]).mail
$mailNickname = ($SourceElements[$SourceElementID]).mailNickname
$ChangeAttributes = @{"field" = "value"}
$ClearAttributes = @()
$renameObject = $false
# name
if ($Name -ne $SourceContactElements[$UpdateContactID].Name) { $renameObject = $true }
# sn
if ($sn -ne $null) { $ChangeAttributes.Add('sn' , "$sn") }
else { $ClearAttributes += "sn" }
# GivenName
if ($GivenName -ne $null) { $ChangeAttributes.Add('GivenName' , "$GivenName") }
else { $ClearAttributes += "GivenName" }
# department
if ($department -ne $null) { $ChangeAttributes.Add('department' , "$department") }
else { $ClearAttributes += "department" }
# title
if ($title -ne $null) { $ChangeAttributes.Add('title' , "$title") }
else { $ClearAttributes += "title" }
# company
if ($company -ne $null) { $ChangeAttributes.Add('company' , "$company") }
else { $ClearAttributes += "company" }
# physicalDeliveryOfficeName
if ($physicalDeliveryOfficeName -ne $null) { $ChangeAttributes.Add('physicalDeliveryOfficeName' , "$physicalDeliveryOfficeName") }
else { $ClearAttributes += "physicalDeliveryOfficeName" }
# telephoneNumber
if ($telephoneNumber -ne $null) { $ChangeAttributes.Add('telephoneNumber' , "$telephoneNumber") }
else { $ClearAttributes += "telephoneNumber" }
# facsimileTelephoneNumber
if ($facsimileTelephoneNumber -ne $null) { $ChangeAttributes.Add('facsimileTelephoneNumber' , "$facsimileTelephoneNumber") }
else { $ClearAttributes += "facsimileTelephoneNumber" }
# mobile
if ($mobile -ne $null) { $ChangeAttributes.Add('mobile' , "$mobile") }
else { $ClearAttributes += "mobile" }
# l
if ($l -ne $null) { $ChangeAttributes.Add('l' , "$l") }
else { $ClearAttributes += "l" }
# postalCode
if ($postalCode -ne $null) { $ChangeAttributes.Add('postalCode' , "$postalCode") }
else { $ClearAttributes += "postalCode" }
# streetAddress
if ($streetAddress -ne $null) { $ChangeAttributes.Add('streetAddress' , "$streetAddress") }
else { $ClearAttributes += "streetAddress" }
# st
if ($st -ne $null) { $ChangeAttributes.Add('st' , "$st") }
else { $ClearAttributes += "st" }
# co
if ($co -ne $null) { $ChangeAttributes.Add('co' , "$co") }
else { $ClearAttributes += "co" }
# mail
if ($mail -ne $null) { $ChangeAttributes.Add('mail' , "$mail"); $OtherAttributes.Add('targetAddress', $mail) }
else { $ClearAttributes += "mail" }
# mailNickname
if ($mailNickname -ne $null) { $ChangeAttributes.Add('mailNickname' , "$mailNickname") }
else { $ClearAttributes += "mailNickname" }
$ChangeAttributes.Remove('field')
#
if ($ChangeAttributes.Count -gt 0) {
Write-Log -Entry "[UPDATE-TARGETCONTACT]REPLACEATTRIBUTE $ContactDN"
Set-ADObject -Identity "$ContactDN" -Server $TargetDC -Credential $TargetCredential -DisplayName $DisplayName -Replace $ChangeAttributes -Confirm:$false
}
if ($ClearAttributes.Count -gt 0) {
Write-Log -Entry "[UPDATE-TARGETCONTACT]CLEARATTRIBUTE $ContactDN"
Set-ADObject -Identity "$ContactDN" -Server $TargetDC -Credential $TargetCredential -DisplayName $DisplayName -Clear $ClearAttributes -Confirm:$false
}
if ($renameObject) {
Write-Log -Entry "[UPDATE-TARGETCONTACT]RENAME $ContactDN"
Rename-ADObject -Identity "$ContactDN" -NewName $Name -Server $TargetDC -Credential $TargetCredential
}
}
}
}
else {
Write-Log -DebugEntry ("[UPDATE-TARGETCONTACT] no contact to update")
}
#------------------------------------------------------------------------------------------------
# create elements (Your Users as your Partners Contacts)
#------------------------------------------------------------------------------------------------
$NewElements = @()
$NewElements = $SourceElements | Where-Object {$_.SHStatus -eq "userNotFound"} | Select-Object -ExpandProperty SHElementID
if ($NewElements) {
foreach ($SourceElementID in $NewElements) {
$NewMailContactWarning = $null
$SetMailContactWarning = $null
$SetContactWarning = $null
Write-Log -DebugEntry ("[CREATE-TARGETCONTACT] "+($SourceElements[$SourceElementID]).DisplayName)
$DisplayName = ($SourceElements[$SourceElementID]).DisplayName
$Name = ($SourceElements[$SourceElementID]).Name
$sn = ($SourceElements[$SourceElementID]).sn
$GivenName = ($SourceElements[$SourceElementID]).GivenName
$department = ($SourceElements[$SourceElementID]).department
$title = ($SourceElements[$SourceElementID]).title
$company = ($SourceElements[$SourceElementID]).company
$physicalDeliveryOfficeName = ($SourceElements[$SourceElementID]).physicalDeliveryOfficeName
$telephoneNumber = ($SourceElements[$SourceElementID]).telephoneNumber
$facsimileTelephoneNumber = ($SourceElements[$SourceElementID]).facsimileTelephoneNumber
$mobile = ($SourceElements[$SourceElementID]).mobile
$l = ($SourceElements[$SourceElementID]).l
$postalCode = ($SourceElements[$SourceElementID]).postalCode
$streetAddress = ($SourceElements[$SourceElementID]).streetAddress
$st = ($SourceElements[$SourceElementID]).st
$co = ($SourceElements[$SourceElementID]).co
$mail = ($SourceElements[$SourceElementID]).mail
$legacyExchangeDN = ($SourceElements[$SourceElementID]).legacyExchangeDN
$mailNickname = ($SourceElements[$SourceElementID]).mailNickname
$extensionAttribute15=($SourceElements[$SourceElementID]).SHHashedGUID
$proxyaddresses=@()
$proxyaddresses += ("SMTP:$mail")
$proxyaddresses += ("X500:$legacyExchangeDN")
$OtherAttributes = @{"field" = "value"}
# DsiplayName
if ($DisplayName -ne $null) { $OtherAttributes.Add('DisplayName' , "$DisplayName") }
# sn
if ($sn -ne $null) { $OtherAttributes.Add('sn' , "$sn") }
# GivenName
if ($GivenName -ne $null) { $OtherAttributes.Add('GivenName' , "$GivenName") }
# department
if ($department -ne $null) { $OtherAttributes.Add('department' , "$department") }
# title
if ($title -ne $null) { $OtherAttributes.Add('title' , "$title") }
# company
if ($company -ne $null) { $OtherAttributes.Add('company' , "$company") }
# physicalDeliveryOfficeName
if ($physicalDeliveryOfficeName -ne $null) { $OtherAttributes.Add('physicalDeliveryOfficeName' , "$physicalDeliveryOfficeName") }
# telephoneNumber
if ($telephoneNumber -ne $null) { $OtherAttributes.Add('telephoneNumber' , "$telephoneNumber") }
# facsimileTelephoneNumber
if ($facsimileTelephoneNumber -ne $null) { $OtherAttributes.Add('facsimileTelephoneNumber' , "$facsimileTelephoneNumber") }
# mobile
if ($mobile -ne $null) { $OtherAttributes.Add('mobile' , "$mobile") }
# l
if ($l -ne $null) { $OtherAttributes.Add('l' , "$l") }
# postalCode
if ($postalCode -ne $null) { $OtherAttributes.Add('postalCode' , "$postalCode") }
# streetAddress
if ($streetAddress -ne $null) { $OtherAttributes.Add('streetAddress' , "$streetAddress") }
# st
if ($st -ne $null) { $OtherAttributes.Add('st' , "$st") }
# co
if ($co -ne $null) { $OtherAttributes.Add('co' , "$co") }
# mail
if ($mail -ne $null) { $OtherAttributes.Add('mail' , "$mail"); $OtherAttributes.Add('proxyaddresses', $proxyaddresses); $OtherAttributes.Add('targetAddress', $mail) }
# mailNickname
if ($mailNickname -ne $null) { $OtherAttributes.Add('mailNickname' , "$mailNickname") }
# User GUID
$OtherAttributes.Add('extensionAttribute15', "$extensionAttribute15")
# Script GUID
$OtherAttributes.Add('extensionAttribute14', "$ThisScriptGUID")
$OtherAttributes.Remove('field')
Write-Log -Entry "[CREATE-TARGETCONTACT] $Name in OU: $TargetContactOU"
$null = New-ADObject -server $TargetDC -Credential $TargetCredential -Name "$Name" -path "$TargetContactOU" -Type contact -OtherAttributes $OtherAttributes -confirm:$false
#Write possible errors to DEBUGLOG
if ($NewMailContactWarning -or $SetMailContactWarning -or $SetContactWarning) {
Write-Log -DebugEntry ("[CREATE-TARGETCONTACT] NewMailContactWarning: "+$NewMailContactWarning)
Write-Log -DebugEntry ("[CREATE-TARGETCONTACT] SetMailContactWarning: "+$NewMailContactWarning)
Write-Log -DebugEntry ("[CREATE-TARGETCONTACT] SetContactWarning: "+$NewMailContactWarning)
}
}
}
else {
Write-Log -DebugEntry ("[CREATE-TARGETCONTACT] no contact to create")
}
##------------------------------------------------------------------------------------------------
## Create, update / delete target elements (Your elements in your partners directory)
##------------------------------------------------------------------------------------------------
$SourceElements = $null
$SourceContactElements = $null
if (-not $DoNotSearchWithinTarget) {
$TargetElements = $null
$TargetContactElements = $null
}
Write-Log -Entry "Script execution is finished!"