From 6a763dc454a3b6262ecfe9964388620d01c019ab Mon Sep 17 00:00:00 2001 From: satijeri <87656508+satijeri@users.noreply.github.com> Date: Tue, 21 Feb 2023 07:29:55 -0500 Subject: [PATCH] Update RBAC_ScopeTags_PolicyAssign.ps1 updated to remove characters that seemed to be added in word or wordpad and caused errors in powershell. Included functions to also find Admin Templates and Catalog Settings type of profiles. Modified the Section in finding ScopeTags to bring up a list of identified Tags and have the person running script select the tag vs typing the full name of the tag. Modified script so it will return all found profiles and not just the first 25 (pagelink) --- RBAC/RBAC_ScopeTags_PolicyAssign.ps1 | 608 +++++++++++++++++++++++++-- 1 file changed, 582 insertions(+), 26 deletions(-) diff --git a/RBAC/RBAC_ScopeTags_PolicyAssign.ps1 b/RBAC/RBAC_ScopeTags_PolicyAssign.ps1 index c9cb25a..71febc6 100644 --- a/RBAC/RBAC_ScopeTags_PolicyAssign.ps1 +++ b/RBAC/RBAC_ScopeTags_PolicyAssign.ps1 @@ -1,6 +1,6 @@ - + <# -  + .COPYRIGHT Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. See LICENSE in the project root for license information. @@ -8,7 +8,8 @@ See LICENSE in the project root for license information. #> #################################################### -  + + function Get-AuthToken { <# @@ -89,13 +90,15 @@ Write-Host "Checking for AzureAD module..." [System.Reflection.Assembly]::LoadFrom($adalforms) | Out-Null $clientId = "d1ddf0e4-d672-4dae-b554-9d5bdfd93547" -  + $redirectUri = "urn:ietf:wg:oauth:2.0:oob" -  + +#This needs to be changed for DOD to "https://graph.microsoft.com" $resourceAppIdURI = "https://graph.microsoft.com" -  + +#This needs to be changed for DOD to "https://login.microsoftonline.com/$Tenant" $authority = "https://login.microsoftonline.com/$Tenant" -  + try { $authContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList $authority @@ -105,7 +108,7 @@ $authority = "https://login.microsoftonline.com/$Tenant" $platformParameters = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.PlatformParameters" -ArgumentList "Auto" - $userId = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.UserIdentifier" -ArgumentList ($User, "OptionalDisplayableId") + $userId = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.comerIdentifier" -ArgumentList ($User, "OptionalDisplayableId") $authResult = $authContext.AcquireTokenAsync($resourceAppIdURI,$clientId,$redirectUri,$platformParameters,$userId).Result @@ -146,7 +149,7 @@ $authority = "https://login.microsoftonline.com/$Tenant" } } -  + #################################################### Function Get-DeviceCompliancePolicy(){ @@ -305,10 +308,180 @@ $DCP_resource = "deviceManagement/deviceConfigurations" else { $uri = "https://graph.microsoft.com/$graphApiVersion/$($DCP_resource)" - (Invoke-RestMethod -Uri $uri -Headers $authToken -Method Get).Value + $results=Invoke-RestMethod -Uri $uri -Headers $authToken -Method Get + $value=$results.value + $pages=$results.'@odata.nextlink' + while($null -ne $pages){ + $additional=(Invoke-RestMethod -Uri $pages -Headers $authToken -Method Get) + if($pages){ + $value+=$additional.Value + $pages=$additional."@odata.nextlink" + } + } + return $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-DeviceConfigurationAdminTemplates(){ + +<# +.SYNOPSIS +This function is used to get device configuration policies from the Graph API REST interface +.DESCRIPTION +The function connects to the Graph API Interface and gets any device configuration policies +.EXAMPLE +Get-DeviceConfigurationPolicy +Returns any device configuration policies configured in Intune +.NOTES +NAME: Get-DeviceConfigurationPolicy +#> + +[cmdletbinding()] + +param +( + $name, + $id +) + +$graphApiVersion = "Beta" +$DCP_resource = "deviceManagement/groupPolicyConfigurations" + + try { + + if($Name){ + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($DCP_resource)" + (Invoke-RestMethod -Uri $uri -Headers $authToken -Method Get).Value | Where-Object { ($_.'displayName').contains("$Name") } + + } + + elseif($id){ + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($DCP_resource)/$id" + Invoke-RestMethod -Uri $uri -Headers $authToken -Method Get + + } + + else { + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($DCP_resource)" + + $results=Invoke-RestMethod -Uri $uri -Headers $authToken -Method Get + $value=$results.value + $pages=$results.'@odata.nextlink' + while($null -ne $pages){ + $additional=(Invoke-RestMethod -Uri $pages -Headers $authToken -Method Get) + if($pages){ + $value+=$additional.Value + $pages=$additional."@odata.nextlink" + } + } + return $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-DeviceConfigurationSettingsCatalog(){ + +<# +.SYNOPSIS +This function is used to get device configuration policies from the Graph API REST interface +.DESCRIPTION +The function connects to the Graph API Interface and gets any device configuration policies +.EXAMPLE +Get-DeviceConfigurationPolicy +Returns any device configuration policies configured in Intune +.NOTES +NAME: Get-DeviceConfigurationPolicy +#> + +[cmdletbinding()] + +param +( + $name, + $id +) + +$graphApiVersion = "Beta" +$DCP_resource = "deviceManagement/configurationPolicies" + + try { + + if($Name){ + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($DCP_resource)" + (Invoke-RestMethod -Uri $uri -Headers $authToken -Method Get).Value | Where-Object { ($_.'Name').contains("$Name") } + + } + + elseif($id){ + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($DCP_resource)/$id" + Invoke-RestMethod -Uri $uri -Headers $authToken -Method Get } + else { + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($DCP_resource)" + + $results=Invoke-RestMethod -Uri $uri -Headers $authToken -Method Get + $value=$results.value + $pages=$results.'@odata.nextlink' + while($null -ne $pages){ + $additional=(Invoke-RestMethod -Uri $pages -Headers $authToken -Method Get) + if($pages){ + $value+=$additional.Value + $pages=$additional."@odata.nextlink" + } + } + return $value + } + } catch { @@ -328,6 +501,7 @@ $DCP_resource = "deviceManagement/deviceConfigurations" } + #################################################### Function Update-DeviceCompliancePolicy(){ @@ -375,7 +549,7 @@ $JSON = @" else { - $object = New-Object –TypeName PSObject + $object = New-Object -TypeName PSObject $object | Add-Member -MemberType NoteProperty -Name '@odata.type' -Value "$Type" $object | Add-Member -MemberType NoteProperty -Name 'roleScopeTagIds' -Value @($ScopeTags) $JSON = $object | ConvertTo-Json @@ -454,7 +628,7 @@ $JSON = @" else { - $object = New-Object –TypeName PSObject + $object = New-Object -TypeName PSObject $object | Add-Member -MemberType NoteProperty -Name '@odata.type' -Value "$Type" $object | Add-Member -MemberType NoteProperty -Name 'roleScopeTagIds' -Value @($ScopeTags) $JSON = $object | ConvertTo-Json @@ -486,6 +660,168 @@ $JSON = @" } + +#################################################### + +Function Update-DeviceConfigurationAdminTemplate(){ + +<# +.SYNOPSIS +This function is used to update a device configuration policy using the Graph API REST interface +.DESCRIPTION +The function connects to the Graph API Interface and updates a device configuration policy +.EXAMPLE +Update-DeviceConfigurationPolicy -id $Policy.id -Type $Type -ScopeTags "1" +Updates an device configuration policy in Intune +.NOTES +NAME: Update-DeviceConfigurationPolicy +#> + +[cmdletbinding()] + +param +( + [Parameter(Mandatory=$true)] + $id, + # [Parameter(Mandatory=$true)] + # $Type, + [Parameter(Mandatory=$true)] + $ScopeTags +) + +$graphApiVersion = "beta" +$Resource = "deviceManagement/groupPolicyConfigurations/$id" + + try { + + if($ScopeTags -eq "" -or $ScopeTags -eq $null){ + +$JSON = @" + +{ + + "roleScopeTagIds": [] +} + +"@ +#took this out of the jason config above just above "roleScopeTagIDs" "@odata.type": "$Type", + } + + else { + + $object = New-Object -TypeName PSObject + #$object | Add-Member -MemberType NoteProperty -Name '@odata.type' -Value "$Type" + $object | Add-Member -MemberType NoteProperty -Name 'roleScopeTagIds' -Value @($ScopeTags) + $JSON = $object | ConvertTo-Json + + } + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($Resource)" + Invoke-RestMethod -Uri $uri -Headers $authToken -Method Patch -Body $JSON -ContentType "application/json" + + Start-Sleep -Milliseconds 100 + + } + + catch { + + Write-Host + $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 Update-DeviceConfigurationSettingsCatalog(){ + +<# +.SYNOPSIS +This function is used to update a device configuration policy using the Graph API REST interface +.DESCRIPTION +The function connects to the Graph API Interface and updates a device configuration policy +.EXAMPLE +Update-DeviceConfigurationPolicy -id $Policy.id -Type $Type -ScopeTags "1" +Updates an device configuration policy in Intune +.NOTES +NAME: Update-DeviceConfigurationPolicy +#> + +[cmdletbinding()] + +param +( + [Parameter(Mandatory=$true)] + $id, + # [Parameter(Mandatory=$true)] + # $Type, + [Parameter(Mandatory=$true)] + $ScopeTags +) + +$graphApiVersion = "beta" +$Resource = "deviceManagement/configurationPolicies/$id" + + try { + + if($ScopeTags -eq "" -or $ScopeTags -eq $null){ + +$JSON = @" + +{ + + "roleScopeTagIds": [] +} + +"@ +#took this out of the jason config above just above "roleScopeTagIDs" "@odata.type": "$Type", + } + + else { + + $object = New-Object -TypeName PSObject + #$object | Add-Member -MemberType NoteProperty -Name '@odata.type' -Value "$Type" + $object | Add-Member -MemberType NoteProperty -Name 'roleScopeTagIds' -Value @($ScopeTags) + $JSON = $object | ConvertTo-Json + + } + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($Resource)" + Invoke-RestMethod -Uri $uri -Headers $authToken -Method Patch -Body $JSON -ContentType "application/json" + + Start-Sleep -Milliseconds 100 + + } + + catch { + + Write-Host + $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-RBACScopeTag(){ @@ -526,7 +862,21 @@ $Resource = "deviceManagement/roleScopeTags" else { $uri = "https://graph.microsoft.com/$graphApiVersion/$Resource" - $Result = (Invoke-RestMethod -Uri $uri -Method Get -Headers $authToken).Value + + + # $Result = (Invoke-RestMethod -Uri $uri -Method Get -Headers $authToken).Value + + $results=Invoke-RestMethod -Uri $uri -Headers $authToken -Method Get + $Result=$results.value + $pages=$results.'@odata.nextlink' + while($null -ne $pages){ + $additional=(Invoke-RestMethod -Uri $pages -Headers $authToken -Method Get) + if($pages){ + $Result+=$additional.Value + $pages=$additional."@odata.nextlink" + } + } + return $Result } @@ -604,9 +954,9 @@ $global:authToken = Get-AuthToken -User $User #################################################### -Write-Host "Are you sure you want to add Scope Tags to all Configuration and Compliance Policies? Y or N?" -$Confirm = read-host - +#Write-Host "Are you sure you want to add Scope Tags to all Configuration and Compliance Policies? Y or N?" +#$Confirm = read-host +$Confirm = "Y" if($Confirm -eq "y" -or $Confirm -eq "Y"){ Write-Host "Checking if any Scope Tags have been created..." @@ -614,6 +964,81 @@ if($Confirm -eq "y" -or $Confirm -eq "Y"){ $ScopeTags = Get-RBACScopeTag + #Modify here so we only work with 1 scope tag at a time instead of all the existing ScopeTags. We do need the '*' as we are using the -like operator. May want to put user input reads to type the Tag name + Write-host "Please type the Scope Tag you would like to apply (Full and correct scope Tag name)" + #region ScopeTags Menu + +Write-Host + +$ScopeTags1 = (Get-RBACScopeTag).displayName | Sort-Object + +if($ScopeTags1){ + +Write-Host "Please specify Scope Tag you want to add to all users / devices in AAD Group:" -ForegroundColor Yellow + +$menu = @{} + +for ($i=1;$i -le $ScopeTags1.count; $i++) +{ Write-Host "$i. $($ScopeTags1[$i-1])" +$menu.Add($i,($ScopeTags1[$i-1]))} + +Write-Host +$ans = Read-Host 'Enter Scope Tag id (Numerical value)' + +if($ans -eq "" -or $ans -eq $null){ + + Write-Host "Scope Tag can't be null, please specify a valid Scope Tag..." -ForegroundColor Red + Write-Host + break + +} + +elseif(($ans -match "^[\d\.]+$") -eq $true){ + +$selection = $menu.Item([int]$ans) + + if($selection){ + + $ScopeTagId = (Get-RBACScopeTag | Where-Object { $_.displayName -eq "$selection" }).id + $inTag= $selection + } + + else { + + Write-Host "Scope Tag selection invalid, please specify a valid Scope Tag..." -ForegroundColor Red + Write-Host + break + + } + +} + +else { + + Write-Host "Scope Tag not an integer, please specify a valid scope tag..." -ForegroundColor Red + Write-Host + break + +} + +Write-Host + +} + +else { + + Write-Host "No Scope Tags created, script can't continue..." -ForegroundColor Red + Write-Host + break + +} + +#endregion + + + + $ScopeTags = $ScopeTags | ?{$_.displayname -eq $inTag} + if($ScopeTags){ Write-Host "Scope Tags found..." -ForegroundColor Green @@ -630,11 +1055,23 @@ if($Confirm -eq "y" -or $Confirm -eq "Y"){ #region Device Compliance Policies - Write-Host "Testing if '$ScopeTag_DN' exists in Device Compliance Policy Display Name..." - - $CPs = Get-DeviceCompliancePolicy | Where-Object { ($_.displayName).contains("$ScopeTag_DN") } | Sort-Object displayName + Write-Host "Type the pattern name of the Compliance Policies you'd like to apply the ScopeTag provided (Compliance Policy name is case sensitive)" + $inCP=read-host +# This is where we update the Complicance Policy names so it only targets anything containing the specified text, no need for '*' as we are using contains operator + $CPs = Get-DeviceCompliancePolicy | Where-Object { ($_.displayName).contains($inCP) } | Sort-Object displayName + if($CPs){ + write-host "These are the identified Compliance Policies that would be tagged with $($ScopeTag.DisplayName)" + foreach($cpls in $CPs){ + write-host $CPls.displayName -foregroundcolor Cyan } + write-host "Are you sure you want to proceed (Y/N)?" + $answerCP=read-host + } + else + { + Write-Host "There were no Compliance Policies that matched your name pattern" -foregroundcolor Red + } - if($CPs){ + if(($CPs) -and (($answerCP -eq "Y") -or ($answerCP -eq "y"))){ foreach($Policy in $CPs){ @@ -692,11 +1129,29 @@ if($Confirm -eq "y" -or $Confirm -eq "Y"){ #region Device Configuration Policies - Write-Host "Testing if '$ScopeTag_DN' exists in Device Configuration Policy Display Name..." + Write-Host "Type the pattern name of the Configuration Profiles you'd like to apply the scope tag provided (Configuration profile name is case sensitive)" + $inDCP=read-host - $DCPs = Get-DeviceConfigurationPolicy | Where-Object { ($_.displayName).contains("$ScopeTag_DN") } | Sort-Object displayName +#Update this displayName.contains with the name/names or wildcard of the Configuration profiles that we want to update no need for a '*' in the contains section + $DCPs = Get-DeviceConfigurationPolicy | Where-Object { ($_.displayName).contains($inDCP) } | Sort-Object displayName + $AdmTemp=Get-DeviceConfigurationAdminTemplates | Where-Object { ($_.displayName).contains($inDCP) } | Sort-Object displayName + $SettCat=get-deviceconfigurationsettingscatalog | Where-Object { ($_.Name).contains($inDCP) } | Sort-Object Name + + +if(($DCPs) -or ($AdmTemp) -or ($SettCat)){ + write-host "These are the identified Configuration Profiles that would be tagged with $($ScopeTag.DisplayName)" + foreach($pol in $DCPs){write-host $pol.displayName -foregroundcolor Cyan} + if($AdmTemp){foreach($templ in $AdmTemp){write-host $templ.displayName -foregroundcolor Cyan}} + if($SettCat){foreach($templ in $SettCat){write-host $templ.Name -foregroundcolor Cyan}} + write-host "Are you sure you want to proceed (Y/N)?" + $answerDCP=read-host + } + else + { + Write-host "There were no Configuration profiles that matched your name pattern" -foregroundcolor Red + } - if($DCPs){ + if(($DCPs) -and (($answerDCP -eq "Y") -or ($answerDCP -eq "y"))){ foreach($Policy in $DCPs){ @@ -746,8 +1201,109 @@ if($Confirm -eq "y" -or $Confirm -eq "Y"){ } +if(($AdmTemp) -and (($answerDCP -eq "Y") -or ($answerDCP -eq "y"))){ + + foreach($Policy in $AdmTemp){ + + $DCP = Get-DeviceConfigurationAdminTemplates -id $Policy.id + + $DCP_DN = $DCP.displayName + + if($DCP.roleScopeTagIds){ + + if(!($DCP.roleScopeTagIds).contains("$ScopeTagId")){ + + $ST = @($DCP.roleScopeTagIds) + @("$ScopeTagId") + + $Result = Update-DeviceConfigurationAdminTemplate -id $DCP.id -ScopeTags $ST + + if($Result.displayname -eq $DCP.displayname){ + + Write-Host "Configuration Policy '$DCP_DN' patched with '$ScopeTag_DN' ScopeTag..." -ForegroundColor Green + + } + + } + + else { + + Write-Host "Scope Tag '$ScopeTag_DN' already assigned to '$DCP_DN'..." -ForegroundColor Red + + } + + } + + else { + + $ST = @("$ScopeTagId") + + $Result = Update-DeviceConfigurationAdminTemplate -id $Policy.id -ScopeTags $ST + + if($Result.displayname -eq $Policy.displayname){ + + Write-Host "Configuration Policy '$DCP_DN' patched with '$ScopeTag_DN' ScopeTag..." -ForegroundColor Green + + } + + } + + } + + } + Write-Host + +if(($SettCat) -and (($answerDCP -eq "Y") -or ($answerDCP -eq "y"))){ + + foreach($Policy in $SettCat){ + + $DCP = Get-DeviceConfigurationsettingscatalog -id $Policy.id + + $DCP_DN = $DCP.Name + + if($DCP.roleScopeTagIds){ + + if(!($DCP.roleScopeTagIds).contains("$ScopeTagId")){ + + $ST = @($DCP.roleScopeTagIds) + @("$ScopeTagId") + + $Result = Update-DeviceConfigurationsettingscatalog -id $DCP.id -ScopeTags $ST + + if($Result -eq ""){ + + Write-Host "Configuration Policy '$DCP_DN' patched with '$ScopeTag_DN' ScopeTag..." -ForegroundColor Green + + } + + } + + else { + + Write-Host "Scope Tag '$ScopeTag_DN' already assigned to '$DCP_DN'..." -ForegroundColor Red + + } + + } + + else { + + $ST = @("$ScopeTagId") + + $Result = Update-DeviceConfigurationsettingscatalog -id $DCP.id -ScopeTags $ST + + if($Result.name -eq $DCP.name){ + + Write-Host "Configuration Policy '$DCP_DN' patched with '$ScopeTag_DN' ScopeTag..." -ForegroundColor Green + + } + + } + + } + + } Write-Host + #endregion #################################################### @@ -758,7 +1314,7 @@ if($Confirm -eq "y" -or $Confirm -eq "Y"){ else { - Write-Host "No Scope Tags configured..." -ForegroundColor Red + Write-Host "No Scope Tags found with that name..." -ForegroundColor Red } @@ -766,8 +1322,8 @@ if($Confirm -eq "y" -or $Confirm -eq "Y"){ else { - Write-Host "Addition of Scope Tags to all Configuration and Compliance Policies was cancelled..." -ForegroundColor Yellow + Write-Host "Addition of Scope Tags to all Configuration and Compliance Policies was cancelled" } -Write-Host \ No newline at end of file +Write-Host