Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Create Access Packages within Azure AD & assign resource access.
# Fastest way to get one of these is to export your token from Graph Explorer.
# Using a custom application registration requires Graph API permission approval & scopes request using an ROPC flow
$graphToken = "SuperLongBase64EncodedJWT-BearerToken"
#Access Package Details
$accessPackageName = "my-access-package"
$accessPackageDescription = "This package contains resources for B2B"
$resourceCatalogName = "General" #This can be updated to use other catalogues. This script does not create catalogs.
#Array of access Access package resources - This example only an AAD Group and the Azure Devops Enterprise app.
$catalogResourceList = @(@{
'displayName' = 'Testing-Group' #Must match the name of the object your are specifying
'description' = 'Group for managers to become a member of' #not used as the description of the object, used as the description of the request
'resourceType' = 'AadGroup' #The type of the resource, such as Application if it is an Azure AD connected application, or SharePoint Online Site for a SharePoint Online site.
'originId' = '3c6aded3-af34-4bac-93fe-b906de09b6c9' # The unique identifier of the resource in the origin system. In the case of an Azure AD group, this is the object id of the group.
'originSystem' = 'AadGroup' #Can be SharePointOnline, AadApplication or AadGroup.
'roleDisplayName' = 'Member' #Access Packages require roles to be assigned to a user. This is the displayname for the role as it appears within Azure AD metadata (for apps) or Member/Owner for groups. If developing programatically, easy to add a AP & pull from that area
'displayName' = 'Azure DevOps'
'description' = 'Group for people using Azure DevOps'
'resourceType' = 'Application'
'originId' = '03004e60-c002-43d3-a63d-36f1f4707e70'
'originSystem' = 'AadApplication'
'roleDisplayName' = 'Default Access'
#Build headers for graph API requests
$authorisationHeaders = @{
'Authorization' = "Bearer $graphToken"
$accessPackageHeaders = @{
'Authorization' = "Bearer $graphToken"
'Content-Type' = "application/json"
Write-Host "Retrieving resource ID for the $resourceCatalogName catalog." -ForegroundColor Green
#Get Resource Catalog
$allCatalogResult = Invoke-RestMethod -Uri '' -Headers $authorisationHeaders
$defaultCatalogId = ($allCatalogResult.Value | Where-Object{$_.displayName -eq "$resourceCatalogName"}).id
Write-Host "Creating Access Package: $accessPackageName" -ForegroundColor Green
#Create Access Package
$accessPackageBody = @{
'catalogId' = $defaultCatalogId
'displayName' = $accessPackageName
'description' = $accessPackageDescription
$accessPackageParams = @{
'Uri' = ""
'Method' = 'Post'
'Headers' = $accessPackageHeaders
'Body' = ($accessPackageBody | ConvertTo-Json)
$accessPackageResult = Invoke-RestMethod @accessPackageParams
#Create Resources within the catalog & assign each to the newly created access package
$catalogResourceList | ForEach-Object{
Write-Host "Creating the $($_.displayName) resource object for consumption within an access package." -ForegroundColor Green
$catalogResourceBody = "{
'catalogId' : '$defaultCatalogId',
'requestType': 'AdminAdd',
'justification': 'Provisioning as part of access Package creation',
'accessPackageResource': {
'displayName': '$($_.displayName)',
'description': '$($_.description)',
'resourceType': '$($_.resourceType)',
'originId': '$($_.originId)',
'originSystem': '$($_.originSystem)'
$catalogResourceParams = @{
'Uri' = ""
'Method' = 'Post'
'Headers' = $accessPackageHeaders
'Body' = $catalogResourceBody
$catalogResourceResult = Invoke-RestMethod @catalogResourceParams
#Get the ID of the resource as represented within access packages
$catalogResource = (Invoke-RestMethod -Uri "$defaultCatalogId/accessPackageResources?`$filter=(displayName eq '$($_.displayName)')" -Headers $authorisationHeaders).value
#Get the ID of the specified role as defined in the original objects
$catalogResourceRole = (Invoke-RestMethod -uri "$defaultCatalogId/accessPackageResourceRoles?`$filter=(originSystem+eq+%27$($_.originSystem)%27+and+accessPackageResource/id+eq+%27$($$($_.roleDisplayName)%27)&`$expand=accessPackageResource" -Headers $authorisationHeaders).value
#Assign the Resource & Associated Role to the Access Package
Write-Host "Assigning resource role $($catalogResourceRole.displayName) for $($_.displayName) to Access Package $($" -ForegroundColor Green
$roleAssignmentBody = "{
'accessPackageResourceRole': {
'accessPackageResource': {
'accessPackageResourceScope': {
$roleAssignmentParams = @{
'Uri' = "$($"
'Method' = 'Post'
'Headers' = $accessPackageHeaders
'Body' = $roleAssignmentBody
$roleAssignmentResult = Invoke-RestMethod @roleAssignmentParams
#Create an admin assignement policy for the access package
Write-Host "Creating an admin assignment policy for access package id: $($" -ForegroundColor Green
$defaultAccessPackagePolicyBody = "{
'@odata.context': '`$metadata#accessPackageAssignmentPolicies/`$entity',
'accessPackageId': '$($',
'displayName': 'Default Access Policy - Admin Assignment',
'description': 'Users with access to this package are assigned by an admin',
'canExtend': false,
'durationInDays': 365,
'expirationDateTime': null,
'accessReviewSettings': null,
'requestorSettings': {
'scopeType': 'NoSubjects',
'acceptRequests': true,
'allowedRequestors': []
'requestApprovalSettings': {
'isApprovalRequired': false,
'isApprovalRequiredForExtension': false,
'isRequestorJustificationRequired': false,
'approvalMode': 'NoApproval',
'approvalStages': []
'questions': []
$defaultAccessPackagePolicyParams = @{
'Uri' = ""
'Method' = 'Post'
'Headers' = $accessPackageHeaders
'Body' = $defaultAccessPackagePolicyBody
$defaultAccessPackagePolicyResult = Invoke-RestMethod @defaultAccessPackagePolicyParams
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment