From da28948693241e25ac03470f6a0301d5220210ab Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 24 Oct 2025 06:04:03 +0000 Subject: [PATCH 1/5] Initial plan From 8dbefbcdf71548acaec2fd3e58158b162a2e824d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 24 Oct 2025 06:13:42 +0000 Subject: [PATCH 2/5] Add ConfigurationPolicy export and import scripts for all technology types Co-authored-by: Mahopper <29206133+Mahopper@users.noreply.github.com> --- .../ConfigurationPolicy_Export.ps1 | 335 ++++++++++++++++++ .../ConfigurationPolicy_Import_FromJSON.ps1 | 248 +++++++++++++ ConfigurationPolicy/readme.md | 178 ++++++++++ 3 files changed, 761 insertions(+) create mode 100644 ConfigurationPolicy/ConfigurationPolicy_Export.ps1 create mode 100644 ConfigurationPolicy/ConfigurationPolicy_Import_FromJSON.ps1 create mode 100644 ConfigurationPolicy/readme.md diff --git a/ConfigurationPolicy/ConfigurationPolicy_Export.ps1 b/ConfigurationPolicy/ConfigurationPolicy_Export.ps1 new file mode 100644 index 0000000..0838902 --- /dev/null +++ b/ConfigurationPolicy/ConfigurationPolicy_Export.ps1 @@ -0,0 +1,335 @@ +Import-Module Microsoft.Graph.Beta.DeviceManagement + +<# region Authentication +To authenticate, you'll use the Microsoft Graph PowerShell SDK. If you haven't already installed the SDK, see this guide: +https://learn.microsoft.com/en-us/powershell/microsoftgraph/installation?view=graph-powershell-1.0 + +The PowerShell SDK supports two types of authentication: delegated access, and app-only access. + +For details on using delegated access, see this guide here: +https://learn.microsoft.com/powershell/microsoftgraph/get-started?view=graph-powershell-1.0 + +For details on using app-only access for unattended scenarios, see Use app-only authentication with the Microsoft Graph PowerShell SDK: +https://learn.microsoft.com/powershell/microsoftgraph/app-only?view=graph-powershell-1.0&tabs=azure-portal +#> + +Function Get-ConfigurationPolicy() { + + <# +.SYNOPSIS +This function is used to get Configuration policies from the Graph API REST interface +.DESCRIPTION +The function connects to the Graph API Interface and gets any Configuration policies +.EXAMPLE +Get-ConfigurationPolicy +Returns any Configuration policies configured in Intune +Get-ConfigurationPolicy -Platform windows10 +Returns any Windows 10 Configuration policies configured in Intune +Get-ConfigurationPolicy -Platform macOS +Returns any MacOS Configuration policies configured in Intune +Get-ConfigurationPolicy -Technology windows365 +Returns any Windows 365 Configuration policies configured in Intune +.NOTES +NAME: Get-ConfigurationPolicy +#> + + [cmdletbinding()] + + param + ( + [parameter(Mandatory = $false)] + [ValidateSet("windows10", "macOS", "iOS", "android")] + [ValidateNotNullOrEmpty()] + [string]$Platform, + + [parameter(Mandatory = $false)] + [ValidateSet("mdm", "windows365", "microsoftSense", "endpointPrivilegeManagement", "configManager", "appleRemoteManagement", "exchangeOnline", "mobileApplicationManagement", "linuxMdm", "extensibility", "enrollment", "windowsOsRecovery", "android")] + [ValidateNotNullOrEmpty()] + [string]$Technology + ) + + $graphApiVersion = "beta" + + if ($Platform -and $Technology) { + + $Resource = "deviceManagement/configurationPolicies?`$filter=platforms has '$Platform' and technologies has '$Technology'" + + } + elseif ($Platform) { + + $Resource = "deviceManagement/configurationPolicies?`$filter=platforms has '$Platform'" + + } + elseif ($Technology) { + + $Resource = "deviceManagement/configurationPolicies?`$filter=technologies has '$Technology'" + + } + else { + + $Resource = "deviceManagement/configurationPolicies" + + } + + try { + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($Resource)" + (Invoke-MgGraphRequest -Uri $uri -Method Get).Value + + } + + catch { + + $ex = $_.Exception + $errorResponse = $ex.Response.GetResponseStream() + $reader = New-Object System.IO.StreamReader($errorResponse) + $reader.BaseStream.Position = 0 + $reader.DiscardBufferedData() + $responseBody = $reader.ReadToEnd(); + Write-Host "Response content:`n$responseBody" -f Red + Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)" + write-host + break + + } + +} + +#################################################### + +Function Get-ConfigurationPolicySettings() { + + <# +.SYNOPSIS +This function is used to get Configuration policy Settings from the Graph API REST interface +.DESCRIPTION +The function connects to the Graph API Interface and gets any Configuration policy Settings +.EXAMPLE +Get-ConfigurationPolicySettings -policyid policyid +Returns any Configuration policy Settings configured in Intune +.NOTES +NAME: Get-ConfigurationPolicySettings +#> + + [cmdletbinding()] + + param + ( + [Parameter(Mandatory = $true)] + [ValidateNotNullOrEmpty()] + $policyid + ) + + $graphApiVersion = "beta" + $Resource = "deviceManagement/configurationPolicies('$policyid')/settings?`$expand=settingDefinitions" + + try { + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($Resource)" + + $Response = (Invoke-MgGraphRequest -Uri $uri -Method Get) + + $AllResponses = $Response.value + + $ResponseNextLink = $Response."@odata.nextLink" + + while ($ResponseNextLink -ne $null) { + + $Response = (Invoke-MgGraphRequest -Uri $ResponseNextLink -Method Get) + $ResponseNextLink = $Response."@odata.nextLink" + $AllResponses += $Response.value + + } + + return $AllResponses + + } + + catch { + + $ex = $_.Exception + $errorResponse = $ex.Response.GetResponseStream() + $reader = New-Object System.IO.StreamReader($errorResponse) + $reader.BaseStream.Position = 0 + $reader.DiscardBufferedData() + $responseBody = $reader.ReadToEnd(); + Write-Host "Response content:`n$responseBody" -f Red + Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)" + write-host + break + + } + +} + +#################################################### + +Function Export-JSONData() { + + <# +.SYNOPSIS +This function is used to export JSON data returned from Graph +.DESCRIPTION +This function is used to export JSON data returned from Graph +.EXAMPLE +Export-JSONData -JSON $JSON +Export the JSON inputted on the function +.NOTES +NAME: Export-JSONData +#> + + param ( + + $JSON, + $ExportPath + + ) + + try { + + if ($JSON -eq "" -or $JSON -eq $null) { + + write-host "No JSON specified, please specify valid JSON..." -f Red + + } + + elseif (!$ExportPath) { + + write-host "No export path parameter set, please provide a path to export the file" -f Red + + } + + elseif (!(Test-Path $ExportPath)) { + + write-host "$ExportPath doesn't exist, can't export JSON Data" -f Red + + } + + else { + + $JSON1 = ConvertTo-Json $JSON -Depth 20 + + $JSON_Convert = $JSON1 | ConvertFrom-Json + + $displayName = $JSON_Convert.name + + # Updating display name to follow file naming conventions - https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247%28v=vs.85%29.aspx + $DisplayName = $DisplayName -replace '\<|\>|:|"|/|\\|\||\?|\*', "_" + + $FileName_JSON = "$DisplayName" + "_" + $(get-date -f dd-MM-yyyy-H-mm-ss) + ".json" + + write-host "Export Path:" "$ExportPath" + + $JSON1 | Set-Content -LiteralPath "$ExportPath\$FileName_JSON" + write-host "JSON created in $ExportPath\$FileName_JSON..." -f cyan + + } + + } + + catch { + + $_.Exception + + } + +} + +#################################################### + +$ExportPath = Read-Host -Prompt "Please specify a path to export the policy data to e.g. C:\IntuneOutput" + +# If the directory path doesn't exist prompt user to create the directory +$ExportPath = $ExportPath.replace('"', '') + +if (!(Test-Path "$ExportPath")) { + + Write-Host + Write-Host "Path '$ExportPath' doesn't exist, do you want to create this directory? Y or N?" -ForegroundColor Yellow + + $Confirm = read-host + + if ($Confirm -eq "y" -or $Confirm -eq "Y") { + + new-item -ItemType Directory -Path "$ExportPath" | Out-Null + Write-Host + + } + + else { + + Write-Host "Creation of directory path was cancelled..." -ForegroundColor Red + Write-Host + break + + } + +} + +#################################################### + +$Policies = Get-ConfigurationPolicy + +if ($Policies) { + + foreach ($policy in $Policies) { + + Write-Host $policy.name -ForegroundColor Yellow + + $AllSettingsInstances = @() + + $policyid = $policy.id + $Policy_Technologies = $policy.technologies + $Policy_Platforms = $Policy.platforms + $Policy_Name = $Policy.name + $Policy_Description = $policy.description + + $PolicyBody = New-Object -TypeName PSObject + + Add-Member -InputObject $PolicyBody -MemberType 'NoteProperty' -Name 'name' -Value "$Policy_Name" + Add-Member -InputObject $PolicyBody -MemberType 'NoteProperty' -Name 'description' -Value "$Policy_Description" + Add-Member -InputObject $PolicyBody -MemberType 'NoteProperty' -Name 'platforms' -Value "$Policy_Platforms" + Add-Member -InputObject $PolicyBody -MemberType 'NoteProperty' -Name 'technologies' -Value "$Policy_Technologies" + + # Checking if policy has a templateId associated + if ($policy.templateReference.templateId) { + + Write-Host "Found template reference" -f Cyan + $templateId = $policy.templateReference.templateId + + $PolicyTemplateReference = New-Object -TypeName PSObject + + Add-Member -InputObject $PolicyTemplateReference -MemberType 'NoteProperty' -Name 'templateId' -Value $templateId + + Add-Member -InputObject $PolicyBody -MemberType 'NoteProperty' -Name 'templateReference' -Value $PolicyTemplateReference + + } + + $SettingInstances = Get-ConfigurationPolicySettings -policyid $policyid + + $Instances = $SettingInstances.settingInstance + + foreach ($object in $Instances) { + + $Instance = New-Object -TypeName PSObject + + Add-Member -InputObject $Instance -MemberType 'NoteProperty' -Name 'settingInstance' -Value $object + $AllSettingsInstances += $Instance + + } + + Add-Member -InputObject $PolicyBody -MemberType 'NoteProperty' -Name 'settings' -Value @($AllSettingsInstances) + + Export-JSONData -JSON $PolicyBody -ExportPath "$ExportPath" + Write-Host + + } + +} + +else { + + Write-Host "No Configuration policies found..." -ForegroundColor Red + Write-Host + +} diff --git a/ConfigurationPolicy/ConfigurationPolicy_Import_FromJSON.ps1 b/ConfigurationPolicy/ConfigurationPolicy_Import_FromJSON.ps1 new file mode 100644 index 0000000..b984433 --- /dev/null +++ b/ConfigurationPolicy/ConfigurationPolicy_Import_FromJSON.ps1 @@ -0,0 +1,248 @@ +Import-Module Microsoft.Graph.Beta.DeviceManagement + +<# region Authentication +To authenticate, you'll use the Microsoft Graph PowerShell SDK. If you haven't already installed the SDK, see this guide: +https://learn.microsoft.com/en-us/powershell/microsoftgraph/installation?view=graph-powershell-1.0 + +The PowerShell SDK supports two types of authentication: delegated access, and app-only access. + +For details on using delegated access, see this guide here: +https://learn.microsoft.com/powershell/microsoftgraph/get-started?view=graph-powershell-1.0 + +For details on using app-only access for unattended scenarios, see Use app-only authentication with the Microsoft Graph PowerShell SDK: +https://learn.microsoft.com/powershell/microsoftgraph/app-only?view=graph-powershell-1.0&tabs=azure-portal +#> + +#################################################### + +Function Test-JSON() { + + <# + .SYNOPSIS + This function is used to test if the JSON passed to a REST Post request is valid + .DESCRIPTION + The function tests if the JSON passed to the REST Post is valid + .EXAMPLE + Test-JSON -JSON $JSON + Test if the JSON is valid before calling the Graph REST interface + .NOTES + NAME: Test-JSON + #> + + param ( + $JSON + ) + + try { + $TestJSON = ConvertFrom-Json $JSON -ErrorAction Stop + $validJson = $true + } + + catch { + $validJson = $false + $_.Exception + } + + if (!$validJson) { + Write-Host "Provided JSON isn't in valid JSON format" -f Red + break + } +} + +#################################################### + +Function Add-ConfigurationPolicy() { + + <# + .SYNOPSIS + This function is used to add a Configuration policy using the Graph API REST interface + .DESCRIPTION + The function connects to the Graph API Interface and adds a Configuration policy + .EXAMPLE + Add-ConfigurationPolicy -JSON $JSON + Adds a Configuration policy in Intune + .NOTES + NAME: Add-ConfigurationPolicy + #> + + [cmdletbinding()] + + param + ( + $JSON + ) + + $graphApiVersion = "beta" + $Resource = "deviceManagement/configurationPolicies" + + try { + + Test-JSON -JSON $JSON + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($Resource)" + Invoke-MgGraphRequest -Uri $uri -Method Post -Body $JSON + + } + + catch { + + $ex = $_.Exception + $errorResponse = $ex.Response.GetResponseStream() + $reader = New-Object System.IO.StreamReader($errorResponse) + $reader.BaseStream.Position = 0 + $reader.DiscardBufferedData() + $responseBody = $reader.ReadToEnd(); + Write-Host "Response content:`n$responseBody" -f Red + Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)" + write-host + break + + } + +} + +#################################################### + +Function Add-ConfigurationPolicySettings() { + + <# + .SYNOPSIS + This function is used to add Configuration policy settings using the Graph API REST interface + .DESCRIPTION + The function connects to the Graph API Interface and adds Configuration policy settings + .EXAMPLE + Add-ConfigurationPolicySettings -JSON $JSON -policyid $policyid + Adds Configuration policy settings in Intune + .NOTES + NAME: Add-ConfigurationPolicySettings + #> + + [cmdletbinding()] + + param + ( + $JSON, + $policyid + ) + + $graphApiVersion = "beta" + $Resource = "deviceManagement/configurationPolicies('$policyid')/settings" + + try { + + Test-JSON -JSON $JSON + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($Resource)" + Invoke-MgGraphRequest -Uri $uri -Method Post -Body $JSON + + } + + catch { + + $ex = $_.Exception + $errorResponse = $ex.Response.GetResponseStream() + $reader = New-Object System.IO.StreamReader($errorResponse) + $reader.BaseStream.Position = 0 + $reader.DiscardBufferedData() + $responseBody = $reader.ReadToEnd(); + Write-Host "Response content:`n$responseBody" -f Red + Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)" + write-host + break + + } + +} + +#################################################### + +$ImportPath = Read-Host -Prompt "Please specify a path to a JSON file to import data from e.g. C:\IntuneOutput\Policies\policy.json" + +# Replacing quotes for Test-Path +$ImportPath = $ImportPath.replace('"', '') + +if (!(Test-Path "$ImportPath")) { + + Write-Host "Import Path for JSON file doesn't exist..." -ForegroundColor Red + Write-Host "Script can't continue..." -ForegroundColor Red + Write-Host + break + +} + +#################################################### + +# Importing JSON file +$JSON_Data = Get-Content -Path "$ImportPath" -Raw + +# Testing if valid JSON +Test-JSON -JSON $JSON_Data + +$JSON_Convert = $JSON_Data | ConvertFrom-Json + +$DisplayName = $JSON_Convert.name + +Write-Host "Configuration Policy '$DisplayName' Found..." -ForegroundColor Yellow +Write-Host + +#################################################### + +# Creating policy body for import +$PolicyBody = New-Object -TypeName PSObject + +Add-Member -InputObject $PolicyBody -MemberType 'NoteProperty' -Name 'name' -Value $JSON_Convert.name +Add-Member -InputObject $PolicyBody -MemberType 'NoteProperty' -Name 'description' -Value $JSON_Convert.description +Add-Member -InputObject $PolicyBody -MemberType 'NoteProperty' -Name 'platforms' -Value $JSON_Convert.platforms +Add-Member -InputObject $PolicyBody -MemberType 'NoteProperty' -Name 'technologies' -Value $JSON_Convert.technologies + +# Checking if policy has a templateId associated +if ($JSON_Convert.templateReference.templateId) { + + Write-Host "Template reference found" -f Cyan + + $PolicyTemplateReference = New-Object -TypeName PSObject + Add-Member -InputObject $PolicyTemplateReference -MemberType 'NoteProperty' -Name 'templateId' -Value $JSON_Convert.templateReference.templateId + Add-Member -InputObject $PolicyBody -MemberType 'NoteProperty' -Name 'templateReference' -Value $PolicyTemplateReference + +} + +$PolicyBody_JSON = $PolicyBody | ConvertTo-Json -Depth 10 + +Write-Host "Adding Configuration Policy '$DisplayName'" -ForegroundColor Yellow + +#################################################### + +# Adding Configuration policy +$CreateResult = Add-ConfigurationPolicy -JSON $PolicyBody_JSON + +Write-Host "Configuration policy created successfully" -ForegroundColor Green +Write-Host "Policy ID:" $CreateResult.id -ForegroundColor Cyan +Write-Host + +#################################################### + +# Adding Settings to the policy +if ($JSON_Convert.settings) { + + # Get policy id from results + $policy_id = $CreateResult.id + + Write-Host "Adding settings to Configuration Policy..." -ForegroundColor Yellow + + foreach ($Setting in $JSON_Convert.settings) { + + $Setting_JSON = $Setting | ConvertTo-Json -Depth 20 + + Write-Host "Adding setting..." + + Add-ConfigurationPolicySettings -JSON $Setting_JSON -policyid $policy_id + + } + + Write-Host + Write-Host "Settings added successfully" -ForegroundColor Green + +} + +Write-Host +Write-Host "Configuration Policy '$DisplayName' imported successfully!" -ForegroundColor Green diff --git a/ConfigurationPolicy/readme.md b/ConfigurationPolicy/readme.md new file mode 100644 index 0000000..2aa18c9 --- /dev/null +++ b/ConfigurationPolicy/readme.md @@ -0,0 +1,178 @@ +# Intune Configuration Policy script samples + +This repository of PowerShell sample scripts show how to retrieve, create, delete, and modify Intune service resources using cmdlets from the Microsoft Graph PowerShell SDK. + +Documentation for Intune and Microsoft Graph can be found here [Intune Graph Documentation](https://developer.microsoft.com/en-us/graph/docs/api-reference/beta/resources/intune_graph_overview). + +Documentation for the Microsoft Graph PowerShell SDK can be found here [Microsoft Graph PowerShell SDK](https://learn.microsoft.com/en-us/powershell/microsoftgraph/get-started?view=graph-powershell-1.0). + +#### Disclaimer +Some script samples retrieve information from your Intune tenant, and others create, delete or update data in your Intune tenant. Understand the impact of each sample script prior to running it; samples should be run using a non-production or "test" tenant account. + +## Background + +Configuration policies in Microsoft Intune use the `deviceManagement/configurationPolicies` endpoint and support various technology types beyond the traditional MDM (Mobile Device Management). These include: + +- **mdm** - Traditional Mobile Device Management policies (Settings Catalog) +- **windows365** - Windows 365 Cloud PC policies +- **microsoftSense** - Microsoft Defender for Endpoint policies +- **endpointPrivilegeManagement** - Endpoint Privilege Management policies +- **configManager** - Configuration Manager policies +- **appleRemoteManagement** - Apple Remote Management policies +- And more... + +Previously, these policies were classified under Settings Catalog. However, several policy types now have unique technology designations and require specialized handling for import/export operations that the standard Settings Catalog scripts don't support. + +## Scripts in this Section + +### 1. ConfigurationPolicy_Export.ps1 +This script gets all configuration policies from the Intune Service that you have authenticated with, regardless of their technology type. The script will then export each policy to .json format in the directory of your choice. + +```PowerShell +$ExportPath = Read-Host -Prompt "Please specify a path to export the policy data to e.g. C:\IntuneOutput" + +# If the directory path doesn't exist prompt user to create the directory + +if(!(Test-Path "$ExportPath")){ + + Write-Host + Write-Host "Path '$ExportPath' doesn't exist, do you want to create this directory? Y or N?" -ForegroundColor Yellow + + $Confirm = read-host + + if($Confirm -eq "y" -or $Confirm -eq "Y"){ + + new-item -ItemType Directory -Path "$ExportPath" | Out-Null + Write-Host + + } + + else { + + Write-Host "Creation of directory path was cancelled..." -ForegroundColor Red + Write-Host + break + + } + +} +``` + +#### Get-ConfigurationPolicy Function +This function is used to get all configuration policies from the Intune Service, supporting filtering by platform and/or technology type. + +It supports optional parameters as input to filter the results: + +```PowerShell +# Returns all Configuration policies configured in Intune +Get-ConfigurationPolicy + +# Returns any Windows 10 Configuration policies configured in Intune +Get-ConfigurationPolicy -Platform windows10 + +# Returns any MacOS Configuration policies configured in Intune +Get-ConfigurationPolicy -Platform macOS + +# Returns any Windows 365 Configuration policies configured in Intune +Get-ConfigurationPolicy -Technology windows365 + +# Returns any Microsoft Defender for Endpoint policies configured in Intune +Get-ConfigurationPolicy -Technology microsoftSense + +# Returns any Endpoint Privilege Management policies configured in Intune +Get-ConfigurationPolicy -Technology endpointPrivilegeManagement +``` + +#### Get-ConfigurationPolicySettings Function +This function retrieves the settings for a specific configuration policy. + +```PowerShell +Get-ConfigurationPolicySettings -policyid $policyid +``` + +#### Export-JSONData Function +This function is used to export the policy information. It has two required parameters -JSON and -ExportPath. + ++ JSON - The JSON data ++ ExportPath - The path where the .json should be exported to + +```PowerShell +Export-JSONData -JSON $JSON -ExportPath "$ExportPath" +``` + +### 2. ConfigurationPolicy_Import_FromJSON.ps1 +This script imports a configuration policy from a JSON file that was previously exported using the ConfigurationPolicy_Export.ps1 script. It supports all technology types including Windows 365, Microsoft Defender for Endpoint, Endpoint Privilege Management, and traditional MDM policies. + +The script will: +1. Read the JSON file +2. Validate the JSON format +3. Create the configuration policy with the specified name, description, platforms, and technologies +4. Add all settings from the exported policy to the newly created policy + +```PowerShell +$ImportPath = Read-Host -Prompt "Please specify a path to a JSON file to import data from e.g. C:\IntuneOutput\Policies\policy.json" +``` + +#### Test-JSON Function +This function validates that the JSON being imported is valid. + +```PowerShell +Test-JSON -JSON $JSON +``` + +#### Add-ConfigurationPolicy Function +This function creates a new configuration policy in Intune. + +```PowerShell +Add-ConfigurationPolicy -JSON $JSON +``` + +#### Add-ConfigurationPolicySettings Function +This function adds settings to an existing configuration policy. + +```PowerShell +Add-ConfigurationPolicySettings -JSON $JSON -policyid $policyid +``` + +## Usage Examples + +### Exporting Policies + +1. Connect to Microsoft Graph: + ```PowerShell + Connect-MgGraph -Scopes "DeviceManagementConfiguration.Read.All" + ``` + +2. Run the export script: + ```PowerShell + .\ConfigurationPolicy_Export.ps1 + ``` + +3. Specify the export path when prompted (e.g., `C:\IntuneBackup`) + +### Importing Policies + +1. Connect to Microsoft Graph: + ```PowerShell + Connect-MgGraph -Scopes "DeviceManagementConfiguration.ReadWrite.All" + ``` + +2. Run the import script: + ```PowerShell + .\ConfigurationPolicy_Import_FromJSON.ps1 + ``` + +3. Specify the path to the JSON file when prompted (e.g., `C:\IntuneBackup\MyPolicy_01-01-2024-10-30-00.json`) + +## Difference from Settings Catalog Scripts + +The key difference between these Configuration Policy scripts and the Settings Catalog scripts is: + +- **Settings Catalog scripts** filter for `technologies has 'mdm'` only +- **Configuration Policy scripts** support ALL technology types, including: + - Windows 365 (`windows365`) + - Microsoft Defender for Endpoint (`microsoftSense`) + - Endpoint Privilege Management (`endpointPrivilegeManagement`) + - And all other technology types + +This makes the Configuration Policy scripts more comprehensive and suitable for modern Intune deployments that use multiple technology types beyond traditional MDM. From 97e3ea287906640b5c925b3555672877f1117d2c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 24 Oct 2025 06:16:24 +0000 Subject: [PATCH 3/5] Add ConfigurationPolicy Get and Remove scripts Co-authored-by: Mahopper <29206133+Mahopper@users.noreply.github.com> --- .../ConfigurationPolicy_Get.ps1 | 127 ++++++++++++++++++ .../ConfigurationPolicy_Remove.ps1 | 119 ++++++++++++++++ ConfigurationPolicy/readme.md | 59 +++++++- 3 files changed, 303 insertions(+), 2 deletions(-) create mode 100644 ConfigurationPolicy/ConfigurationPolicy_Get.ps1 create mode 100644 ConfigurationPolicy/ConfigurationPolicy_Remove.ps1 diff --git a/ConfigurationPolicy/ConfigurationPolicy_Get.ps1 b/ConfigurationPolicy/ConfigurationPolicy_Get.ps1 new file mode 100644 index 0000000..df4d40b --- /dev/null +++ b/ConfigurationPolicy/ConfigurationPolicy_Get.ps1 @@ -0,0 +1,127 @@ +Import-Module Microsoft.Graph.Beta.DeviceManagement + +#################################################### + +<# region Authentication +To authenticate, you'll use the Microsoft Graph PowerShell SDK. If you haven't already installed the SDK, see this guide: +https://learn.microsoft.com/en-us/powershell/microsoftgraph/installation?view=graph-powershell-1.0 + +The PowerShell SDK supports two types of authentication: delegated access, and app-only access. + +For details on using delegated access, see this guide here: +https://learn.microsoft.com/powershell/microsoftgraph/get-started?view=graph-powershell-1.0 + +For details on using app-only access for unattended scenarios, see Use app-only authentication with the Microsoft Graph PowerShell SDK: +https://learn.microsoft.com/powershell/microsoftgraph/app-only?view=graph-powershell-1.0&tabs=azure-portal + +#> + +#endregion + +#################################################### + +Function Get-ConfigurationPolicy() { + + <# +.SYNOPSIS +This function is used to get Configuration policies from the Graph API REST interface +.DESCRIPTION +The function connects to the Graph API Interface and gets any Configuration policies +.EXAMPLE +Get-ConfigurationPolicy +Returns any Configuration policies configured in Intune +Get-ConfigurationPolicy -Platform windows10 +Returns any Windows 10 Configuration policies configured in Intune +Get-ConfigurationPolicy -Platform macOS +Returns any MacOS Configuration policies configured in Intune +Get-ConfigurationPolicy -Technology windows365 +Returns any Windows 365 Configuration policies configured in Intune +.NOTES +NAME: Get-ConfigurationPolicy +#> + + [cmdletbinding()] + + param + ( + [parameter(Mandatory = $false)] + [ValidateSet("windows10", "macOS", "iOS", "android")] + [ValidateNotNullOrEmpty()] + [string]$Platform, + + [parameter(Mandatory = $false)] + [ValidateSet("mdm", "windows365", "microsoftSense", "endpointPrivilegeManagement", "configManager", "appleRemoteManagement", "exchangeOnline", "mobileApplicationManagement", "linuxMdm", "extensibility", "enrollment", "windowsOsRecovery", "android")] + [ValidateNotNullOrEmpty()] + [string]$Technology + ) + + $graphApiVersion = "beta" + + if ($Platform -and $Technology) { + + $Resource = "deviceManagement/configurationPolicies?`$filter=platforms has '$Platform' and technologies has '$Technology'" + + } + elseif ($Platform) { + + $Resource = "deviceManagement/configurationPolicies?`$filter=platforms has '$Platform'" + + } + elseif ($Technology) { + + $Resource = "deviceManagement/configurationPolicies?`$filter=technologies has '$Technology'" + + } + else { + + $Resource = "deviceManagement/configurationPolicies" + + } + + try { + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($Resource)" + (Invoke-MgGraphRequest -Uri $uri -Method Get).Value + + } + + catch { + + $ex = $_.Exception + $errorResponse = $ex.Response.GetResponseStream() + $reader = New-Object System.IO.StreamReader($errorResponse) + $reader.BaseStream.Position = 0 + $reader.DiscardBufferedData() + $responseBody = $reader.ReadToEnd(); + Write-Host "Response content:`n$responseBody" -f Red + Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)" + write-host + break + + } + +} + +#################################################### + +$Policies = Get-ConfigurationPolicy + +write-host + +foreach ($Policy in $Policies) { + + write-host "Configuration Policy:" $Policy.name -f Yellow + write-host " ID:" $Policy.id + write-host " Description:" $Policy.description + write-host " Platforms:" $Policy.platforms + write-host " Technologies:" $Policy.technologies + write-host " Created:" $Policy.createdDateTime + write-host " Last Modified:" $Policy.lastModifiedDateTime + + if ($Policy.templateReference.templateId) { + write-host " Template ID:" $Policy.templateReference.templateId -f Cyan + } + + Write-Host + +} diff --git a/ConfigurationPolicy/ConfigurationPolicy_Remove.ps1 b/ConfigurationPolicy/ConfigurationPolicy_Remove.ps1 new file mode 100644 index 0000000..c48daa0 --- /dev/null +++ b/ConfigurationPolicy/ConfigurationPolicy_Remove.ps1 @@ -0,0 +1,119 @@ +Import-Module Microsoft.Graph.Beta.DeviceManagement + +<# + +.COPYRIGHT +Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. +See LICENSE in the project root for license information. + +#> +#################################################### + +<# region Authentication +To authenticate, you'll use the Microsoft Graph PowerShell SDK. If you haven't already installed the SDK, see this guide: +https://learn.microsoft.com/en-us/powershell/microsoftgraph/installation?view=graph-powershell-1.0 + +The PowerShell SDK supports two types of authentication: delegated access, and app-only access. + +For details on using delegated access, see this guide here: +https://learn.microsoft.com/powershell/microsoftgraph/get-started?view=graph-powershell-1.0 + +For details on using app-only access for unattended scenarios, see Use app-only authentication with the Microsoft Graph PowerShell SDK: +https://learn.microsoft.com/powershell/microsoftgraph/app-only?view=graph-powershell-1.0&tabs=azure-portal + +#> + +#endregion + +#################################################### + +Function Remove-ConfigurationPolicy() { + + <# +.SYNOPSIS +This function is used to remove a Configuration policy from the Graph API REST interface +.DESCRIPTION +The function connects to the Graph API Interface and removes a Configuration policy +.EXAMPLE +Remove-ConfigurationPolicy -policyId $policyId +Removes a Configuration policy configured in Intune +.NOTES +NAME: Remove-ConfigurationPolicy +#> + + [cmdletbinding()] + + param + ( + [Parameter(Mandatory = $true)] + [ValidateNotNullOrEmpty()] + [string]$policyId + ) + + $graphApiVersion = "beta" + $Resource = "deviceManagement/configurationPolicies('$policyId')" + + try { + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($Resource)" + Invoke-MgGraphRequest -Uri $uri -Method Delete + + } + + catch { + + $ex = $_.Exception + $errorResponse = $ex.Response.GetResponseStream() + $reader = New-Object System.IO.StreamReader($errorResponse) + $reader.BaseStream.Position = 0 + $reader.DiscardBufferedData() + $responseBody = $reader.ReadToEnd(); + Write-Host "Response content:`n$responseBody" -f Red + Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)" + write-host + break + + } + +} + +#################################################### + +$PolicyId = Read-Host -Prompt "Please specify the Configuration Policy ID to remove" + +if ($PolicyId) { + + $graphApiVersion = "beta" + $Resource = "deviceManagement/configurationPolicies('$PolicyId')" + $uri = "https://graph.microsoft.com/$graphApiVersion/$($Resource)" + + try { + $Policy = Invoke-MgGraphRequest -Uri $uri -Method Get + + if ($Policy) { + Write-Host "Configuration Policy found:" $Policy.name -ForegroundColor Yellow + Write-Host + Write-Host "Are you sure you want to remove this Configuration Policy? Y or N?" -ForegroundColor Yellow + $Confirm = read-host + + if ($Confirm -eq "y" -or $Confirm -eq "Y") { + Remove-ConfigurationPolicy -policyId $PolicyId + Write-Host "Configuration Policy" $Policy.name "removed successfully" -ForegroundColor Green + } + else { + Write-Host "Removal of Configuration Policy cancelled..." -ForegroundColor Red + } + } + } + catch { + Write-Host "Configuration Policy with ID $PolicyId doesn't exist or couldn't be retrieved..." -ForegroundColor Red + Write-Host + } + +} +else { + + Write-Host "No Configuration Policy ID specified..." -ForegroundColor Red + Write-Host + +} diff --git a/ConfigurationPolicy/readme.md b/ConfigurationPolicy/readme.md index 2aa18c9..8deb7d6 100644 --- a/ConfigurationPolicy/readme.md +++ b/ConfigurationPolicy/readme.md @@ -25,7 +25,17 @@ Previously, these policies were classified under Settings Catalog. However, seve ## Scripts in this Section -### 1. ConfigurationPolicy_Export.ps1 +### 1. ConfigurationPolicy_Get.ps1 +This script retrieves and displays all configuration policies from the Intune Service, showing their key properties including ID, name, description, platforms, technologies, and template references. + +```PowerShell +# Get all configuration policies +.\ConfigurationPolicy_Get.ps1 +``` + +The script will display detailed information about each policy, making it easy to identify policy IDs for other operations like removal or export. + +### 2. ConfigurationPolicy_Export.ps1 This script gets all configuration policies from the Intune Service that you have authenticated with, regardless of their technology type. The script will then export each policy to .json format in the directory of your choice. ```PowerShell @@ -100,7 +110,22 @@ This function is used to export the policy information. It has two required para Export-JSONData -JSON $JSON -ExportPath "$ExportPath" ``` -### 2. ConfigurationPolicy_Import_FromJSON.ps1 +### 3. ConfigurationPolicy_Remove.ps1 +This script removes a configuration policy from Intune. It requires the policy ID and will prompt for confirmation before deletion. + +```PowerShell +# Remove a specific configuration policy +.\ConfigurationPolicy_Remove.ps1 +``` + +When prompted, enter the Configuration Policy ID (which can be obtained from the ConfigurationPolicy_Get.ps1 script). The script will: +1. Retrieve and display the policy details +2. Ask for confirmation +3. Remove the policy if confirmed + +**Important**: This action is permanent and cannot be undone. + +### 4. ConfigurationPolicy_Import_FromJSON.ps1 This script imports a configuration policy from a JSON file that was previously exported using the ConfigurationPolicy_Export.ps1 script. It supports all technology types including Windows 365, Microsoft Defender for Endpoint, Endpoint Privilege Management, and traditional MDM policies. The script will: @@ -136,6 +161,20 @@ Add-ConfigurationPolicySettings -JSON $JSON -policyid $policyid ## Usage Examples +### Getting Policy Information + +1. Connect to Microsoft Graph: + ```PowerShell + Connect-MgGraph -Scopes "DeviceManagementConfiguration.Read.All" + ``` + +2. Run the get script: + ```PowerShell + .\ConfigurationPolicy_Get.ps1 + ``` + +This will display all configuration policies with their IDs and properties, which you can use for export or removal operations. + ### Exporting Policies 1. Connect to Microsoft Graph: @@ -164,6 +203,22 @@ Add-ConfigurationPolicySettings -JSON $JSON -policyid $policyid 3. Specify the path to the JSON file when prompted (e.g., `C:\IntuneBackup\MyPolicy_01-01-2024-10-30-00.json`) +### Removing Policies + +1. Connect to Microsoft Graph: + ```PowerShell + Connect-MgGraph -Scopes "DeviceManagementConfiguration.ReadWrite.All" + ``` + +2. Get the policy ID using the Get script or from the Intune portal + +3. Run the remove script: + ```PowerShell + .\ConfigurationPolicy_Remove.ps1 + ``` + +4. Enter the policy ID when prompted and confirm the removal + ## Difference from Settings Catalog Scripts The key difference between these Configuration Policy scripts and the Settings Catalog scripts is: From 244c8ed8c80a39e39d80d56a3e90b567a324620c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 24 Oct 2025 06:19:31 +0000 Subject: [PATCH 4/5] Add ConfigurationPolicy assignment scripts (Assign and Get_Assign) Co-authored-by: Mahopper <29206133+Mahopper@users.noreply.github.com> --- .../ConfigurationPolicy_Assign.ps1 | 190 ++++++++++++++++++ .../ConfigurationPolicy_Get_Assign.ps1 | 169 ++++++++++++++++ ConfigurationPolicy/readme.md | 75 ++++++- 3 files changed, 433 insertions(+), 1 deletion(-) create mode 100644 ConfigurationPolicy/ConfigurationPolicy_Assign.ps1 create mode 100644 ConfigurationPolicy/ConfigurationPolicy_Get_Assign.ps1 diff --git a/ConfigurationPolicy/ConfigurationPolicy_Assign.ps1 b/ConfigurationPolicy/ConfigurationPolicy_Assign.ps1 new file mode 100644 index 0000000..8b708ab --- /dev/null +++ b/ConfigurationPolicy/ConfigurationPolicy_Assign.ps1 @@ -0,0 +1,190 @@ +Import-Module Microsoft.Graph.Beta.DeviceManagement + +#################################################### + +<# region Authentication +To authenticate, you'll use the Microsoft Graph PowerShell SDK. If you haven't already installed the SDK, see this guide: +https://learn.microsoft.com/en-us/powershell/microsoftgraph/installation?view=graph-powershell-1.0 + +The PowerShell SDK supports two types of authentication: delegated access, and app-only access. + +For details on using delegated access, see this guide here: +https://learn.microsoft.com/powershell/microsoftgraph/get-started?view=graph-powershell-1.0 + +For details on using app-only access for unattended scenarios, see Use app-only authentication with the Microsoft Graph PowerShell SDK: +https://learn.microsoft.com/powershell/microsoftgraph/app-only?view=graph-powershell-1.0&tabs=azure-portal + +#> +#endregion + +#################################################### + +Function Add-ConfigurationPolicyAssignment() { + + <# +.SYNOPSIS +This function is used to add a Configuration policy assignment using the Graph API REST interface +.DESCRIPTION +The function connects to the Graph API Interface and adds a Configuration policy assignment +.EXAMPLE +Add-ConfigurationPolicyAssignment -ConfigurationPolicyId $ConfigurationPolicyId -TargetGroupId $TargetGroupId +Adds a Configuration policy assignment in Intune +.NOTES +NAME: Add-ConfigurationPolicyAssignment +#> + + [cmdletbinding()] + + param + ( + [parameter(Mandatory = $true)] + [ValidateNotNullOrEmpty()] + $ConfigurationPolicyId, + + [parameter(Mandatory = $true)] + [ValidateNotNullOrEmpty()] + $TargetGroupId, + + [parameter(Mandatory = $false)] + [ValidateSet("Include", "Exclude")] + $AssignmentType = "Include" + ) + + $graphApiVersion = "beta" + $Resource = "deviceManagement/configurationPolicies('$ConfigurationPolicyId')/assign" + + try { + + if ($AssignmentType -eq "Exclude") { + + $TargetGroup = @{ + '@odata.type' = '#microsoft.graph.exclusionGroupAssignmentTarget' + groupId = $TargetGroupId + } + + } + + else { + + $TargetGroup = @{ + '@odata.type' = '#microsoft.graph.groupAssignmentTarget' + groupId = $TargetGroupId + } + + } + + $Assignment = @{ + assignments = @( + @{ + target = $TargetGroup + } + ) + } + + $JSON = $Assignment | ConvertTo-Json -Depth 3 + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($Resource)" + Invoke-MgGraphRequest -Uri $uri -Method Post -Body $JSON + + } + + catch { + + $ex = $_.Exception + $errorResponse = $ex.Response.GetResponseStream() + $reader = New-Object System.IO.StreamReader($errorResponse) + $reader.BaseStream.Position = 0 + $reader.DiscardBufferedData() + $responseBody = $reader.ReadToEnd(); + Write-Host "Response content:`n$responseBody" -f Red + Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)" + write-host + break + + } + +} + +#################################################### + +# Setting application AAD Group to assign Policy + +$AADGroup = Read-Host -Prompt "Enter the Azure AD Group name or ID where policies will be assigned" + +# Try to get group by ID first, then by display name +try { + $TargetGroup = Get-MgGroup -GroupId "$AADGroup" -ErrorAction SilentlyContinue +} +catch { + # If getting by ID fails, try searching by display name + $TargetGroup = Get-MgGroup -Filter "displayName eq '$AADGroup'" -ErrorAction SilentlyContinue +} + +if ($null -eq $TargetGroup -or $TargetGroup -eq "") { + + Write-Host "AAD Group - '$AADGroup' doesn't exist, please specify a valid AAD Group..." -ForegroundColor Red + Write-Host + exit + +} + +Write-Host "Found AAD Group:" $TargetGroup.displayName -ForegroundColor Green +Write-Host + +#################################################### + +$PolicyId = Read-Host -Prompt "Enter the Configuration Policy ID to assign" + +if ($PolicyId -eq "" -or $null -eq $PolicyId) { + + Write-Host "No Configuration Policy ID specified..." -ForegroundColor Red + Write-Host + exit + +} + +# Verify the policy exists +$graphApiVersion = "beta" +$Resource = "deviceManagement/configurationPolicies('$PolicyId')" +$uri = "https://graph.microsoft.com/$graphApiVersion/$($Resource)" + +try { + $Policy = Invoke-MgGraphRequest -Uri $uri -Method Get + + if ($Policy) { + + Write-Host "Configuration Policy found:" $Policy.name -ForegroundColor Yellow + Write-Host + + # Prompt for assignment type + Write-Host "Assignment Type:" -ForegroundColor Yellow + Write-Host "1. Include (Assign policy to group members)" -ForegroundColor Cyan + Write-Host "2. Exclude (Exclude group members from policy)" -ForegroundColor Cyan + $AssignmentChoice = Read-Host -Prompt "Select assignment type (1 or 2, default is 1)" + + $AssignmentType = "Include" + if ($AssignmentChoice -eq "2") { + $AssignmentType = "Exclude" + } + + Write-Host + Write-Host "Assigning Configuration Policy to group..." -ForegroundColor Yellow + + Add-ConfigurationPolicyAssignment -ConfigurationPolicyId $PolicyId -TargetGroupId $TargetGroup.id -AssignmentType $AssignmentType + + if ($AssignmentType -eq "Exclude") { + Write-Host "Configuration Policy '$($Policy.name)' excluded from group '$($TargetGroup.displayName)' successfully" -ForegroundColor Green + } + else { + Write-Host "Configuration Policy '$($Policy.name)' assigned to group '$($TargetGroup.displayName)' successfully" -ForegroundColor Green + } + + } + +} +catch { + + Write-Host "Configuration Policy with ID '$PolicyId' doesn't exist or couldn't be retrieved..." -ForegroundColor Red + Write-Host + +} diff --git a/ConfigurationPolicy/ConfigurationPolicy_Get_Assign.ps1 b/ConfigurationPolicy/ConfigurationPolicy_Get_Assign.ps1 new file mode 100644 index 0000000..fc75f27 --- /dev/null +++ b/ConfigurationPolicy/ConfigurationPolicy_Get_Assign.ps1 @@ -0,0 +1,169 @@ +Import-Module Microsoft.Graph.Beta.DeviceManagement +Import-Module Microsoft.Graph.Groups + +#################################################### + +<# region Authentication +To authenticate, you'll use the Microsoft Graph PowerShell SDK. If you haven't already installed the SDK, see this guide: +https://learn.microsoft.com/en-us/powershell/microsoftgraph/installation?view=graph-powershell-1.0 + +The PowerShell SDK supports two types of authentication: delegated access, and app-only access. + +For details on using delegated access, see this guide here: +https://learn.microsoft.com/powershell/microsoftgraph/get-started?view=graph-powershell-1.0 + +For details on using app-only access for unattended scenarios, see Use app-only authentication with the Microsoft Graph PowerShell SDK: +https://learn.microsoft.com/powershell/microsoftgraph/app-only?view=graph-powershell-1.0&tabs=azure-portal + +#> + +#endregion + +#################################################### + +Function Get-ConfigurationPolicyAssignments() { + + <# +.SYNOPSIS +This function is used to get Configuration policy assignments from the Graph API REST interface +.DESCRIPTION +The function connects to the Graph API Interface and gets a Configuration policy assignments +.EXAMPLE +Get-ConfigurationPolicyAssignments -ConfigurationPolicyId $ConfigurationPolicyId +Returns any Configuration policy assignments configured in Intune +.NOTES +NAME: Get-ConfigurationPolicyAssignments +#> + + [cmdletbinding()] + + param + ( + [parameter(Mandatory = $true)] + [ValidateNotNullOrEmpty()] + $ConfigurationPolicyId + ) + + $graphApiVersion = "beta" + $Resource = "deviceManagement/configurationPolicies('$ConfigurationPolicyId')/assignments" + + try { + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($Resource)" + (Invoke-MgGraphRequest -Uri $uri -Method Get).Value + + } + + catch { + + $ex = $_.Exception + $errorResponse = $ex.Response.GetResponseStream() + $reader = New-Object System.IO.StreamReader($errorResponse) + $reader.BaseStream.Position = 0 + $reader.DiscardBufferedData() + $responseBody = $reader.ReadToEnd(); + Write-Host "Response content:`n$responseBody" -f Red + Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)" + write-host + break + + } + +} + +#################################################### + +$PolicyId = Read-Host -Prompt "Enter the Configuration Policy ID to get assignments" + +if ($PolicyId -eq "" -or $null -eq $PolicyId) { + + Write-Host "No Configuration Policy ID specified..." -ForegroundColor Red + Write-Host + exit + +} + +# Verify the policy exists +$graphApiVersion = "beta" +$Resource = "deviceManagement/configurationPolicies('$PolicyId')" +$uri = "https://graph.microsoft.com/$graphApiVersion/$($Resource)" + +try { + $Policy = Invoke-MgGraphRequest -Uri $uri -Method Get + + if ($Policy) { + + Write-Host "Configuration Policy:" $Policy.name -ForegroundColor Yellow + Write-Host + + $Assignments = Get-ConfigurationPolicyAssignments -ConfigurationPolicyId $PolicyId + + if ($Assignments) { + + Write-Host "Assignments found:" -ForegroundColor Cyan + Write-Host + + foreach ($Assignment in $Assignments) { + + if ($Assignment.target.'@odata.type' -eq '#microsoft.graph.groupAssignmentTarget') { + + $GroupId = $Assignment.target.groupId + + try { + $Group = Get-MgGroup -GroupId $GroupId + Write-Host " - Include: $($Group.displayName)" -ForegroundColor Green + Write-Host " Group ID: $GroupId" + } + catch { + Write-Host " - Include: Group (Unable to retrieve name)" -ForegroundColor Green + Write-Host " Group ID: $GroupId" + } + + } + elseif ($Assignment.target.'@odata.type' -eq '#microsoft.graph.exclusionGroupAssignmentTarget') { + + $GroupId = $Assignment.target.groupId + + try { + $Group = Get-MgGroup -GroupId $GroupId + Write-Host " - Exclude: $($Group.displayName)" -ForegroundColor Red + Write-Host " Group ID: $GroupId" + } + catch { + Write-Host " - Exclude: Group (Unable to retrieve name)" -ForegroundColor Red + Write-Host " Group ID: $GroupId" + } + + } + elseif ($Assignment.target.'@odata.type' -eq '#microsoft.graph.allLicensedUsersAssignmentTarget') { + + Write-Host " - All Users" -ForegroundColor Green + + } + elseif ($Assignment.target.'@odata.type' -eq '#microsoft.graph.allDevicesAssignmentTarget') { + + Write-Host " - All Devices" -ForegroundColor Green + + } + + Write-Host + + } + + } + else { + + Write-Host "No assignments found for this Configuration Policy" -ForegroundColor Yellow + Write-Host + + } + + } + +} +catch { + + Write-Host "Configuration Policy with ID '$PolicyId' doesn't exist or couldn't be retrieved..." -ForegroundColor Red + Write-Host + +} diff --git a/ConfigurationPolicy/readme.md b/ConfigurationPolicy/readme.md index 8deb7d6..3132fb4 100644 --- a/ConfigurationPolicy/readme.md +++ b/ConfigurationPolicy/readme.md @@ -125,7 +125,48 @@ When prompted, enter the Configuration Policy ID (which can be obtained from the **Important**: This action is permanent and cannot be undone. -### 4. ConfigurationPolicy_Import_FromJSON.ps1 +### 4. ConfigurationPolicy_Assign.ps1 +This script assigns a configuration policy to an Azure AD group. You can choose to include or exclude the group from the policy. + +```PowerShell +# Assign a configuration policy to a group +.\ConfigurationPolicy_Assign.ps1 +``` + +The script will: +1. Prompt for the Azure AD group name or ID +2. Prompt for the Configuration Policy ID +3. Ask whether to include or exclude the group +4. Create the assignment + +#### Add-ConfigurationPolicyAssignment Function +This function creates an assignment for a configuration policy. + +```PowerShell +Add-ConfigurationPolicyAssignment -ConfigurationPolicyId $policyId -TargetGroupId $groupId -AssignmentType "Include" +``` + +### 5. ConfigurationPolicy_Get_Assign.ps1 +This script retrieves and displays all assignments for a specific configuration policy, showing which groups are included or excluded. + +```PowerShell +# Get assignments for a configuration policy +.\ConfigurationPolicy_Get_Assign.ps1 +``` + +When prompted, enter the Configuration Policy ID. The script will display: +- All group assignments (included and excluded) +- All Users assignments +- All Devices assignments + +#### Get-ConfigurationPolicyAssignments Function +This function retrieves all assignments for a configuration policy. + +```PowerShell +Get-ConfigurationPolicyAssignments -ConfigurationPolicyId $policyId +``` + +### 6. ConfigurationPolicy_Import_FromJSON.ps1 This script imports a configuration policy from a JSON file that was previously exported using the ConfigurationPolicy_Export.ps1 script. It supports all technology types including Windows 365, Microsoft Defender for Endpoint, Endpoint Privilege Management, and traditional MDM policies. The script will: @@ -219,6 +260,38 @@ This will display all configuration policies with their IDs and properties, whic 4. Enter the policy ID when prompted and confirm the removal +### Assigning Policies to Groups + +1. Connect to Microsoft Graph: + ```PowerShell + Connect-MgGraph -Scopes "DeviceManagementConfiguration.ReadWrite.All", "Group.Read.All" + ``` + +2. Run the assign script: + ```PowerShell + .\ConfigurationPolicy_Assign.ps1 + ``` + +3. Enter the Azure AD group name or ID when prompted + +4. Enter the Configuration Policy ID + +5. Choose whether to include or exclude the group + +### Getting Policy Assignments + +1. Connect to Microsoft Graph: + ```PowerShell + Connect-MgGraph -Scopes "DeviceManagementConfiguration.Read.All", "Group.Read.All" + ``` + +2. Run the get assignments script: + ```PowerShell + .\ConfigurationPolicy_Get_Assign.ps1 + ``` + +3. Enter the Configuration Policy ID when prompted to see all assignments + ## Difference from Settings Catalog Scripts The key difference between these Configuration Policy scripts and the Settings Catalog scripts is: From ab287099abd8dce2d81f49f1d21819a0ccd0ee73 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 24 Oct 2025 06:22:40 +0000 Subject: [PATCH 5/5] Refactor ConfigurationPolicy_Get_Assign.ps1 to reduce code duplication Co-authored-by: Mahopper <29206133+Mahopper@users.noreply.github.com> --- .../ConfigurationPolicy_Get_Assign.ps1 | 54 ++++++++++++------- 1 file changed, 34 insertions(+), 20 deletions(-) diff --git a/ConfigurationPolicy/ConfigurationPolicy_Get_Assign.ps1 b/ConfigurationPolicy/ConfigurationPolicy_Get_Assign.ps1 index fc75f27..d43208e 100644 --- a/ConfigurationPolicy/ConfigurationPolicy_Get_Assign.ps1 +++ b/ConfigurationPolicy/ConfigurationPolicy_Get_Assign.ps1 @@ -73,6 +73,34 @@ NAME: Get-ConfigurationPolicyAssignments #################################################### +Function Get-GroupDisplayName() { + + <# +.SYNOPSIS +Helper function to retrieve group display name by ID +.DESCRIPTION +Retrieves the display name for a group, with error handling +.EXAMPLE +Get-GroupDisplayName -GroupId $groupId +#> + + param ( + [parameter(Mandatory = $true)] + [string]$GroupId + ) + + try { + $Group = Get-MgGroup -GroupId $GroupId + return $Group.displayName + } + catch { + return "Group (Unable to retrieve name)" + } + +} + +#################################################### + $PolicyId = Read-Host -Prompt "Enter the Configuration Policy ID to get assignments" if ($PolicyId -eq "" -or $null -eq $PolicyId) { @@ -108,31 +136,17 @@ try { if ($Assignment.target.'@odata.type' -eq '#microsoft.graph.groupAssignmentTarget') { $GroupId = $Assignment.target.groupId - - try { - $Group = Get-MgGroup -GroupId $GroupId - Write-Host " - Include: $($Group.displayName)" -ForegroundColor Green - Write-Host " Group ID: $GroupId" - } - catch { - Write-Host " - Include: Group (Unable to retrieve name)" -ForegroundColor Green - Write-Host " Group ID: $GroupId" - } + $GroupName = Get-GroupDisplayName -GroupId $GroupId + Write-Host " - Include: $GroupName" -ForegroundColor Green + Write-Host " Group ID: $GroupId" } elseif ($Assignment.target.'@odata.type' -eq '#microsoft.graph.exclusionGroupAssignmentTarget') { $GroupId = $Assignment.target.groupId - - try { - $Group = Get-MgGroup -GroupId $GroupId - Write-Host " - Exclude: $($Group.displayName)" -ForegroundColor Red - Write-Host " Group ID: $GroupId" - } - catch { - Write-Host " - Exclude: Group (Unable to retrieve name)" -ForegroundColor Red - Write-Host " Group ID: $GroupId" - } + $GroupName = Get-GroupDisplayName -GroupId $GroupId + Write-Host " - Exclude: $GroupName" -ForegroundColor Red + Write-Host " Group ID: $GroupId" } elseif ($Assignment.target.'@odata.type' -eq '#microsoft.graph.allLicensedUsersAssignmentTarget') {