i'm trying to create a script that checks for permissions of SmbShares on a few Servers. The goal is to check if any share has a "everyone" permission. However i trying a find a more elegant solution than this mess:
$ADComputer = Get-ADComputer -Filter 'Name -like "Test-Server-*' | Where-Object { $excludeList -notcontains $_.name }
foreach ($server in $ADComputer) {
$shares = Invoke-Command -ComputerName $server -ScriptBlock { Get-SmbShare }
foreach ($share in $shares) {
$permissions = Invoke-Command -ComputerName $server -ScriptBlock { Get-SmbShareAccess -Name $share.name }
foreach ($permission in $permissions) {
if ( $permission ) ...
}
}
}
I can't wrapp my head around this. How can i solve this without using so many nested for loops?
Any ideas or hints?
CodePudding user response:
A good pattern to follow here is:
- Solve the whole problem for local execution on a single machine
- Use
Invoke-Command
to repeat across multiple remote hosts
So let's start by writing a single function/script to solve the problem locally first:
function Find-SmbShareEveryoneGrant {
# We can pipe the output from one cmdlet to the next, and solve the problem in a single pipeline
Get-SmbShare |Get-SmbShareAccess |Where-Object { $_.AccessControlType -eq 'Allow' -and $_.AccountName -eq 'Everyone'}
}
Now that you have a function that can be repeated anywhere, it's as simple as calling Invoke-Command
against all the servers - the -ComputerName
parameter accepts an array, so explicitly looping over $ADComputers
is not necessary:
Invoke-Command -ComputerName $ADComputer -ScriptBlock ${function:Find-SmbShareEveryoneGrant} |Select PSComputerName,Name,ScopeName,AccessRight
4-5 lines of code total, much more concise than all those nested loops and successive calls to Invoke-Command