Help validating PowerShell script to set Logon Hours to zero in AD: Powershell BeforeModify Rule

Thiago Santana da Silva
Fri, 05 Sep 2025 00:43:40 +0000

Hi community,

I’m working on a use case in Identity Security Cloud where I need to block certain users from logging into Active Directory.
The approach I’m testing is to trigger a PowerShell script via IQService that updates the logonHours attribute in AD and sets all values to zero (no allowed hours), effectively preventing logon.

From what I understand, the logonHours attribute is a 21-byte (168-bit) array that represents each hour of the week, and to prevent logon, all bits must be set to 0.

I created the following Zero-LogonHours.ps1 script, but I’d really appreciate your feedback on the logic and whether there are best practices I should follow when manipulating the logonHours attribute.

PowerShell Script (Zero-LogonHours.ps1)

#Requires -Version 7.3
param (
    [Parameter(Mandatory=$true)][System.String]$requestString
)

# Import SailPoint class library
Add-Type -Path "C:\SailPoint\IQService\Utils.dll"

# Import Active Directory module
Import-Module ActiveDirectory

# Logging setup
$logDate = Get-Date -UFormat "%Y%m%d"
$logFile = "C:\SailPoint\Scripts\Logs\ManageLogonHours_$logDate.log"
$enableDebug = $true

function LogToFile([String] $info) {
    $timestamp = (Get-Date).ToString("yyyy-MM-dd HH:mm:ss")
    "[LOGS] $timestamp - $info" | Out-File $logFile -Append -Encoding UTF8
}

Try {
    LogToFile("Starting Before Script execution")

    ##########################
    # SailPoint protected code (do not modify)
    $sReader = New-Object System.IO.StringReader([System.String]$env:Request)
    $xmlReader = [System.xml.XmlTextReader]([SailPoint.Utils.xml.XmlUtil]::getReader($sReader))
    $requestObject = New-Object SailPoint.Utils.objects.AccountRequest($xmlReader)
    ##########################

    $nativeIdentity = $requestObject.NativeIdentity
    LogToFile("Processing user: $nativeIdentity")

    # Loop through attribute requests to check group membership changes
    foreach ($attribute in $requestObject.AttributeRequests) {
        if ($attribute.Name -eq "memberOf") {

            # Normalize the attribute value to an array
            $groups = @()
            if ($attribute.Value -is [System.Collections.ArrayList]) {
                $groups = $attribute.Value
            } else {
                $groups = @($attribute.Value)
            }

            LogToFile("Groups in request: $($groups -join ', ') | Operation: $($attribute.Operation)")

            # If the group g_ferias_afastado is being added → disable user logon
            if ($attribute.Operation -eq "Add" -and $groups -contains "g_ferias_afastado") {
                LogToFile("Detected addition of group g_ferias_afastado → setting logonHours to zero")
                $logonHours = [byte[]](0..20 | ForEach-Object { 0 })
                $logonHoursAttribute = New-Object SailPoint.Utils.objects.AttributeRequest
                $logonHoursAttribute.Name = "logonHours"
                $logonHoursAttribute.Value = $logonHours
                $logonHoursAttribute.Operation = "Set"
                $requestObject.AttributeRequests.Add($logonHoursAttribute)
                LogToFile("logonHours set to zero successfully for $nativeIdentity")
            }

            # If the group g_ferias_afastado is being removed → restore full access
            if ($attribute.Operation -eq "Remove" -and $groups -contains "g_ferias_afastado") {
                LogToFile("Detected removal of group g_ferias_afastado → restoring logonHours")
                $logonHours = [byte[]](0..20 | ForEach-Object { 255 })
                $logonHoursAttribute = New-Object SailPoint.Utils.objects.AttributeRequest
                $logonHoursAttribute.Name = "logonHours"
                $logonHoursAttribute.Value = $logonHours
                $logonHoursAttribute.Operation = "Set"
                $requestObject.AttributeRequests.Add($logonHoursAttribute)
                LogToFile("logonHours restored successfully for $nativeIdentity")
            }

        }
    }

    LogToFile("Before Script execution completed successfully for $nativeIdentity")

} Catch {
    $ErrorMessage = $_.Exception.Message
    $ErrorType = $_.Exception.GetType().FullName
    LogToFile("ERROR [$ErrorType]: $ErrorMessage")
    exit 1
}

# Write the modified request XML back to file for IQService to process
LogToFile("Writing modified request XML to file: $($args[0])")
$requestObject.toxml() | Out-File $args[0] -Encoding UTF8
LogToFile("XML successfully written. Script finished.")

Will this script reliably ensure that the logonHours attribute is fully reset in AD?

The purpose of the script is to control logon access in Active Directory by resetting or restoring the user’s logonHours attribute based on the addition or removal of the Active Directory group: g_ferias_afastado.

Do you recommend any additional safeguards or best practices when executing this via IQService?

Thanks a lot for your help!