Public/TenantConfiguration/Baseline/Add-ConfigurationPolicies.ps1

function Add-ConfigurationPolicies {
    param(
        [Parameter(Mandatory)]
        [string]$TenantId
    )

    try {
        Connect-CustomerGraph -CustomerTenantId $TenantId

        $ConfigurationPolicies = (Invoke-GraphRequest -Method GET -Uri 'https://graph.microsoft.com/beta/deviceManagement/configurationPolicies?$filter=%28platforms%20eq%20%27windows10%27%20or%20platforms%20eq%20%27macOS%27%20or%20platforms%20eq%20%27iOS%27%29%20and%20%28technologies%20has%20%27mdm%27%20or%20technologies%20has%20%27windows10XManagement%27%20or%20technologies%20has%20%27appleRemoteManagement%27%29').value

        $ConfigurationPoliciesFiles = Get-ChildItem -Path "$PSScriptRoot\ConfigurationPolicies" -Filter *.json
        $ConfigurationPolicyFilesParsed = New-Object System.Collections.ArrayList
        foreach($ConfigurationPolicyFile in $ConfigurationPoliciesFiles) {
            $ConfigurationPolicy = Get-Content -Path $ConfigurationPolicyFile.FullName | ConvertFrom-Json -AsHashtable -Depth 100
            $ConfigurationPolicyFilesParsed.Add($ConfigurationPolicy) | Out-Null
        }

        $SelectedConfigurationPolicies = $ConfigurationPolicyFilesParsed | Select-Object Name, Description | Out-ConsoleGridView -Title "Configuration Policies to be added"

        $SelectedConfigurationPoliciesArray = @()
        $SelectedConfigurationPoliciesArray = $ConfigurationPolicyFilesParsed | Where-Object { $_.name -contains $SelectedConfigurationPolicies.name }

        foreach($SelectedConfigurationPolicy in $SelectedConfigurationPoliciesArray) {
            if($ConfigurationPolicies.name -contains $SelectedConfigurationPolicy.name) {
                Write-Host "Configuration policy '$($SelectedConfigurationPolicy.name)' already exists, not creating.." -ForegroundColor Yellow
            } else {
                Write-Host "Creating configuration policy '$($SelectedConfigurationPolicy.name)'.."
                # Seperate the "assignments" property from the configuration policy, as it is not supported in the POST request, and put it into its own variable for later use

                $Assignments = $SelectedConfigurationPolicy.assignments
                $SelectedConfigurationPolicy.Remove("assignments")
                switch($SelectedConfigurationPolicy.name) {
                    # Manually replace group in JyskIT-Baseline-SEC-LocalUserGroupMembership
                    # TODO: Find a way to dynamically create groups for use inside configuration policies, and not just assigned ones..
                    "JyskIT-Baseline-SEC-LocalUserGroupMembership" {
                        $GroupName = $SelectedConfigurationPolicy.settings.settingInstance.groupSettingCollectionValue[0].children[0].groupSettingCollectionValue.children[0].choiceSettingValue.children[0].simpleSettingCollectionValue[1].value
                        $Group = Get-MgGroup -Filter "displayName eq '$GroupName'"
                        if($Group -eq $null) {
                            Write-Host "Group '$GroupName' does not exist, creating.." -ForegroundColor Yellow
                            $Group = New-MgGroup -DisplayName $GroupName -MailEnabled:$false -MailNickname $GroupName -SecurityEnabled:$true
                            Write-Host "Created group '$GroupName'." -ForegroundColor Green
                        }
                        $SID =  Convert-EntraIDObjectIDToSid -ObjectId $Group.id
                        $SelectedConfigurationPolicy.settings.settingInstance.groupSettingCollectionValue[0].children[0].groupSettingCollectionValue.children[0].choiceSettingValue.children[0].simpleSettingCollectionValue[1].value = $SID
                        Write-Host "Replaced group SID in configuration policy '$($SelectedConfigurationPolicy.name)' with SID $($SID)." -ForegroundColor Green
                    }
                    "JyskIT-Baseline-CONF-OneDrive" {
                        $SelectedConfigurationPolicy.settings[4].settingInstance.choiceSettingValue.children[4].simpleSettingValue.value = $TenantId
                        Write-Host "Replaced tenant id in configuration policy '$($SelectedConfigurationPolicy.name)' with tenant id $($TenantId)." -ForegroundColor Green
                    }
                    "JyskIT-Baseline-SEC-EDR" {
                        Write-Host "You need to onboard the tenant into Microsoft Defender for Endpoint before $($SelectedConfigurationPolicy.name) can be imported." -ForegroundColor Cyan
                        Write-Host "Visit https://security.microsoft.com/smb-onboarding and wait for the onboarding to complete. This can take several minutes." -ForegroundColor Cyan
                        Write-Host "When the wizard appears, skip everything until it is done. Then visit https://security.microsoft.com/securitysettings/endpoints/integration and enable 'Microsoft Intune connection'." -ForegroundColor Cyan
                        Read-Host  "When you have completed these steps, you can press ENTER to continue."
                        Add-MobileThreatDefenseConnectors -TenantId $TenantId
                    }
                }
                
                $SelectedConfigurationPolicy = Invoke-GraphRequest -Method POST -Uri "https://graph.microsoft.com/beta/deviceManagement/configurationPolicies" -Body $SelectedConfigurationPolicy
                Write-Host "Created configuration policy '$($SelectedConfigurationPolicy.name)'." -ForegroundColor Green

                # If selected configuration policy contains a "assignments" property, assign the policy to the target - if the target is a group create the group if it does not exist
                if($Assignments -ne $null) {
                    $TargetType = $Assignments.target."@odata.type"
                    switch($TargetType) {
                        "#microsoft.graph.groupAssignmentTarget" {
                            $Group = Get-MgGroup -Filter "displayName eq '$($Assignments.target.groupId)'"
                            if($Group -eq $null) {
                                Write-Host "Group '$($Assignments.target.groupId)' does not exist, creating.." -ForegroundColor Yellow
                                $Group = New-MgGroup -DisplayName $Assignments.target.groupId -MailEnabled:$false -MailNickname $Assignments.target.groupId -SecurityEnabled:$true
                                Write-Host "Created group '$($Assignments.target.groupId)'." -ForegroundColor Green
                            } else {
                                Write-Host "Group '$($Assignments.target.groupId)' already exists, not creating.." -ForegroundColor Yellow
                            }
                            $Assignments.target.groupId = $Group.Id
                        }
                    }
                    $AssignedProfile = Invoke-GraphRequest -Method POST -Uri "https://graph.microsoft.com/beta/deviceManagement/configurationPolicies/$($SelectedConfigurationPolicy.id)/assign" -Body @{
                        "assignments" = @($Assignments)
                    }
                    Write-Host "Assigned configuration policy '$($SelectedConfigurationPolicy.name)' to $($TargetType) ($($Group.DisplayName)." -ForegroundColor Green
                } else {
                    Write-Host "assignment to all devices"
                    $AssignedProfile = Invoke-MgGraphRequest -Method POST -Uri "https://graph.microsoft.com/beta/deviceManagement/configurationPolicies/$($SelectedConfigurationPolicy.id)/assign" -Body @{
                        "assignments" =  @(
                            @{
                                "target" = @{
                                    "@odata.type" = "#microsoft.graph.allDevicesAssignmentTarget"
                                }
                            }
                        )
                    }
                    Write-Host "Assigned configuration policy '$($SelectedConfigurationPolicy.name)' to all devices." -ForegroundColor Green
                }

            }
        }

    }
    catch {
        throw "Failed to create configuration policies: $_"
    }
}