Understanding and Implementing Privileged Identity Management (PIM) Using BICEP
Introduction
In today’s digital landscape, managing privileged identities has become paramount for enterprises aiming to safeguard their IT environments against unauthorized access and potential breaches. Privileged Identity Management (PIM) solutions are vital for controlling, managing, and auditing privileged access across all parts of an IT environment. In this blog post, I will delve into how to implement PIM using BICEP and the necessity of a P2 Entra license.
What is Privileged Identity Management (PIM)?
Privileged Identity Management (PIM) refers to the control and monitoring of access and rights for users with elevated permissions who have the authority to make critical changes within Azure. PIM solutions help to prevent security breaches by ensuring that only authorized users can access sensitive systems and data.
Why BICEP?
BICEP is a domain-specific language developed by Microsoft, used primarily for deploying Azure resources declaratively. It simplifies the management of infrastructure as code (IaC), offering a cleaner and more concise syntax compared to traditional ARM templates. Using BICEP to implement PIM can streamline the deployment of Azure resources that are specifically configured for enhanced security protocols.
The Role of P2 Entra Licensing
Microsoft Entra, formerly known as Azure Active Directory (Azure AD), offers comprehensive identity and access management solutions, with P2 licensing providing advanced protection features critical for PIM. A P2 license is essential for accessing premium PIM capabilities in Azure, such as just-in-time (JIT) privileged access, risk-based conditional access policies, and detailed auditing and reporting features.
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//// This script is used to elevate a group or a user to a built-in role in Azure using Privileged Identity Management (PIM)
//// The script uses the roleEligibilityScheduleRequests API to elevate the user or group to the specified role
//// The script supports the following built-in roles: GlobalAdmin, Owner, Contributor, Reader
//// The script requires the subscription ID, the principal ID of the user or group to elevate, and the built-in role to assign
//// The script also requires the start date and time for the eligibility schedule and the duration for which the eligibility is valid
//// The script creates a roleEligibilityScheduleRequests resource for each built-in role to assign
//// The script uses the subscription scope to assign the role to the user or group
//// The script uses the role definition IDs for each built-in role to assign
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
targetScope = 'subscription'
param subscriptionId string
// Set the subscription scope using the subscription ID
var subscriptionScope = '/subscriptions/${subscriptionId}'
@description('The start date and time for the eligibility schedule in ISO 8601 format')
param startDateTime string = utcNow()
@description('The duration for which the eligibility is valid in ISO 8601 format (e.g., P90D for 90 days)')
param duration string = 'P90D'
@allowed([
'GlobalAdmin'
'Owner'
'Contributor'
'Reader'
])
@description('Built-in role to assign')
param builtInRoleType string
var role = {
GlobalAdmin: '/subscriptions/${subscription().subscriptionId}/providers/Microsoft.Authorization/roleDefinitions/62e90394-69f5-4237-9190-012177145e10'
Owner: '/subscriptions/${subscription().subscriptionId}/providers/Microsoft.Authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635'
Contributor: '/subscriptions/${subscription().subscriptionId}/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c'
Reader: '/subscriptions/${subscription().subscriptionId}/providers/Microsoft.Authorization/roleDefinitions/acdd72a7-3385-48ef-bd42-f606fba81ae7'
}
param principalIdToElevate string // The principal ID of the user or group to elevate
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//// Deployment starts here
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@description('Elevate User to Reader')
resource pimAssignment 'Microsoft.Authorization/roleEligibilityScheduleRequests@2022-04-01-preview' = if (builtInRoleType == 'Reader') {
name: guid(subscriptionScope, principalIdToElevate, role.Reader)
scope: subscription()
properties: {
principalId: principalIdToElevate
requestType: 'AdminAssign'
roleDefinitionId: role[builtInRoleType]
scheduleInfo: {
expiration: {
duration: duration
type: 'AfterDuration'
}
startDateTime: startDateTime
}
}
}
@description('Elevate User to Contributor')
resource pimAssignment2 'Microsoft.Authorization/roleEligibilityScheduleRequests@2022-04-01-preview' = if (builtInRoleType == 'Contributor') {
name: guid(subscriptionScope, principalIdToElevate, role.Contributor)
scope: subscription()
properties: {
principalId: principalIdToElevate
requestType: 'AdminAssign'
roleDefinitionId: role[builtInRoleType]
scheduleInfo: {
expiration: {
duration: duration
type: 'AfterDuration'
}
startDateTime: startDateTime
}
}
}
@description('Elevate User to Owner')
resource pimAssignment3 'Microsoft.Authorization/roleEligibilityScheduleRequests@2022-04-01-preview' = if (builtInRoleType == 'Owner') {
name: guid(subscriptionScope, principalIdToElevate, role.Owner)
scope: subscription()
properties: {
principalId: principalIdToElevate
requestType: 'AdminAssign'
roleDefinitionId: role[builtInRoleType]
scheduleInfo: {
expiration: {
duration: duration
type: 'AfterDuration'
}
startDateTime: startDateTime
}
}
}
@description('Elevate User to Global Admin')
resource pimAssignment4 'Microsoft.Authorization/roleEligibilityScheduleRequests@2022-04-01-preview' = if (builtInRoleType == 'GlobalAdmin') {
name: guid(subscriptionScope, principalIdToElevate, role.GlobalAdmin)
scope: subscription()
properties: {
principalId: principalIdToElevate
requestType: 'AdminAssign'
roleDefinitionId: role[builtInRoleType]
scheduleInfo: {
expiration: {
duration: duration
type: 'AfterDuration'
}
startDateTime: startDateTime
}
}
}
To call this script you can use the below code
az deployment sub create `
--name $deploymentID `
--location $location `
--template-file ./PIM.bicep `
--parameters subscriptionId=$subscriptionID builtInRoleType=$builtInRoleType principalIdToElevate=$principalIdToElevate `
--confirm-with-what-if `
--output none
I hope you find this script useful, let me know if you have any feedback on this post.







