Azure Global Administrator is the most powerful role in your Microsoft Entra ID (formerly Azure AD) tenant—equivalent to holding the master key to your entire cloud environment. Compromising a single Global Administrator account can give attackers complete control over your Azure subscriptions, Microsoft 365 services, and all associated data. This guide covers essential practices for securing these critical accounts.
This article is part of our comprehensive cloud security tips guide, focusing specifically on Azure privileged identity protection.
Overview
Securing Global Administrator accounts requires a defense-in-depth approach:
- Minimize permanent Global Admins: Limit standing privileges to essential accounts
- Implement emergency access accounts: Ensure you can always access your tenant
- Use Privileged Identity Management: Provide just-in-time elevation
- Enforce strong authentication: Require phishing-resistant MFA
- Monitor privileged activities: Alert on suspicious admin actions
- Separate admin and user accounts: Reduce attack surface
Prerequisites
Before implementing these practices, ensure you have:
- Azure AD Premium P2 license (required for PIM)
- Existing Global Administrator access to configure settings
- Azure CLI (2.50.0+) and/or Microsoft Graph PowerShell module
- Security team alignment on policies and procedures
- Understanding of conditional access and MFA concepts
Step 1: Audit Current Global Administrators
First, identify all accounts with Global Administrator privileges.
Using Azure Portal
- Navigate to Microsoft Entra admin center (entra.microsoft.com)
- Go to Identity > Roles and administrators
- Search for and select Global Administrator
- Review the list of assigned users (both permanent and eligible)
Using Azure CLI
# Install the Microsoft Graph extension if needed
az extension add --name account
# List all Global Administrator role assignments
az ad role assignment list \
--role "62e90394-69f5-4237-9190-012177145e10" \
--all \
--query "[].{Principal:principalName, Type:principalType, Scope:scope}" \
--output table
# The GUID is the Global Administrator role template ID
Using Microsoft Graph PowerShell
# Connect to Microsoft Graph
Connect-MgGraph -Scopes "RoleManagement.Read.Directory"
# Get Global Administrator role
$globalAdminRole = Get-MgDirectoryRole -Filter "displayName eq 'Global Administrator'"
# List all members
Get-MgDirectoryRoleMember -DirectoryRoleId $globalAdminRole.Id | ForEach-Object {
Get-MgUser -UserId $_.Id | Select-Object DisplayName, UserPrincipalName, AccountEnabled
}
Step 2: Create Emergency Access Accounts
Emergency access accounts are critical for maintaining access during outages or lockouts.
Requirements for Emergency Access Accounts
- Cloud-only accounts (not federated or synced)
- Excluded from all conditional access policies
- Long, complex passwords (20+ characters) stored securely offline
- No MFA (or use FIDO2 security key stored in a safe)
- Monitored for any sign-in activity
- At least two accounts for redundancy
Using Azure Portal
- Go to Microsoft Entra admin center > Users > New user
- Create a cloud-only account with a clear naming convention (e.g.,
[email protected]) - Generate a strong password and store it securely (offline, in a safe)
- Assign the Global Administrator role permanently
- Repeat for a second emergency access account
Using Azure CLI
# Create first emergency access account
az ad user create \
--display-name "Emergency Admin 01" \
--user-principal-name "[email protected]" \
--password "$(openssl rand -base64 32)COMPLEX!Pass#2026" \
--force-change-password-next-sign-in false
# Store the password securely before proceeding!
# Get the user object ID
EMERGENCY_USER_ID=$(az ad user show \
--id "[email protected]" \
--query id -o tsv)
# Assign Global Administrator role
az ad role assignment create \
--role "62e90394-69f5-4237-9190-012177145e10" \
--assignee-object-id $EMERGENCY_USER_ID \
--assignee-principal-type User
Exclude from Conditional Access
# List conditional access policies
az rest --method GET \
--url "https://graph.microsoft.com/v1.0/identity/conditionalAccess/policies" \
--query "value[].{Name:displayName, State:state, Id:id}" \
--output table
# For each policy, add emergency accounts to exclusions
# This requires Graph API calls - see PowerShell example below
# Get all conditional access policies
Connect-MgGraph -Scopes "Policy.ReadWrite.ConditionalAccess"
$policies = Get-MgIdentityConditionalAccessPolicy
# Get emergency account IDs
$emergencyAccounts = @(
(Get-MgUser -UserId "[email protected]").Id,
(Get-MgUser -UserId "[email protected]").Id
)
foreach ($policy in $policies) {
# Add emergency accounts to exclusions
$excludedUsers = $policy.Conditions.Users.ExcludeUsers + $emergencyAccounts | Select-Object -Unique
$params = @{
Conditions = @{
Users = @{
ExcludeUsers = $excludedUsers
}
}
}
Update-MgIdentityConditionalAccessPolicy -ConditionalAccessPolicyId $policy.Id -BodyParameter $params
Write-Host "Updated policy: $($policy.DisplayName)"
}
Step 3: Configure Privileged Identity Management (PIM)
PIM provides just-in-time privileged access, dramatically reducing your attack surface.
Enable PIM for Azure AD Roles
- Navigate to Microsoft Entra admin center > Identity Governance > Privileged Identity Management
- Select Azure AD roles
- Click Roles and search for Global Administrator
- Review current assignments
Configure Role Settings
# Connect to Microsoft Graph with PIM permissions
Connect-MgGraph -Scopes "RoleManagement.ReadWrite.Directory"
# Get Global Administrator role definition
$globalAdminRoleId = "62e90394-69f5-4237-9190-012177145e10"
# Get current role settings
$roleSettings = Get-MgPolicyRoleManagementPolicyAssignment -Filter "scopeId eq '/' and scopeType eq 'DirectoryRole' and roleDefinitionId eq '$globalAdminRoleId'"
# Configure activation settings via Azure Portal or Graph API
# Key settings to configure:
# - Maximum activation duration: 8 hours (or less)
# - Require MFA on activation: Yes
# - Require justification: Yes
# - Require approval: Yes (for highly sensitive environments)
# - Require ticket information: Optional
Using Azure Portal for Role Settings
- In PIM, go to Azure AD roles > Settings
- Click on Global Administrator
- Configure activation settings:
- Activation maximum duration: 4-8 hours
- On activation, require: Azure MFA
- Require justification: Yes
- Require ticket information: Optional
- Require approval to activate: Yes (recommended)
- Configure assignment settings:
- Allow permanent eligible assignment: No
- Expire eligible assignments after: 6-12 months
- Allow permanent active assignment: Only for emergency accounts
- Configure notification settings for role activation alerts
Convert Permanent Admins to Eligible
# Get all permanent Global Administrator assignments
$permanentAdmins = Get-MgRoleManagementDirectoryRoleAssignment -Filter "roleDefinitionId eq '$globalAdminRoleId'" |
Where-Object { $_.DirectoryScopeId -eq "/" }
foreach ($assignment in $permanentAdmins) {
# Skip emergency access accounts
$user = Get-MgUser -UserId $assignment.PrincipalId
if ($user.UserPrincipalName -like "emergency-admin*") {
Write-Host "Skipping emergency account: $($user.UserPrincipalName)"
continue
}
# Remove permanent assignment
Remove-MgRoleManagementDirectoryRoleAssignment -UnifiedRoleAssignmentId $assignment.Id
# Create eligible assignment
$params = @{
Action = "adminAssign"
Justification = "Converting to eligible assignment for security"
RoleDefinitionId = $globalAdminRoleId
DirectoryScopeId = "/"
PrincipalId = $assignment.PrincipalId
ScheduleInfo = @{
StartDateTime = Get-Date
Expiration = @{
Type = "afterDuration"
Duration = "P365D" # 1 year eligible assignment
}
}
}
New-MgRoleManagementDirectoryRoleEligibilityScheduleRequest -BodyParameter $params
Write-Host "Converted $($user.UserPrincipalName) to eligible assignment"
}
Step 4: Enforce Strong Authentication
Global Administrators must use the strongest available authentication methods.
Require Phishing-Resistant MFA
Create a conditional access policy specifically for administrators:
Connect-MgGraph -Scopes "Policy.ReadWrite.ConditionalAccess"
# Create admin MFA policy
$params = @{
DisplayName = "Require Phishing-Resistant MFA for Administrators"
State = "enabled"
Conditions = @{
Users = @{
IncludeRoles = @(
"62e90394-69f5-4237-9190-012177145e10", # Global Administrator
"e8611ab8-c189-46e8-94e1-60213ab1f814", # Privileged Role Administrator
"194ae4cb-b126-40b2-bd5b-6091b380977d" # Security Administrator
)
ExcludeUsers = @($emergencyAccounts)
}
Applications = @{
IncludeApplications = @("All")
}
}
GrantControls = @{
Operator = "OR"
AuthenticationStrength = @{
Id = "00000000-0000-0000-0000-000000000004" # Phishing-resistant MFA
}
}
}
New-MgIdentityConditionalAccessPolicy -BodyParameter $params
Require Compliant Devices
# Additional policy requiring compliant or hybrid joined devices
$deviceParams = @{
DisplayName = "Require Compliant Device for Admin Access"
State = "enabled"
Conditions = @{
Users = @{
IncludeRoles = @("62e90394-69f5-4237-9190-012177145e10")
ExcludeUsers = @($emergencyAccounts)
}
Applications = @{
IncludeApplications = @(
"797f4846-ba00-4fd7-ba43-dac1f8f63013", # Azure Management
"00000003-0000-0000-c000-000000000000" # Microsoft Graph
)
}
Platforms = @{
IncludePlatforms = @("all")
}
}
GrantControls = @{
Operator = "OR"
BuiltInControls = @("compliantDevice", "domainJoinedDevice")
}
}
New-MgIdentityConditionalAccessPolicy -BodyParameter $deviceParams
Step 5: Monitor Privileged Activities
Set up comprehensive monitoring for all administrative actions.
Configure Azure AD Audit Log Alerts
# Create action group for admin alerts
az monitor action-group create \
--name "AdminSecurityAlerts" \
--resource-group "rg-security-monitoring" \
--short-name "AdminAlerts" \
--email-receiver name="SecurityTeam" email-address="[email protected]" \
--webhook-receiver name="SIEM" uri="https://your-siem.com/webhook"
# Create alert for Global Admin role assignments
az monitor activity-log alert create \
--name "GlobalAdminRoleAssignment" \
--resource-group "rg-security-monitoring" \
--condition category=Administrative and operationName="Add member to role" \
--action-group "AdminSecurityAlerts" \
--description "Alert when users are added to Global Administrator role"
Log Analytics Query for Admin Activities
// Query for PIM role activations
AuditLogs
| where TimeGenerated > ago(24h)
| where OperationName == "Add member to role in PIM completed (permanent)"
or OperationName == "Add eligible member to role in PIM completed"
or OperationName == "Add member to role in PIM completed (timebound)"
| where TargetResources[0].displayName == "Global Administrator"
| project TimeGenerated, InitiatedBy.user.userPrincipalName, TargetResources[0].userPrincipalName, OperationName, Result
// Query for emergency access account sign-ins (should be rare/never)
SigninLogs
| where TimeGenerated > ago(7d)
| where UserPrincipalName startswith "emergency-admin"
| project TimeGenerated, UserPrincipalName, IPAddress, Location, Status, AppDisplayName
Create Workbook for Admin Monitoring
{
"version": "Notebook/1.0",
"items": [
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
"query": "AuditLogs | where Category == 'RoleManagement' | where TimeGenerated > ago(30d) | summarize count() by bin(TimeGenerated, 1d), OperationName | render timechart",
"title": "Role Management Activities (30 days)"
}
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
"query": "SigninLogs | where UserPrincipalName in ('[email protected]', '[email protected]') | project TimeGenerated, UserPrincipalName, IPAddress, Status",
"title": "Emergency Account Sign-ins (Alert: Should be empty)"
}
}
]
}
Step 6: Implement Separation of Duties
Administrators should use separate accounts for privileged and daily work.
Account Naming Convention
Daily work account: [email protected]
Admin account: [email protected]
Emergency account: [email protected]
Restrict Admin Accounts
# Block admin accounts from non-administrative applications
$restrictAdminParams = @{
DisplayName = "Block Admin Accounts from User Apps"
State = "enabled"
Conditions = @{
Users = @{
IncludeUsers = @("All")
ExcludeGroups = @($regularUsersGroupId)
}
Applications = @{
IncludeApplications = @(
"00000002-0000-0ff1-ce00-000000000000", # Office 365 Exchange
"00000003-0000-0ff1-ce00-000000000000" # Office 365 SharePoint
)
}
ClientAppTypes = @("all")
}
GrantControls = @{
Operator = "OR"
BuiltInControls = @("block")
}
}
New-MgIdentityConditionalAccessPolicy -BodyParameter $restrictAdminParams
Best Practices Summary
Do's
- Limit permanent Global Administrators to 4-5 accounts maximum
- Always have 2 emergency access accounts configured and tested
- Use PIM for just-in-time privileged access
- Require phishing-resistant MFA for all admin activities
- Monitor and alert on all privileged operations
- Regularly review and recertify access (quarterly minimum)
- Test emergency access procedures annually
Don'ts
- Never use Global Administrator accounts for daily work
- Never share admin credentials between users
- Don't skip MFA for convenience
- Don't ignore alerts about privileged activities
- Never store emergency account passwords digitally
Terraform Configuration
For infrastructure-as-code deployments:
# Configure Azure AD provider
terraform {
required_providers {
azuread = {
source = "hashicorp/azuread"
version = "~> 2.47"
}
}
}
# Create emergency access account
resource "azuread_user" "emergency_admin_01" {
user_principal_name = "emergency-admin-01@${var.domain}"
display_name = "Emergency Admin 01"
password = var.emergency_admin_password # Use secrets manager
lifecycle {
prevent_destroy = true # Prevent accidental deletion
}
}
# Assign Global Administrator role
resource "azuread_directory_role_assignment" "emergency_admin_global" {
role_id = "62e90394-69f5-4237-9190-012177145e10"
principal_object_id = azuread_user.emergency_admin_01.object_id
}
# Create conditional access policy for admins
resource "azuread_conditional_access_policy" "admin_mfa" {
display_name = "Require MFA for Administrators"
state = "enabled"
conditions {
users {
included_roles = [
"62e90394-69f5-4237-9190-012177145e10" # Global Administrator
]
excluded_users = [
azuread_user.emergency_admin_01.object_id
]
}
applications {
included_applications = ["All"]
}
}
grant_controls {
operator = "OR"
built_in_controls = ["mfa"]
}
}
Troubleshooting
Issue: Locked Out of Tenant
If all Global Administrators are locked out:
- Use an emergency access account to sign in
- If emergency accounts are also locked, contact Microsoft Support
- Provide proof of tenant ownership for recovery
Issue: PIM Role Activation Fails
# Check if user has eligible assignment
Get-MgRoleManagementDirectoryRoleEligibilitySchedule -Filter "principalId eq '$userId' and roleDefinitionId eq '62e90394-69f5-4237-9190-012177145e10'"
# Check activation requirements
Get-MgPolicyRoleManagementPolicyRule -UnifiedRoleManagementPolicyId $policyId
Issue: Emergency Account Excluded from Too Many Policies
Regularly audit emergency account exclusions:
# List all policies excluding emergency accounts
Get-MgIdentityConditionalAccessPolicy | ForEach-Object {
if ($_.Conditions.Users.ExcludeUsers -contains $emergencyAccountId) {
Write-Host "Policy: $($_.DisplayName) excludes emergency account"
}
}