Public/Add-SiSAccessPackageResource.ps1
|
function Add-SiSAccessPackageResource { <# .SYNOPSIS Adds a role from a resource - an Entra group, an application or a SharePoint Online site - to one or more access packages. .DESCRIPTION Same flow for every resource type: 1. reads each access package and what it already grants (nothing is changed yet) 2. shows one preview and asks for confirmation once 3. adds the resource to the package's catalog if it isn't there yet 4. adds the role to the package A package that already has the role is reported as AlreadyAdded and left alone, so re-running is safe. Everyone already assigned to the package gets the new role. Accepts access packages from the pipeline (anything with an Id or AccessPackageId property, e.g. the output of New-SiSAccessPackage). .PARAMETER AccessPackageId One or more access package ObjectIds. Accepts pipeline input by property name (Id / AccessPackageId). .PARAMETER GroupId Entra group ObjectId. (ParameterSet 'Group', default) .PARAMETER Role Group role: Member (default) or Owner. (ParameterSet 'Group') .PARAMETER ApplicationId ObjectId of the application's service principal (Enterprise application), not the app registration's appId. (ParameterSet 'Application') .PARAMETER SiteUrl SharePoint Online site URL. (ParameterSet 'SharePoint') .PARAMETER RoleName For applications and SharePoint: the role's display name or originId. Use Get-SiSAccessPackageResourceRole to see what exists. .PARAMETER WhatIf Reads and shows what would change, then stops. Returns 'Preview - <action>' per package. .PARAMETER Confirm Asks before changing (the default). -Confirm:$false changes without asking. .EXAMPLE # New package with a group, in one go New-SiSAccessPackage -DisplayName "License - Baseline 5" -Description "..." -CatalogName "Identity - Employee" | Add-SiSAccessPackageResource -GroupId $licE5GroupId .EXAMPLE # App role Add-SiSAccessPackageResource -AccessPackageId $apId -ApplicationId $sapSpId -RoleName "User" .EXAMPLE # SharePoint site role Add-SiSAccessPackageResource -AccessPackageId $apId -SiteUrl "https://contoso.sharepoint.com/sites/Sales" -RoleName "Members" .EXAMPLE # Swap a resource (naming standard: the package stays, the content changes) Add-SiSAccessPackageResource -AccessPackageId $apId -GroupId $licE7GroupId Remove-SiSAccessPackageResource -AccessPackageId $apId -GroupId $licE5GroupId .OUTPUTS SiSGovernance.ResourceChangeResult, one per package: AccessPackageId, AccessPackageName, ResourceType, Resource, Role, Status (Added / AlreadyAdded / Preview - ... / Cancelled / Failed), Error. .NOTES Required scopes: EntitlementManagement.ReadWrite.All Least privileged role: Access package manager on the catalog (via PIM). Adding a resource to a catalog may also require rights on the resource itself (e.g. group owner or app owner), depending on the catalog setup. #> [OutputType('SiSGovernance.ResourceChangeResult')] # The confirmation is asked once for the whole run, in Invoke-AccessPackageResourceChange - # -WhatIf and -Confirm reach it through the preference variables [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '', Justification = 'ShouldProcess is called in Invoke-AccessPackageResourceChange, which this function calls')] [CmdletBinding(DefaultParameterSetName = 'Group', SupportsShouldProcess = $true, ConfirmImpact = 'High')] param( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [Alias('Id')] [guid[]]$AccessPackageId, [Parameter(Mandatory = $true, ParameterSetName = 'Group')] [guid]$GroupId, [Parameter(Mandatory = $false, ParameterSetName = 'Group')] [ValidateSet('Member', 'Owner')] [string]$Role = 'Member', [Parameter(Mandatory = $true, ParameterSetName = 'Application')] [guid]$ApplicationId, [Parameter(Mandatory = $true, ParameterSetName = 'SharePoint')] [ValidatePattern('^https://')] [string]$SiteUrl, [Parameter(Mandatory = $true, ParameterSetName = 'Application')] [Parameter(Mandatory = $true, ParameterSetName = 'SharePoint')] [string]$RoleName ) begin { $collectedIds = [System.Collections.Generic.List[string]]::new() } process { # Pipeline input (e.g. from New-SiSAccessPackage) is collected first, so # there's one preview and one confirmation for all packages foreach ($id in $AccessPackageId) { $collectedIds.Add($id.ToString('D')) } } end { $ids = @($collectedIds | Sort-Object -Unique) if ($ids.Count -eq 0) { Write-Warning "No access packages received. Nothing to do." return } $spec = ConvertTo-AccessPackageResourceSpec -Type $PSCmdlet.ParameterSetName ` -GroupId $(if ($GroupId) { $GroupId.ToString('D') }) -GroupRole $Role -ApplicationId $(if ($ApplicationId) { $ApplicationId.ToString('D') }) -SiteUrl $SiteUrl -RoleName $RoleName Invoke-AccessPackageResourceChange -Action Add -AccessPackageId $ids -Spec $spec } } |