Archive for the ‘Quest’ tag
Quest AD Management Shell – Moving AD User Objects
Code Snippet: Moving disable user objects in Active Directory using PowerShell and Quest Management cmdlets.Task:
Task: Moving all disabled users in the ‘/Users’ OU to the /Users/Disabled OU.
Code:
Add-PSSnapin -Name Quest.ActiveRoles.ADManagement -ErrorAction SilentlyContinue $Users = Get-QADUser -SearchRoot 'ad.domain.com/Users/' -Disabled Write-Host "Moving $Users.Count Users." ForEach($User In $Users){ Move-QADObject $User.DN -NewParentContainer 'ad.domain.com/Users/Disabled'}
Hope this helps
All information is provided on an AS-IS basis, with no warranties and confers no rights.
AD and Kerberos Token Bloat – Analyzing Group Nesting
How To: Analyze Nested AD Groups.
I am working on a Kerberos Token size issue (Token Bloat) and need to accurately depict a groups nested members for token size analysis and remediation.
Brief Token Bloat Explanation:
Token Bloat is where due to several factors including deep group nesting the Kerberos token utilized in AD for resource authentication bloats towards the set limit or even beyond. This can cause larger logon times to resources and even issues in applications like Exchange 2003 that can only exist on a 32Bit OS.
I came across this article on the “Microsoft Active Directory Group PowerShell” blog, it has a great script for analysing nested group memberships. Unfortunately to use the PowerShell script you need to be running Windows 2008 servers for the Active Directory cmdlets to be available. The environment that I required the script for was not W2008 so I converted the script to use the Quest cmdlets available with the Quest Active Roles Management PSSnapIn.
You will need to have these installed before using this script.
The script originally written by the MS AD PowerShell team, provides a visual tree view of the groups and their nested levels, a ‘MaxNestingLevel’ value and a ‘NestedGroupMembershipCount’.
Example:
PS C:\> Get-QADGroupNesting.ps1 group-name
Or
PS C:\> Get-QADGroupNesting.ps1 group-name -ShowTree
The above example not only displays group statistics it also plots the structure of the group in a tree format.
Download Script at PoshCode.org
Code:
##########Copy the below script into a new file called Get-ADGroupNesting.ps1 Param ( [Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true, HelpMessage="DN or ObjectGUID of the AD Group." )] [string]$groupIdentity, [switch]$showTree ) #Validate Quest PSSnapin is loaded Add-PSSnapin -Name Quest.ActiveRoles.ADManagement -ErrorAction SilentlyContinue $global:numberOfRecursiveGroupMemberships = 0 $lastGroupAtALevelFlags = @() function Get-GroupNesting ([string] $identity, [int] $level, [hashtable] $groupsVisitedBeforeThisOne, [bool] $lastGroupOfTheLevel) { $group = $null $group = Get-QADGroup -Identity $identity -SizeLimit 0 if($lastGroupAtALevelFlags.Count -le $level) { $lastGroupAtALevelFlags = $lastGroupAtALevelFlags + 0 } if($group -ne $null) { if($showTree) { for($i = 0; $i -lt $level - 1; $i++) { if($lastGroupAtALevelFlags[$i] -ne 0) { Write-Host -ForegroundColor Blue -NoNewline " " } else { Write-Host -ForegroundColor Blue -NoNewline "│ " } } if($level -ne 0) { if($lastGroupOfTheLevel) { Write-Host -ForegroundColor Blue -NoNewline "└─" } else { Write-Host -ForegroundColor Blue -NoNewline "├─" } } Write-Host -ForegroundColor Blue $group.Name } $groupsVisitedBeforeThisOne.Add($group.DN,$null) $global:numberOfRecursiveGroupMemberships ++ $groupMemberShipCount = $group.memberOf.Count if ($groupMemberShipCount -gt 0) { $maxMemberGroupLevel = 0 $count = 0 foreach($groupDN in $group.memberOf) { $count++ $lastGroupOfThisLevel = $false if($count -eq $groupMemberShipCount){$lastGroupOfThisLevel = $true; $lastGroupAtALevelFlags[$level] = 1} if(-not $groupsVisitedBeforeThisOne.Contains($groupDN)) #prevent cyclic dependancies { $memberGroupLevel = Get-GroupNesting -Identity $groupDN -Level $($level+1) -GroupsVisitedBeforeThisOne $groupsVisitedBeforeThisOne -lastGroupOfTheLevel $lastGroupOfThisLevel if ($memberGroupLevel -gt $maxMemberGroupLevel){$maxMemberGroupLevel = $memberGroupLevel} } } $level = $maxMemberGroupLevel } else #we've reached the top level group, return it's height { return $level } return $level } } $global:numberOfRecursiveGroupMemberships = 0 $groupObj = Get-QADGroup -Identity $groupIdentity -SizeLimit 0 if($groupObj) { [int]$maxNestingLevel = Get-GroupNesting -Identity $groupIdentity -Level 0 -GroupsVisitedBeforeThisOne @{} -lastGroupOfTheLevel $false Add-Member -InputObject $groupObj -MemberType NoteProperty -Name MaxNestingLevel -Value $maxNestingLevel -Force Add-Member -InputObject $groupObj -MemberType NoteProperty -Name NestedGroupMembershipCount -Value $($global:numberOfRecursiveGroupMemberships - 1) -Force $groupObj | Select-Object Name,DN,MaxNestingLevel,NestedGroupMembershipCount | Format-List }
Hope this helps
All information is provided on an AS-IS basis, with no warranties and confers no rights.
Scanning Active Directory for SMTP Addresses
How To: Scanning Active Directory for SMTP Addresses.
When an object in AD is mail enabled it is assigned an SMTP address. Sometimes these addresses are assigned incorrectly to objects or a requested address is already in use on a object and you need to find the object that it is assigned to. I come across this situation sometimes and the simplest way is to query AD for the SMTP address. The SMTP addresses are stored in an AD attribute called “proxyAddresses” this holds all addresses including SMTP. Using the QUEST PowerShell PSSnapIn, you can query AD for this attribute using an LDAP filter.
Querying AD using Quest cmdlets and LDAP query.
Get-QADObject -LdapFilter "(proxyAddresses=*$Address*)" -IncludedProperties "proxyAddresses"
Using the above command with perform the filter, however you will only pull back the default cached set of attributes for the object so I add the ‘-includeallproperties’ switch to pull all attributes available for the object back into the cache.
I also set the ‘-SizeLimit 0′ so the result set isn’t limited to the standard 1000 returned objects.
The below code turns the basic shell command into a ‘Function’ called ‘Get-ProxyAddress.ps1′.
Instructions:
- Copy the below code into a file called ‘Get-ProxyAddress.ps1′
- Open the PowerShell shell and traverse to the directory that hosts the above file
- Run the script using this syntax, “./Get-ProxyAddress.ps1 address@domain.com”
- address@domain.com being the SMTP address you are searching for.
The output details either that the SMTP address is not found in AD or the below attributes are listed for the object that own the SMTP address.
- Name
- DisplayName
- ObjectClass
- AccountisDisabled
- AccountisLockedOut
- MailNickName
- LegacyExchangeDN
Download Script from PoshCode.org
Code:
Param ( [Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true, HelpMessage="Enter SMTP address to search for in Active-Directory." )] [string]$objSMTP ) Function Get-ProxyAddresses ([string]$Address){ $objAD = $null $objAD = Get-QADObject -LdapFilter "(proxyAddresses=*$Address*)" -IncludeAllProperties -SizeLimit 0 -ErrorAction SilentlyContinue Write-Output $objAD }#Close Function #Validate Quest PSSnapin is loaded Add-PSSnapin -Name Quest.ActiveRoles.ADManagement -ErrorAction SilentlyContinue #Run Function to search AD for SMTP address $Results = $null $Results = Get-ProxyAddresses -Address $objSMTP | Select-Object Name,DisplayName,ObjectClass,Email,AccountisDisabled,AccountisLockedOut,MailNickName,LegacyExchangeDN -ErrorAction SilentlyContinue IF($Results -eq $null){ Write-Host "" Write-Host "No Object Found with .attribute[proxyAddress] containing $objSMTP."} Else{$Results | Format-List *} #End
Hope this helps.
All information is provided on an AS-IS basis, with no warranties and confers no rights.
Searching for DL's with Exchange Expansion Servers
Question:
Do we have any Email enabled groups in Active Directory that have an Exchange 2003 expansion server explicitly specified in its properties and who manages them?
Expansion Server:
“Exchange server dedicated to expanding the members of a specific mail enabled group (distribution list)”
Answer:
So I would need to look at Active Directory for all email enabled distribution lists that have the attribute ‘msExchExpansionServerName’ (which only exists when a group is mail enabled), and that it’s value is not blank. If the attribute is blank the distribution list is set to default which is ‘Any server in the organization’. The value can be viewed on the ‘Exchange Advanced’ TAB on the groups properties in ADUC.
Here is the PowerShell one line command that I used. I am utilizing the Quest Active Roles Management cmdlets.
You will need the following:
- DN, GUID or Canonical Name of the Domain or Container where you wish to search for groups. (The example quotes a DN for the group container)
- Quest Active Roles Management Shell snapin.
Get-QADGroup -SearchRoot 'OU=GrouOU,DC=company,DC=com' -SizeLimit 0 -LdapFilter '(msExchExpansionServerName=*)' -IncludeAllProperties | Select-Object name,msexchexpansionservername,managedby
If you need any assistance in using the Quest Active Roles Management cmdlets see this article.
Note:
I use the ‘-IncludeAllProperties’property of the ‘Get-QADGroup’ cmdlet to ensure the ‘msExchExpansionServerName’ attribute is returned into the local cached object result set, by default this would not be returned, for more information see this article..
Hope this helps.
All information is provided on an AS-IS basis, with no warranties and confers no rights.
Getting Exchange 2003 Database Statistics
I routinely analyze Exchange 2003 stores. To do this I previously had written a VB script that dumps all the mailboxes on an Exchange 2003 server using the Exchange_Mailbox WMI class, but as this is a PowerShell article i hear you say “How does this help me?”.
I use PowerShell more and more I really enjoy the simplicity and power of the PowerShell cmdline. So I started to look into producing some clean one liners or small scripts to produce something similar to my large VB script solution.
Note: In all examples below just replace “Server” with an Exchange 2003 server name.
Getting all Exchange 2003 Mailboxes on a single server using WMI,
GWMI -NameSpace Root\MicrosoftExchangeV2 -Class Exchange_Mailbox -ComputerName $Server | Export-CSV "C:\Scripts\Mailboxes.csv" -NoTypeInformation
The next step is to start filtering the output to get detailed information on trouble spots, for example to look for any mailboxes that contain more than ’5000′ items.
To find these we use the ‘.totalItems’ property of the ‘Exchange_Mailbox’ class.
Getting all Exchange 2003 Mailboxes on a single server that have more than 5000 ‘Items’,
GWMI -NameSpace Root\MicrosoftExchangeV2 -Class Exchange_Mailbox -ComputerName $Server | Where{$_.totalitems -gt '5000'} | Export-CSV "C:\Scripts\Mailboxes.csv" -NoTypeInformation
Another WMI ‘Exchange_Mailbox’ class property I use is the ‘.DateDiscoveredAbsentInDS’ this tells me the date the mailbox was disconnected/deleted from the User Object in AD. If for any reason you do not want the store to clean up these automatically you can script the purge of the mailboxes using VBScript or PowerShell. The below code will enable you to see the mailboxes that are ready to be purged but will take no action.
Getting all Exchange 2003 Mailboxes that have been deleted (disconnected from their AD User object) and are ready to be ‘Purged’ on a single server,
GWMI -NameSpace Root\MicrosoftExchangeV2 -Class Exchange_Mailbox -ComputerName $Server | Where{$_.DateDiscoveredAbsentInDS -ne $NULL} | Export-CSV "C:\Scripts\Mailboxes.csv" -NoTypeInformation
Another part to the Exchange Mailbox is the counterpart attributes held in the User object. Some of these attributes are the status of the Mailbox, for example “Is the user over his/her set limits?” or “Is the account disabled in AD?”. To find out the answers here we need to interrogate the user object attribute values. To do this there are many methods depending upon the version of PowerShell you are using and if you have the Quest Management tools loaded. In the example below i am utilizing the Quest Management Tools.
Hope this helps.
All information is provided on an AS-IS basis, with no warranties and confers no rights.
Quest Get-QADUser – All User Attributes
This article is part of a series of articles on the Quest Active Roles Management Shell and the CmdLets that are included in that.
Previously:
Getting Started
Get-QADGroup
The Get-QADUser CmdLet from Quest Tools can be used to return attributes back from your AD directory on a specific user object and place them in the local memory cache. The object returned by the CmdLet contains a pre-defined set of attributes. You can view or modify this default attribute set using the Get- or Set-QADPSSnapinSettings CmdLet. You can also change the returned attribute set on the returned object on an Ad-Hoc basis by using the -ExcludedProperties and -IncludedProperties parameters with the Get-QADUser CmdLet. One final option is the -IncludeAllProperties parameter, with this you can return all attributes of the user object and access them through the returned object in the memory cache.
So Examples,
The default attributes accessible in the returned object can be found here on page 39 in the “Quest Active Roles Management Shell for AD” guide.
Or enter this at the command line(With the Quest snap-in loaded)
Get-QADUser -Name accountname | Get-Member -MemberType Properties
To obtain all available attributes for a user object in your AD directory using the -IncludeAllProperties parameter.
Get-QADUser -Name accountname -IncludeAllProperties | Get-Member -MemberType Properties
Note: The above command will include all properties available in your AD directory in the returned user object, however when outputting the results to the cmdline the default attribute set controlled by the Get- or Set-QADPSSnapinSettings will prevail.
To see all user object attribute values
Get-QADUser -Name accountname -IncludeAllProperties | Format-List *
Export them to a .csv file
Get-QADUser -Name accountname -IncludeAllProperties | Export-CSV "C:\Scripts\UserDump.csv"
Including all properties(attributes) when you do not need them can add time to your executing code. I find it wise to minimize the data being queried and returned back whenever possible.
Using the above examples you can start to complete more complex user object queries.
For Example:
I would like to search for a user based on their SMTP address (.mail attribute) and then retrieve their set mailbox limits. The SMTP address or mail attribute is a standard attribute we can filter on using the -Email parameter. See here o n page 34 of the “Quest Active Roles Management Shell for AD” guide. The required returned object attribute of .mDBUseDefaults, .mDBStorageQuota and .mDBOoverQuotaLimit are not attributes cached by default in the returned object. To gain these attributes you need to include them in the returned object and specify them in the output pipe.
Get-QADUser -Email 'user@domain.com' -IncludedProperties mDBUseDefaults','mDBStorageQuota','mDBOoverQuotaLimit' | Format-List name,displayname,mDBUseDefaults,mDBStorageQuota,mDBOoverQuotaLimit
From this you should get back all the details of the user object specified in the Format-List command.
Hope this helps.
All information is provided on an AS-IS basis, with no warranties and confers no rights.
Quest AD Management Shell – Get-QADGroup
In my previous blog entry “Getting Started” I went over downloading and installing the Quest AD Management shell, registering the snapins and running some basic commands using the Get-QADUser CmdLet.
Today I will be looking at the Get-QADGroup CmdLet.
This allows easy access to Active Directory “Group” objects.
As before open a PowerShell Shell window and add in your snapins.
add-pssnapin Quest.ActiveRoles.ADManagementGetting the number of members in a group.
(Get-QADGroup "GroupName").members.count
Export out the members of a group to a formatted table including the name,displayname,mail(SMTP) and office for each member.
Function Get-MemberName() { Process { ForEach($Member In $_) { Get-QADUser –ObjectAttributes @{distinguishedName=$Member} } } } (Get-QADGroup "GroupName").members | Get-MemberName | Format-Table name,displayname,mail,office
I often have to clean up groups by looking for disabled users.
To do this you can just add the “accountisdisabled” property to the script above.
E.g.
(Get-QADGroup "GroupName").members | Get-MemberName | Format-Table name,displayname,mail,office,accountisdisabled
Export out the members of a group to a CSV file with all properties.
Function Get-MemberName() { Process { ForEach($Member In $_) { Get-QADUser –ObjectAttributes @{distinguishedName=$Member} } } } (Get-QADGroup "GroupName").members | Get-MemberName | Export-Csv "C:\GroupMembers.csv"
Above are some useful examples of using Quest AD CmdLets to enumerate Active Directory Group objects.
Hope this helps.
All information is provided on an AS-IS basis, with no warranties and confers no rights.
Quest AD Management Shell – Getting Started
Until now I have always used ADSI and LDAP to query Active Directory for object stored information.
I have been following Dimitry’s examples with the Quest AD PowerShell CmdLets and I thought it was about time I started to embrace them into my PowerShell scripts.
You can download the “ActiveRoles Management Shell for AD” Here.
Before running the Quest ActiveRoles Management Shell snapins I would recommend reading the “Requirements on Active Directory” section (p21) in the administration guide.
After you have installed the Quest ActiveRoles Management Shell you will have to register the PowerShell snapin at the PowerShell prompt.
Enter the command:
add-pssnapin Quest.ActiveRoles.ADManagementOnce you are ready to go and the Quest ActiveRoles Management Shell snapins are installed and registered you can get started with some basic commands.
For Example:
Getting the .displayName of your Active Directory account.
$User = Get-QADUser -Name "YourAccountName" $User.DisplayName
Getting the Sam Account Name of your Active Directory account.
(Get-QADUSer -Name "YourAccountName").SamAccountName
Checking if a user account is disabled.
(Get-QADUSer -Name "UserAccount").AccountIsDisabled
Using the Get-QADUser with no previously specified connection details allows the Cmdlet to connect to any available domain controller with the credentials of the locally logged on user.
Next time I will start to go through mail enabled groups, their memberships and properties.
Hope this helps.
All information is provided on an AS-IS basis, with no warranties and confers no rights.
