Currently, Terraform does not support eligible assignments of permissions in Azure RBAC, and only active assignments using the azurerm_role_assignment resource. Continue reading if you want to be able to assign your eligible assignments using ARM or Terraform (Terraform willl use the ARM template).
With the 3rd version of the PIM APIs, we have something called Role Eligibility Schedule Request, available through documented through the API documentation and the ARM documentation. However, the documentation can be a bit difficult to understand, especially because the roleDefinitionId in the ARM template must be provided differently than the when using the API.
Let’s first define an ARM template, as below, that can be used to assign eligible permissions:
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
// Service principal objectid or user objectid
"principalId": {
"type": "string"
},
// Full role definition id, such as Contributor: subscriptions/1232951b-df54-45eb-9c08-a8c93ea18306/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c
"roleDefinitionId": {
"type": "string"
},
// Random unique GUID, to identify the request
"id": {
"type": "string",
"defaultValue": "[newGuid()]"
},
// Random unique GUID, to identify the request
"requestType": {
"type": "string",
"defaultValue": "AdminUpdate"
}
},
"outputs": {},
"resources": [
{
"type": "Microsoft.Authorization/roleEligibilityScheduleRequests",
"apiVersion": "2020-10-01-preview",
"name": "[parameters('id')]",
"properties": {
"principalId": "[parameters('principalId')]",
"roleDefinitionId": "[parameters('roleDefinitionId')]",
"requestType": "[parameters('requestType')]",
"scheduleInfo": {
"startDateTime": "2021-10-13T08:32:07.0706351+02:00",
"expiration": {
"type": "AfterDuration",
"duration": "P365D"
}
}
}
}
]
}
Parameter – principalId
This should be the objectid of the principal you are granting the access to. If you are assigning permissions to user IrvinS@M365x942777.OnMicrosoft.com, use the following value:

Parameter – roleDefinitionId
I spent way too much time to figure out the format of the value for this parameter, but it should be like this:
subscriptions/1272951b-df54-45eb-9c08-a8c93ea18302/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c
The first guid (1272951b-df54-45eb-9c08-a8c93ea18302) should be changed to the subscription id of your subscription, while the second guid (b24988ac-6180-42a0-ab88-20f7382dd24) is the Azure RBAC role id, found here. The example provided is “Contributor”.
Parameter – id
All eligible schedule requests have a unique ID, defined client side, so this should basically just be a unique guid. The ARM template generates ut automatically.
Parameter – requestType
I have defaulted this to AdminUpdate, as that will also work with new assignments. However, due to how PIM works, in order to actually remove an assignment, you must deploy the ARM template with the value “AdminRemove”. This is super anoying, from a Terraform perspective. Also, when deploying with AdminRemove for a second time, it fails with RoleAssignmentDoesNotExist.
Deploying using ARM template
Here is how to deploy eligible contributor permission to a user with objectid e9176fb9-63d3-480a-a51f-e5399059b588 on subscription level:
az deployment sub create --template-file .\pim_assignment.json --parameters principalId=e9176fb9-63d3-480a-a51f-e5399059b588 roleDefinitionId=subscriptions/4272951b-df54-45eb-9c08-a8c93ea18306/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c --name "contributor_assignment_1" --location westeurope
And this is how to do the same thing on resource group level:
az deployment group create --resource-group mygroup --template-file .\pim_assignment.json --parameters principalId=e9176fb9-63d3-480a-a51f-e5399059b588 roleDefinitionId=subscriptions/4272951b-df54-45eb-9c08-a8c93ea18306/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c --name "contributor_assignment_1"
Now that we have things going with ARM template, let’s do it with Terraform aswell.
Deploying using Terraform
Some say it’s cheating, but we need to use the ARM template here aswell. This is because currently no Terraform resource exist for eligible role assignments.
Also, Terraform does not support comments in JSON documents, so remove them before saving the file.
Go to https://github.com/goodworkaround/terraform-az-rbac-pim-assignment and clone my Terraform example. The example uses the Azure AD provider to create groups, which is not necessary. You can get away with only the AzureRM provider, but then you need to specify the objectids of the principals you are granting access to.
There are two modules available:
PIM Assignment – Subscription
The following code will create an Azure AD group called “subscription_owner_group_1” and assign it eligible “Owner”
// Example for subscription owner as PIM role
resource "azuread_group" "subscription_owner_group_1" {
display_name = "subscription_owner_group_1"
mail_enabled = false
security_enabled = true
}
module "pim_assignment_1" {
source = "./PIM Assignment - Subscription"
principal_id = azuread_group.subscription_owner_group_1.object_id
role_definition_name = "Owner"
}
As an admin in PIM, you will find the following assignment:

Members of the group should see this in PIM:

It is worth noting that simply unloading the module will not remove the assignment. Instead, the module must be used with request_type = “AdminRemove”, as it will remove the permission. Then you can remove the module.
PIM Assignment – Resource Group
The following code will create an Azure AD group called “rg_contributor_group_1”, a resource group “rg1” and delegate the group eligible Contributor on the resource group:
// Example for contributor role on resource group
resource "azuread_group" "rg_contributor_group_1" {
display_name = "rg_contributor_group_1"
mail_enabled = false
security_enabled = true
}
resource "azurerm_resource_group" "rg1" {
name = "rg1"
location = "westeurope"
}
module "pim_assignment_2" {
source = "./PIM Assignment - Resource Group"
resource_group_name = azurerm_resource_group.rg1.name
principal_id = azuread_group.rg_contributor_group_1.object_id
role_definition_name = "Contributor"
}
As an admin in PIM, you will find the following assignment:

Members of the group should see this in PIM:

It is worth noting that simply unloading the module will not remove the assignment. Instead, the module must be used with request_type = “AdminRemove”, as it will remove the permission. Then you can remove the module.
Have fun!
Nice article, could you please tell me the Role that is assigned to the service principle doing this task?
Hi, if you mean the role of the principal that deploys the ARM template, it is either Owner or User Access Administrator. 🙂
thank you! I will try with that.
Have you tried using AdminRemove test for the same principle ID which was added by AdminAdd step? It fails every time.
I have, with success – what is your error message?
Error: removing items provisioned by this Template Deployment: `properties.OutputResources` was nil – insufficient data to clean up this Template Deployment
Ah yes, can you try to disable the delete_nested_items_during_deletion setting of the azurerm provider to see if that resolves things?
yup that worked, I don’t really use ARM deployment with TF, but your article has been quite helpful.
one more thing I noticed, after assigning az resource PIM role to principleID, If I run the same release again, it fails with error that {
“code”: “Conflict”,
“message”: “A role assignment request with Id: a2d47b66-96d6-16d4-5b35-29b3139cae94 already exists”
}
. I thought it would just pass through
Yes I know. The API expects a unique is each time. Terrible design on the Microsoft side
Will this work for ADRoles like “User Administrator” or “Application Administrator” . I am trying to work make PIM for Azure AD roles
No, this is for RBAC only. Azure AD PIM roles is a completely different api 🙂
That is right, also make sure yours SPN has the right api permissions and Rbac to do this via code for Az Resource Roles or AD roles 🙂
For Resource Roles I was able to get it working with User Access Admin on the subscription as well as Contributor Access
with User.Read, PrivilegedAccess.Read.AzureResources and PrivilegedAccess.Write.AzureResources access with Grant persimmons as least .
Great solution!
A couple of questions if you don’t mind!
1/ we were thinking to use ‘az rest’ to achieve the same but all of our testing using:
https://docs.microsoft.com/en-us/rest/api/authorization/role-eligibility-schedule-requests/create#requesttype
with basically an identical payload it didn’t create the assignment, it left it in a strange ‘pending’ state
any thoughts on why this might be?
2/ any ideas on setting the role policy via ARM or REST? eg MFA required, 4 hours, etc… it uses PATCH method:
https://docs.microsoft.com/en-us/rest/api/authorization/privileged-role-policy-rest-sample#update-a-role-management-policy
This is great solution but I am facing an issue when running AdminRemove on resource group template, it fails by saying below error:
Error: removing items provisioned by this Template Deployment: deleting Nested Resource “/subscriptions/***/resourceGroups/***/providers/Microsoft.Authorization/roleEligibilityScheduleRequests/***”: resources.Client#DeleteByID: Failure sending request: StatusCode=405 — Original Error: Code=”Failed” Message=”The async operation failed.” AdditionalInfo=[{“message”:”The requested resource does not support http method ‘DELETE’.”}]
Hi, for this you will need to disable the delete_nested_items_during_deletion feature tag. This was defaulted to true some point in the past.
https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/resource_group_template_deployment
Marius