Getting effective user Permissions for many directories - powershell

Usually $Plist would be an array but for example we take just one directory.
My problem is I can't use the $ids var. Somehow I cant read out the data and can't bypass it to:
Get-ADGroup -Identity $id -Properties member | Select-Object -ExpandProperty member
I need the usernames per directory with their group names.
Like : Path GroupName UserList
Can someone help? Maybe tweak my code or make something similar :)
$plist = "\\Server\Share"
$FList = foreach($dir in $Plist)
{
Resolve-Path -Path $dir
Get-Acl -Path $dir -Filter Access | Select-Object -ExpandProperty Access | Where-Object {$_.IdentityReference -like "Domain\*"} | Select-Object IdentityReference
Get-Item $dir | select FullName
}
$Flist | ft FullName, IdentityReference
$identity = $Flist.IdentityReference | out-string
$ids = foreach($ident in $identity)
{
$ident = $ident.Replace("Domain\","")
$ident
}
foreach($id in $ids)
{
$id
Get-ADGroup -Identity $id -Properties member | Select-Object -ExpandProperty member
}

Do not use ft (Format-Table) or Out-String on values that you may ned later in your script.
$ids = foreach($ident in $Flist.IdentityReference){
"$ident".Replace('Domain\','')
}
You could also strip the domain prefix from all the user names in one go with the -replace operator:
foreach($id in $flist.IdentityReference.Value -replace 'Domain\\')
{
Get-ADGroup $id -Properties member | Select-Object -ExpandProperty member
}

The Final Script is this, for people who might need something similar. So you can read out the effective permissions and show the group member of permission granted groups.
$ErrorActionPreference = "SilentlyContinue"
$Path = "\\Server\Share\Logs\"
$Log = $Path + "Effective_Permissions" + ".log"
$PPath = Read-Host "Enter Path to scan"
$plist = Get-Childitem -Path $PPath -Recurse | ?{ $_.PSIsContainer } | Select-Object FullName
foreach($Dir in $PList)
{
$Dir = $Dir -replace "#{FullName=", "" -replace "}"
Resolve-Path -Path $Dir
Write-Output "`n" | Out-File $log -append
Write-Output "#######################################################################" | Out-File $Log -append
Get-Item $Dir | select FullName | Out-File $Log -append
$AclList = Get-Acl -Path $Dir -Filter Access | Select-Object -ExpandProperty Access | Where-Object {$_.IdentityReference -like "Domain\*"} | Select-Object IdentityReference
Get-Acl -Path $dir -Filter Access | Select-Object -ExpandProperty Access | Where-Object {$_.IdentityReference -like "Domain\*"} | Out-File $Log -append
foreach($Id in $AclList.IdentityReference.Value -replace 'Domain\\')
{
$ADGroup = Get-ADGroup $Id -Properties member | Select-Object -ExpandProperty member
Write-Output "`n" | Out-File $Log -append
Write-Output "Member of $Id `n
---------------------------------" | Out-File $Log -append
foreach ($Object in $ADGroup)
{
$Group = Get-ADUser -filter * -SearchBase "$Object"
if($Group -ne $null)
{
$GrName = $Group.Name
Write-Output "$GrName" | Out-File $Log -append
}
}
}
Clear-Variable Object, Group, ADGroup, ACLList, GRName, Id
}

Related

Export groups and username of a user in Active Directory

I am trying to find out the Active Directory groups all our active users are in and want to export it to a CSV file. However the following command presents garbage in the related CSV file.
This is my code failing:
Import-Module ActiveDirectory
Get-ADUser -SearchBase "CN=Users,DC=Mycompany,DC=de" -Filter * | where { $_.enabled -eq "true" } | foreach-object {
write-host "User:" $_.Name
Get-ADPrincipalGroupMembership $_.SamAccountName | foreach-object {
write-host "Member of:" $_.name | export-csv "C:\scripts\output\ad-user-with-group-memberhip.csv" -NoTypeInformation -Encoding UTF8
}
}
Any idea what am I doing wrong here?
Write-Host only writes text to the console window. It doesn't output anything useful to pipe through to Export-Csv.
Also, unless you add switch -Append, you should set the Export-Csv cmdlet as last line in the code, otherwise you will overwrite it in every iteration.
Try
with Select-Object
Import-Module ActiveDirectory
Get-ADUser -SearchBase "CN=Users,DC=Mycompany,DC=de" -Filter "Enabled -eq $true" |
Select-Object Name, #{Name = 'Groups'; Expression = {($_ | Get-ADPrincipalGroupMembership).Name -join '; '}} |
Export-Csv -Path "C:\scripts\output\ad-user-with-group-memberhip.csv" -NoTypeInformation -Encoding UTF8
or with ForEach-Object
Import-Module ActiveDirectory
$result = Get-ADUser -SearchBase "CN=Users,DC=Mycompany,DC=de" -Filter "Enabled -eq $true" |
ForEach-Object {
[PsCustomObject]#{
Name = $_.Name
Groups = ($_ | Get-ADPrincipalGroupMembership).Name -join '; '
}
}
$result | Export-Csv -Path "C:\scripts\output\ad-user-with-group-memberhip.csv" -NoTypeInformation -Encoding UTF8

powershell active directory excel report

I have those two scripts
$Path = 'C:\Users\akouyoumjian\Desktop\Report4.csv'
Get-ADUser -Filter {enabled -eq $true} -Properties LastLogonTimeStamp |
Select-Object Name,#{Name="Stamp"; Expression={[DateTime]::FromFileTime($_.lastLogonTimestamp).ToString('yyyy-MM-dd_hh:mm:ss')}} | Export-Csv -Path $Path –notypeinformation
and this one:
Get-ADComputer -Filter {(OperatingSystem -like "windows 7") -and (Enabled -eq "True")} -Properties OperatingSystem | Sort Name | select -Unique OperatingSystem
I would like to merge those into one file
Thanks
would this answer found here work: https://stackoverflow.com/a/27893253/10542366
This will append all the files together reading them one at a time:
get-childItem "YOUR_DIRECTORY\*.txt"
| foreach {[System.IO.File]::AppendAllText
("YOUR_DESTINATION_FILE", [System.IO.File]::ReadAllText($_.FullName))}
This one will place a new line at the end of each file entry if you need it:
get-childItem "YOUR_DIRECTORY\*.txt" | foreach
{[System.IO.File]::AppendAllText("YOUR_DESTINATION_FILE",
[System.IO.File]::ReadAllText($_.FullName) + [System.Environment]::NewLine)}
Skipping the first line:
$getFirstLine = $true
get-childItem "YOUR_DIRECTORY\*.txt" | foreach {
$filePath = $_
$lines = $lines = Get-Content $filePath
$linesToWrite = switch($getFirstLine) {
$true {$lines}
$false {$lines | Select -Skip 1}
}
$getFirstLine = $false
Add-Content "YOUR_DESTINATION_FILE" $linesToWrite
}

PowerShell Get-ACL with SamAccountName values

I'm trying to collect folder permissions to a csv file with Powershell. My problem is that I'd need the results to contain both the SamAccountName and FileSystemRights.
I tried two different method. The first I came up with was a simple approach that gave me IdentityReference and FileSystemRights, but I couldn't find any working method that can get SamAccountName from IdentityReference.
The second one I found on the internet was much more sophisticated. It collects all the accounts that has access to the folder, but it doesn't show FileSystemRights and I couldn't figure out how to change it to do so.
My own solution
(Get-Acl "FolderPath").Access | Select-Object IdentityReference, FileSystemRights
The solution I found
Get-Acl $UncPath | Select-Object -ExpandProperty Access | Where-Object { (-not $_.IsInherited) -and ('NT AUTHORITY\SYSTEM','BUILTIN\Administrators','CREATOR OWNER' -notcontains $_.IdentityReference) } | Select-Object -ExpandProperty IdentityReference | ForEach-Object { $_.Translate('System.Security.Principal.SecurityIdentifier').Value } | Get-ADGroup -ErrorAction SilentlyContinue | get-adgroupmember | select-object SamAccountName | Format-Table | Out-String
Is there any working method that can get me a result where I can see SamAccountName and FileSystemRights?
Thank you in advance.
$UncPath = 'E:\temp\test'
$all = Get-Acl $UncPath |
Select -ExpandProperty Access |
Where-Object { (-not $_.IsInherited) -and ('NT AUTHORITY\SYSTEM','BUILTIN\Administrators','CREATOR OWNER' -notcontains $_.IdentityReference) } |
Select-Object #{ Name = 'Identity'; Expression = { $_.IdentityReference -replace "\w+\\(.+)", '$1' } }, FileSystemRights
# Here you can get Users ACL
$distinct_users = $all |
Select-Object Identity, #{ Name = 'sAMAccountName'; Expression = { (Get-ADUser -Identity $_.Identity -ErrorAction SilentlyContinue).sAMAccountName }}, FileSystemRights |
Where-Object sAMAccountName -ne $null
# Here we will expand group acls
$groups = $all |
Select-Object Identity, #{ Name = 'sAMAccountName'; Expression = { (Get-ADGroup -Identity $_.Identity -ErrorAction SilentlyContinue).sAMAccountName }}, FileSystemRights |
Where-Object sAMAccountName -ne $null
# now we will get groups membership
$group_users = #()
Foreach($group in $groups){
Get-ADGroupMember -Identity $group.Identity | ForEach-Object { $group_users += [PSCustomObject]#{
'Identity' = $group.Identity
'sAMAccountName' = $_.sAMAccountName
'FileSystemRights' = $group.FileSystemRights
} }
}
$everyone = $distinct_users + $group_users
$everyone | Export-Csv -Path D:\example.csv
Check $everyone variable it will contain 3 columns: Identity as it was in the ACL, sAMAccountName and FileSystem Rights.

Get-Acl list only Users

I need a list of all directories (recursive) which have user-permissions registered (not user-groups).
Something like:
Get-ChildItem -Recurse c:\scripte | Get-Acl |
Where-Object -FilterScript {$_.objectclass -eq 'user'}
I think there must be some Get-ADUser stuff?
Something like this should do, assuming that you have PowerShell v3 or newer:
Get-ChildItem c:\scripte -Recurse -Directory | Where-Object {
(Get-Acl $_.FullName).Access.IdentityReference -match "^$env:USERDOMAIN\\" -replace '^.*\\' |
ForEach-Object { Get-ADUser -Filter "SamAccountName -eq $_" }
}
If you're stuck with PowerShell v2 the statement gets a little more elaborate:
Get-ChildItem c:\scripte -Recurse | Where-Object {
$_.PSIsContainer -and
(Get-Acl $_.FullName | Select-Object -Expand Access |
Select-Object -Expand IdentityReference) -match "^$env:USERDOMAIN\\" -replace '^.*\\' |
ForEach-Object { Get-ADUser -Filter "SamAccountName -eq $_" }
}
here ya go
{
param(
[parameter(mandatory=$true)]$Path
)
$IDs = (get-acl $Path).Access | Select IdentityReference,FileSystemRights
foreach ($ID in $IDs)
{
$thisUser = ($ID.IdentityReference).ToString()
$Rights = ($ID.FileSystemRights).ToString()
$User = $thisUser.split("\")[1]
$Object = Get-ADobject -LDAPFilter "(samAccountName=$user)" | Select ObjectClass
[pscustomObject]#{
Type = $Object.ObjectClass
samAccountName = $User
Rights = $Rights
}
}
}

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 Administrator#my-domain.dk
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"
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