WIP wrapper module for PnP PowerShell SharePoint permissions
This commit is contained in:
parent
ab2740394a
commit
030730448d
234
m365/PnPFolderAcl/PnPFolderAcl.psm1
Normal file
234
m365/PnPFolderAcl/PnPFolderAcl.psm1
Normal file
@ -0,0 +1,234 @@
|
||||
|
||||
#region Private Helpers
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Tests if a PnP Group exists.
|
||||
.DESCRIPTION
|
||||
This function tests if a PnP Group exists in the current SharePoint site.
|
||||
.PARAMETER Identity
|
||||
The identity of the group to test.
|
||||
.EXAMPLE
|
||||
Test-PnPGroup -Identity "MyGroup"
|
||||
#>
|
||||
function Test-PnPGroup {
|
||||
param(
|
||||
[string]$Identity
|
||||
)
|
||||
|
||||
try {
|
||||
Get-PnPGroup -Identity $Identity -ErrorAction Stop | Out-Null
|
||||
return $true
|
||||
} catch {
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Tests if an Entra ID Group exists and PnP can resolve it.
|
||||
.DESCRIPTION
|
||||
This function tests if a Entra ID Group exists and can be resolved by PnP.
|
||||
.PARAMETER Identity
|
||||
The identity of the group to test.
|
||||
.EXAMPLE
|
||||
Test-EntraIdGroup -Identity "MyGroup"
|
||||
#>
|
||||
function Test-EntraIdGroup {
|
||||
param(
|
||||
[string]$Identity
|
||||
)
|
||||
|
||||
try {
|
||||
Get-PnPEntraIdGroup -Identity $Identity -ErrorAction Stop | Out-Null
|
||||
return $true
|
||||
} catch {
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Functions
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Sets permissions on a folder in a SharePoint document library.
|
||||
.DESCRIPTION
|
||||
This script breaks permission inheritance on a specified folder in a SharePoint document library and assigns permissions to a specified owner group and additional groups defined in the ACL parameter.
|
||||
.PARAMETER Name
|
||||
The name of the folder to set permissions on.
|
||||
.PARAMETER List
|
||||
The name of the document library containing the folder. Default is 'Shared Documents'.
|
||||
.PARAMETER Owner
|
||||
The name of the SharePoint group to assign as the owner of the folder with 'Full Control' permissions.
|
||||
.PARAMETER Acl
|
||||
An array of objects defining additional groups and their permissions to assign to the folder. Each object should have a 'DisplayName' property for the group name and a 'Role' property for the permission level (e.g., 'Read', 'Edit').
|
||||
.EXAMPLE
|
||||
$Acl = @(
|
||||
@{ DisplayName = "SG-ADMIN-AdvocateFloats-Dynamic"; Role = "Edit" },
|
||||
@{ DisplayName = "SG-ADMIN-AdvocateManagers-Dynamic"; Role = "Edit" }
|
||||
)
|
||||
.\Set-PnPFolderAcl.ps1 -Name "ProjectX" -List "Shared Documents" -Owner "Project Owners" -Acl $Acl
|
||||
#>
|
||||
function Set-PnPFolderAcl {
|
||||
[CmdletBinding(
|
||||
SupportsShouldProcess = $true,
|
||||
ConfirmImpact = 'High'
|
||||
)]
|
||||
param(
|
||||
[Parameter(
|
||||
Mandatory,
|
||||
ValueFromPipeline,
|
||||
ValueFromPipelineByPropertyName
|
||||
)]
|
||||
[string]$FolderName,
|
||||
|
||||
[Parameter()]
|
||||
[string]$List = 'Shared Documents',
|
||||
|
||||
[Parameter(Mandatory)]
|
||||
[string]$Owner,
|
||||
|
||||
[Parameter(Mandatory)]
|
||||
[pscustomobject[]]$Acl
|
||||
)
|
||||
|
||||
begin {
|
||||
if (-not (Get-PnPContext)) {
|
||||
Throw "Not connected to a SharePoint site. Run Connect-PnPOnline first."
|
||||
}
|
||||
|
||||
if (-not (Get-PnPList -Identity $List -ErrorAction SilentlyContinue)) {
|
||||
Throw "The specified list '$List' does not exist."
|
||||
}
|
||||
|
||||
if (-not (Test-PnPGroup -Identity $Owner)) {
|
||||
Throw "The specified owner group '$Owner' does not exist."
|
||||
}
|
||||
|
||||
$ValidRoles = Get-PnPRoleDefinition | Select-Object -ExpandProperty Name
|
||||
|
||||
if (-not $ValidRoles) {
|
||||
throw "Unable to retrieve SharePoint role definitions."
|
||||
}
|
||||
|
||||
|
||||
foreach ($entry in $Acl) {
|
||||
if (-not ($entry.PSObject.Properties.Name -contains 'Group' -and
|
||||
$entry.PSObject.Properties.Name -contains 'Role')) {
|
||||
Throw "Each ACL entry must contain 'Group' and 'Role' properties."
|
||||
}
|
||||
if (-not (Test-PnPGroup -Identity $entry.Group) -and
|
||||
-not (Test-EntraIdGroup -Identity $entry.Group)) {
|
||||
Throw "The specified group '$($entry.Group)' does not exist as a PnP Group or Entra ID Group."
|
||||
}
|
||||
if ($entry.Role -notin $ValidRoles) {
|
||||
Throw "Invalid role '$($entry.Role)' specified for group '$($entry.Group)'. Valid roles are: $($ValidRoles -join ', ')."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
process {
|
||||
$FolderPath = "$List/$FolderName"
|
||||
|
||||
# Retrieve folder and current permissions
|
||||
$FolderItem = Get-PnPFolder -Url $FolderPath -ErrorAction Stop
|
||||
$ListItem = Get-PnPListItem -List $List -Id $FolderItem.ListItemAllFields.Id
|
||||
|
||||
|
||||
# Break inheritance ONLY IF the folder doesn't already have unique permissions
|
||||
if (-not $ListItem.HasUniqueRoleAssignments) {
|
||||
|
||||
if ($PSCmdlet.ShouldProcess(
|
||||
$FolderPath,
|
||||
"Break inheritance and grant Full Control to '$Owner' on '$FolderPath'."
|
||||
)) {
|
||||
|
||||
Write-Verbose "Breaking inheritance for '$FolderPath'."
|
||||
Write-Verbose "Granting 'Full Control' to '$Owner' on '$FolderPath'."
|
||||
|
||||
Set-PnPFolderPermission `
|
||||
-List $List `
|
||||
-Identity $FolderPath `
|
||||
-Group $Owner `
|
||||
-AddRole 'Full Control' `
|
||||
-ClearExisting
|
||||
}
|
||||
}
|
||||
|
||||
# Get existing role assignments
|
||||
$RoleAssignments = Get-PnPProperty -ClientObject $ListItem -Property RoleAssignments
|
||||
|
||||
$CurrentAcl = foreach ($ra in $RoleAssignments) {
|
||||
$principal = Get-PnPProperty -ClientObject $ra -Property Member
|
||||
$bindings = Get-PnPProperty -ClientObject $ra -Property RoleDefinitionBindings
|
||||
|
||||
foreach ($binding in $bindings) {
|
||||
[pscustomobject]@{
|
||||
Principal = $principal.Title
|
||||
Role = $binding.Name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# foreach ($entry in $CurrentAcl) {
|
||||
|
||||
# if ($entry.Principal -eq $Owner) {
|
||||
# continue
|
||||
# }
|
||||
|
||||
# if
|
||||
# }
|
||||
|
||||
foreach ($entry in $Acl) {
|
||||
|
||||
$GroupName = $entry.Group
|
||||
$Role = $entry.Role
|
||||
|
||||
$AlreadyAssigned = $ResolvedRoles | Where-Object {
|
||||
$_.Principal -eq $GroupName -and
|
||||
$_.Role -eq $Role
|
||||
}
|
||||
|
||||
if ($AlreadyAssigned) {
|
||||
Write-Verbose "Permission '$Role' already assigned to '$GroupName' on '$FolderPath'. Skipping."
|
||||
continue
|
||||
}
|
||||
|
||||
if (Test-PnPGroup $GroupName) {
|
||||
if ($PSCmdlet.ShouldProcess(
|
||||
$FolderPath,
|
||||
"Grant '$Role' to SharePoint group '$GroupName' on '$FolderPath'."
|
||||
)) {
|
||||
|
||||
Write-Verbose "Granting '$Role' to SharePoint group '$GroupName' on '$FolderPath'."
|
||||
|
||||
Set-PnPFolderPermission `
|
||||
-List $List `
|
||||
-Identity $FolderPath `
|
||||
-Group $GroupName `
|
||||
-AddRole $Role
|
||||
}
|
||||
} elseif (Test-EntraIdGroup $GroupName) {
|
||||
if ($PSCmdlet.ShouldProcess(
|
||||
$FolderPath,
|
||||
"Grant '$Role' to Entra ID group '$GroupName' on '$FolderPath'."
|
||||
)) {
|
||||
|
||||
Write-Verbose "Granting '$Role' to Entra ID group '$GroupName' on '$FolderPath'."
|
||||
|
||||
Set-PnPFolderPermission `
|
||||
-List $List `
|
||||
-Identity $FolderPath `
|
||||
-Group $GroupName `
|
||||
-AddRole $Role
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
Export-ModuleMember -Function Set-PnPFolderAcl
|
||||
Loading…
x
Reference in New Issue
Block a user