New-AADConnectRule-DisableExpiredAccts.ps1
<#PSScriptInfo
.VERSION 1.1 .GUID d5b9d5b5-3360-44e6-bb32-77561e2367e5 .AUTHOR Aaron Guilmette .COMPANYNAME Planet Technologies .COPYRIGHT 2023 .TAGS AADCONNECT Expired .LICENSEURI .PROJECTURI https://www.undocumented-features.com/2023-01-25-working-around-accounts-that-expire-with-aad-connect .ICONURI .EXTERNALMODULEDEPENDENCIES .REQUIREDSCRIPTS .EXTERNALSCRIPTDEPENDENCIES .RELEASENOTES .DESCRIPTION Create a new AADConnect rule to disable corresponding cloud accounts for on-premises accounts that meet conditions for accountExpires or ForceChangePassword. .PRIVATEDATA #> <# .SYNOPSIS Create a new AADConnect rule to disable corresponding cloud accounts for on-premises accounts that meet conditions for accountExpires or ForceChangePassword. .PARAMETER BlockExpiredAccounts This option sets a cloud account to disabled (BlockCredential:$true) if the corresponding on-premises account has expired. This parameter is enabled by default. Set this parameter to $false to skip configuring this rule. .PARAMETER BlockForceChangePassswordAccounts This option sets a cloud account to disabled (BlockCredential:$true) if the corresponding on-premises account is flagged for immediate password reset. If your organization uses Microsoft 365 Self-Service Password Reset (SSPR), enabling this option will prevent users forced to change password on next logon from using SSPR. Accounts with BlockCredential:true are ineligible to use SSPR. This parameter is disabled by default. Set this parameter to $true to configure this rule. .EXAMPLE .\New-AADConnect-DisableExpiredAccounts.ps1 Run with default options (-BlockExpiredAccounts $true -BlockForceChangePasswordAccounts $false) .LINK https://www.powershellgallery.com/packages/New-AADConnectRule-DisableExpiredAccts .LINK https://www.undocumented-features.com/2023-01-25-working-around-accounts-that-expire-with-aad-connect .NOTES 2023-02-13 - 1.1 Updated to correctly account for objects that previously had an account expiration set (accountExpires -eq 0). 2023-01-25 - 1.0.2 Updated help file. 2023-01-25 - 1.0.1 Updated help file. 2023-01-24 - 1.0 Initial release. #> param ( [bool]$BlockExpiredAccounts = $true, [bool]$BlockForceChangePassswordAccounts = $false ) ## Define vars # Select AAD Connector [string]$Connector = (Get-ADSyncConnector | ? { $_.Name -like "* - AAD" }).Identifier.ToString() # Retrieve ImmutableTag values, which are used to determine if this script has been run before to create the rules. [array]$Tags = (Get-ADSyncRule).ImmutableTag.TagValue ## Disable accounts past accountExpires time if ($BlockExpiredAccounts) { If ($Tags -notcontains "DisableExpiredAccount") { # Generate Guid for rule [string]$DisableExpiredAccountIdentifier = [Guid]::NewGuid().ToString() # Determine lowest precedence for rules [array]$AllRulesPrecedence = (Get-ADSyncRule).Precedence $DisableExpiredAccountPrecedence = (($AllRulesPrecedence | Measure-Object -Minimum).Minimum - 1) New-ADSyncRule ` -Name 'Out to AAD - Disable Expired Account' ` -Identifier $DisableExpiredAccountIdentifier ` -Description 'Disable corresponding cloud account for on-premises account past accountExpires time' ` -Direction 'Outbound' ` -Precedence $DisableExpiredAccountPrecedence ` -PrecedenceAfter '00000000-0000-0000-0000-000000000000' ` -PrecedenceBefore '00000000-0000-0000-0000-000000000000' ` -SourceObjectType 'person' ` -TargetObjectType 'user' ` -Connector $Connector ` -LinkType 'Join' ` -SoftDeleteExpiryInterval 0 ` -ImmutableTag 'DisableExpiredAccount.2' ` -OutVariable syncRule Add-ADSyncAttributeFlowMapping ` -SynchronizationRule $syncRule[0] ` -Destination 'accountEnabled' ` -FlowType 'Expression' ` -ValueMergeType 'Update' ` -Expression 'IIF(CStr([extension_accountExpires])="0",True,(IIF(CStr([extension_accountExpires])="9223372036854775807",True,IIF(DateFromNum([extension_accountExpires])>(CDate(NumFromDate(Now()))),True,False))))' ` -OutVariable syncRule New-Object ` -TypeName 'Microsoft.IdentityManagement.PowerShell.ObjectModel.ScopeCondition' ` -ArgumentList 'accountEnabled', 'TRUE', 'EQUAL' ` -OutVariable condition0 New-Object ` -TypeName 'Microsoft.IdentityManagement.PowerShell.ObjectModel.ScopeCondition' ` -ArgumentList 'extension_accountExpires', '9223372036854775807', 'NOTEQUAL' ` -OutVariable condition1 Add-ADSyncScopeConditionGroup ` -SynchronizationRule $syncRule[0] ` -ScopeConditions @($condition0[0], $condition1[0]) ` -OutVariable syncRule New-Object ` -TypeName 'Microsoft.IdentityManagement.PowerShell.ObjectModel.ScopeCondition' ` -ArgumentList 'accountEnabled', 'TRUE', 'EQUAL' ` -OutVariable condition0 New-Object ` -TypeName 'Microsoft.IdentityManagement.PowerShell.ObjectModel.ScopeCondition' ` -ArgumentList 'extension_accountExpires', '0', 'NOTEQUAL' ` -OutVariable condition1 Add-ADSyncScopeConditionGroup ` -SynchronizationRule $syncRule[0] ` -ScopeConditions @($condition0[0], $condition1[0]) ` -OutVariable syncRule Add-ADSyncRule ` -SynchronizationRule $syncRule[0] ## END RULE $RuleData1 = Get-ADSyncRule -Identifier $DisableExpiredAccountIdentifier IF ($RuleData1) { Write-Host -ForegroundColor Green 'Rule "Out to AAD - Disable Expired Accounts" has been successfully created by this script.' } } Else { Write-Host -ForegroundColor Cyan 'Rule "Out to AAD - Disable Expired Accounts" has already been created by this script.' Write-Host -ForegroundColor Cyan 'Please use the AAD Connect Synchronization Rules Editor to update it.' } } ## Disable corresponding cloud accounts for on-premises account with 'Force Change Password' set if ($BlockForceChangePassswordAccounts) { If ($Tags -notcontains "DisableForcedChangePassword") { # Generate Guid for rule [string]$DisableForceChangePasswordAccountIdentifier = [Guid]::NewGuid().ToString() # Determine precedence for new rule [array]$AllRulesPrecedence = (Get-ADSyncRule).Precedence $DisableForceChangePasswordAccountPrecedence = (($AllRulesPrecedence | Measure-Object -Minimum).Minimum - 1) New-ADSyncRule ` -Name 'Out to AAD - Disable accounts with passwords set to ForceChange' ` -Identifier $DisableForceChangePasswordAccountIdentifier ` -Description '' ` -Direction 'Outbound' ` -Precedence $DisableForceChangePasswordAccountPrecedence ` -PrecedenceAfter '00000000-0000-0000-0000-000000000000' ` -PrecedenceBefore '00000000-0000-0000-0000-000000000000' ` -SourceObjectType 'person' ` -TargetObjectType 'user' ` -Connector $Connector ` -LinkType 'Join' ` -SoftDeleteExpiryInterval 0 ` -ImmutableTag 'DisableForcedChangePassword' ` -OutVariable syncRule Add-ADSyncAttributeFlowMapping ` -SynchronizationRule $syncRule[0] ` -Destination 'accountEnabled' ` -FlowType 'Expression' ` -ValueMergeType 'Update' ` -Expression 'IIF(CStr([pwdLastSet])="16010101000000.0Z",False,True)' ` -OutVariable syncRule New-Object ` -TypeName 'Microsoft.IdentityManagement.PowerShell.ObjectModel.ScopeCondition' ` -ArgumentList 'accountEnabled', 'TRUE', 'EQUAL' ` -OutVariable condition0 Add-ADSyncScopeConditionGroup ` -SynchronizationRule $syncRule[0] ` -ScopeConditions @($condition0[0]) ` -OutVariable syncRule Add-ADSyncRule ` -SynchronizationRule $syncRule[0] $RuleData2 = Get-ADSyncRule $DisableForceChangePasswordAccountIdentifier If ($RuleData2) { Write-Host -ForegroundColor Green 'Rule Out to AAD - Disable accounts with passwords set to ForceChange" has been successfully created by this script.' } } else { Write-Host -ForegroundColor Cyan 'Rule "Out to AAD - Disable accounts with passwords set to ForceChange" has already been created by this script.' Write-Host -ForegroundColor Cyan 'Please use the AAD Connect Synchronization Rules Editor to update it.' } } |