Home > Software engineering >  How to list users with logonhours denied
How to list users with logonhours denied

Time:09-08

I need a list of users with the logonhours set to denied. I found another question (68558481) that partially got me there but I seem to be doing something wrong when trying to loop through my group.

$userToFind = Get-ADGroupMember -identity "AD group" | Sort-Object samAccountName | Select SamAccountName
# try and find the user also gathering its LogonHours property
Foreach ($username in $userToFind){
$user = Get-ADUser -Filter "SamAccountName -eq '$username'" -Properties LogonHours -ErrorAction SilentlyContinue
if ($user) {
    # test if the property has been set. If not set, the user is allowed to login anytime of the week
    if ($null -ne $user.LogonHours -and @($user.LogonHours).Count) {
        # initialize a variable
        $loginAllowed = $false
        # loop through the 21 bytes and exit the loop if we found a non-zero byte
        foreach ($byte in $user.LogonHours) { 
            if ($byte -ne 0) { 
                $loginAllowed = $true  # set the flag to $true
                break                  # and exit the loop
            }
        }
        if (!$loginAllowed) {
            "User $username - Login disabled"
        }
    }
}
else {
    Write-Warning "User $username does not exist.."
}
}

My results for this is all users do not exist. Where am I going wrong?

|

CodePudding user response:

The main issue is that $userToFind is an object or array of objects which's property is SamAccountName, so when you use it in your filter "SamAccountName -eq '$username'", the result is the stringification of each object:

$username = [pscustomobject]@{
    samAccountName = 'someuser'
}

"SamAccountName -eq '$username'" # => SamAccountName -eq '@{samAccountName=someuser}'

What you want to do instead is get the value of each object, a string or array of strings in this case:

$username = [pscustomobject]@{
    samAccountName = 'someuser'
} | Select-Object -ExpandProperty samAccountName

"SamAccountName -eq '$username'" # => SamAccountName -eq 'someuser'

You can also use member-access enumeration instead of Select-Object, so in your code it would be:

$userToFind = (Get-ADGroupMember -Identity "AD group" | Sort-Object samAccountName).SamAccountName

As for the current code, you could make an improvement by only searching for users member of the group which's logonHours attribute is populated. That way, there is no need to check if the user has the attribute set and no need to check if the user was found or not.

# get the DN of the group
$group = (Get-ADGroup -Identity "AD group").DistinguishedName
$param = @{
    LDAPFilter = "(&(memberof=$group)(logonhours=*))"
    Properties = "logonHours"
}
# enumerate all users members of this group which's attribute `LogonHours` is set
foreach($user in Get-ADUser @param) {
    $loginAllowed = $false
    foreach($byte in $user.LogonHours) {
        if ($byte -ne 0) {
            $loginAllowed = $true
            break
        }
    }
    if (-not $loginAllowed) {
        "User {0} - Login disabled" -f $user.SamAccountName
    }
}
  • Related