Public/Grant-FSMTargetSharePermissions.ps1
|
function Grant-FSMTargetSharePermissions { <# .SYNOPSIS Applies exported share-level permissions to shares on a target file server. .DESCRIPTION Reads a permission CSV and applies each allow/deny entry to the matching share on the target. SMB deny entries are full denies by design, so the right is not needed for them. SAFETY: preview mode by default; add -Execute to apply. Each entry is handled in its own try/catch, so an unresolvable account (common when migrating between domains) becomes a 'Failed' row instead of stopping the run. Use -RemoveEveryone to strip the default Everyone permission after the real ones are applied. .PARAMETER TargetServer The file server to apply permissions on. .PARAMETER PermissionCsvPath Path to the permission CSV (from Export-FSMSharePermissions). .PARAMETER RemoveEveryone After applying permissions, remove the default Everyone entry from each share. .PARAMETER Credential Optional credentials for the remote connection. .PARAMETER Execute Actually apply changes. Without it, you get a preview only. .EXAMPLE Grant-FSMTargetSharePermissions -TargetServer newfs01 -PermissionCsvPath C:\Temp\perms.csv .EXAMPLE Grant-FSMTargetSharePermissions -TargetServer newfs01 -PermissionCsvPath C:\Temp\perms.csv -RemoveEveryone -Execute #> [CmdletBinding()] param( [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string]$TargetServer, [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string]$PermissionCsvPath, [switch]$RemoveEveryone, [pscredential]$Credential, [switch]$Execute ) if (-not (Test-Path -Path $PermissionCsvPath)) { throw "Permission CSV not found: '$PermissionCsvPath'." } $permissions = @(Import-Csv -Path $PermissionCsvPath) Assert-FSMCsvColumn -InputObject $permissions ` -RequiredColumn 'ShareName', 'AccountName', 'AccessControlType', 'AccessRight' ` -Path $PermissionCsvPath # Each cast is parenthesised: in argument-parsing mode an unparenthesised # [bool]$Execute is read as the literal string '[bool]False', not a cast, # which then fails to bind to the remote [bool] parameters. Invoke-FSMRemote -ComputerName $TargetServer -Credential $Credential ` -ArgumentList $permissions, ([bool]$RemoveEveryone), ([bool]$Execute) -ScriptBlock { param($Permissions, [bool]$RemoveEveryone, [bool]$Execute) foreach ($perm in $Permissions) { try { $shareExists = Get-SmbShare -Name $perm.ShareName -ErrorAction SilentlyContinue if (-not $shareExists) { [pscustomobject]@{ ShareName = $perm.ShareName; Account = $perm.AccountName Right = $perm.AccessRight; Type = $perm.AccessControlType Action = 'Skipped'; Reason = 'Share does not exist on target' } continue } if (-not $Execute) { [pscustomobject]@{ ShareName = $perm.ShareName; Account = $perm.AccountName Right = $perm.AccessRight; Type = $perm.AccessControlType Action = 'WhatIf'; Reason = 'Would apply permission. Re-run with -Execute to apply.' } continue } if ($perm.AccessControlType -eq 'Allow') { Grant-SmbShareAccess -Name $perm.ShareName -AccountName $perm.AccountName ` -AccessRight $perm.AccessRight -Force -ErrorAction Stop | Out-Null } elseif ($perm.AccessControlType -eq 'Deny') { Block-SmbShareAccess -Name $perm.ShareName -AccountName $perm.AccountName ` -Force -ErrorAction Stop | Out-Null } else { throw "Unknown AccessControlType '$($perm.AccessControlType)'" } [pscustomobject]@{ ShareName = $perm.ShareName; Account = $perm.AccountName Right = $perm.AccessRight; Type = $perm.AccessControlType Action = 'Applied'; Reason = 'Permission applied' } } catch { [pscustomobject]@{ ShareName = $perm.ShareName; Account = $perm.AccountName Right = $perm.AccessRight; Type = $perm.AccessControlType Action = 'Failed'; Reason = $_.Exception.Message } } } if ($RemoveEveryone -and $Execute) { $Permissions.ShareName | Sort-Object -Unique | ForEach-Object { $shareName = $_ try { $everyonePerm = Get-SmbShareAccess -Name $shareName -ErrorAction SilentlyContinue | Where-Object { $_.AccountName -in @('Everyone', 'BUILTIN\Everyone') } foreach ($entry in $everyonePerm) { Revoke-SmbShareAccess -Name $shareName -AccountName $entry.AccountName -Force -ErrorAction Stop | Out-Null [pscustomobject]@{ ShareName = $shareName; Account = $entry.AccountName Right = $entry.AccessRight; Type = $entry.AccessControlType Action = 'Removed'; Reason = 'Default Everyone permission removed' } } } catch { [pscustomobject]@{ ShareName = $shareName; Account = 'Everyone' Right = $null; Type = $null Action = 'Failed'; Reason = "Could not remove Everyone: $($_.Exception.Message)" } } } } } } |