TechnoGist

gist (jst)# The central idea; the essence…

Archive for the ‘Quest’ tag

Quest AD Management Shell – Moving AD User Objects

without comments

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.

Written by Paul Brice

January 28th, 2010 at 7:00 pm

Posted in AD,PowerShell,Quest

Tagged with , ,

AD and Kerberos Token Bloat – Analyzing Group Nesting

with one comment

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.

Written by Paul Brice

January 25th, 2010 at 8:33 pm

Scanning Active Directory for SMTP Addresses

without comments

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:

  1. Copy the below code into a file called ‘Get-ProxyAddress.ps1′
  2. Open the PowerShell shell and traverse to the directory that hosts the above file
  3. Run the script using this syntax, “./Get-ProxyAddress.ps1 address@domain.com”
  4. 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
  • Email
  • 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.

Written by Paul Brice

January 19th, 2010 at 11:54 pm

Searching for DL's with Exchange Expansion Servers

without comments

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:

  1. 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)
  2. 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.

Written by Paul Brice

June 8th, 2009 at 1:43 am

Getting Exchange 2003 Database Statistics

without comments

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.

Written by Paul Brice

May 26th, 2009 at 10:23 am

Quest Get-QADUser – All User Attributes

without comments

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.

Written by Paul Brice

April 28th, 2009 at 4:52 pm

Quest AD Management Shell – Get-QADGroup

without comments

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.ADManagement

Getting 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.

Written by Paul Brice

April 21st, 2009 at 10:45 am

Quest AD Management Shell – Getting Started

with one comment

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.ADManagement

Once 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.

Written by Paul Brice

April 20th, 2009 at 7:49 pm

Posted in PowerShell

Tagged with , , ,