title: Find user and AD group relation via nested AD groups
body: <p>Basically, in our environment, we have a ton of security groups. Security groups that are nested within other groups etc. So it is a real PITA to find out why a setting is applying to a user, because of one of the nested groups they may or may not be a part of</p>
  
  <p>For e.g. If you add a user to group X, they suddenly have a published application in Citrix. Citrix is configured for security group Y. Attempting to find the link between X and Y is very time consuming but can be automated.</p>
  
  <p>I want to create a script where, you enter a user and the end security group (group Y from above), and the script outputs the intermediary groups that connects the user to the final group. If this makes sense?</p>
  
  <p>Something like this:</p>
  
  <pre><code>function get-grouprelationship($username, $knownsecuritygroup)
  {
      $getallgroups = get-adgroupmember $knownsecuritygroup | where-object {$_.ObjectClass -eq "Group" | select-object SamAccountName | foreach-object {get-adgroupmember $_.SamAccountName}
  }
  </code></pre>
  
  <p>(The above variable takes your group, and loops through all members of that group, printing their members)</p>
  
  <pre><code>$usergroups = (get-aduser -identity $username -Properties memberof | select-object memberof).memberof
  </code></pre>
  
  <p>(The above gets all groups that a user is in)</p>
  
  <pre><code>$usergroups1 = $usergroups.split(",")
  $usergroups2 = $usergroups1[0]
  $usergroups3 = $usergroups2.substring(3)
  </code></pre>
  
  <p>(the above formats the text nicely)</p>
  
  <pre><code>if ($usergroups3 -contains $groupname){write-host "$username is directly in $groupname}
  </code></pre>
  
  <p>From here, I am quite stuck as I basically need to nest multiple for loops, depending on how many groups are in each group. Then do a condition check that </p>
  
  <pre><code>if ($groupname -eq $currentgroup){write-host "connected by $groupname and $currentgroup}
  </code></pre>
  
  <p>I'm also stuck with the <code>$getallgroups</code> variable, because it only checks 1 level down. It would then need another <code>foreach</code> loop inside that, which would need another one inside that etc.</p>
  
  <p>Having no prior coding experience, I am really struggling to get my head around an easy way to achieve my goal.</p>
  
  <p>EDIT:</p>
  
  <p>I found this script here - <a href="http://practical-admin.com/blog/?p=1380" rel="nofollow noreferrer" title="here">script</a>. Below basically works, except it is way to verbose:</p>
  
  <pre><code>import-module activedirectory
  $username = read-host "What's their username?"
  Function RecurseUsersInGroup {
      Param ([string]$object = "", [int]$level = 0)
      $indent = "-" * $level
  
      $x = Get-ADObject -Identity $object -Properties SamAccountName
  
      if ($x.ObjectClass -eq "group") {
          Write-Host "# $($x.SamAccountName)"
  
          $y = Get-ADGroup -Identity $object -Properties Members
  
          $y.Members | %{
              $o = Get-ADObject -Identity $_ -Properties SamAccountName
  
              if ($o.ObjectClass -eq "user" -and $o.SamAccountName -eq $username) {
                  Write-Host "-&gt; $($o.SamAccountName)"
              } elseif ($o.ObjectClass -eq "group") {
                  RecurseUsersInGroup $o.DistinguishedName ($level + 1)
              }
          }
      } else {
          Write-Host "$($object) is not a group, it is a $($x.ObjectClass)"
      }
  }
  $thegroup = read-host "What's the Group?"
  RecurseUsersInGroup (get-adgroup $thegroup).DistinguishedName
  </code></pre>
  
  <p>That works fine, but appears to output every security group, oppose to the connecting ones. Certainly a step in the right direction though! If I find the source I will post the credit as well. </p>