Farid
02/06/2025, 1:15 PMjvitech
02/06/2025, 1:43 PMFarid
02/06/2025, 2:04 PMjvitech
02/06/2025, 5:56 PMChris Schrameyer
02/07/2025, 10:24 AMFarid
02/24/2025, 3:56 PMJeff Riechers
02/25/2025, 1:21 PMkeislij
02/25/2025, 7:05 PMFarid
03/20/2025, 9:31 AMSebastian Parelius
03/20/2025, 11:17 AMJulian Jakob
03/20/2025, 11:24 AMFarid
03/20/2025, 12:08 PMSebastian Parelius
03/20/2025, 12:15 PMFarid
03/20/2025, 12:16 PMFarid
03/20/2025, 12:54 PMJoost Sannen
03/25/2025, 7:40 AMSebastian Parelius
03/25/2025, 7:42 AMJulian Jakob
03/25/2025, 7:42 AMJoost Sannen
03/25/2025, 7:49 AMSebastian Parelius
03/25/2025, 7:51 AMJoost Sannen
03/25/2025, 10:06 AMDisclaimer: This code is provided “as-is” without any warranty of correctness, functionality, or fitness for a particular purpose. Use it at your own risk. The author is not responsible for any damage, loss, or errors resulting from its use. Carefully review and test the code before deploying it in a production environment.Azure Automation Subscription • Create subscription • Give a Global Administrator account owner rights • Subscription renamed to SUB-ICT Resource group • Create resource group MGMT-RG-ICT-AA in subscription SUB-ICT Automation account • Create Azure Automation Account “MGMT-AUTO-MFA” in subscription SUB-ICT Entra ID Group • Create an Entra ID functional group “MFA-AuthenticatorEnabledUsers” • Save the group id for later reference Rights for the Automation Account
connect-azuread
$TenantID = "[TENANTID]"
$DisplayNameOfMSI= "MGMT-AUTO-MFA"
$GraphAppId = "00000003-0000-0000-c000-000000000000"
$PermissionName1 = "User.Read.All"
$PermissionName2 = "Group.ReadWrite.All"
$PermissionName3 = "UserAuthenticationMethod.Read.All"
$MSI = (Get-AzureADServicePrincipal -Filter "displayName eq '$DisplayNameOfMSI'")
Start-Sleep -Seconds 10
$GraphServicePrincipal = Get-AzureADServicePrincipal -Filter "appId eq '$GraphAppId'"
$AppRole = $GraphServicePrincipal.AppRoles | Where-Object {$_.Value -eq $PermissionName1 -and $_.AllowedMemberTypes -contains "Application"}
New-AzureAdServiceAppRoleAssignment -ObjectId $MSI.ObjectId -PrincipalId $MSI.ObjectId -ResourceId $GraphServicePrincipal.ObjectId -Id $AppRole.Id
$AppRole = $GraphServicePrincipal.AppRoles | Where-Object {$_.Value -eq $PermissionName2 -and $_.AllowedMemberTypes -contains "Application"}
New-AzureAdServiceAppRoleAssignment -ObjectId $MSI.ObjectId -PrincipalId $MSI.ObjectId -ResourceId $GraphServicePrincipal.ObjectId -Id $AppRole.Id
$AppRole = $GraphServicePrincipal.AppRoles | Where-Object {$_.Value -eq $PermissionName3 -and $_.AllowedMemberTypes -contains "Application"}
New-AzureAdServiceAppRoleAssignment -ObjectId $MSI.ObjectId -PrincipalId $MSI.ObjectId -ResourceId $GraphServicePrincipal.ObjectId -Id $AppRole.Id
• Open the just created Azure Automation account
• Remove demo runbooks if present
• Create a new runbook MGMT-AUTO-RB-MFAEnabledUsers
◦ Runbook type: Powershell
◦ Runtime version: 7.2
◦ In shared resources. Add gallery modules on runtime version 7.2:
▪︎ Microsoft.Graph.Authentication
▪︎ Microsoft.Graph.Groups
▪︎ Microsoft.Graph.Identity.SignIns
▪︎ Microsoft.Graph.Users
◦ In script modify the group id en write-output:
Connect-AzAccount -Identity -ErrorAction Stop | Out-Null
$AccessToken = Get-AzAccessToken -ResourceTypeName MSGraph -ErrorAction Stop | select -ExpandProperty Token
$targetParameter = (Get-Command Connect-MgGraph).Parameters['AccessToken']
if ($targetParameter.ParameterType -eq [securestring]){
Connect-MgGraph -AccessToken ($AccessToken |ConvertTo-SecureString -AsPlainText -Force) -NoWelcome
} else {
Connect-MgGraph -AccessToken $AccessToken -NoWelcome
}
Write-Output "Connected to Microsoft Graph"
$users = get-mguser -All -Filter "OnPremisesSyncEnabled eq true and UserType eq 'Member'"
Write-Output "All synced members retrieved"
$groups = Get-MgGroupMember -GroupId ' 700a03be-fd2d-4646-b5f5-d49470bfaff2’
Write-Output "Members of group F_MFA-AuthenticatorEnabledUsers retrieved"
$results=@();
#loop through each user account
foreach ($user in $users) {
$myObject = [PSCustomObject]@{
user = "-"
displayname = "-"
MFAstatus = "_"
app = "-"
password = "-"
}
$MFAData=Get-MgUserAuthenticationMethod -UserId $user.UserPrincipalName #-ErrorAction SilentlyContinue
$myobject.displayname = $user.displayname
$myobject.user = $user.id;
#check authentication methods for each user
ForEach ($method in $MFAData) {
Switch ($method.AdditionalProperties["@odata.type"]) {
"#microsoft.graph.microsoftAuthenticatorAuthenticationMethod" {
$<http://myObject.app|myObject.app> = $true
$myObject.MFAstatus = "Enabled"
}
}
}
$results+= $myObject;
}
Write-Output "Authentication methods of users retrieved"
foreach ($result in $results)
{
$name = $result.displayname
if ($result.MFAStatus -eq 'Enabled')
{
Write-Output "User $name added to F_MFA-AuthenticatorEnabledUsers"
New-MgGroupMember -GroupId '[GROUPID]' -DirectoryObjectId $result.user -ErrorAction Ignore
} else {
Write-Output "User $name didn't configure MFA authenticator yet"
}
}
Do a manual test and when successful create a schedule for each moment you want it to run. Bind the schedules to the runbook.