Azure AD Conditional Access Maintenance and Automation Task - chadmcox/Azure_Active_Directory GitHub Wiki

Add Break Glass to All Conditional Access Policies

Conditional Access Backup and Restore Procedure

Objective:

  • Backup and restore Conditional Access Policies in Azure AD
  • Backup and restore Conditional Access Named Location in Azure AD

Notes:

These two cmdlets are junk "New-MgIdentityConditionalAccessPolicy" and "New-MgIdentityConditionalAccessPolicy"

Backup Policies

Using PowerShell

  • This will require the Microsoft.Graph.Authentication modules
#check to see if module installed
PS C:\> get-module Microsoft.Graph.Authentication -listavailable

#if not installed, then install it
PS C:\> install-module Microsoft.Graph.Authentication

#or install all the microsoft.graph modules
PS C:\> install-module Microsoft.Graph
  • Sign-in to the tenant with an account with Global Admins, Conditional Access Admins, or Security Admins
  • Will also need to provide the permissions and consent
PS C:\> Connect-MgGraph -Scopes "Policy.Read.All", "Policy.ReadWrite.ConditionalAccess", "Directory.ReadWrite.All", "Directory.AccessAsUser.All"
  • Create a folder to store the backups
# Create folder
PS C:\> new-item c:\backup -type directory
PS C:\> new-item 'c:\backup\conditional access policies' -type directory

  • Backup the policies
# Export Conditional Access policies from graph to variable named caps
PS C:\> Invoke-MgGraphRequest -Method GET -uri "https://graph.microsoft.com/beta/identity/conditionalAccess/policies" -OutputType PSObject | select -ExpandProperty value -OutVariable caps

# Write the conditional access policies to files
PS C:\> $caps | foreach {$cap = $_;$cap | convertto-json -Depth 99 | out-file "c:\backup\conditional access policies\$(Get-Date -Format "yyyy_MM_dd") $($cap.displayname -replace("/"," ")).json"}

  • Should look something like this in the folder
PS C:\> dir 'c:\backup\conditional access policies' | select name

Name                                                                                                            
----                                                                                                            
2022_04_06 All Users - Block Legacy Authentication.json                                                         
2022_04_06 All Users - Block Tor Exit Nodes.json                                                                
2022_04_06 All Users - Require Compliant Device for All Cloud Apps.json                                         
2022_04_06 All Users - Require MFA Device Join Registration.json                                                
2022_04_06 All Users - Require MFA for All Cloud Apps.json           

Restore Policies

Using PowerShell

  • Sign-in to the tenant with an account with Global Admins, Conditional Access Admins, or Security Admins
  • Will also need to provide the permissions and consent
PS C:\> Connect-MgGraph -Scopes "Policy.Read.All", "Policy.ReadWrite.ConditionalAccess", "Directory.ReadWrite.All", "Directory.AccessAsUser.All"
  • Read the file and import the policy
# Read the json and store in a variable as an object
PS C:\> get-content 'c:\backup\conditional access policies\2022_04_06 All Users - Block Legacy Authentication.json' | convertfrom-json  | select displayName, state, sessionControls, conditions, grantControls -OutVariable restorePolicy

# Using graph import the contents of the json
PS C:\> Invoke-MgGraphRequest -Method POST -uri "https://graph.microsoft.com/v1.0/identity/conditionalAccess/policies" `
        -ContentType "application/json" -Body ($restorePolicy | convertto-json -Depth 99)

Backup Named Locations

  • Create a folder to store the backups
# Create folder
PS C:\> new-item c:\backup -type directory
PS C:\> new-item 'c:\backup\named locations' -type directory
  • Backup the named locations
# Export Conditional Access policies from graph to variable named caps
PS C:\> Invoke-MgGraphRequest -Method GET -uri "https://graph.microsoft.com/v1.0/identity/conditionalAccess/namedLocations" -OutputType PSObject | select -ExpandProperty value -OutVariable caps

# Write the conditional access policies to files
PS C:\> $caps | foreach {$cap = $_;$cap | convertto-json -Depth 99 | out-file "c:\backup\named locations\$(Get-Date -Format "yyyy_MM_dd") $($cap.displayname -replace("/"," ")).json"}

  • Should look something like this in the folder
PS C:\> dir 'c:\backup\named locations' | select name

Name                                    
----                                    
2022_04_06 Office 1.json
2022_04_06 Tor Exit Nodes.json    
2022_04_06 Office 2.json                  
2022_04_06 Office 3.json                  
2022_04_06 Office 4.json         

Restore Named Locations

# Read the file and store to variable
get-content 'c:\backup\named locations\2022_04_06 Tor Exit Nodes.json' | convertfrom-json | select "@odata.type",displayName,isTrusted,ipRanges -OutVariable restoreNameLocation 

# import named location
Invoke-MgGraphRequest -Method POST -Uri "https://graph.microsoft.com/v1.0/identity/conditionalAccess/namedLocations" -Body ($restoreNameLocation | convertto-json -Depth 99)

Automate Exclusion of BreakGlass / Emergency Access Account.

This link will take you to script that does this

Automate Exclusion Group Creation for Conditional Access Policies.

Using PowerShell

Connect-MgGraph -Scopes "Policy.Read.All", "Policy.ReadWrite.ConditionalAccess", "Directory.ReadWrite.All", "Directory.AccessAsUser.All", "GroupMember.ReadWrite.All","Group.ReadWrite.All"

#update this to meet requirements
$groupprefix = "GRP.CAP.Exclude"

#Create Admin Unit

$body = @"
{
    "displayName": "AU.CAP.Exclusion - Conditional Access Policy Exclusion Groups",
    "description": "Conditional Access Policy Exclusion Groups for administration",
    "visibility": "HiddenMembership"
}
"@

$au = Invoke-MgGraphRequest -Method POST -uri "https://graph.microsoft.com/beta/administrativeUnits" -ContentType 'application/json' -body $body
$AllPolicies = (Invoke-MgGraphRequest -Method GET -uri "https://graph.microsoft.com/v1.0/identity/conditionalAccess/policies" -OutputType PSObject).value

#Create groups for each policy, link to admin unit and update cap
#will need to run rest of this code together.

foreach($p in $AllPolicies){
$body = @"
{
  "@odata.type": "#Microsoft.Graph.Group",
  "description": "Group to Exclude Conditional Access Policy: $($p.displayname)",
  "displayName": "$groupprefix - $($p.displayname)",
  "groupTypes": [
  ],
  "mailEnabled": false,
  "mailNickname": "capExclude$(1..10000 | get-random)",
  "securityEnabled": true,
}
"@

$grp = Invoke-MgGraphRequest -Method POST -uri "https://graph.microsoft.com/beta/administrativeUnits/$($au.id)/members" -ContentType 'application/json' -body $body

#add to conditional access policy
$addtoexc = @(($p.conditions.users.excludeGroups + $($grp.id)) -join("`",`""))

$body = @"
{
    "conditions": {
        "users": {
            "excludeGroups": [
                "$addtoexc"
            ]
        }
    }
}
"@

$uri = "https://graph.microsoft.com/v1.0/identity/conditionalAccess/policies/$($p.id)"
Invoke-MgGraphRequest -Uri $Uri -Method PATCH -ContentType "application/json" -body $body

}