Public/New-SiSAccessPackage.ps1
|
function New-SiSAccessPackage { <# .SYNOPSIS Creates a new, empty Access Package in an Entitlement Management catalog. .DESCRIPTION Resolves the catalog (by id or name), checks that no access package with the same name already exists in that catalog, and creates the access package after confirmation. Only the package itself - resources are added with Add-SiSAccessPackageResource (groups, applications, SharePoint sites), which takes this function's output from the pipeline. No assignment policy is created. .PARAMETER DisplayName Name of the new access package. .PARAMETER Description Description shown to users in My Access. .PARAMETER CatalogId The ObjectId of the catalog. (ParameterSet 'CatalogId') .PARAMETER CatalogName Display name of the catalog. Stops if more than one catalog has that name. (ParameterSet 'CatalogName', default) .PARAMETER IsHidden Hides the access package from My Access - users need the direct link to request it. .PARAMETER WhatIf Runs the catalog lookup and duplicate check, shows what would be created, then stops. .PARAMETER Confirm Asks before creating (the default). -Confirm:$false creates without asking. .EXAMPLE # Preview first New-SiSAccessPackage -DisplayName "AP - Sales - Read" -Description "Read access for Sales" ` -CatalogName "Sales" -WhatIf .EXAMPLE # Create it, and add a group in the same pipeline New-SiSAccessPackage -DisplayName "AP - Sales - Read" -Description "Read access for Sales" ` -CatalogName "Sales" | Add-SiSAccessPackageResource -GroupId $groupId .OUTPUTS SiSGovernance.AccessPackage: Id, DisplayName, CatalogId, CatalogName, IsHidden. Id binds to Add-SiSAccessPackageResource -AccessPackageId through the pipeline. .NOTES Required scopes: EntitlementManagement.ReadWrite.All Least privileged role: Access package manager on the catalog (via PIM) #> [OutputType('SiSGovernance.AccessPackage')] [CmdletBinding(DefaultParameterSetName = 'CatalogName', SupportsShouldProcess = $true, ConfirmImpact = 'High')] param( [Parameter(Mandatory = $true)] [string]$DisplayName, [Parameter(Mandatory = $true)] [string]$Description, [Parameter(Mandatory = $true, ParameterSetName = 'CatalogId')] [Nullable[guid]]$CatalogId, [Parameter(Mandatory = $true, ParameterSetName = 'CatalogName')] [string]$CatalogName, [Parameter(Mandatory = $false)] [switch]$IsHidden ) Write-Host "==========================================" -ForegroundColor DarkGray Write-Host " NEW ACCESS PACKAGE " -ForegroundColor Cyan Write-Host "==========================================" -ForegroundColor DarkGray if (-not (Confirm-GraphConnection -Scopes 'EntitlementManagement.ReadWrite.All')) { return } $catalog = Resolve-AccessPackageCatalog -CatalogId $(if ($CatalogId) { $CatalogId.ToString('D') }) -CatalogName $CatalogName if (-not $catalog) { return } # Entra happily creates two access packages with the same name in the same # catalog, which is confusing for everyone afterwards - so stop here instead. Write-Host "`n--- DUPLICATE CHECK ---" -ForegroundColor Cyan $safeName = $DisplayName -replace "'", "''" $uri = "https://graph.microsoft.com/v1.0/identityGovernance/entitlementManagement/accessPackages?`$filter=displayName eq '$safeName'&`$expand=catalog" try { $existing = @(Get-GraphPagedResult -Uri $uri) | Where-Object { $_.catalog.id -eq $catalog.id } } catch { Write-Error -Message "Could not check for existing access packages. $($_.Exception.Message)" -Category ReadError -TargetObject $DisplayName return } if ($existing) { Write-Error -Message "An access package named '$DisplayName' already exists in '$($catalog.displayName)' (id $(@($existing)[0].id))." -Category ResourceExists -TargetObject $DisplayName return } Write-Host "No existing access package with that name in this catalog." -ForegroundColor Green Write-Host "`n Create:" -ForegroundColor Yellow Write-Host " Name : $DisplayName" -ForegroundColor White Write-Host " Description : $Description" -ForegroundColor White Write-Host " Catalog : $($catalog.displayName)" -ForegroundColor White Write-Host " Hidden : $($IsHidden.IsPresent)" -ForegroundColor White if (-not $PSCmdlet.ShouldProcess("'$DisplayName' in catalog '$($catalog.displayName)'", 'Create access package')) { if (-not $WhatIfPreference) { Write-Warning "Cancelled - no changes were made." } return } Write-Host "`n--- CREATE ACCESS PACKAGE ---" -ForegroundColor Cyan $body = @{ displayName = $DisplayName description = $Description isHidden = $IsHidden.IsPresent catalog = @{ id = $catalog.id } } | ConvertTo-Json -Depth 5 try { $accessPackage = Invoke-MgGraphRequest -Method POST ` -Uri "https://graph.microsoft.com/v1.0/identityGovernance/entitlementManagement/accessPackages" ` -Body $body -ContentType 'application/json' -ErrorAction Stop } catch { Write-Error -Message "Failed to create access package '$DisplayName'. $($_.Exception.Message)" -Category WriteError -TargetObject $DisplayName return } Write-Host "Access Package created: $($accessPackage['displayName'])" -ForegroundColor Green Write-Host " Id: $($accessPackage['id'])" -ForegroundColor White Write-Host "`n==========================================" -ForegroundColor DarkGray Write-Host " OPERATION COMPLETE" -ForegroundColor Cyan Write-Host "==========================================" -ForegroundColor DarkGray Write-Host " Remember: the access package has no resources and no assignment" -ForegroundColor Yellow Write-Host " policy yet - add them with Add-SiSAccessPackageResource and a policy." -ForegroundColor Yellow return [PSCustomObject]@{ PSTypeName = 'SiSGovernance.AccessPackage' Id = $accessPackage['id'] DisplayName = $accessPackage['displayName'] CatalogId = $catalog.id CatalogName = $catalog.displayName IsHidden = $IsHidden.IsPresent } } |