.netwindowspowershellactive-directorydirectoryservices

PowerShell - Error when querying AD if user enters credentials


Trying to create a basic script for my IT helpdesk team that queries our AD to see if a computer's hostname is already on the domain. I want this to not require any modules so it can run on any Windows computer without additional software (because of this I am using DirectoryServices).

Also company coding policy prevents me from predefining credentials, so I want to make it user-defined. However, it seems that the script will run successfully only if they are predefined. Getting the below error if credentials are user-defined.

Exception calling "FindAll" with "0" argument(s): "The user name or password is incorrect."

Below is a redacted version of what I have.

$username = read-host 'Enter username' 
$password = read-host 'Enter password' -AsSecureString
$hostname = hostname

Write-Host "Checking if $hostname is on the domain..."
$filter = "(&(ObjectCategory=computer)(Name=$hostname))"
$de = New-Object DirectoryServices.DirectoryEntry("LDAP://contoso.com/DC=contoso,DC=onmicrosoft,DC=com",$username,$password)
$ds = New-Object DirectoryServices.DirectorySearcher $de
$ds.filter = $filter
$ds.findall() |
ForEach-Object -Begin {} -Process{$_.properties.item(“Name”)} -End { [string]$ds.FindAll().Count } | Out-Null
  if ($ds.FindAll().Count)
    {
        Write-Host "true"
    }
  else
    {
        Write-Host "false"
    }

Is it possible for the credentials to be user-defined or does it have to be predefined?


Solution

  • The DirectoryEntry constructor you're using requires the password argument to be a string instead of a secure string.

    Read-Host when used with the -AsSecureString outputs a System.Security.SecureString object. Converting it back to string and passing it as argument for the constructor should solve the problem:

    $secpassw = Read-Host 'Enter password' -AsSecureString
    $password = [System.Net.NetworkCredential]::new('', $secpassw).Password
    

    It's also worth noting that since you're asking for Username and Password, Get-Credential might be a more elegant way for asking it and the same technique using NetworkCredential to transform the secure string will work:

    $cred  = Get-Credential
    $passw = [System.Net.NetworkCredential]::new('', $cred.Password).Password