Mission Objective
Overhaul Azure Automation security—replace the fragile AzureRunAs account with a Managed Identity tied to Microsoft Graph. Eliminate certificate expiry risks, secure script ops, and pull tenant data with precision.
Gear Check
Azure Subscription: Automation Account live, Contributor role assigned.
Managed Identity: System-assigned (default) or user-assigned, prepped.
PowerShell: Microsoft.Graph module (Install-Module Microsoft.Graph -Scope CurrentUser).
Azure AD: Admin access for Graph API permissions (e.g., Directory.Read.All, User.Read.All).
Runbook: Existing script with AzureRunAs to overhaul.
The Play
Shift to Managed Identity and hook into Graph with this sequence:
# Install Module (if missing)
Install-Module -Name Microsoft.Graph -Scope CurrentUser -Force
# Connect with Managed Identity
Connect-MgGraph -Identity -NoWelcome
# Test Graph Access
$users = Get-MgUser -Top 10 -Property DisplayName,UserPrincipalName
$users | Format-Table -Property DisplayName,UserPrincipalName
# Add Your Logic
<Your existing script here, no AzureRunAs needed>
Execution
Step 1—Drop AzureRunAs:
In Azure Portal, hit your Automation Account > “Accounts” blade. Spot AzureRunAs—cert-driven, expires yearly, a weak link. We’re phasing it out.
Step 2—Activate Managed Identity:
Navigate to “Identity” blade. Flip “System-assigned” to “On” (or attach a User-assigned Identity if set). Save. Note the Object ID—your new asset.
Step 3—Assign Permissions:
Head to Azure AD > “Enterprise Applications” > search the Object ID (or Automation Account name for system-assigned).
Under “Permissions,” add Microsoft Graph API scopes: Directory.Read.All for tenant-wide reads, User.Read.All for user details—match your script’s needs.
Click “Grant admin consent” if flagged.
In IAM (Automation Account), confirm “Contributor” role on the identity—covers runtime access.
Step 4—Refit Runbook:
Open your runbook in Edit mode.
Scrap Connect-AzAccount -Credential (Get-AutomationPSCredential -Name 'AzureRunAs')—it’s obsolete.
Replace with Connect-MgGraph -Identity -NoWelcome—direct, no token hops.
Plug in your script logic—Graph calls like Get-MgUser now run free.
Step 5—Test Run: Hit the Test Pane. Execute. Look for Graph output—user names, UPNs, no hiccups.
Verify: Save, publish, launch the job. Check Automation Logs—Graph responds, no cert expiry ghosts.
TRAINING MISSION:
Our example will focus on adding the SharePoint “User.Read.All” permission so the automation can connect to SharePoint and pull user profile data from Delve—a recent mission requirement.
Step 1: Gather the SharePoint API ID
Head to Graph Explorer and look up the SharePoint API ID. This ID should be consistent across tenants. Use this query:
https://graph.microsoft.com/v1.0/servicePrincipals?$filter=appID eq '00000003-0000-0ff1-ce00-000000000000'
You’ll get a response with an “id” value.
Save it as $sharepointApiId:
$sharepointApiId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
Step 2: Locate the Service Principal ID
Find the Service Principal ID for your Automation account. Get it from the Azure portal by searching for the Service Principal name, or use Graph Explorer with this query:
https://graph.microsoft.com/v1.0/servicePrincipals?$search="displayName:<your automation account name>"
Replace <your automation account name> with the name of your Managed Identity. Assign the resulting “id” to $servicePrincipalId:
$servicePrincipalId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
Step 3: Identify the App Role ID
Find the ID for the app role you want to assign—in this case, “User.Read.All.” Run this in Graph Explorer:
https://graph.microsoft.com/v1.0/servicePrincipals/<sharepointApiID>/appRoles
Replace <sharepointApiID> with the value from Step 1. Look through the results for “User.Read.All.” (The search in Graph Explorer is inefficient, so you may want to copy the output into Notepad++ to find it.) Store the “id” as $appRoleId:
$appRoleId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
Step 4: Connect to Graph and Assign Permissions
Connect to Microsoft Graph using a global admin account. Stick to username/password login here—certificate or app-based methods might not carry the needed permissions.
Connect-MgGraph -TenantId $Tenant_Id
Then, run this to assign the permission:
$oAppRoleAssignment = @{
"PrincipalId" = $servicePrincipalId
"ResourceId" = $sharepointApiId
"AppRoleId" = $appRoleId
}
New-MgServicePrincipalAppRoleAssignment `
-ServicePrincipalId $oAppRoleAssignment.PrincipalId `
-BodyParameter $oAppRoleAssignment `
-Verbose
Permissions assigned.
Step 5: Test It in Your Runbook
Head back to your runbook and test the connection. Here’s a sample script:
Import-Module PnP.PowerShell
# Check if the module loaded
$moduleCk = Get-Module PnP.PowerShell
if ($null -ne $moduleCk) {
"PnP.PowerShell Module is available"
} else {
$ErrorMessage = "Module PnP.PowerShell is missing. Please install module in PowerShell Cloud Environment"
Write-Output $ErrorMessage
Exit 2
}
try {
Write-Output "Connecting to SharePoint..."
Connect-PnPOnline -Url https://<tenantname>-admin.sharepoint.com -ManagedIdentity
} catch {
Write-Warning "$($_.Exception.Message)"
$ErrorMessage = "$($_.Exception.Message)"
throw $_.Exception
Exit 2
}
$upn = "<userprincipalname you want to look up>"
$userprofile = Get-PnPUserProfileProperty -Account $upn
Write-Output $userprofile.DisplayName
Swap <tenantname> and <userprincipalname you want to look up> with your targets. Execute clean, and you’ll get the user’s display name in the clear.
Mission Value
AzureRunAs is a relic—certs expire, creds dangle. Managed Identity locks it tight: no renewals, no secrets, direct Graph access. Scripts fire secure, pulling M365 data with zero drift.
Field Notes
Identity flops? Recheck “Contributor” role or network rules. Graph denies? Scope perms—Directory.Read.All might need backup like Group.Read.All. No output? Test Connect-MgGraph -Identity solo. Intel—I’m on watch.