{"id":917,"date":"2014-12-31T15:31:33","date_gmt":"2014-12-31T20:31:33","guid":{"rendered":"https:\/\/www.softwareab.net\/wordpress\/?p=917"},"modified":"2014-12-31T15:38:31","modified_gmt":"2014-12-31T20:38:31","slug":"powershell-get-domain-users-group-memberships","status":"publish","type":"post","link":"https:\/\/www.softwareab.net\/wordpress\/powershell-get-domain-users-group-memberships\/","title":{"rendered":"PowerShell: Get *All* Domain User&#8217;s Group Memberships"},"content":{"rendered":"<p>Hi All &#8211; Need to get all of a user&#8217;s group memberships &#8211; both domain and local? Do you need <strong>indirect<\/strong> memberships also? Then read on!<\/p>\n<p><!--more--><\/p>\n<p>I&#8217;m busy installing Lync Server 2013 and came to a point where I needed to add my &#8220;Lync Admin&#8221; user to a local user group on the Lync dedicated front-end.<\/p>\n<p>But &#8211; I was pretty sure that my &#8220;Lync Admin&#8221; user already had this membership, via some indirect group. However, I was too lazy to want to track this down; I want the system to tell me *all* of my user&#8217;s group memberships. This includes both domain and local memberships. Sounds simple, but it was more complex than I thought.<\/p>\n<p>I turned to PowerShell for the answer. Here&#8217;s what I do:<\/p>\n<ol>\n<ul>Get the domain group memberships for my user. This is easy enough; <code>$adGroups = (Get-AdUser $userName -Properties MemberOf).MemberOf<\/code><\/ul>\n<ul>Found and modified a recursive function that would go check indirect group memberships, passing in the groups I got from above as a starter set.<\/ul>\n<ul>Then things got tricky; there&#8217;s no &#8220;recursive&#8221; <em>local<\/em> group membership that I could find. So I resorted to an ugly set of nested loops to check for all group memberships.<\/ul>\n<\/ol>\n<p>It&#8217;s a simple script although not particularly fast. Hope it&#8217;s useful to all!<\/p>\n<pre style=\"font-size:smaller;\">\r\n# list-user-groups.ps1, ABr, 20141231\r\n# list all group memberships - domain and local - for the passed account.\r\n# assumes current domain (just use the account name, no domain).\r\n# example use: list-user-groups.ps myAccount\r\nparam(\r\n  [string]$userName\r\n)\r\n\r\n# we require AD module\r\nimport-module activedirectory\r\n\r\n# this recursive function takes in a list of groups and recursively\r\n# gets all indirect group memberships from the current domain.\r\nFunction Get-ADGroupsRecursive{\r\n  Param([String[]]$Groups)\r\n  Begin{\r\n    $Results = @()\r\n  }\r\n  Process{\r\n    ForEach($Group in $Groups){\r\n      $Results+=$Group\r\n      ForEach($Object in (Get-ADGroupMember $Group|?{$_.objectClass -eq \"Group\"})){\r\n        $Results += Get-ADGroupsRecursive $Object\r\n      }\r\n    }\r\n  }\r\n  End{\r\n   $Results | Select -Unique\r\n  }\r\n}\r\n\r\n# we'll assume we're running on the current system\r\n$Computer = [ADSI]\"WinNT:\/\/$env:COMPUTERNAME\"\r\n\r\n# all groups is the result (starts empty)\r\n$allGroups = @()\r\n\r\n# get the Active Directory user object, including group memberships\r\n$user = Get-AdUser $userName -Properties MemberOf\r\n\r\n# now expand the current list\r\n$userAdGroups = $user.MemberOf\r\n$userAdGroups += $userAdGroups | %{Get-ADGroupsRecursive $_}\r\n\r\n# remove any duplicates\r\n$userAdGroups = $userAdGroups | Select -Unique\r\n\r\n# the AD groups come back with FQDN. this is nice, but the PsBase calls\r\n# below just return the group name. to make it easy for me, I'm extracting\r\n# the group name here from the FQDN.\r\nForEach ($userAdGroup in $userAdGroups) {\r\n  $found = $userAdGroup -Match 'CN=([^,]+).*'\r\n  If ($found) { $allGroups += $matches[1] }\r\n}\r\n\r\n# now get all local groups\r\n$localGroups = $Computer.psbase.Children | Where {$_.psbase.schemaClassName -eq \"group\"}\r\n\r\n# this gets ugly. we need to iterate over all local groups repeatedly.\r\n$foundGroup = $TRUE\r\n$iterCount = 0\r\nwhile ($foundGroup) {\r\n  # keep track of how many times we've done this foolishness...\r\n  $iterCount += 1\r\n  Write-Debug \"Iteration $iterCount...\"\r\n\r\n  # reset our flag; we'll assume we don't find any more indirect memberships\r\n  $foundGroup = $FALSE\r\n  ForEach ($localGroup in $localGroups) {\r\n    # get the name of this local group\r\n    $localGroupName = $localGroup.GetType().InvokeMember(\"Name\", 'GetProperty', $Null, $localGroup, $Null)\r\n\r\n    # quick check to see if the local group is already in our result list\r\n    $foundLocalGroup = $allGroups -Contains $localGroupName\r\n    if ($foundLocalGroup) { Continue }\r\n\r\n    # it's not...we need to check this local group by looking at its members\r\n    Write-Debug \"  Checking group '$localGroupName'...\"\r\n    $localGroupMembers = @($localGroup.psbase.Invoke(\"Members\"))\r\n    ForEach ($localGroupMember In $localGroupMembers) {\r\n      # extract local group member info\r\n      $localGroupMemberClass = $localGroupMember.GetType().InvokeMember(\"Class\", 'GetProperty', $Null, $localGroupMember, $Null)\r\n      $localGroupMemberName = $localGroupMember.GetType().InvokeMember(\"Name\", 'GetProperty', $Null, $localGroupMember, $Null)\r\n\r\n      # should this local group be added? this will be the case if the local\r\n      # group member is one of our AD groups *or* if the user account is in\r\n      # the local group\r\n      $addLocalGroup = $False\r\n      $localGroupMemberIsGroup = ([string]::Compare($localGroupMemberClass, \"Group\", $True) -eq 0)\r\n      if (-Not $localGroupMemberIsGroup) {\r\n        # this local group member is a user...is it us??\r\n        if ([string]::Compare($localGroupMemberName, $userName, $True) -eq 0) {\r\n          # ah, our AD account is in this local group. let's add the local group\r\n          # to our list of groups.\r\n          $addLocalGroup = $True\r\n        }\r\n      } else {\r\n        Write-Debug \"    Checking subgroup '$localGroupMemberName'...\"\r\n\r\n        # the logic here is: is this sub-group in our list of discovered groups?\r\n        $foundLocalGroupMember = $allGroups -Contains $localGroupMemberName\r\n        if ($foundLocalGroupMember) {\r\n          # woohoo. we found an indirect membership.\r\n          $addLocalGroup = $True\r\n        }\r\n      }\r\n      if ($addLocalGroup) {\r\n        # add the local group to our list of all groups\r\n        Write-Debug \"      Added local group '$localGroupMemberName'...\"\r\n        $allGroups += $localGroupName\r\n\r\n        # set our flag to continue the controlling iteration...\r\n        $foundGroup = $True\r\n\r\n        # ...but we don't need to check this local group anymore.\r\n        Break\r\n      }\r\n    }\r\n  }\r\n\r\n  # so why the outer loop? consider this group membership chain:\r\n  #   domainUser = my account\r\n  #   domainGroup = a domain group with my account\r\n  # on the local computer, we have two groups:\r\n  #   localGroupA - contains localGroupB as a member\r\n  #   localGroupB - contains domainGroup as a member\r\n  # here's the logic:\r\n  #  1. My list of discovered groups starts only with \"domainGroup\".\r\n  #  2. I check localGroupA - it has only localGroupB as a member, which fails my test.\r\n  #     So, I ignore localGroupA.\r\n  #  3. I check localGroupB - aha! it has domainGroup as a member, and I'm a member\r\n  #     a member of domainGroup, so I add localGroupB to my list.\r\n  # the problem? because I check localGroupA *before* I get to localGroupB, I never\r\n  # discover that I have an indirect membership (via my domain group membership in\r\n  # localGroupB). the outer WHILE loop, in conjunction with my \"$foundGroup\" flag,\r\n  # solves this problem.\r\n}\r\n\r\n# print the list of all groups...sorry, no indication of whether they are\r\n# domain or local. maybe next script ;)\r\n$allGroups\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Hi All &#8211; Need to get all of a user&#8217;s group memberships &#8211; both domain and local? Do you need indirect memberships also? Then read on!<\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1,12],"tags":[21,22,18],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v22.2 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>PowerShell: Get *All* Domain User&#039;s Group Memberships - softwareab<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.softwareab.net\/wordpress\/powershell-get-domain-users-group-memberships\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"PowerShell: Get *All* Domain User&#039;s Group Memberships - softwareab\" \/>\n<meta property=\"og:description\" content=\"Hi All &#8211; Need to get all of a user&#8217;s group memberships &#8211; both domain and local? Do you need indirect memberships also? Then read on!\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.softwareab.net\/wordpress\/powershell-get-domain-users-group-memberships\/\" \/>\n<meta property=\"og:site_name\" content=\"softwareab\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/cloudraticsolutions\/\" \/>\n<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/cloudraticsolutions\/\" \/>\n<meta property=\"article:published_time\" content=\"2014-12-31T20:31:33+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2014-12-31T20:38:31+00:00\" \/>\n<meta name=\"author\" content=\"Andrew Bruce\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@realcloudratics\" \/>\n<meta name=\"twitter:site\" content=\"@realcloudratics\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Andrew Bruce\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"4 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.softwareab.net\/wordpress\/powershell-get-domain-users-group-memberships\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.softwareab.net\/wordpress\/powershell-get-domain-users-group-memberships\/\"},\"author\":{\"name\":\"Andrew Bruce\",\"@id\":\"https:\/\/www.softwareab.net\/wordpress\/#\/schema\/person\/1337443eaeb75104e0410b508e67f600\"},\"headline\":\"PowerShell: Get *All* Domain User&#8217;s Group Memberships\",\"datePublished\":\"2014-12-31T20:31:33+00:00\",\"dateModified\":\"2014-12-31T20:38:31+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.softwareab.net\/wordpress\/powershell-get-domain-users-group-memberships\/\"},\"wordCount\":213,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.softwareab.net\/wordpress\/#\/schema\/person\/1337443eaeb75104e0410b508e67f600\"},\"keywords\":[\"programming\",\"scripting\",\"sysadmin\"],\"articleSection\":[\"Teknocratica\",\"Windows Server\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.softwareab.net\/wordpress\/powershell-get-domain-users-group-memberships\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.softwareab.net\/wordpress\/powershell-get-domain-users-group-memberships\/\",\"url\":\"https:\/\/www.softwareab.net\/wordpress\/powershell-get-domain-users-group-memberships\/\",\"name\":\"PowerShell: Get *All* Domain User's Group Memberships - softwareab\",\"isPartOf\":{\"@id\":\"https:\/\/www.softwareab.net\/wordpress\/#website\"},\"datePublished\":\"2014-12-31T20:31:33+00:00\",\"dateModified\":\"2014-12-31T20:38:31+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/www.softwareab.net\/wordpress\/powershell-get-domain-users-group-memberships\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.softwareab.net\/wordpress\/powershell-get-domain-users-group-memberships\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.softwareab.net\/wordpress\/powershell-get-domain-users-group-memberships\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.softwareab.net\/wordpress\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"programming\",\"item\":\"https:\/\/www.softwareab.net\/wordpress\/tag\/programming\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"PowerShell: Get *All* Domain User&#8217;s Group Memberships\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.softwareab.net\/wordpress\/#website\",\"url\":\"https:\/\/www.softwareab.net\/wordpress\/\",\"name\":\"softwareab\",\"description\":\"Technocratica, Technopolitik, Technophobia\",\"publisher\":{\"@id\":\"https:\/\/www.softwareab.net\/wordpress\/#\/schema\/person\/1337443eaeb75104e0410b508e67f600\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.softwareab.net\/wordpress\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\/\/www.softwareab.net\/wordpress\/#\/schema\/person\/1337443eaeb75104e0410b508e67f600\",\"name\":\"Andrew Bruce\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.softwareab.net\/wordpress\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/www.softwareab.net\/wordpress\/wp-content\/uploads\/2024\/03\/andy-cartoon.jpg\",\"contentUrl\":\"https:\/\/www.softwareab.net\/wordpress\/wp-content\/uploads\/2024\/03\/andy-cartoon.jpg\",\"width\":400,\"height\":330,\"caption\":\"Andrew Bruce\"},\"logo\":{\"@id\":\"https:\/\/www.softwareab.net\/wordpress\/#\/schema\/person\/image\/\"},\"description\":\"Team-oriented systems mentor with deep knowledge of numerous software methodologies, technologies, languages, and operating systems. Excited about turning emerging technology into working production-ready systems. Focused on moving software teams to a higher level of world-class application development. Specialties:Software analysis and development...Product management through the entire lifecycle...Discrete product integration specialist!\",\"sameAs\":[\"http:\/\/cloudraticsolutions.net\/\",\"https:\/\/www.facebook.com\/cloudraticsolutions\/\",\"https:\/\/twitter.com\/realcloudratics\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"PowerShell: Get *All* Domain User's Group Memberships - softwareab","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.softwareab.net\/wordpress\/powershell-get-domain-users-group-memberships\/","og_locale":"en_US","og_type":"article","og_title":"PowerShell: Get *All* Domain User's Group Memberships - softwareab","og_description":"Hi All &#8211; Need to get all of a user&#8217;s group memberships &#8211; both domain and local? Do you need indirect memberships also? Then read on!","og_url":"https:\/\/www.softwareab.net\/wordpress\/powershell-get-domain-users-group-memberships\/","og_site_name":"softwareab","article_publisher":"https:\/\/www.facebook.com\/cloudraticsolutions\/","article_author":"https:\/\/www.facebook.com\/cloudraticsolutions\/","article_published_time":"2014-12-31T20:31:33+00:00","article_modified_time":"2014-12-31T20:38:31+00:00","author":"Andrew Bruce","twitter_card":"summary_large_image","twitter_creator":"@realcloudratics","twitter_site":"@realcloudratics","twitter_misc":{"Written by":"Andrew Bruce","Est. reading time":"4 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.softwareab.net\/wordpress\/powershell-get-domain-users-group-memberships\/#article","isPartOf":{"@id":"https:\/\/www.softwareab.net\/wordpress\/powershell-get-domain-users-group-memberships\/"},"author":{"name":"Andrew Bruce","@id":"https:\/\/www.softwareab.net\/wordpress\/#\/schema\/person\/1337443eaeb75104e0410b508e67f600"},"headline":"PowerShell: Get *All* Domain User&#8217;s Group Memberships","datePublished":"2014-12-31T20:31:33+00:00","dateModified":"2014-12-31T20:38:31+00:00","mainEntityOfPage":{"@id":"https:\/\/www.softwareab.net\/wordpress\/powershell-get-domain-users-group-memberships\/"},"wordCount":213,"commentCount":0,"publisher":{"@id":"https:\/\/www.softwareab.net\/wordpress\/#\/schema\/person\/1337443eaeb75104e0410b508e67f600"},"keywords":["programming","scripting","sysadmin"],"articleSection":["Teknocratica","Windows Server"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.softwareab.net\/wordpress\/powershell-get-domain-users-group-memberships\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.softwareab.net\/wordpress\/powershell-get-domain-users-group-memberships\/","url":"https:\/\/www.softwareab.net\/wordpress\/powershell-get-domain-users-group-memberships\/","name":"PowerShell: Get *All* Domain User's Group Memberships - softwareab","isPartOf":{"@id":"https:\/\/www.softwareab.net\/wordpress\/#website"},"datePublished":"2014-12-31T20:31:33+00:00","dateModified":"2014-12-31T20:38:31+00:00","breadcrumb":{"@id":"https:\/\/www.softwareab.net\/wordpress\/powershell-get-domain-users-group-memberships\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.softwareab.net\/wordpress\/powershell-get-domain-users-group-memberships\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.softwareab.net\/wordpress\/powershell-get-domain-users-group-memberships\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.softwareab.net\/wordpress\/"},{"@type":"ListItem","position":2,"name":"programming","item":"https:\/\/www.softwareab.net\/wordpress\/tag\/programming\/"},{"@type":"ListItem","position":3,"name":"PowerShell: Get *All* Domain User&#8217;s Group Memberships"}]},{"@type":"WebSite","@id":"https:\/\/www.softwareab.net\/wordpress\/#website","url":"https:\/\/www.softwareab.net\/wordpress\/","name":"softwareab","description":"Technocratica, Technopolitik, Technophobia","publisher":{"@id":"https:\/\/www.softwareab.net\/wordpress\/#\/schema\/person\/1337443eaeb75104e0410b508e67f600"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.softwareab.net\/wordpress\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/www.softwareab.net\/wordpress\/#\/schema\/person\/1337443eaeb75104e0410b508e67f600","name":"Andrew Bruce","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.softwareab.net\/wordpress\/#\/schema\/person\/image\/","url":"https:\/\/www.softwareab.net\/wordpress\/wp-content\/uploads\/2024\/03\/andy-cartoon.jpg","contentUrl":"https:\/\/www.softwareab.net\/wordpress\/wp-content\/uploads\/2024\/03\/andy-cartoon.jpg","width":400,"height":330,"caption":"Andrew Bruce"},"logo":{"@id":"https:\/\/www.softwareab.net\/wordpress\/#\/schema\/person\/image\/"},"description":"Team-oriented systems mentor with deep knowledge of numerous software methodologies, technologies, languages, and operating systems. Excited about turning emerging technology into working production-ready systems. Focused on moving software teams to a higher level of world-class application development. Specialties:Software analysis and development...Product management through the entire lifecycle...Discrete product integration specialist!","sameAs":["http:\/\/cloudraticsolutions.net\/","https:\/\/www.facebook.com\/cloudraticsolutions\/","https:\/\/twitter.com\/realcloudratics"]}]}},"_links":{"self":[{"href":"https:\/\/www.softwareab.net\/wordpress\/wp-json\/wp\/v2\/posts\/917"}],"collection":[{"href":"https:\/\/www.softwareab.net\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.softwareab.net\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.softwareab.net\/wordpress\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/www.softwareab.net\/wordpress\/wp-json\/wp\/v2\/comments?post=917"}],"version-history":[{"count":3,"href":"https:\/\/www.softwareab.net\/wordpress\/wp-json\/wp\/v2\/posts\/917\/revisions"}],"predecessor-version":[{"id":920,"href":"https:\/\/www.softwareab.net\/wordpress\/wp-json\/wp\/v2\/posts\/917\/revisions\/920"}],"wp:attachment":[{"href":"https:\/\/www.softwareab.net\/wordpress\/wp-json\/wp\/v2\/media?parent=917"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.softwareab.net\/wordpress\/wp-json\/wp\/v2\/categories?post=917"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.softwareab.net\/wordpress\/wp-json\/wp\/v2\/tags?post=917"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}