ADSI Search for DistinguishedName of the primary group based on primarygroupid - powershell

Because we don't have the active directory module available on all our systems we're using ADSI instead. The following code retrieves a user object from AD by using the AdsiSearcher:
$ADUser = ([AdsiSearcher]"(samaccountname=$SamAccountName)").FindOne()
This results in finding the property primarygroupid which represents the domain primary group for user, usually number 513. When we have this number we would like to find the distinguishedName of the group. However, the code below does that just fine I was wondering if there is a better filter that can be used instead of filtering after the FindAll() method?
$searcher = [adsisearcher]'objectclass=group'
$searcher.PropertiesToLoad.Add('primarygrouptoken')
$searcher.PropertiesToLoad.Add('distinguishedName')
$searcher.FindAll() |
Where-Object { $_.Properties.primarygrouptoken -eq 513}
Something like this would be great but it's not possible:
([adsisearcher]”(&(objectCategory=group)(primaryGroupid=513))”).FindOne()

The primaryGroupToken is a constructed attribute, meaning that it's not actually materialized in the database, and can't be filtered using LDAP.
In order to build an equivalent filter we'll need to look at how it is constructed - and the primary group token in Active Directory is always the same as the group's RID part (the relative identifier) of the objectSid attribute.
So, if we want to search by it, we can simply filter by objectSid instead:
# Obtain domain SID
$dncDN = ([adsi]"LDAP://RootDSE").defaultNamingContext
$dnc = [adsi]"LDAP://$dncDN"
$domainSID = [System.Security.Principal.SecurityIdentifier]::new($dnc.objectSid.Value, 0)
# Set the group ID we're looking for
$RID = 513
# Search for group by objectSid value:
([adsisearcher]"(&(objectCategory=group)(objectSid=${domainSID}-${RID}))").FindOne()

Related

PowerShell script to get distribution group report

I am looking for a PowerShell script to get a export Distribution Group with following Information.
Group Display Name
Group Owner
Group Member
Last Activity Date
Member Count
Received Email Count
Group ID
I am working on a script but it is returning error
$groupmembers = foreach ($i in Get-DistributionGroup)
{
Get-DistributionGroupMember $i | select Display Name, #{n='Member';e={$i.DisplayName}}
}
Get-DistributionGroupMember returns an object of type ReducedRecipient which does not contain a fields called Display or Name - but it does contain a field called DisplayName - i think this is probably your issue.
If you dont want to read the docs, an easy way of seeing the members of an object is to use ConvertTo-Json. Temporarily add the line Get-DistributionGroupMember $i | ConvertTo-Json inside your foreach loop above the command that is failing. It will output the entire ReducedRecipient Object in JSON format so you can easily read the available property names and their current values.

Modifying Powershell LDAPFilter to add enabled=true

I've built a filter to look for a number of AD fields and properties that works well until I try to add a section looking for 'enabled -eq $true.'
Here is the filter that works successfully:
$filter = "(&(msExchMailboxguid=*)"+"(facilityID=12345)"+"(|(jobCodeID=0001)"+"(jobCodeID=0002)"+"(jobCodeID=0003)(jobCodeID=0004)"+"(jobCodeID=0005)"+"(jobCodeID=0006)))"
Get-ADUser -SearchBase "dc=acme,dc=corp" -LDAPFilter $filter
This works, and produces the correct AD user objects (four total).
But if I try looking for enabled accounts only, like so:
$filter = "(&(msExchMailboxguid=*)"+"(facilityID=12345)"+"(enabled=$true)"+"(|(jobCodeID=0001)"+"(jobCodeID=0002)"+"(jobCodeID=0003)(jobCodeID=0004)"+"(jobCodeID=0005)"+"(jobCodeID=0006)))"
It either fails with "the search filter can not be recognized," or it returns nothing at all depending on whether there are 3 or 4 closed parentheses. I've tried a bunch of variations like (enabled=true), (enabled -eq true) but none of them work.
The issue is that you are using an LDAP filter which is different than a native PowerShell filter and so has a different syntax. Even though most LDAP fields match pretty closely to their normal names, the Enabled field is not stored as a "normal" property (e.g. boolean true/false). Instead, it is held in a part of a bitmasked property userAccountControl. That means you have to use the "intuitive" filter:
(!(userAccountControl:1.2.840.113556.1.4.803:=2))
To filter out only the enabled accounts.
So that makes your filter for your example to become:
$filter = "(&(msExchMailboxguid=*)"+"(facilityID=12345)"+"(!(userAccountControl:1.2.840.113556.1.4.803:=2))"+"(|(jobCodeID=0001)"+"(jobCodeID=0002)"+"(jobCodeID=0003)(jobCodeID=0004)"+"(jobCodeID=0005)"+"(jobCodeID=0006)))"

LDAP userAccountControl atttribute

In PowerShell I use the following LDAP query to retrieve the active directory properties of a host name:
$Filter = "(&(ObjectCategory=Computer)(ObjectClass=Computer)(CN=$ComputerName))"
if ($Found = ([ADSISEARCHER]$Filter).FindOne()) {
$Details = $Found.GetDirectoryEntry()
}
Once I have these properties I would like to check if the computer account is disabled. The following LDAP query is allowing me to do that:
$Filter = "(&(objectCategory=computer)(userAccountControl:1.2.840.113556.1.4.803:=2)(CN=$ComputerName))"
([ADSISEARCHER]$Filter).FindOne()
What I would like to know is, how can I avoid using the second LDAP query and use the variable $Details from the first LDAP query to obtain $True or $False if the computer account is disabled?
I found some extra information but I can't seem to put the pieces together.
Thank you for your help.
The information you're looking for is encoded in the userAccountControl of the directory entry object. However, the property contains an array with a numeric value, so you need to check if the "disabled" flag (numeric value 2) in the first array element is set:
$disabled = [bool]($Details.userAccountControl[0] -band 2)

Retrieving an RDN from an Active Directory User Object

Is it possible to retrieve the RDN of a user object in Active Directory with the attribute intact.
I've done a lot of reading on this and found that an AD user object stores the RDN in an property called "name". Supposedly the value of the name (rdn) property should be something like name = "cn=Smith, Joe". The cn attribute is part of what should be returned. However whenever I retrieve the name property of an object the "cn=" always seems to be missing. For instance
$foo = get-aduser -filter 'Name -like "Smith, Joe"'
$foo.name
will return "Smith, Joe" not "cn=Smith, Joe". Is there someway to query and get the full RDN to return?
An alternative, is to grab the full DN of the object, split the DN, and display the first element in the resulting array, which will be the RDN, either CN= or otherwise, object dependent
$((foo.distinguishedname).split(","))[0]
Not really an answer but informations :
First the attributeId of the RDN attribute is fixed by the schema :
On the RDN point of view Active-Directory inherit from X500 standard. That is to say that you don't choose the attribute you want to create the RDN (in other LDAP directories you can). In Active-Directory the RDN attribute is given in the class schema by rDNAttID, it specifies the attributeId of the RDN attribute. If you look the schema for the class user it's CN.
So you can use :
"CN=$((get-aduser 'Smith, Joe').Name)"
Second do the following experiment :
In an OU create a user called 'Mananegement' you have the following DN CN=MAnagement,OU=MyOU,... now try to create, in the same OU, an OU named 'Mananegement' it should create an object with the following DN OU=MAnagement,OU=MyOU,..., but you receive an error. This error makes me beleive that somehow Active-Directory consider 'Mananegement' as the RDN and not 'CN=Mananegement' like others directories.
$current.Substring($current.IndexOf('OU='))

How to filter Win32_UserAccount results by OU

In PowerShell, I already know how to use DirectoryEntry and DirectorySearcher to get a list of users in a certain OU. The results of this method are mostly what I am looking for in AD, but it seems easier to get the same information by using a WMI query Win32_UserAccount. I like the properties of this class better and the SID is already in the correct string format (in the first method it needs to be converted from a hex byte array to string).
The problem I have with using Win32_UserAccount is that I cannot find a way to filter it by an OU. I can successfully filter by domain and name, and have tried several guesses with WQL, but can't seem to find any syntax for an OU filter. Most of my attempts result in "Invalid query." The following is an example of a query that works:
$user = gwmi Win32_UserAccount -filter "name='somebody' AND domain='mydomain'"
If there is no way to filter this by OU then I will go back to using the DirectoryEntry/DirectorySearcher.
Given that there are no LDAP related properties for the Win32_Account class I think you're out of luck unfortunately.
You could of course use this to get the SID in the format you want in addition to the directory searching to get the LDAP related data.
Are you familiar with the free AD cmdlets from Quest?
http://www.quest.com/powershell/activeroles-server.aspx
You can filter users based on OU and get the SID in various formats:
PS> Get-QADUser SizeLimit 0 -SearchRoot <OU_DistinguishedName>' | fl *sid*
objectSid : 0105000000000005150000006753F33372134F3FF673476FF4023001
Sid : S-1-5-21-54781788-1045369324-1866953526-501
(...)