Search code examples
powershellaclactive-directory-group

Get group member names from Get-Acl and Append to CSV


I need to extract all the members of a group and then format that into Names, so I only get the Full Names like "Don Joe" is member of my-domain\UNCShareDrive

I need that to appear in my CSV after I have exported the ACL lists.

As an example:

Path                                                                 FileSystemRights AccessControlType IdentityReference          
----                                                                 ---------------- ----------------- -----------------          
Microsoft.PowerShell.Core\FileSystem::\\fileshare\management\DK           FullControl             Allow MY-DOMAIN\Drev Management
Microsoft.PowerShell.Core\FileSystem::\\fileshare\management\           FullControl             Allow BUILTIN\Administratorer    
Microsoft.PowerShell.Core\FileSystem::\\fileshare\management\     FullControl             Allow MY-DOMAIN\Drev Management
Microsoft.PowerShell.Core\FileSystem::\\fileshare\management\     FullControl             Allow BUILTIN\Administratorer    




**These persons has access to the drive:**

**Finding group:  MY-DOMAIN\Administrators** 

Name                   SamAccountName Mail                     
----                   -------------- ----                     
Administrator          Administrator  [email protected]

This is what I have so far done in Powershell:

$Searching = Get-ADGroup -Filter * -SearchBase "DC=my-domain,DC=local"

$mypath = "U:\mytest.csv"

if((Test-Path -Path "U:\mytest.csv" -pathtype Container) -eq $True){
  Write-Host -ForegroundColor red "We found a file: $mypath --> REMOVING!`r`n"
  Remove-Item $mypath -Force
}

$ShareName = "\\\sharename\D$"

$shares = Get-Childitem -path $ShareName |
          Where-Object {$_.PSIsContainer} |
          Get-ACL |
          Select-Object Path -ExpandProperty Access |
          Select Path, FileSystemRights,AccessControlType,IdentityReference |
          export-csv $mypath -Delimiter ';' -NoTypeInformation -Encoding UTF8
$foldertotal = 0
Add-Content $mypath "" 
Add-Content $mypath "" 
Add-Content $mypath "Disse personer har adgang til share navnet"
Add-Content $mypath "" 
Add-Content $mypath ""

$myLoop = ''
foreach ($testLoop in $myLoop) {
  $Group = Get-ADGroup -Filter * -SearchBase "DC=my-domain,DC=local" -Properties IdentityReference |
           Select-Object Name # Need only groups in $Shares - who are displayed
  $myLoop += Write-Host -ForegroundColor Yellow "Finding group: $($Group.name).....`n"
  $myLoop += ForEach ($Group in $share) {
               Get-ADGroupMember -identity $($Group.name) -recursive |
                 Get-ADUser -Properties Name,SamAccountName,Mail |
                 Select-Object Name,SamAccountName,Mail
             } 
  $testLoop | Out-File -filePath $mypath -append -encoding utf8
}

Write-Host -ForegroundColor Cyan "$($Group.name) is now exported to: $mypath`n"

I have also a hard time to filter out only the share path:

$shares.Replace('Microsoft.PowerShell.Core\FileSystem::', ' ') |
  Out-File -filePath $mypath -append -encoding utf8

How come that this thing Works when I use User Input and not just automatically loop through it without the console prompt:

$Searching = Get-ADGroup -Filter * -SearchBase "DC=MY-DOMAIN,DC=local"

$mypath = "U:\mytest.csv"
$networkPath = "\\ShareName\D$"
$acl = Get-acl -path $networkPath

if((Test-Path -Path "U:\mytest.csv" -pathtype Container) -eq $True){
  Write-Host -ForegroundColor red "We found a file: $mypath --> REMOVING!`r`n"
  Remove-Item $mypath -Force
}

Write-Host -ForegroundColor Yellow "Eksempel på share: "`r`n\\ShareName\D$`r`n\\ShareTwo\\E$`r`n\\ShareName\management`r`n""
$ShareName = Read-host "Hvilket sharenavn vil du finde Access Control List fra?"
if($ShareName -eq "1"){
  $Sharename = "\\ShareName\D$"
}
if($ShareName -eq "2"){
  $Sharename = "\\ShareTwo\\E$"
}
if($ShareName -eq "3"){
  $Sharename = "\\ShareName\management"
}

Get-Childitem -path $ShareName |
  Where-Object {$_.PSIsContainer} |
  Get-ACL |
  Select-Object Path -ExpandProperty Access |
  Select Path, FileSystemRights,AccessControlType,IdentityReference |
  FT -AutoSize |
  Out-File -Encoding utf8 $mypath
Add-Content $mypath "" 
Add-Content $mypath "" 
Add-Content $mypath "Disse personer har adgang til share navnet"
Add-Content $mypath "" 

$users = get-aduser -Filter {Name -Like "*"} -Searchbase "dc=MY-DOMAIN,dc=local" -Properties MemberOf |
         Where-Object { $_.Enabled -eq 'True' }

Write-Host -ForegroundColor red "Example:  Drev Management`r`n"
$myGroups = Read-Host "Hvilken Gruppe vil du bruge?"
if($myGroups -eq "1"){
  $myGroups = " Drev Management"
}
$Groups = Get-ADGroup -filter {Name -like $myGroups} | Select-Object Name 

Add-Content $mypath "Finding group: $($group.name)"
Write-Host -ForegroundColor Yellow "Finding group: $($Group.name).....`n"
Add-Content -Path $mypath $result

ForEach ($Group in $Groups) {
  Get-ADGroupMember -identity $($Group.name) -recursive |
    Get-ADUser -Properties Name,SamAccountName,Mail |
    Select-Object Name,SamAccountName,Mail |
    FT -AutoSize |
    Out-File -Append -encoding utf8 $mypath
}
Write-Host -ForegroundColor Cyan "$($Group.name) is now exported to: $mypath`n"

Solution

  • Your second code sample works, because it doesn't make the same mistakes as the first one.

    $myLoop = ''
    foreach ($testLoop in $myLoop) {
      $Group = Get-ADGroup -Filter * ...
      $myLoop += Write-Host ...
      $myLoop += ForEach ($Group in $share) {
                   Get-ADGroupMember ...
                 } 
      $testLoop | Out-File -filePath $mypath -append -encoding utf8
    }
    
    • You make $myLoop an empty string, then iterate over each element of $myLoop (one empty string), so you get a single loop cycle, no matter what you append to $myLoop inside the loop.
    • Instead of the group members you write the content of $testLoop (an empty string) to the output file.
    • You read AD groups into the variable $Group, and then overwrite its content when you use $Group as the loop variable in foreach ($Group in $share).
    • $share is emtpy, because it's never initialized anywhere. Even $shares is empty, because when you write the ACL information to the CSV, no output is left that could be assigned to the variable.

    And as a side-note: you can't append Write-Host output to anything, because the cmdlet writes to the host process (i.e. the console), not a stream that could be captured or redirected.

    You need to capture the ACL information in $shares before writing it to a file:

    $shares = Get-Childitem -Path $ShareName |
              Where-Object {$_.PSIsContainer} |
              Get-ACL |
              Select-Object Path -ExpandProperty Access |
              Select Path, FileSystemRights,AccessControlType,IdentityReference
    $shares | Export-Csv $mypath -Delimiter ';' -NoTypeInformation -Encoding UTF8
    

    Then you can determine the members of the groups having access to shares like this:

    $shares | Select-Object -Expand IdentityReference |
      Select-Object -Expand Value |
      ForEach-Object {
        $name = $_ -replace '^DOMAIN\\'  # <-- replace with actual domain name
        Get-ADObject -Filter { Name -eq $name }
      } |
      Where-Object { $_.ObjectClass -eq 'group' } |
      Get-ADGroupMember |
      Get-ADUser -Properties * |
      Select-Object Name, SamAccountName, Mail |
      Out-File $mypath -Append -Encoding UTF8
    

    Note that this will not resolve nested groups, and also won't distinguish between shares.

    If you want to store both the group name and its members you need to add a loop to the pipeline:

    $shares | Select-Object -Expand IdentityReference |
      Select-Object -Expand Value |
      ForEach-Object {
        $name = $_ -replace '^DOMAIN\\'  # <-- replace with actual domain name
        Get-ADObject -Filter { Name -eq $name }
      } |
      Where-Object { $_.ObjectClass -eq 'group' } |
      ForEach-Object {
        $_
        Get-ADGroupMember -Identity $_ |
          Get-ADUser -Properties * |
          Select-Object Name, SamAccountName, Mail
      } |
      Out-File $mypath -Append -Encoding UTF8