I need to collect the security permission for each folders in a share, the result returns me the SID but i need the username (or the group name), how i can do this?
$FolderPath = Get-ChildItem -Directory -Path "Y:\" -Recurse -Force
$Output = #()
ForEach ($Folder in $FolderPath) {
$Acl = Get-Acl -Path $Folder.FullName
ForEach ($Access in $Acl.Access) {
$Properties = [ordered]#{'Folder Name'=$Folder.FullName;'Group/User'=$Access.IdentityReference;'Permissions'=$Access.FileSystemRights;'Inherited'=$Access.IsInherited}
$Output += New-Object -TypeName PSObject -Property $Properties
}
}
$Output | Out-GridView
The Access property already maps to a code path that attempts to resolve the account identity from the SID, so if you're seeing SID strings instead of names, it might be an indication that the SID cannot be resolved by the machine.
You can still make an attempt to translate the individual SID value into an [NTAccount] object like this:
$Principal = try {
$Access.IdentityReference.Translate([System.Security.Principal.NTAccount])
}
catch {
# If the translation fails we fall back to SID
$Access.IdentityReference
}
Then use $Principal in place of $Access.IdentityReference in the property dictionary.
Related
I have to make a script who change users domain of my shared folder and add them in addition to the existing users rights.
1st :
I do a script in PowerShell to get all NTFS rights of my directories (It worked perfectly) :
$FolderPath = Get-ChildItem -Directory -LiteralPath "C:\MYPATH" -Recurse -Force
$Report = #()
Foreach ($Folder in $FolderPath) {
$Acl = Get-Acl -Path $Folder.FullName
foreach ($Access in $acl.Access)
{
$Properties = [ordered]#{'FolderName'=$Folder.FullName;'Users'=$Access.IdentityReference;'Rights'=$Access.FileSystemRights;'Inherit'=$Access.IsInherited;}
$Report += New-Object -TypeName PSObject -Property $Properties
}
}
$Report | Export-Csv -Encoding UTF8 -LiteralPath "E:\MYPATH\FolderPermissions2.csv"
2nd : I modify my CSV to find and replace with my new domain.
There is a part of my CSV :
"E:\test migration\MYPATH\MYPATH à la tireuse plans","BUILTIN\Users","AppendData","True"
"E:\test migration\MYPATH\MYPATH","BUILTIN\Users","CreateFiles","True"
"E:\test migration\MYPATH","OLD_DOMAIN\user_name","FullControl","True"
"E:\test migration\MYPATH","OLD_DOMAIN\user_name","ReadAndExecute, Synchronize","True"
"E:\test migration\MYPATH","BUILTIN\Administrators","FullControl","True"
"E:\test migration\MYPATH","NT AUTHORITY\SYSTEM","FullControl","True"
"E:\test migration\MYPATH","OLD_DOMAIN\a_nbe","FullControl","True"
3rd : And I do another script to re-import all rights from my modified CSV and Set them to the same folder :
Import-Module NTFSSecurity
Import-Module ActiveDirectory
$CSV = Import-Csv -Delimiter "," -LiteralPath "E:\MYPATH\FolderPermissions2.csv"
$CSV | ForEach-Object {
$FolderName = $_.FolderName
$Users = $_.Users
$Rights = $_.Rights
$Inherit = $_.Inherit
Add-NTFSAccess -Path $FolderName -IdentityReference $Users -FileSystemRights $Rights
$acl = Get-Acl $FolderName
if ($Inherit = "True", $acl.SetAccessRuleProtection($false,$True)) {
} else {
$acl.SetAccessRuleProtection($false,$False)
}
}
The first part of this script worked perfectly, all of my folder get the "new users" with my new domain with exactly the same rights.
BUT the part where I define my "IsInherited" don't work, I get the path and not my boolean...
screenshot of the error
Anybody has an idea where I do a mistake, please ?
Thank you !
#Cred= Get-Credential
$FolderPath = dir -Directory -Path "\\abc\dc\da" -Recurse -Force | where {$_.psiscontainer -eq $true}
$Report = #()
Foreach ($Folder in $FolderPath) {
$Acl = Get-Acl -Path $Folder.FullName
# $Name= Get-ChildItem $Folder -Recurse | where {!$_.PSIsContainer} |select-object fullname
foreach ($Access in $acl.Access)
{
$Properties = [ordered]#{'FolderName'=$Folder.FullName;'AD
Group or User'=$Access.IdentityReference;'Permissions'=$Access.FileSystemRights;'Inherited'=$Access.IsInherited}
$Report += New-Object -TypeName PSObject -Property $Properties
}
}
$Report | Export-Csv -path "C:\Output\Test_16-06-2021.csv"
In the above script, I'm able to get all my folder structure with permission but I want to do with a custom parameter like if I want to only folder level 3 it should get me the output as below
\\abc\a\b\c
\\abc\a\c\d
not like
\\abc\a\b\c\d\text.txt
\\abc\a\c\d\e\f\g\demo.pdf
If you're using PowerShell 5.0, you can use the -Recurse and -Depth parameters combined:
[string]$rootFolder = Read-Host -Prompt "Enter root folder path (no trailing '\')"
[int]$recursionDepth = Read-Host -Prompt "Enter recursion depth"
[string]$outputCsv = Read-Host -Prompt "Enter output .csv file (full path)"
$folders = Get-ChildItem -Directory -Path $rootFolder -Recurse -Depth $recursionDepth -Force | Where-Object { $_.PSIsContainer -eq $true }
[array]$report = #()
foreach ($folder in $folders) {
$acl = Get-Acl -Path $folder.FullName
foreach ($access in $acl.access) {
[hashtable]$properties = [ordered]#{
'FolderName' = $folder.FullName;
'AD Group or User' = $access.IdentityReference;
'Permissions' = $access.FileSystemRights;
'Inherited' = $access.IsInherited
}
$report += New-Object -TypeName PSObject -Property $properties
}
}
Write-Host $report
$report | Export-Csv -Path $outputCsv
If that isn't an option, you can try the following:
[string]$rootFolder = Read-Host -Prompt "Enter root folder path (no trailing '\')"
[int]$recursionDepth = Read-Host -Prompt "Enter recursion depth"
[string]$outputCsv = Read-Host -Prompt "Enter output .csv file (full path)"
[string]$recursionStr = if ($recursionDepth -eq 0) { "\*" } else { ("\*" * ($recursionDepth + 1)) }
$folders = Get-ChildItem -Directory -Path "$rootFolder$recursionStr" -Force | Where-Object { $_.PSIsContainer -eq $true }
[array]$report = #()
foreach ($folder in $folders) {
$acl = Get-Acl -Path $folder.FullName
foreach ($access in $acl.access) {
[hashtable]$properties = [ordered]#{
'FolderName' = $folder.FullName;
'AD Group or User' = $access.IdentityReference;
'Permissions' = $access.FileSystemRights;
'Inherited' = $access.IsInherited
}
$report += New-Object -TypeName PSObject -Property $properties
}
}
Write-Host $report
$report | Export-Csv -Path $outputCsv
See Limit Get-ChildItem recursion depth
i imported from file IDs and base on this ID i am trying to get information from AD...and insert this information as columns in original file...this is the code:
$import = Import-Csv C:\Temp\coputerstatus.csv
Foreach ($item in $import) {
$user = Get-ADUSer -Identity $item.ID
#$item = New-Object psobject
$item | Add-Member -MemberType NoteProperty -Name "office" -Value $user.office
$item | Add-Member -MemberType NoteProperty -Name "title" -Value $user.title
$item | Add-Member -MemberType NoteProperty -Name "displayname" -Value $user.name
} #foreach
$import | Export-Csv C:\temp\my.csv
but it is no working very well..i success to insert the headers but the value is empty(,,,)
i would like to same help
thanks
Get-ADUser and other active directory cmdlets operate a little funny. When you ask for an ADUser object Get-ADuser only returns a small subset of the properties available. Office and title are not available in this default set. To get what you want add the -Property parameter to Get-ADUser and ask for title and office in addition to the defaults it normally returns
$user = Get-ADUSer -Identity $item.ID -Property Title, Office
if you want to retrieve all possible properties use an asterisk
$user = Get-ADUSer -Identity $item.ID -Property *
It actually sounds like you may not be getting any user object back from Get-ADUser. Have a look at what is in the ID column in your csv files. Manually check what you are getting back from the import-csv command
$import = Import-Csv C:\Temp\coputerstatus.csv
$import | gm
Make sure that you have an ID property in that list. If so go ahead and check if your objects have ID values that you expect
$import.ID
If everything looks fine there try taking one of those IDs and manually running the Get-ADuser command replacing $item.ID with one of the actual IDs.
Get-ADUSer -Identity TESTID -Property Title, Office
Do you get anything back?
Two ways...you can use splatting to dump all of the properties into the CSV for each like this...
$import = Import-Csv C:\Temp\coputerstatus.csv
$myUsers = #()
Foreach ($item in $import) {
$user = Get-ADUSer -Identity $item.ID -Properties *
[pscustomobject]$MyItem = #{
"userProps" = $user
}
$myUsers += $MyItem.Values
} #foreach
$myUsers | Export-Csv 'C:\temp\my.csv' -NoTypeInformation
Or you can select specific properties that you care about, like this...
$import = Import-Csv C:\Temp\coputerstatus.csv
$myUsers = #()
Foreach ($item in $import) {
$user = Get-ADUSer -Identity $item.ID -Properties *
[pscustomobject]$MyItem = #{
"DisplayName" = $user.Name
"Office" = $user.office
"Title" = $user.title
}
$myUsers += $MyItem.Values
} #foreach
$myUsers | Export-Csv 'C:\temp\my.csv' -NoTypeInformation
I have a list of users in a CSV File that I want to find out if/when they last logged in. I can get this info for an individual account but I need to write this to a file for several accounts.
The error I'm getting:
At line:5 char:7
import-module activedirectory
Missing = operator after key in hash literal
hash literal was incomplete
My Code:
$resultList = #()
Import-Csv C:\Users\admin\Desktop\SamAccountName.csv -header("SamAccountName") | Foreach-Object{
$user = ([adsisearcher]"(samAccountName=$($_.SamAccountName))").FindOne()
$resultList += New-Object -TypeName PSObject -Property #{
SamAccountName = $_.SamAccountName
Import-Module ActiveDirectory
function Get-ADUserLastLogon([string]$_.userName)
{
$dcs = Get-ADDomainController -Filter {Name -like "*"}
$time = 0
foreach($dc in $dcs)
{
$hostname = $dc.HostName
$user = Get-ADUser $userName | Get-ADObject -Properties lastLogon
if($user.LastLogon -gt $time)
{
$time = $user.LastLogon
}
}
$dt = [DateTime]::FromFileTime($time)
Write-Host $username "last logged on at:" $dt }
Get-ADUserLastLogon -UserName $user
}
}
}
$resultList | export-csv -Path c:\users\admin\desktop\SamAccountName_results.csv -NoTypeInfo
Instead of this:
$user = ([adsisearcher]"(samAccountName=$($_.SamAccountName))").FindOne()
$resultList += New-Object -TypeName PSObject -Property #{
SamAccountName = $_.SamAccountName
Please do this:
$user = ([adsisearcher]"(samAccountName=$($_.SamAccountName))").FindOne()
$resultList += New-Object -TypeName PSObject -Property #{
SamAccountName = $_.SamAccountName
}
I am writing a script to get permissions and some other info on shares throughout the a network and I am having trouble getting the shares permissions. I read online that one can use "GetAccessMask" but I thought it was just for the current user.
#loop for each computer in computers file
ForEach ($computer in $allComputers)
{
Write-Host "Checking - $computer"
If($computer -ne '')
{
#check if online, this uses WMI so if you don't have access to the machine it will show as offline
If(Test-Connection -Computername $computer -ErrorAction SilentlyContinue)
{
$shares = Get-WmiObject -Class Win32_share -ComputerName $computer -Credential $uCredentials
ForEach($share in $shares)
{
$sName = $share.Name
$sPath = $share.Path
$sDesc = $share.Description
$objShare = New-Object -TypeName PSObject
$objShare = Add-Member -PassThru -InputObject $objShare -NotePropertyName Server -NotePropertyValue $computer
$objShare = Add-Member -PassThru -InputObject $objShare -NotePropertyName Online -NotePropertyValue $True
$objShare = Add-Member -PassThru -InputObject $objShare -NotePropertyName Share -NotePropertyValue $sName
$objShare = Add-Member -PassThru -InputObject $objShare -NotePropertyName Path -NotePropertyValue $sPath
$objShare = Add-Member -PassThru -InputObject $objShare -NotePropertyName Description -NotePropertyValue $sDesc
$objShare | Export-CSV -Path $fOutfile -Append -NoClobber -NoTypeInformation
}
}
}
}
Above is a snippet of my script (as a whole it reads server list from a file, lists the share name,path, description) and I am wondering if anyone knows how I could get permissions on a given share for all users/groups with rights to the share.
Thanks in advance!
After you get the Shares from win32_share Class, Get the Share Permissions from the Win32_LogicalShareSecuritySetting Class, like this:
$Shares = Get-WmiObject Win32_Share -ComputerName $computer -Credential $uCredentials |
? {$_.Type -eq 0} ## 0 for Disk Drive shares only see: https://learn.microsoft.com/en-us/windows/win32/cimwin32prov/win32-share
$Array = #()
$ACL = #()
Foreach ($Share in $Shares)
{
$ShareName = $share.name
$SharePermissions = Get-WmiObject Win32_LogicalShareSecuritySetting -Filter "name='$ShareName'" -ComputerName $computer
Foreach ($SP in $SharePermissions)
{
$SecDesc = $SP.GetSecurityDescriptor().Descriptor
foreach($ace in $SecDesc.DACL){
$UserName = $ace.Trustee.Name
If ($ace.Trustee.Domain -ne $Null) {$UserName = "$($ace.Trustee.Domain)\$UserName"}
If ($ace.Trustee.Name -eq $Null) {$UserName = $ace.Trustee.SIDString }
$ACL += New-Object Security.AccessControl.FileSystemAccessRule($UserName, $ace.AccessMask, $ace.AceType)
}
}
$Results = "" | Select Server,Name,Status,Path,Description, ID, Rights
$Results.Server = $Share.__Server
$Results.Name = $Share.Name
$Results.Status = $Share.Status
$Results.Path = $Share.Path
$Results.Description = $Share.Description
$Results.ID = $ACL | % {$_.IdentityReference}
$Results.Rights = $ACL | % {$_.FileSystemRights}
$Results = $Results | ? {$_.id -ne $null}
$Array += $Results
}
$Array