Sunday, June 9, 2013

Chain of Command

This post isn't specifically InfoSec in nature, but it is definitely related. When doing investigations or verifying authorization for specific requests, I often have the need to find a user's chain of command. In most organizations, certain requests require the manager's approval, while other requests may require director or VP approval. Looking this up manually can take a lot of clicky-clicky that I'm not a huge fan of.

To make this process easier, I wrote a little function that searches Active Directory for a specified user and, using the Manager property of the user object, loops through to return each manager's manager until reaching the Chief Executive Officer.


This function requires the Active Directory module but the code below doesn't call it directly. If you are running PowerShell 3.0, the module will be imported automatically when the functon is called (as long as the module is installed). In my case, I simply put it in my PowerShell profile which already explicitly imports the AD module. The function returns ADUser objects for use in the pipeline or, if you prefer, use the -format option to display only the most commonly needed properties (ID, Name, Title, Office, Email Address, and Phone Number) in a table.

I've been using this function for a few months and find it quite useful. I just cleaned it up a bit and added support for Get-Help so hopefully you'll get as much out of it as I do. Just change the $CEOTitle variable to suit your environment and search away.

                                                                 
function Get-ChainOfCommand
{
    <#
        .SYNOPSIS
        Queries AD for the chain of command for a given User ID or Display Name.

        .PARAMETER samaccountname
        The UserID (logon) or the Display Name (usually the full name of the user) is used
        here.

        .PARAMETER format
        When set, this optional flag will cause a limited set of the output to be displayed 
        on screen in a user-friendly format. Without it, the function outputs the objects for
        use in a pipeline.

        .EXAMPLE
        Get-ChainOfCommand jbloke
        This will return the chain of command for the person with the UserID "jbloke"

        .EXAMPLE
        Get-ChainOfCommand "John Bloke"
        This will return the chain of command for the person with the Display Name "John Bloke"

        .EXAMPLE
        Get-ChainOfCommand jbloke -format
        This will return the chain of command for the person with the UserID "jbloke", displaying a user-friendly output

        .EXAMPLE
        Get-ChainOfCommand jbloke | ConvertTo-HTML | out-file jbloke_chain.html
        This sends jbloke's chain of command through the pipeline to convert the results to HTML then save the file (If you're into that sort of thing).

        .NOTES
        Created by Tony Guthrie = June 2013

        .LINK
        http://www.gruntingfrog.com
        http://www.defensivepowershell.com
    #>

    [cmdletbinding()]


    Param(
        [Parameter(mandatory=$True, HelpMessage="Enter the employee's UserID or Display Name.")]
        [string]$samaccountname,

        [switch]$format
        )

    #Start#

    #Set the title to use as the highest up the chain to go.
    $CEOTitle = "Chief Executive Officer"

    #get user object by name or ID - - the -properties option lists additional properties beyond the default to retrieve from AD
    $users = $samaccountname | foreach{get-aduser -filter {(displayname -eq $_) -or (samaccountname -eq $_)} -properties manager, displayname, title, office, mail, telephoneNumber}
        

    if($users -ne $null){

        foreach($user in $users){
           
            if($user.manager){
                #$distname will hold the distinguished name of the user's manager
                $distName = $user.manager
                 $chainArray = @($user)
            
                #Cycle through chain until we reach the CEO
                while($mgrtitle -notlike $CEOTitle){
                    #get user object for the manager in $distname - the -properties option lists additional properties beyond the default
                    #to retrieve from AD
                    $mgrobject = get-aduser -filter {(distinguishedname -eq $distName)} -properties manager, displayname, title, office, mail, telephoneNumber
         
                    #add the manager's ad object to an array so we can output all the chain of command in one nice table.  
                    $chainArray = $chainArray + $mgrobject
        
                    #set the $distname to the next person up the chain for the next run through the loop
                    $distname = $mgrobject.manager
            
                    #set the title to the current title for testing the condition for the next loop
                    $mgrtitle = $mgrobject.title
                                 
                }#End while($mgrtitle...)
            
            }else{
                $chainArray = @($user)
              
            } #End if($user.manager)

            #Return the Array of objects.
            #If the $format switch was used on the command line, display only the most common items in
            #user-friendly table.
         
            if($format){
                $chainArray | format-table -hidetableheaders -autosize samAccountName, DisplayName, Title, Office, mail, TelephoneNumber
            }else{
                $chainArray
            } #End if($format)
        } #End Foreach($user in $users)
    
    }else{ # else if($users -ne $null)
        write-output "No matching users found for $samaccountname."
    } #End if($users -ne $null)

} #End function Get-ChainOfCommand

2 comments:

  1. Your one rule should be "Don't be a dick."
    Wait. Did I just violate rule one?

    ReplyDelete
  2. Nah. That's Wil Wheaton's rule. Mine's just slightly different. :P

    ReplyDelete

One rule: Don't be a jerk.

You can correct me or other commenters all you want, just be cool about it. Of course, I mean "cool" in the nerdiest way possible.