Having trouble getting the output I want from some powershell commands. I'm creating a powershell script to help clean up home directories. I need to get the permissions of the directory and make sure that the name of the directoy and the user who has access match.
I'm using the Get-Acl function and it has alot of extra data. In theory the file permissions on these directories should have Administrators as the owner, the user should be the only person listed under Access.
PS C:\> Get-Acl "\\fs1\home\e55555"
Directory: \\fs1\home
Path Owner Access
---- ----- ------
e55555 BUILTIN\Administrators DOM\e55555 Allow ...
I would like to filter out everything except what is under access. I tried piping | select Access but it doesn't give me the same output.
I know I'll have extra information besides the UserID so I figured I could write to a file and try to "grep" what I needed. Through some googling and experimentation I got some output I felt would be easy to parse, here is the command and output:
PS C:\> $test = Get-Acl \\fs1\home\\e55555 | Select-Object -ExpandProperty Access
| select IdentityReference
IdentityReference
-----------------
DOM\e55555
NT AUTHORITY\SYSTEM
BUILTIN\Administrators
NT AUTHORITY\Authenticated Users
Tried to use regex to find the line I wanted, none of the things I tried gave me any output. I tried different variations of the commands below and also tried parsing a file instead of a variable:
echo $test | Select-String -pattern "^DOM"
[regex]::matches($test,"^DOM")
So how can I trim down my output on my get-acl command? And how can I "grep" for any lines starting with DOM without extra data?
This should give you the access-objects for all users in your domain
$path = "\\fs1\home\\e55555"
(Get-Acl $path).Access | where { $_.IdentityReference -like "DOM*"}
If you want to check that user is in there, you could use:
$path = "\\fs1\home\\e55555"
$username = $path | Split-Path -Leaf
(Get-Acl $path).Access | where { $_.IdentityReference -like "DOM\$username"}
I didn't extract the Identityreference property since you need the whole access object if you want to check the permissions. If you save the Get-Acl outputs to a variable (ex. $access = Get-Acl ......), you can check that the user had a access rule by using if($access) { do something }
EDIT: Just as an idea. If you only want the folders where a user with the same name as the folder doesn't have an access rule(without checking what kind of rights the user has), you could try:
$acls = Get-ChildItem "\\fs1\home\" | Get-Acl
foreach ($acl in $acls) {
$users = $acl.Access | select -ExpandProperty IdentityReference
$username = $acl.PSChildName
if ($users -notcontains "DOM\$username") { $username }
}
This should output an array of foldernames(ex. "e55555") where something IS wrong(ex. user "e55555" doesn't have any access to the folder "e55555").
I think you think-string all the time. Try to see objects instead. And to filter - use where, not select-string. E.g.:
$HomeDrive = '\\fs1\home\'
$User = 'e55555'
(Get-Acl $HomeDrive$User).Access |
where { $_.IdentityReference -match $user }
That should get you started...? :)
Try adding the -Expand to IdentityReference too. To build on what you were doing:
Get-Acl "\\fs1\home\\e55555" | Select-Object -ExpandProperty Access |
select -expand IdentityReference | ?{ $_.StartsWith("DOM") }
To make it simpler:
(Get-Acl "\\fs1\home\\e55555").Access | Select -Expand IdentityReference | ?{ $_.StartsWith("DOM") }
Related
Basically at my new work we have a shared network area with individual folders for each department. Each folder has multiple sub folders. The problem is the previous manager assigned 'full access' security rights on each folder and subfolder to absolutely everyone, including the 'everyone' group. I'd like to change the 'full access' security permissions for modify, but not for certain security groups like domain admins and certain other security groups.
I have some code in PowerShell that gives me a list of which groups have full access permissions but I need to be able to take that list and change them to modify.
This is what I shamelessly stole and modified from someone else.
$path = "\\srv-shared\sharedfolders"
$ExcludeUsers = 'Domain\Domain Admins',
'NT AUTHORITY\SYSTEM',
'BUILTIN\Administrator',
'domain\Administrator'
# Create regex-pattern to match all excluded users
$ExcludeUsersRegex = ($ExcludeUsers | % { [regex]::Escape($_) }) -join '|'
Get-Childitem $path -Recurse -Directory | ForEach-Object {
$file = $_
Get-Acl -Path $file.FullName |
Select-Object -ExpandProperty Access |
Where-Object {
$_.IdentityReference -notmatch $ExcludeUsersRegex -and
$_.AccessControlType -eq "Allow" -and
$_.FileSystemRights -eq "FullControl"
} | ForEach-Object {
#Foreach ACL
New-Object psobject -Property #{
Path = $file.FullName
ACL = $_.IdentityReference
}
}
} | Select-Object -Property Path, ACL | Export-Csv e:\check_acl.csv -NoTypeInformation
Basically in the #Foreach ACL section i need it to change the full access permission for the group/user its just found and change it to modify instead.
I need to create a script to iterate through a list of user samaccountnames and identify network directories matching their samaccountname on the network. It doesn't seem to work though. Users home folders on the network use their samaccountname in the path. Here is what I have so far:
$userList = "C:\Users\sfp01\My
Documents\Data_Deletion_Testing\User_SamAccountName.csv"
$userDirectory = foreach ($user in $userList)
{
Get-ChildItem -Path "\\ceoii\" -Directory -Recurse | ? {}
}
Export-Csv -Path "C:\Users\sfp01\My
Documents\Data_Deletion_Testing\User_Directory.csv"
First, you need to import the csv as your first line just saves the location of the file in the variable rather than the contents of the file.
Second, you didn't provide the column name of the csv file that contains the user's saMAccountName. You'll need to set up your Where-Object to filter using that information. I am using -match on saMAccountName, but edit this to reflect your requirements.
And I don't think that \\servername\ isn't a valid share name, it should be a share like \\servername\share\ If you want to get all the shares from a server you could enumerate them with something like this invoke-command -ComputerName ceoii -ScriptBlock {Get-SmbShare}
You also probably want to only pull the list of folders once and then filter for each user.
Lastly, you save the information in $userDirectory so you'll want to pipe that information into your export-csv.
$userList = Import-CSV 'C:\Users\sfp01\My Documents\Data_Deletion_Testing\User_SamAccountName.csv'
$folders = Get-ChildItem -Path "\\ceoii\sharename" -Directory -Recurse
$userDirectory = foreach ($user in $userList) {
$folders | Where-Object {$_.name -match $user.saMAcountName}
}
$userDirectory | Export-Csv -Path 'C:\Users\sfp01\My Documents\Data_Deletion_Testing\User_Directory.csv'
More efficient than that would be to use -in or -contains if you know that the folder names exactly match.
$folders = Get-ChildItem -Path "\\ceoii\sharename" -Directory -Recurse
$userList = Import-CSV 'C:\Users\sfp01\My Documents\Data_Deletion_Testing\User_SamAccountName.csv' |
Select-Object -ExpandProperty saMAccountName
$folders |
Where-Object {$_.name -in $userList} |
Export-Csv -Path 'C:\Users\sfp01\My Documents\Data_Deletion_Testing\User_Directory.csv'
I figured this might be an easy answer, but for the life of me I can't suss out why this simple thing seems to be beating me. I am looking to output the results of
Get-Mailbox –Server MYserverName | Get-MailboxPermission | FL
piped into individual text files for each individual mailbox, with the text file named for the mailbox - e.g. I want to have a folder with the content:
C:\Example\MailboxUser1.txt
C:\Example\MailboxUser2.txt
C:\Example\MailboxUser3.txt
with each containing the mailbox permission results.
I know I can do a foreach loop along the lines of:
ForEach-Object {Out-file $_.name}
to generate the output files, but I'm not too sure how I would do this in a single step to get the permissions for all my mailboxes into individual files (I know this will give me a lot of text files!)?
Something along the lines of:
$directory = "C:\example\"
$count = 0
Get-Mailbox –Server "MYserverName" | Foreach-Object {
Get-MailboxPermission | Format-List |
Out-File (Join-Path $directory "MailboxUser-$(++$count).txt")
}
At each pass of the ForEach-Object loop (mailbox), a file will be generated with the output of the Get-MailboxPermission command.
++$count increments the value just before using it (as opposed to $count++)
If you prefer to user the Name property of the mailbox object to name the files:
$directory = "C:\example\"
Get-Mailbox –Server "MYserverName" | Foreach-Object {
$mailboxName = $_.Name
Get-MailboxPermission | Format-List |
Out-File (Join-Path $directory "MailboxUser-$mailboxName.txt")
}
Get-Mailbox –Server MYserverName | Get-MailboxPermission | foreach {out-file "$($_.name).txt"}
This would be able to get you all the permissions you need IF "name" was the property you were looking at. I don't work with exchange cmdlets so I don't know if that will count.
Beginner here.
How can I modify this script to list files owned by a particular user rather than listing every single file. For instance, I only want to see files owned by user john doe.
Set-StrictMode -Version Latest $files = Get-ChildItem foreach($file in $files) {$owner=(Get-Acl $file).Owner $file | Add-Member NoteProperty Owner $owner $file}
Your help is greatly appreciated.
Try something like this:
$files = Get-ChildItem | Select *,#{n='Owner';e={(Get-Acl $_).Owner}} |
Where {!$_.PSIsContainer -and ($_.Owner -eq 'Domain\name')}
On V3 you can simplify this to:
$files = Get-ChildItem -File | Select *,#{n='Owner';e={(Get-Acl $_).Owner}} |
Where {$_.Owner -eq 'Domain\name'}
The simplest I've found is:
Get-ChildItem | Get-Acl | Where-Object { $_.Owner -match 'Domain\username' }
This might be faster:
$Owner = 'user1'
$SID = (Get-ADUser $Owner).sid
Get-ChildItem |
where { (Get-Acl $_).sddl -like "O:$SID*" } |
select *,#{l='Owner';e={$Owner}}
The ACL is stored as an SDDL string. The SID of file owner will always be at the beginning of the SDDL string, prefixed with O:. NTFS has to resolve the SIDs to an owner name. It takes less time to do a string match for the SID than to do the lookup and then match the name. It's not much, and it won't make much difference just doing a file or 10, but it starts to add up when you start doing thousands of them.
Another variant, but using .NET's File.GetAccessControl https://learn.microsoft.com/en-us/dotnet/api/system.io.file.getaccesscontrol?view=netframework-4.8 instead of Get-Acl cmdlet.
Credit to Get File Owner/Author
Get-ChildItem <path> -File | Select-Object fullname, LastAccessTime, LastWriteTime, CreationTime, #{N='Owner';E={$_.GetAccessControl().Owner}}
I am still on the learning curve with powershell, i currently have the following script:
$users = Get-Acl $Path |
Select-Object -ExpandProperty access |
ft identityreference |
where { $_.identityreference -like "UK\"}
$Path is the location of a particular share on a server. I currently have a CSV file called "test" with about 100 share names on the same server (The first column heading named "ShareNames"), the second column is named "GroupName".
I need to update this script to search through the first column in the CSV file called "test.csv" and push out the appropriate group permission to that share in the second column. I have to also admit the last part of the script does not work :( i am having trouble filtering out a common group name we have as i do not want the whole list of groups for every share only group names that start with ("uk\gro...").
Thank you for any guidance / help
I would choose -match over -like and skip the Format-Table. The following would filter the ACEs on their property IdentityReference using the regex ^UK\\ -- I am assuming that 'UK\' is the domain portion of the group name within the ACEs:
$user = Get-Acl $path |
Select-Object -ExpandProperty access |
Where-Object { $_.IdentityReference -match '^UK\\' }
Then you can ft as desired:
$user | Format-Table
If you need to feed in a CSV of paths, you can pipe an Import-Csv into a ForEach-Object wrapped around the above example.
Import-Csv test.csv |
ForEach-Object {
Write-Output "ACEs on $($_.ShareNames) matching 'UK\'"
Get-Acl $_.ShareNames |
Select-Object -ExpandProperty access |
Where-Object { $_.IdentityReference -match '^UK\\' }
}
I'm still not clear on how you intend to populate the "GroupName" column in the output as there could be multiple entries for groups beginning with 'UK\'.