Skip to content

Commit d583776

Browse files
Added script for uniqueness check with default examples (#47)
* Added script for uniqueness check with default examples * Moved files to subfolder for built-in * Added logging for dryrun and no aref available and use correct aRef property * Added default examples for AD OU calculation * Added Readme for built-in folder * Fix: dryRun * Added note to uniqueness check * Changed highlight the "Note" --------- Co-authored-by: rhouthuijzen <r.houthuijzen@tools4ever.com>
1 parent 6c40cee commit d583776

15 files changed

+607
-0
lines changed

built-in/README.md

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
# Built-in Scripts
2+
3+
This folder contains PowerShell scripts used in the built-in Microsoft Active Directory (AD) connector for HelloID Provisioning. These scripts are automatically triggered during specific actions such as Create, Enable, Update, Disable, and Post-actions. You can customize them to reflect your internal structure and logic.
4+
5+
---
6+
7+
## Scripts
8+
9+
### `uniquenessCheck.ps1`
10+
- **Description:** Checks if key user attributes like `sAMAccountName`, `userPrincipalName`, `mail`, and `proxyAddresses` are unique in Active Directory.
11+
- **Use Case:** Use when HelloID's default uniqueness check isn't flexible enough—for example, when you want to sync `sAMAccountName` and `cn` separately from `mail` and `UPN`.
12+
13+
> [!NOTE]
14+
> The built-in uniqueness check should not be used together with this script. You must choose one or the other. If you opt to use this script, make sure to deselect all the fields from the "unique fields" section that you want to check with the script.
15+
>
16+
> While it’s technically possible to use both, for example, by selecting `userPrincipalName`, `mail`, and `proxyAddresses` for the built-in check and using this script for `commonName` and `sAMAccountName`, it's recommended to use only one method. This ensures greater clarity and simplicity in your configuration.
17+
18+
19+
---
20+
21+
## `orgUnit` Folder
22+
23+
These scripts determine which Organizational Unit (OU) a user should be placed in during specific lifecycle events.
24+
25+
### `initialContainer.ps1`
26+
- **Description:** Calculates the OU where a user account should go when it is created.
27+
- **Use Case:** Place new accounts in different OUs based on department or other person attributes.
28+
29+
### `enableContainer.ps1`
30+
- **Description:** Calculates the OU where a user account should go when it is enabled.
31+
- **Use Case:** Useful when enabled users need to be placed in active OUs that differ per department.
32+
33+
### `updateContainer.ps1`
34+
- **Description:** Calculates the OU where a user account should go when it is updated. If the account is enabled, it goes to the active OU; if disabled, to the disabled OU.
35+
- **Use Case:** Keeps users in the correct OU based on their current status and department.
36+
37+
### `disableContainer.ps1`
38+
- **Description:** Calculates the OU where a user account should go when it is disabled.
39+
- **Use Case:** Useful when disabled users need to be placed in active OUs that differ per department.
40+
41+
### `orgUnit.DefaultOUFallback.ps1`
42+
- **Description:** Calculates a target OU based on department and graduation year. If no specific OU is found, it falls back to a default OU.
43+
- **Use Case:** Use this when OUs are structured by department and year, and you want to ensure a fallback OU exists. Especially useful in education or large organizations where users are grouped by year or department.
44+
45+
### `orgUnit.Disable.DynamicLocation.ReferenceExample.ps1`
46+
- **Description:** Calculates the OU based on user location when the account is disabled. Resolves a base OU and searches for a specific OU inside it.
47+
- **Use Case:** Useful in organizations where disabled accounts are organized by geographic location.
48+
49+
### `orgUnit.Enable.DynamicLocation.ReferenceExample.ps1`
50+
- **Description:** Calculates the OU based on user location when the account is enabled. Works the same way as the disable variant but for active accounts.
51+
- **Use Case:** Use when enabled users must be placed in location-specific OUs.
52+
53+
### `orgUnit.Update.DynamicLocation.ReferenceExample.ps1`
54+
- **Description:** Calculates the OU based on both location and account status (enabled or disabled) when the account is updated.
55+
- **Use Case:** Use this when user OU placement depends on both geographic location and whether the account is active or not.
56+
57+
---
58+
59+
## `postAdAction` Folder
60+
61+
These scripts run after the main AD action has been completed (Create, Enable, Update, or Disable).
62+
63+
### `postAdAction.create.UpdateADAccountMsExchHideFromAddressLists.ps1`
64+
- **Description:** Updates the `msExchHideFromAddressLists` attribute after account creation.
65+
- **Use Case:** Hide a user’s mailbox from Exchange address lists when not using the built-in Exchange integration or when the options of the built-in Exchange integration do not suffice.
66+
67+
### `postAdAction.disable.UpdateADAccountDescription.ps1`
68+
- **Description:** Updates the `description` field in AD after the account is disabled, appending a timestamp and reason.
69+
- **Use Case:** Useful for audit trails or tracking when and why an account was disabled.
70+
71+
### `postAdAction.enable.ResetPassword.ps1`
72+
- **Description:** Generates a new random password and resets it for the user after the account is enabled.
73+
- **Use Case:** Provide a fresh password as part of the enablement process, making it available for the notifications.
74+
75+
### `postAdAction.enable.UpdateADAccountDescription.ps1`
76+
- **Description:** Updates the `description` field in AD after the account is enabled, appending a timestamp and reason.
77+
- **Use Case:** Add clarity to AD records by documenting HelloID enablement.
78+
79+
### `postAdAction.update.UpdateADAccountNames.ps1`
80+
- **Description:** Updates the `sAMAccountName`, `userPrincipalName`, and `email` if the user's first or last name changes.
81+
- **Use Case:** Use when updates should only be performed if specific properties, such as givenName or surName, have changed, and should not trigger updates when other properties, like department or title, are modified.
82+
83+
---
84+
85+
## Getting Started
86+
87+
To use these scripts:
88+
- Make sure your HelloID Provisioning environment is properly configured.
89+
- Customize the logic to reflect your organization's structure.
90+
- Test in a non-production environment before deploying to production.
91+
92+
---
93+
94+
> ⚠️ Note: These scripts are templates and examples. Review and adapt them to your specific environment before use.

built-in/orgUnit/disableContainer.ps1

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# Initialize default properties
2+
$p = $person | ConvertFrom-Json
3+
$m = $manager | ConvertFrom-Json
4+
$a = $accountReference | ConvertFrom-Json
5+
$ma = $managerAccountReference | ConvertFrom-Json
6+
7+
# The entitlementContext contains the configuration
8+
# - configuration: The configuration that is set in the Custom PowerShell configuration
9+
$eRef = $entitlementContext | ConvertFrom-Json
10+
11+
$success = $false
12+
13+
$VerbosePreference = "SilentlyContinue"
14+
$InformationPreference = "Continue"
15+
$WarningPreference = "Continue"
16+
17+
# Calculate AD OU based on department
18+
# example.com/Disabled Users/Dept1 - Dept1 & Dept1Team
19+
# example.com/Disabled Users/Dept2 - Dept2 & Dept2Team
20+
# example.com/Disabled Users/Dept3 - Dept3 & Dept3Team
21+
# example.com/Disabled Users/Default - Everything else
22+
Write-Verbose "Department: '$($p.PrimaryContract.Department.ExternalId)'"
23+
switch ($p.PrimaryContract.Department.ExternalId) {
24+
{ $_ -in "Dept1", "Dept1Team" } {
25+
$ouDistinguishedName = 'OU=Dept1,OU=Disabled Users,DC=example,DC=com'
26+
}
27+
{ $_ -in "Dept2", "Dept2Team" } {
28+
$ouDistinguishedName = 'OU=Dept2,OU=Disabled Users,DC=example,DC=com'
29+
}
30+
{ $_ -in "Dept3", "Dept3Team" } {
31+
$ouDistinguishedName = 'OU=Dept3,OU=Disabled Users,DC=example,DC=com'
32+
}
33+
default {
34+
$ouDistinguishedName = 'OU=Default,OU=Disabled Users,DC=example,DC=com'
35+
}
36+
}
37+
Write-Verbose "ouDistinguishedName: '$($ouDistinguishedName)'"
38+
39+
try {
40+
Write-Verbose "Querying AD OU [$ouDistinguishedName]"
41+
42+
$adOU = Get-ADOrganizationalUnit -Identity $ouDistinguishedName -Properties canonicalName, name, objectGuid
43+
if ($null -ne $adOU) {
44+
$organizationalUnit = [PSCustomObject]@{
45+
canonicalName = $adOU.canonicalName
46+
name = $adOU.distinguishedName
47+
objectGuid = $adOU.objectGuid
48+
}
49+
}
50+
else {
51+
throw "No AD OU found with Distinguished Name [$ouDistinguishedName]"
52+
}
53+
54+
$success = $true
55+
Write-Verbose "Successfully queried AD OU [$ouDistinguishedName]"
56+
}
57+
catch {
58+
$success = $false
59+
60+
$ex = $PSItem
61+
Write-Warning "Error at Line '$($ex.InvocationInfo.ScriptLineNumber)': $($ex.InvocationInfo.Line). Error message: $($ex)"
62+
throw "Could not query AD OU with Distinguished Name [$ouDistinguishedName]. Error: $($ex.Exception.Message)"
63+
}
64+
65+
# Build up result
66+
$result = [PSCustomObject]@{
67+
Success = $success
68+
OrganizationalUnit = $organizationalUnit
69+
};
70+
71+
# Send result back
72+
Write-Output $result | ConvertTo-Json -Depth 2

built-in/orgUnit/enableContainer.ps1

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# Initialize default properties
2+
$p = $person | ConvertFrom-Json
3+
$m = $manager | ConvertFrom-Json
4+
$a = $accountReference | ConvertFrom-Json
5+
$ma = $managerAccountReference | ConvertFrom-Json
6+
7+
# The entitlementContext contains the configuration
8+
# - configuration: The configuration that is set in the Custom PowerShell configuration
9+
$eRef = $entitlementContext | ConvertFrom-Json
10+
11+
$success = $false
12+
13+
$VerbosePreference = "SilentlyContinue"
14+
$InformationPreference = "Continue"
15+
$WarningPreference = "Continue"
16+
17+
# Calculate AD OU based on department
18+
# example.com/Users/Dept1 - Dept1 & Dept1Team
19+
# example.com/Users/Dept2 - Dept2 & Dept2Team
20+
# example.com/Users/Dept3 - Dept3 & Dept3Team
21+
# example.com/Users/Default - Everything else
22+
Write-Verbose "Department: '$($p.PrimaryContract.Department.ExternalId)'"
23+
switch ($p.PrimaryContract.Department.ExternalId) {
24+
{ $_ -in "Dept1", "Dept1Team" } {
25+
$ouDistinguishedName = 'OU=Dept1,OU=Users,DC=example,DC=com'
26+
}
27+
{ $_ -in "Dept2", "Dept2Team" } {
28+
$ouDistinguishedName = 'OU=Dept2,OU=Users,DC=example,DC=com'
29+
}
30+
{ $_ -in "Dept3", "Dept3Team" } {
31+
$ouDistinguishedName = 'OU=Dept3,OU=Users,DC=example,DC=com'
32+
}
33+
default {
34+
$ouDistinguishedName = 'OU=Default,OU=Users,DC=example,DC=com'
35+
}
36+
}
37+
Write-Verbose "ouDistinguishedName: '$($ouDistinguishedName)'"
38+
39+
try {
40+
Write-Verbose "Querying AD OU [$ouDistinguishedName]"
41+
42+
$adOU = Get-ADOrganizationalUnit -Identity $ouDistinguishedName -Properties canonicalName, name, objectGuid
43+
if ($null -ne $adOU) {
44+
$organizationalUnit = [PSCustomObject]@{
45+
canonicalName = $adOU.canonicalName
46+
name = $adOU.distinguishedName
47+
objectGuid = $adOU.objectGuid
48+
}
49+
}
50+
else {
51+
throw "No AD OU found with Distinguished Name [$ouDistinguishedName]"
52+
}
53+
54+
$success = $true
55+
Write-Verbose "Successfully queried AD OU [$ouDistinguishedName]"
56+
}
57+
catch {
58+
$success = $false
59+
60+
$ex = $PSItem
61+
Write-Warning "Error at Line '$($ex.InvocationInfo.ScriptLineNumber)': $($ex.InvocationInfo.Line). Error message: $($ex)"
62+
throw "Could not query AD OU with Distinguished Name [$ouDistinguishedName]. Error: $($ex.Exception.Message)"
63+
}
64+
65+
# Build up result
66+
$result = [PSCustomObject]@{
67+
Success = $success
68+
OrganizationalUnit = $organizationalUnit
69+
};
70+
71+
# Send result back
72+
Write-Output $result | ConvertTo-Json -Depth 2

built-in/orgUnit/initialContainer.ps1

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# Initialize default properties
2+
$p = $person | ConvertFrom-Json
3+
$m = $manager | ConvertFrom-Json
4+
$a = $accountReference | ConvertFrom-Json
5+
$ma = $managerAccountReference | ConvertFrom-Json
6+
7+
# The entitlementContext contains the configuration
8+
# - configuration: The configuration that is set in the Custom PowerShell configuration
9+
$eRef = $entitlementContext | ConvertFrom-Json
10+
11+
$success = $false
12+
13+
$VerbosePreference = "SilentlyContinue"
14+
$InformationPreference = "Continue"
15+
$WarningPreference = "Continue"
16+
17+
# Calculate AD OU based on department
18+
# example.com/Users/Dept1 - Dept1 & Dept1Team
19+
# example.com/Users/Dept2 - Dept2 & Dept2Team
20+
# example.com/Users/Dept3 - Dept3 & Dept3Team
21+
# example.com/Users/Default - Everything else
22+
Write-Verbose "Department: '$($p.PrimaryContract.Department.ExternalId)'"
23+
switch ($p.PrimaryContract.Department.ExternalId) {
24+
{ $_ -in "Dept1", "Dept1Team" } {
25+
$ouDistinguishedName = 'OU=Dept1,OU=Users,DC=example,DC=com'
26+
}
27+
{ $_ -in "Dept2", "Dept2Team" } {
28+
$ouDistinguishedName = 'OU=Dept2,OU=Users,DC=example,DC=com'
29+
}
30+
{ $_ -in "Dept3", "Dept3Team" } {
31+
$ouDistinguishedName = 'OU=Dept3,OU=Users,DC=example,DC=com'
32+
}
33+
default {
34+
$ouDistinguishedName = 'OU=Default,OU=Users,DC=example,DC=com'
35+
}
36+
}
37+
Write-Verbose "ouDistinguishedName: '$($ouDistinguishedName)'"
38+
39+
try {
40+
Write-Verbose "Querying AD OU [$ouDistinguishedName]"
41+
42+
$adOU = Get-ADOrganizationalUnit -Identity $ouDistinguishedName -Properties canonicalName, name, objectGuid
43+
if ($null -ne $adOU) {
44+
$organizationalUnit = [PSCustomObject]@{
45+
canonicalName = $adOU.canonicalName
46+
name = $adOU.distinguishedName
47+
objectGuid = $adOU.objectGuid
48+
}
49+
}
50+
else {
51+
throw "No AD OU found with Distinguished Name [$ouDistinguishedName]"
52+
}
53+
54+
$success = $true
55+
Write-Verbose "Successfully queried AD OU [$ouDistinguishedName]"
56+
}
57+
catch {
58+
$success = $false
59+
60+
$ex = $PSItem
61+
Write-Warning "Error at Line '$($ex.InvocationInfo.ScriptLineNumber)': $($ex.InvocationInfo.Line). Error message: $($ex)"
62+
throw "Could not query AD OU with Distinguished Name [$ouDistinguishedName]. Error: $($ex.Exception.Message)"
63+
}
64+
65+
# Build up result
66+
$result = [PSCustomObject]@{
67+
Success = $success
68+
OrganizationalUnit = $organizationalUnit
69+
};
70+
71+
# Send result back
72+
Write-Output $result | ConvertTo-Json -Depth 2

0 commit comments

Comments
 (0)