PIM for Azure Resources provides Just in Time (JIT) and Temporary access capabilities for Azure Resources. See more at https://docs.microsoft.com/en-us/azure/active-directory/privileged-identity-management/azure-pim-resource-rbac
How cool would it be if I can use the underlying api’s of PIM api’s to build custom applications. For example, your IT Org has N different resource groups where you want to activate every day. It would be time consuming to activate them one by one. Instead, you can build a custom app using PowerShell or UI so that you can activate to all of these resource groups in one shot.
In this blog, I will share a sample to list all your eligible roles and activate or deactivate them. And a bonus, it will work even if your role requires MFA
I will share the full source code so you can customize it to suit your needs. This is just a sample and comes with no warranties. Just save this as a .ps1 file and run it with PowerShell.
Screenshot
Source code
#####################################################################Functions##############################################################################################
#Loads Active Directory Authentication Library
function Load-ActiveDirectoryAuthenticationLibrary(){
$moduleDirPath = [Environment]::GetFolderPath("MyDocuments") + "WindowsPowerShellModules"
$modulePath = $moduleDirPath + "AADGraph"
if(-not (Test-Path ($modulePath+"Nugets"))) {New-Item -Path ($modulePath+"Nugets") -ItemType "Directory" | out-null}
$adalPackageDirectories = (Get-ChildItem -Path ($modulePath+"Nugets") -Filter "Microsoft.IdentityModel.Clients.ActiveDirectory*" -Directory)
if($adalPackageDirectories.Length -eq 0){
Write-Host "Active Directory Authentication Library Nuget doesn't exist. Downloading now ..." -ForegroundColor Yellow
if(-not(Test-Path ($modulePath + "Nugetsnuget.exe")))
{
Write-Host "nuget.exe not found. Downloading from http://www.nuget.org/nuget.exe ..." -ForegroundColor Yellow
$wc = New-Object System.Net.WebClient
$wc.DownloadFile("http://www.nuget.org/nuget.exe",$modulePath + "Nugetsnuget.exe");
}
$nugetDownloadExpression = $modulePath + "Nugetsnuget.exe install Microsoft.IdentityModel.Clients.ActiveDirectory -Version 2.14.201151115 -OutputDirectory " + $modulePath + "Nugets | out-null"
Invoke-Expression $nugetDownloadExpression
}
$adalPackageDirectories = (Get-ChildItem -Path ($modulePath+"Nugets") -Filter "Microsoft.IdentityModel.Clients.ActiveDirectory*" -Directory)
$ADAL_Assembly = (Get-ChildItem "Microsoft.IdentityModel.Clients.ActiveDirectory.dll" -Path $adalPackageDirectories[$adalPackageDirectories.length-1].FullName -Recurse)
$ADAL_WindowsForms_Assembly = (Get-ChildItem "Microsoft.IdentityModel.Clients.ActiveDirectory.WindowsForms.dll" -Path $adalPackageDirectories[$adalPackageDirectories.length-1].FullName -Recurse)
if($ADAL_Assembly.Length -gt 0 -and $ADAL_WindowsForms_Assembly.Length -gt 0){
Write-Host "Loading ADAL Assemblies ..." -ForegroundColor Green
[System.Reflection.Assembly]::LoadFrom($ADAL_Assembly[0].FullName) | out-null
[System.Reflection.Assembly]::LoadFrom($ADAL_WindowsForms_Assembly.FullName) | out-null
return $true
}
else{
Write-Host "Fixing Active Directory Authentication Library package directories ..." -ForegroundColor Yellow
$adalPackageDirectories | Remove-Item -Recurse -Force | Out-Null
Write-Host "Not able to load ADAL assembly. Delete the Nugets folder under" $modulePath ", restart PowerShell session and try again ..."
return $false
}
}
#Acquire AAD token
function AcquireToken($mfa){
$clientID = "1950a258-227b-4e31-a9cf-717495945fc2"
$redirectUri = "urn:ietf:wg:oauth:2.0:oob"
$authority = "https://login.microsoftonline.com/common"
$authContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList $authority,$false
if($mfa)
{
$authResult = $authContext.AcquireToken("https://management.core.windows.net/",$ClientID,$redirectUri,[Microsoft.IdentityModel.Clients.ActiveDirectory.PromptBehavior]::Auto, [Microsoft.IdentityModel.Clients.ActiveDirectory.UserIdentifier]::AnyUser, "amr_values=mfa")
Set-Variable -Name mfaDone -Value $true -Scope Global
}
else
{
$authResult = $authContext.AcquireToken("https://management.core.windows.net/",$ClientID,$redirectUri,[Microsoft.IdentityModel.Clients.ActiveDirectory.PromptBehavior]::Always)
}
if($authResult -ne $null)
{
Write-Host "User logged in successfully ..." -ForegroundColor Green
}
Set-Variable -Name headerParams -Value @{'Authorization'="$($authResult.AccessTokenType) $($authResult.AccessToken)"} -Scope Global
Set-Variable -Name assigneeId -Value $authResult.UserInfo.UniqueId -Scope Global
}
#Gets my jit assignments
function MyJitAssignments(){
$url = $serviceRoot + "roleAssignments?`$expand=linkedAssignment,subject,roleDefinition(`$expand=resource)&`$filter=level+eq+'Eligible'"
$response = Invoke-WebRequest -UseBasicParsing -Headers $headerParams -Uri $url -Method Get
$assignments = ConvertFrom-Json $response.Content
Write-Host ""
Write-Host "Role assignments..." -ForegroundColor Green
$i = 0
$obj = @()
foreach ($assignment in $assignments.value)
{
$item = New-Object psobject -Property @{
id = ++$i
IdGuid = $assignment.id
ResourceId = $assignment.roleDefinition.resource.id
OriginalId = $assignment.roleDefinition.resource.originalId
ResourceName = $assignment.roleDefinition.resource.displayName
ResourceType = $assignment.roleDefinition.resource.resourcetype
RoleId = $assignment.roleDefinition.id
RoleName = $assignment.roleDefinition.displayName
ExpirationDate = $assignment.expirationDateTime
SubjectId = $assignment.subject.id
}
$obj = $obj + $item
}
return $obj
}
#Activates the user
function Activate($isRecursive = $false){
if($isRecursive -eq $false)
{
$assignments = MyJitAssignments
$assignments | Format-Table -AutoSize -Wrap id,RoleName,ResourceName,ResourceType,ExpirationDate
$choice = Read-Host "Enter Id to activate"
[int]$hours = Read-Host "Enter Activation duration in hours"
$reason = Read-Host "Enter Reason"
}
$id = $assignments[$choice-1].IdGuid
$resourceId = $assignments[$choice-1].ResourceId
$roleDefinitionId = $assignments[$choice-1].RoleId
$subjectId = $assignments[$choice-1].SubjectId
$url = $serviceRoot + "roleAssignmentRequests"
$postParams = '{"id":"00000000-0000-0000-0000-000000000000","assignmentLevel":"Member","evaluateOnly":false,"requestType":"UserAdd","reason":"' + $reason + '","roleDefinition":{"id":"' + $roleDefinitionId + '","resource":{"id":"' + $resourceId + '"}},"schedule":{"duration":"PT' + $hours + 'H","startDateTime":"' + (Get-Date).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffZ") + '","type":"Once"},"subject":{"id":"' + $subjectId + '","type":"User"},"targetLinkedRoleAssignmentId":"' + $id + '"}'
try
{
$response = Invoke-WebRequest -UseBasicParsing -Headers $headerParams -Uri $url -Method Post -ContentType "application/json" -Body $postParams
Write-Host "Activation request queued successfully ..." -ForegroundColor Green
$recursive = $false
}
catch
{
$stream = $_.Exception.Response.GetResponseStream()
$stream.Position = 0;
$streamReader = New-Object System.IO.StreamReader($stream)
$err = $streamReader.ReadToEnd()
$streamReader.Close()
$stream.Close()
if($mfaDone -eq $false -and $err.Contains("MfaRule"))
{
Write-Host "Prompting the user for mfa ..." -ForegroundColor Green
AcquireToken true
Activate $true
}
else
{
Write-Host $err -ForegroundColor Red
}
}
}
#Deactivates the user
function Deactivate($isRecursive = $false){
if($isRecursive -eq $false)
{
$assignments = MyJitAssignments
$assignments | Format-Table -AutoSize -Wrap id,RoleName,ResourceName,ResourceType,ExpirationDate
$choice = Read-Host "Enter Id to deactivate"
}
$id = $assignments[$choice-1].IdGuid
$resourceId = $assignments[$choice-1].ResourceId
$roleDefinitionId = $assignments[$choice-1].RoleId
$subjectId = $assignments[$choice-1].SubjectId
$url = $serviceRoot + "roleAssignmentRequests"
$postParams = '{"id":"' + $id + '","assignmentLevel":"Member","evaluateOnly":false,"requestType":"UserRemove","roleDefinition":{"id":"' + $roleDefinitionId + '","resource":{"id":"' + $resourceId + '"}},"subject":{"id":"' + $subjectId + '","type":"User"}}'
$response = Invoke-WebRequest -UseBasicParsing -Headers $headerParams -Uri $url -Method Post -ContentType "application/json" -Body $postParams
Write-Host "Role deactivated successfully ..." -ForegroundColor Green
$recursive = $false
}
#Show menu
function ShowMenu()
{
Write-Host ""
Write-Host "Azure RBAC JIT - PowerShell Menu v1.0"
Write-Host " 1. List your eligible role assignments"
Write-Host " 2. Activate an eligible role"
Write-Host " 3. Deactivate an active role"
Write-Host " 4. Exit"
}
############################################################################################################################################################################
$global:serviceRoot = "https://api.azrbac.mspim.azure.com/api/v1/providers('00000000-0000-0000-0000-000000000002')/"
$global:headerParams = ""
$global:assigneeId = ""
$global:mfaDone = $false;
Load-ActiveDirectoryAuthenticationLibrary
AcquireToken
do
{
ShowMenu
$input = Read-Host "Enter your selection"
switch ($input)
{
'1'
{
$assignments = MyJitAssignments
$assignments | Format-Table -AutoSize -Wrap id,RoleName,ResourceName,ResourceType,ExpirationDate
}
'2'
{
Activate
}
'3'
{
Deactivate
}
'4'
{
return
}
}
}
until ($input -eq '4')
Write-Host ""
This post first appeared on MSDN Blogs | Get The Latest Information, Insights, Announcements, And News From Microsoft Experts And Developers In The MSDN Blogs., please read the originial post: here