Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 87ecd00

Browse files
authored
Merge pull request UiPath#43 from UiPath/fix/ad_sync
Update Sync-UiPathADUsers to include child domains
2 parents eafd3a8 + aa83665 commit 87ecd00

File tree

3 files changed

+114
-88
lines changed

3 files changed

+114
-88
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ bld/
2626

2727
# Visual Studio 2015 cache/options directory
2828
.vs/
29+
# Visual Studio Code cache/options directory
30+
.vscode/
2931
# Uncomment if you have tasks that create the project's static files in wwwroot
3032
#wwwroot/
3133

Examples/Sync-UiPathADUsers.ps1

Lines changed: 112 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,10 @@ param(
4545
[ValidateSet('Remove', 'List', 'Ignore')]
4646
[string] $OrphanedUsersAction = 'Ignore',
4747
[Parameter()]
48-
[switch] $AllowUsernameTruncate)
48+
[switch] $AllowUsernameTruncate,
49+
[Parameter()]
50+
[string[]] $AllowedDomainNames = @()
51+
)
4952

5053
$ErrorActionPreference = "Stop"
5154

@@ -60,15 +63,27 @@ function Get-IsWindows {
6063
return $isWindows
6164
}
6265

66+
function Get-DomainName{
67+
param(
68+
[Parameter(Position=0, Mandatory=$True)] $distinguishedName
69+
)
70+
71+
$dcs = $distinguishedName -split ','| Select-String -Pattern "DC=" | ForEach-Object{ $_ -replace 'DC=', ''}
72+
$extractedDomainName = $dcs -join '.'
73+
Write-Verbose "extracted domain: $extractedDomainName from distinguishedName: $distinguishedName extracted as $extractedDomainName"
74+
return $dcs -join '.'
75+
}
76+
6377
function Format-UiPathUserName {
6478
param(
65-
[Parameter(Position=0, Mandatory=$True)] $userName
79+
[Parameter(Position=0, Mandatory=$True)] $userName,
80+
[Parameter(Position=1, Mandatory=$False)] $adNetBiosName = $null
6681
)
6782

68-
if (-not [string]::IsNullOrWhiteSpace($domainName)) {
69-
$userName = $domainName + '\' + $userName
83+
if (-not [string]::IsNullOrWhiteSpace($adNetBiosName)) {
84+
$userName = $adNetBiosName + '\' + $userName
7085
}
71-
86+
7287
if ($userName.Length -gt 32) {
7388
if ($AllowUsernameTruncate) {
7489
Write-Warning "AD Username $username exceeds the 32 character limit."
@@ -83,7 +98,7 @@ function Format-UiPathUserName {
8398

8499
function Get-ADGroupUser {
85100
param(
86-
[Parameter(Position=0)] $dc,
101+
[Parameter(Position=0)] $groupDomainName,
87102
[Parameter(Position=1)] $adGroup
88103
)
89104

@@ -94,45 +109,52 @@ function Get-ADGroupUser {
94109

95110

96111
Write-Progress -Id 1 `
97-
-Activity "Retrieve group members: $adGroup" `
112+
-Activity "Retrieve group members: $groupDomainName" `
98113

99-
Write-Verbose "Get-ADGroupMember -Server $($dc.PDCEmulator) -Identity $adGroup"
100-
$members = @(Get-ADGroupMember -Server $dc.PDCEmulator -Identity $adGroup)
114+
Write-Verbose "Get-ADGroupMember -Server $($groupDomainName) -Identity $adGroup"
115+
$members = @(Get-ADGroupMember -Server $groupDomainName -Identity $adGroup)
101116

102117
foreach($member in $members)
103118
{
119+
$currentDomainName = Get-DomainName $member.DistinguishedName
120+
121+
if(-not $knownDomains.ContainsKey($currentDomainName)){
122+
continue
123+
}
104124

125+
$dc = $knownDomains[$currentDomainName]
105126

106127
if ($member.objectClass -eq 'user')
107128
{
108129
$userInfo = @{
109130
SamAccountName = $member.SamAccountName;
110-
Username = Format-UiPathUserName $member.SamAccountName
131+
Username = Format-UiPathUserName $member.SamAccountName $dc.NetBIOSName;
132+
DNSRoot = $currentDomainName
111133
}
112134

113135
$users += $userInfo
114136
}
115137
elseif ($member.objectClass -eq 'group')
116138
{
117-
$childUsers = Get-ADGroupUser $dc $member.SamAccountName
139+
$childUsers = Get-ADGroupUser $currentDomainName $member.SamAccountName
118140
$users += $childUsers
119141
}
120142
}
121143
}
122144

123145
if (Get-IsAzureAD) {
124-
$adGroupObject = Get-AzureADGroup -SearchString $adGroup | where {$_.DisplayName -eq $adGroup}
146+
$adGroupObject = Get-AzureADGroup -SearchString $adGroup | Where-Object {$_.DisplayName -eq $adGroup}
125147
Write-Verbose "Get-AzureADGroupMember $($adGroupObject.ObjectId)"
126148
$members = Get-AzureADGroupMember -ObjectId $adGroupObject.ObjectId
127149

128-
$users += $members | foreach {@{
150+
$users += $members | ForEach-Object {@{
129151
UPN = $_.UserPrincipalName;
130152
Username = Format-UiPathUserName $_.UserPrincipalName;
131153
Name=$_.DisplayName;
132154
}}
133155
}
134156

135-
$users | foreach {Write-Verbose "$adGroup AD group user for sync: $($_.UPN) Username:$($_.Username) Name:$($_.Name)"}
157+
$users | ForEach-Object {Write-Verbose "$adGroup AD group user for sync: $($_.UPN) Username:$($_.Username) Name:$($_.Name)"}
136158

137159
$users
138160
}
@@ -142,23 +164,23 @@ function Get-UiPathADUsers {
142164
[Parameter(Position=0)] $domain)
143165

144166
Write-Verbose "Get-UiPathUser -Type User "
145-
$allUsers = Get-UiPathUser -Type User | where {$_.Username -ne "Admin"}
167+
$allUsers = Get-UiPathUser -Type User | Where-Object {$_.Username -ne "Admin"}
146168
$OrchestratorADUsers = @()
147-
169+
$conditions = $null
148170
if (Get-IsWindows) {
149-
$OrchestratorADUsers += $allUsers | Select UserName, Id, RolesList, EmailAddress | where {$_.UserName.StartsWith($domain + '\', [System.StringComparison]::OrdinalIgnoreCase)}
171+
$dcNetBiosNames = $knownDomains.Values | ForEach-Object {$_.NetBIOSName}
172+
$conditions = {$dcNetBiosNames -contains $_.UserName.Split('\')[0]}
150173
}
151174

152175
if (Get-IsAzureAD) {
153176
# Orchestrator maps user to Azure AD identities based on Orchestrator user Email address
154177
Write-Verbose "Get-AzureADDomain"
155-
$domains = Get-AzureADDomain | foreach {$_.Name}
156-
$domains | foreach { Write-Verbose "AzureAD Email domain: $_"}
157-
158-
$OrchestratorADUsers += $allUsers | Select UserName, Id, RolesList, EmailAddress | where {$domains -contains $_.EmailAddress.Split('@')[1]}
178+
$domains = Get-AzureADDomain | ForEach-Object {$_.Name}
179+
$domains | ForEach-Object { Write-Verbose "AzureAD Email domain: $_"}
180+
$conditions = {$domains -contains $_.EmailAddress.Split('@')[1]}
159181
}
160-
161-
$OrchestratorADUsers | foreach {Write-Verbose "Orchestrator user for sync: $($_.Id) $($_.Username) $($_.EmailAddress)"}
182+
$OrchestratorADUsers += $allUsers | Where-Object $conditions | Select-Object UserName, Id, RolesList, EmailAddress
183+
$OrchestratorADUsers | ForEach-Object {Write-Verbose "Orchestrator user for sync: $($_.Id) $($_.Username) $($_.EmailAddress)"}
162184

163185
return $OrchestratorADUsers
164186
}
@@ -188,18 +210,26 @@ try
188210
-PercentComplete ($i/$RolesMapping.Values.Count*100)
189211
$i += 1
190212
$role = Get-UiPathRole -Name $roleName
191-
if ($role -eq $null)
213+
if ($null -eq $role)
192214
{
193215
throw "Could not find the Orchestrator role name: $roleName"
194216
}
195217
Write-Verbose "Role ok: $roleName $($role.Name)"
196218
}
197219

198-
$dc = $null
220+
$knownDomains = @{}
221+
$mainDc = $null
199222

200223
if (Get-IsWindows) {
201224
Write-Verbose "Get-ADDomain $DomainName"
202225
$dc = Get-ADDomain -Identity $DomainName
226+
$knownDomains.Add($dc.DNSRoot,$dc)
227+
$mainDc = $dc;
228+
foreach($dn in $AllowedDomainNames){
229+
Write-Verbose "Get-ADDomain $dn"
230+
$dc = Get-ADDomain -Identity $dn
231+
$knownDomains.Add($dc.DNSRoot,$dc)
232+
}
203233
}
204234

205235
$idxOperationStep += 1
@@ -220,13 +250,13 @@ try
220250

221251
$mappedRole = $RolesMapping[$adGoupName]
222252

223-
$adGroupMembers = Get-ADGroupUser $dc $adGoupName | Sort-Object {$_.Username} -Unique
253+
$adGroupMembers = Get-ADGroupUser $DomainName $adGoupName | Sort-Object {$_.Username} -Unique
224254

225255
foreach($adGroupMember in $adGroupMembers)
226256
{
227257
$userName = $adGroupMember.Username
228258
$adUser = $allADUsers[$userName]
229-
if ($adUser -eq $null)
259+
if ($null -eq $adUser)
230260
{
231261
$adUser = @{ roles = @(); userInfo = $adGroupMember}
232262
$null = $allADUsers.Add($userName, $adUser)
@@ -260,7 +290,7 @@ try
260290
{
261291
$op = $operations[$adUserName]
262292
$adUser = $allADUsers[$adUserName]
263-
if ($op -eq $null)
293+
if ($null -eq $op)
264294
{
265295
$op = @{isNew = $true; adUser = $adUser}
266296
$operations.Add($adUserName, $op)
@@ -290,8 +320,8 @@ try
290320
$idxExisting = 0
291321
$idxNew = 0
292322

293-
$existingRoles = $op.existingRoles | sort -Unique
294-
$newRoles = $op.newRoles | sort -Unique
323+
$existingRoles = $op.existingRoles | Sort-Object -Unique
324+
$newRoles = $op.newRoles | Sort-Object -Unique
295325

296326
# Oh, Powershell....
297327
if ($existingRoles -isnot [array])
@@ -331,7 +361,7 @@ try
331361
$idxNew += 1
332362
continue
333363
}
334-
elseif ($newRole -eq $null -or (($existingRole -ne $null) -and ($existingRole -lt $newRole)))
364+
elseif ($null -eq $newRole -or (($null -ne $existingRole) -and ($existingRole -lt $newRole)))
335365
{
336366
# user must be removed from this existing role
337367
$roleName = $existingRole
@@ -346,7 +376,7 @@ try
346376
$addOrRemove = 'add'
347377
}
348378
$changedRole = $changedRoles[$roleName]
349-
if ($changedRole -eq $null)
379+
if ($null -eq $changedRole)
350380
{
351381
$changedRole = @{addedUsers=@();removedUsers=@()}
352382
$changedRoles.Add($roleName, $changedRole)
@@ -390,64 +420,63 @@ try
390420
-Activity $operationSteps[$idxOperationStep] `
391421
-CurrentOperation $newUser.userName `
392422
-PercentComplete ($i/$newUsers.Count * 100)
393-
394-
if (Get-IsWindows) {
395-
# We postponed getting the details until actually needed to reduce AD chit-chat
396-
Write-Verbose "Get-ADUser -Server $($dc.PDCEmulator) -Identity $($newUser.userInfo.SamAccountName) -Properties EmailAddress"
397-
$adUserInfo = Get-ADUser -Server $dc.PDCEmulator -Identity $newUser.userInfo.SamAccountName -Properties EmailAddress
398-
399-
if (-not [string]::IsNullOrWhiteSpace($adUserInfo.EmailAddress)) {
400-
$newUser.userInfo.EmailAddress = $adUserInfo.EmailAddress
423+
try {
424+
$userDomainName = $DomainName
425+
if (Get-IsWindows) {
426+
$userDomainName = $mainDc.DNSRoot
427+
# We postponed getting the details until actually needed to reduce AD chit-chat
428+
Write-Verbose "Get-ADUser -Server $($newUser.userInfo.DNSRoot) -Identity $($newUser.userInfo.SamAccountName) -Properties EmailAddress"
429+
$adUserInfo = Get-ADUser -Server $newUser.userInfo.DNSRoot -Identity $newUser.userInfo.SamAccountName -Properties EmailAddress
430+
431+
if (-not [string]::IsNullOrWhiteSpace($adUserInfo.EmailAddress)) {
432+
$newUser.userInfo.EmailAddress = $adUserInfo.EmailAddress
433+
}
434+
elseif (-not [string]::IsNullOrWhiteSpace($adUserInfo.UserPrincipalName)) {
435+
$newUser.userInfo.EmailAddress = $adUserInfo.UserPrincipalName
436+
}
401437
}
402-
elseif (-not [string]::IsNullOrWhiteSpace($adUserInfo.UserPrincipalName)) {
403-
$newUser.userInfo.EmailAddress = $adUserInfo.UserPrincipalName
438+
439+
$cmdMsg = "Add-UiPathUser -Username $($newUser.userName) -RolesList ..."
440+
$cmd = 'Add-UiPathUser -Username $newUser.userName -RolesList $newUser.roles'
441+
442+
if (Get-IsWindows) {
443+
$cmdMsg += " -Domain $($userDomainName)"
444+
$cmd += ' -Domain $userDomainName'
445+
}else{
446+
if (-not [string]::IsNullOrWhiteSpace($newUser.userInfo.name)) {
447+
$cmdMsg += " -Name $($newUser.userInfo.name)"
448+
$cmd += ' -Name $newUser.userInfo.name'
449+
}
450+
451+
if (-not [string]::IsNullOrWhiteSpace($newUser.userInfo.Surname)) {
452+
$cmdMsg += " -Surname $($newUser.userInfo.Surname)"
453+
$cmd += ' -Surname $newUser.userInfo.Surname'
454+
}
404455
}
405-
406-
if (-not [string]::IsNullOrWhiteSpace($adUserInfo.GivenName)) {
407-
$newUser.userInfo.Name = $adUserInfo.GivenName
456+
457+
if (-not [string]::IsNullOrWhiteSpace($newUser.userInfo.EmailAddress)) {
458+
$cmdMsg += " -EmailAddress $($newUser.userInfo.EmailAddress)"
459+
$cmd += ' -EmailAddress $newUser.userInfo.EmailAddress'
460+
} elseif (-not [string]::IsNullOrWhiteSpace($newUser.userInfo.UPN)) {
461+
$cmdMsg += " -EmailAddress $($newUser.userInfo.UPN)"
462+
$cmd += ' -EmailAddress $newUser.userInfo.UPN'
408463
}
409-
elseif (-not [string]::IsNullOrWhiteSpace($adUserInfo.Name)) {
410-
$newUser.userInfo.Name = $adUserInfo.Name
464+
465+
if ($null -ne $ouId) {
466+
$cmdMsg += " -OrganizationUnitIds @($ouId)"
467+
$cmd += ' -OrganizationUnitIds @($ouId)'
411468
}
412-
413-
if (-not [string]::IsNullOrWhiteSpace($adUserInfo.Surname)) {
414-
$newUser.userInfo.Surname =$adUserInfo.Surname
415-
}
416-
}
417-
418-
$cmdMsg = "Add-UiPathUser -Username $($newUser.userName) -RolesList ..."
419-
$cmd = 'Add-UiPathUser -Username $newUser.userName -RolesList $newUser.roles'
420-
421-
if (Get-IsWindows) {
422-
$cmdMsg += " -Domain $($dc.NetBIOSName)"
423-
$cmd += ' -Domain $dc.NetBIOSName'
469+
470+
Write-Verbose $cmdMsg
471+
$null = Invoke-Expression $cmd
424472
}
473+
catch {
474+
$e = $_.Exception
475+
$line = $_.InvocationInfo.ScriptLineNumber
476+
$msg = $e.Message
425477

426-
if (-not [string]::IsNullOrWhiteSpace($newUser.userInfo.name)) {
427-
$cmdMsg += " -Name $($newUser.userInfo.name)"
428-
$cmd += ' -Name $newUser.userInfo.name'
478+
Write-Warning "$($line): $msg"
429479
}
430-
431-
if (-not [string]::IsNullOrWhiteSpace($newUser.userInfo.Surname)) {
432-
$cmdMsg += " -Surname $($newUser.userInfo.Surname)"
433-
$cmd += ' -Surname $newUser.userInfo.Surname'
434-
}
435-
436-
if (-not [string]::IsNullOrWhiteSpace($newUser.userInfo.EmailAddress)) {
437-
$cmdMsg += " -EmailAddress $($newUser.userInfo.EmailAddress)"
438-
$cmd += ' -EmailAddress $newUser.userInfo.EmailAddress'
439-
} elseif (-not [string]::IsNullOrWhiteSpace($newUser.userInfo.UPN)) {
440-
$cmdMsg += " -EmailAddress $($newUser.userInfo.UPN)"
441-
$cmd += ' -EmailAddress $newUser.userInfo.UPN'
442-
}
443-
444-
if ($ouId -ne $null) {
445-
$cmdMsg += " -OrganizationUnitIds @($ouId)"
446-
$cmd += ' -OrganizationUnitIds @($ouId)'
447-
}
448-
449-
Write-Verbose $cmdMsg
450-
$null = Invoke-Expression $cmd
451480
}
452481

453482
$idxOperationStep += 1

UiPath.PowerShell/Cmdlets/AddUser.cs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,6 @@ protected override void ProcessRecord()
5454
{
5555
Domain = parts[0];
5656
}
57-
58-
if (0 != string.Compare(Domain, parts[0], true))
59-
{
60-
throw new Exception($"The NT username {Username} must match the domain {Domain}.");
61-
}
6257
}
6358

6459
var user = new UserDto

0 commit comments

Comments
 (0)