Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions Deploy-Policies.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@
.PARAMETER PoliciesFolder
Path of the folder where the templates are located e.g. C:\Repos\ConditionalAccess\Policies

.PARAMETER ExistingPoliciesFolder
Path of the folder where dumps of existing policies are stored e.g. C:\Repos\ConditionalAccess\Policies\ImplementedPolicies

.PARAMETER ExclusionGroupsPrefix
Prefix of the exclusion groups that are created for each policy, if no value is specified, the prefix value is used
If no value is provided:
Expand Down Expand Up @@ -96,6 +99,9 @@ Param(
[System.String]$PoliciesFolder
,
[Parameter(Mandatory=$False)]
[System.String]$ExistingPoliciesFolder
,
[Parameter(Mandatory=$False)]
[System.String]$ExclusionGroupsPrefix
,
[Parameter(Mandatory=$False)]
Expand Down Expand Up @@ -139,6 +145,7 @@ if(-not $EmergencyAccessAccountsGroup){$EmergencyAccessAccountsGroup = $Prefix +
if(-not $RingTargeted){$RingTargeted = $False}
if(-not $RingGroup){$RingGroup = $Prefix + "_" + $Ring}
if(-not $AdministratorGroup){$AdministratorGroup = $Prefix + "_Administrator"}
if(-not $ExistingPoliciesFolder){$ExistingPoliciesFolder = '.\PolicySets\Implemented policies\'}
#endregion

#region functions
Expand Down Expand Up @@ -192,6 +199,17 @@ $Policies = foreach($Item in $Templates){
}
#endregion

#region import existing policies from the repo
Write-Host "Importing existing policies"
$ExisitingPoliciesFiles = Get-ChildItem -Path $ExistingPoliciesFolder
if ($ExisitingPoliciesFiles) {
$ExistingPolicies = foreach($Item in $ExisitingPoliciesFiles){
$ExistingPolicy = Get-Content -Raw -Path $Item.FullName | ConvertFrom-Json
$ExistingPolicy
}
}
#endregion

#region create or update policies
foreach($Policy in $Policies){
Write-Host "Working on policy: $($Policy.displayName)"
Expand Down Expand Up @@ -274,6 +292,13 @@ foreach($Policy in $Policies){
$Policy.conditions.users.excludeGroups = $excludeGroups
}

#Add policy ID to the template if policy file is stored in the repo

if ($ExistingPolicy) {
$policyID = ($ExistingPolicies | Where-Object {$_.DisplayName -eq $Policy.DisplayName}).Id
if ($policyID){$Policy | add-member -name "id" -MemberType NoteProperty -Value $policyID}
}

#Create or update

$requestBody = $Policy | ConvertTo-Json -Depth 3
Expand Down
125 changes: 125 additions & 0 deletions Save-Policies.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
<#
.SYNOPSIS
Script for storing existing Conditional Access Policies in specified folder based on JSON representations

.DESCRIPTION
Connects to Microsoft Graph

Imports policies from Azure AD
Replaces object ID in policies with their display names
Exports JSON representations of conditional access policies to a specified folder

.PARAMETER PoliciesFolder
Path of the folder where the templates are located e.g. C:\Repos\ConditionalAccess\Policies

.PARAMETER Endpoint
Allows you to specify the Graph endpoint (Beta or Canary), if not specified it will default to Beta

.PARAMETER TenantId
If you use a guest account for signing in you may specify tenant ID to establish session with proper Azure AD tenant

.NOTES
Version: 0.1
Author: Szymon Baranek
Creation date: 2023-04-11
Last modified: 2023-04-26

The script is based on the logic from Deploy-Policies.ps1 script developed by Alexander Filipin.

.EXAMPLE
.\Save-Policies.ps1 -PoliciesFolder "C:\Repos\ConditionalAccess\PolicySets\Implemented policies"

.EXAMPLE
#>
Param(
[Parameter(Mandatory = $True)]
[System.String]$PoliciesFolder
,
[Parameter(Mandatory = $False)]
[System.String]$Endpoint
,
[Parameter(Mandatory = $False)]
[System.String]$TenantId
)
#Requires -Modules Microsoft.Graph.Authentication, Microsoft.Graph.Identity.SignIns, Microsoft.Graph.Groups, Microsoft.Graph.Identity.DirectoryManagement

#region connect
Import-Module -Name Microsoft.Graph.Authentication -ErrorAction Stop
Import-Module -Name Microsoft.Graph.Groups -ErrorAction Stop
Import-Module -Name Microsoft.Graph.Identity.SignIns -ErrorAction Stop
Import-Module -Name Microsoft.Graph.Identity.DirectoryManagement -ErrorAction Stop

if ($Endpoint -eq "Beta") {
Select-MgProfile -Name "beta"
}
elseif ($Endpoint -eq "V1") {
Select-MgProfile -Name "v1.0"
}
else {
Select-MgProfile -Name "beta"
}
try { Disconnect-MgGraph -ErrorAction SilentlyContinue } catch {}

$mgScopes = @("Application.Read.All", "Group.ReadWrite.All", "Policy.Read.All", "Policy.ReadWrite.ConditionalAccess", "Directory.Read.All", "RoleManagement.Read.All")

if ($TenantId) {
Connect-MgGraph -Scopes $mgScopes -TenantId $TenantId -ErrorAction Stop
}
else {
Connect-MgGraph -Scopes $mgScopes -ErrorAction Stop
}
#endregion

#region retrive policies and resolve object IDs for display names
$Policies = Get-MgIdentityConditionalAccessPolicy -All
$SelectedPolicies = $Policies | Out-GridView -PassThru

foreach ($Policy in $SelectedPolicies) {
Write-Host "Working on policy: $($Policy.displayName)"

if ($Policy.conditions.users.includeGroups) {
[System.Collections.ArrayList]$groupIds = $Policy.conditions.users.includeGroups
$groupNames = New-Object -TypeName System.Collections.ArrayList
foreach ($groupId in $groupIds) {
$groupName = (get-mggroup -GroupId $groupId).DisplayName
$groupNames.Add($groupName) > $null
}

$Policy.conditions.users.includeGroups = $groupNames
}

if ($Policy.conditions.users.excludeGroups) {
[System.Collections.ArrayList]$groupIds = $Policy.conditions.users.excludeGroups
$groupNames = New-Object -TypeName System.Collections.ArrayList
foreach ($groupId in $groupIds) {
$groupName = (get-mggroup -GroupId $groupId).DisplayName
$groupNames.Add($groupName) > $null
}

$Policy.conditions.users.excludeGroups = $groupNames
}

if ($Policy.conditions.users.IncludeRoles) {
$roles = Get-MgDirectoryRoleTemplate -All
[System.Collections.ArrayList]$roleIds = $Policy.conditions.users.IncludeRoles
$roleNames = New-Object -TypeName System.Collections.ArrayList
foreach ($roleId in $roleIds) {
$roleName = ($roles | where-object { $_.Id -eq $roleId }).DisplayName
$roleNames.Add($roleName) > $null
}

$Policy.conditions.users.IncludeRoles = $roleNames
}

# Save policy files

$requestBody = $Policy | ConvertTo-Json -Depth 3
$policyFilename = $Policy.displayName.Replace(":", "") + ".json"
$policyFilePath = $PoliciesFolder + $policyFilename
Out-File -InputObject $requestBody -FilePath $policyFilePath -Force:$true -Confirm:$false -Encoding utf8
}
#endregion

#region disconnect
try {Disconnect-MgGraph -ErrorAction SilentlyContinue} catch {}
#endregion