diff --git a/CloudAPIPowerShellManagement.psm1 b/CloudAPIPowerShellManagement.psm1 index ce73107..63d6d50 100644 --- a/CloudAPIPowerShellManagement.psm1 +++ b/CloudAPIPowerShellManagement.psm1 @@ -107,6 +107,7 @@ function Initialize-CloudAPIManagement if($tenantId) { + Write-Host "Using Tenant Id: $tenantId" $global:AzureAppId = $appId $global:ClientSecret = $secret $global:ClientCert = $certificate @@ -115,37 +116,37 @@ function Initialize-CloudAPIManagement if($global:AzureAppId) { - Write-Log "Using Azure App Id: " + Write-Host "Using Azure App Id: $($global:AzureAppId)" } else { - Write-Log "Azure App Id is missing. Use -AppId on the command line" 2 + Write-Warning "Azure App Id is missing. Use -AppId on the command line" } if($global:ClientSecret -or $global:ClientCert) { if($global:ClientSecret) { - Write-Log "Using Azure App Secret" + Write-Host "Using Azure App Secret" } else { - Write-Log "Using Azure App Certificate" + Write-Host "Using Azure App Certificate" } } else { - Write-Log "Azure App Secret or Certificate is missing. Use -Secret or -Certificate on the command line" 2 + Write-Warning "Azure App Secret or Certificate is missing. Use -Secret or -Certificate on the command line" } if($global:UseGraphEnvironment) { - Write-Log "Using Azure Graph Environment: $($global:UseGraphEnvironment)" + Write-Host "Using Azure Graph Environment: $($global:UseGraphEnvironment)" } if($global:GCCType) { - Write-Log "Using Graph Environment type: $($global:GCCType)" + Write-Host "Using Graph Environment type: $($global:GCCType)" } } diff --git a/Core.psm1 b/Core.psm1 index 5593545..96cd1c5 100644 --- a/Core.psm1 +++ b/Core.psm1 @@ -2910,6 +2910,19 @@ function Get-DataGridValues ($dataGrid.ItemsSource | Select -Property $properties) } +function Get-GUIDs +{ + param($text) + + $regExpGuid = "[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}" + + $uniqueGuids = New-Object System.Collections.Generic.HashSet[String] + + # Use regular expressions to extract the GUIDs + [regex]::Matches($text, $regExpGuid) | ForEach-Object { $uniqueGuids.Add($_.Value) | Out-Null } + + $uniqueGuids +} New-Alias -Name ?? -value Invoke-Coalesce New-Alias -Name ?: -value Invoke-IfTrue diff --git a/Extensions/EndpointManager.psm1 b/Extensions/EndpointManager.psm1 index 0657e1a..e3f3897 100644 --- a/Extensions/EndpointManager.psm1 +++ b/Extensions/EndpointManager.psm1 @@ -608,6 +608,7 @@ function Invoke-InitializeModule ViewProperties = @("name","description","Id") Expand="Settings" Icon="DeviceConfiguration" + PreImportCommand = { Start-PreImportSettingsCatalog @args } PostExportCommand = { Start-PostExportSettingsCatalog @args } PreUpdateCommand = { Start-PreUpdateSettingsCatalog @args } PostGetCommand = { Start-PostGetSettingsCatalog @args } @@ -626,9 +627,6 @@ function Invoke-InitializeModule ViewProperties = @("name","description","Id") Expand="Settings" Icon="DeviceConfiguration" - PostExportCommand = { Start-PostExportSettingsCatalog @args } - PreUpdateCommand = { Start-PreUpdateSettingsCatalog @args } - PostGetCommand = { Start-PostGetSettingsCatalog @args } GroupId = "DeviceConfiguration" }) @@ -3294,6 +3292,75 @@ function Start-PostFileImportRoleDefinitions #endregion #region SettingsCatalog + +function Start-PreImportSettingsCatalog +{ + param($obj, $objectType) + + $returnHT = @{} + $updated = $false + + if($obj.templateReference.templateId) { + # I do not like this at all and it is a lazy but simple implementation... + # It turns out that settingInstanceTemplateId and settingValueTemplateId are case sensitive + # and there is ONE setting with a different casing in the Windows Baseline template. + # The export saves it with lowercase which causes the import to fail. + + Write-Log "Get template $($obj.templateReference.templateId)" + $templateObj = Invoke-GraphRequest -Url "/deviceManagement/configurationPolicyTemplates('$($obj.templateReference.templateId)')" + if($templateObj.lifecycleState -and $templateObj.lifecycleState -ne "active") { + Write-Log "Template '$($templateObj.displayName)' '$($templateObj.displayVersion)' is in '$($templateObj.lifecycleState)' state. Current state: $($templateObj.lifecycleState). Import might fail." 2 + } + #Todo: Should probably check for the latest active version and use that instead of the one in the templateReference + + if(-not $script:baseLineTemplate) { + $script:baseLineTemplate = @{} + } + if($script:baseLineTemplate.ContainsKey($obj.templateReference.templateId)) { + $templateReference = $script:baseLineTemplate[$obj.templateReference.templateId] + } + else { + Write-Log "Get template settings for '$($templateObj.displayName)' '$($templateObj.displayVersion)' ($($obj.templateReference.templateId))" + $templateReference = Invoke-GraphRequest -Url "/deviceManagement/configurationPolicyTemplates('$($obj.templateReference.templateId)')/settingTemplates?`$expand=settingDefinitions&top=1000" + $script:baseLineTemplate.Add($obj.templateReference.templateId, $templateReference) + } + + if($templateReference) { + $newObjJson = $obj | ConvertTo-Json -Depth 50 + $templateIDs = Get-GUIDs ($templateReference | ConvertTo-Json -Depth 50) + $objectIDs = Get-GUIDs ($obj.Settings | ConvertTo-Json -Depth 50) + $diff = Compare-Object $templateIDs $objectIDs -CaseSensitive + foreach($diffItem in ($diff | where SideIndicator -eq "=>")) { + $templateID = $templateIDs | Where { $_ -eq $diffItem.InputObject } + if($templateID) { + # Found but with different casing + $newObjJson = $newObjJson -replace $diffItem.InputObject, $templateID + $updated = $true + } + } + if($updated) { + $returnHT.Add("JSON", $newObjJson) + } + } + } + return $returnHT +} + +function Invoke-CheckSettingsCatalogIds +{ + param($obj, $templateReference) + + foreach($settingTemplate in $obj.value) { + if($settingTemplate.settingDefinitions) { + foreach($settingDefinition in $settingTemplate.settingDefinitions) { + if($settingDefinition.id -and $settingDefinition.id -ne $obj.Id) { + Write-Log "Setting definition ID $($settingDefinition.id) does not match the settings catalog ID $($obj.Id)" 2 + } + } + } + } +} + function Start-PostExportSettingsCatalog { param($obj, $objectType, $path) diff --git a/Extensions/MSGraph.psm1 b/Extensions/MSGraph.psm1 index 9ead93c..e886482 100644 --- a/Extensions/MSGraph.psm1 +++ b/Extensions/MSGraph.psm1 @@ -3776,7 +3776,12 @@ function Import-GraphObject if($ret.ContainsKey("AdditionalHeaders") -and $ret["AdditionalHeaders"] -is [HashTable]) { $params.Add("AdditionalHeaders",$ret["AdditionalHeaders"]) - } + } + + if($ret.ContainsKey("JSON")) + { + $obj = $ret["JSON"] | ConvertFrom-Json + } } }