1.0.3/BackTheGraphUp.psm1

Function Get-BGUAccessToken {
    [CmdletBinding()]
    param (
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphVersion = "beta",
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphHost = "graph.microsoft.com",
        [string]
        $ClientID,
        [string]
        $ClientSecret,
        #Your Azure Tenent ID
        [string]
        $TenantId,
        [Parameter(DontShow = $true)]
        $GraphURI = "https://$MSGraphHost/$MsGraphVersion",
        [string]
        $DelegateID
    )

    begin {
        $RequireMod = Get-Module -Name "Connect-AzAD_Token" -ListAvailable
        if (!($RequireMod)) {
            try {
                Write-Host -ForegroundColor Cyan "Attempting to Install the Connect-AzADToken Powershell module..."
                Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force -ErrorAction Stop | Out-Null
                Install-Module "Connect-AzAD_token" -Force -ErrorAction Stop
            }
            catch {
                Throw "Failed to install the AzureAD PowerShell Module" 
            }   
        }

        Import-Module Connect-AzAD_Token

        $ConnectParams = @{}
        IF ($ClientID){$ConnectParams.Add('ClientID', $ClientID)}
        IF ($ClientSecret){$ConnectParams.Add('ClientSecret', $ClientSecret)}
        IF ($DelegateID){$ConnectParams.Add('DelegateID', $DelegateID)}
        IF ($TenantId){
            $ConnectParams.Add('Tenant', $TenantId)
        } ELSE {
            $TenantID = $UserInfo.TenantID
        }

    }
    #Process The Function
    Process {
        try {
            $Global:BGUAccessToken = Connect-AzAD_Token @ConnectParams
        }
        catch {
            $Error[0]
            throw "Failed to obtain access token"
        }
    }
}

##################################################################################
##################################################################################
# #
# Admin Templates #
# #
##################################################################################
##################################################################################

Function Get-AdminTemplates {
    [CmdletBinding()]
    param (
        [ValidateSet('All','FilterQuery')]
        $Type,
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphVersion = "beta",
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphHost = "graph.microsoft.com",
        [Parameter(DontShow = $true)]
        $GraphURI = "https://$MSGraphHost/$MsGraphVersion"
    )

    DynamicParam {
        #If the Import Param is used, Create the File Param
        switch ($Type) {
            FilterQuery {
                $FAttrib = New-Object System.Management.Automation.ParameterAttribute
                $FAttrib.Mandatory = $true
                #create an attributecollection object for the attribute we just created.
                $attributeCollection = new-object System.Collections.ObjectModel.Collection[System.Attribute]
                #add custom FileAttribute attribute
                $attributeCollection.Add($FAttrib)
                #add our paramater specifying the attribute collection
                $FilterID = New-Object System.Management.Automation.RuntimeDefinedParameter('FilterID', [string], $attributeCollection)
                #expose the name of our parameter
                $paramDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
                $paramDictionary.Add('FilterID', $FilterID)
                return $paramDictionary
            }
        }
    }

    begin {
       IF (-Not ($BGUAccessToken)) {
           Throw "You must first obtain an access token by running Get-BGUAccessToken, please obtain a token and retry this action"
       } 
       elseif ($BGUAccessToken.ExpiresOn.LocalDateTime -LT $(Get-Date)) {
           Throw "You're access token expired $($BGUAccessToken.ExpiresOn.LocalDateTime), you must obtain a new access token by running Get-BGUAccessToken."
       }

        $GraphHeader = @{Authorization = "Bearer $($BGUAccessToken.AccessToken)"}

    }
    #Process The Function
    Process {

        try {
            $GraphParams = @{
                Method = "GET"
                URI = "$GraphURI/deviceManagement/groupPolicyConfigurations"
                Headers = $GraphHeader
            }
    
            $GraphRequest = Invoke-RestMethod @GraphParams -ErrorAction Stop
            $global:All_GraphRequest = @()
            $All_GraphRequest += $GraphRequest
            while($GraphRequest.'@odata.nextLink') {
                $GraphRequest_NextLink = @{
                    Method = "GET"
                    URI = $GraphRequest.'@odata.nextLink'
                    Headers = $GraphHeader
                    ContentType = "application/JSON"
                }
                $GraphRequest = Invoke-RestMethod @$GraphRequest_NextLink -ErrorAction Stop
                $All_GraphRequest += $GraphRequest
            }
        }
        catch {
            $Error[0]
            Throw "The Microsoft Graph Query Failed,"
        }
        
        Switch ($Type) {
            Default {
                $All_GraphRequest | Select-Object -ExpandProperty Value
            }
            FilterQuery {
                $All_GraphRequest | Select-Object -ExpandProperty Value | Where-Object id -Match $($PSBoundParameters.FilterID)
            }
        }
    }
}
Function Import-AdminTemplate {
    [CmdletBinding()]
    param (
        [ValidateSet('Object','File')]
        $Type,
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphVersion = "beta",
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphHost = "graph.microsoft.com",
        [Parameter(DontShow = $true)]
        $GraphURI = "https://$MSGraphHost/$MsGraphVersion"
    )

    DynamicParam {
        switch ($Type) {
            File { 
                #If the Import Param is used, Create the File Param
                $FileAttribute = New-Object System.Management.Automation.ParameterAttribute
                $FileAttribute.Mandatory = $true
                #create an attributecollection object for the attribute we just created.
                $attributeCollection = new-object System.Collections.ObjectModel.Collection[System.Attribute]
                #add custom FileAttribute attribute
                $attributeCollection.Add($FileAttribute)
                #add our paramater specifying the attribute collection
                $File = New-Object System.Management.Automation.RuntimeDefinedParameter('File', [string], $attributeCollection)
                #expose the name of our parameter
                $paramDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
                $paramDictionary.Add('File', $File)
                return $paramDictionary 
            }
            Object {
                $ObjectAttrib = New-Object System.Management.Automation.ParameterAttribute
                $ObjectAttrib.Mandatory = $true
                #create an attributecollection object for the attribute we just created.
                $attributeCollection = new-object System.Collections.ObjectModel.Collection[System.Attribute]
                #add custom ObjectAttrib attribute
                $attributeCollection.Add($ObjectAttrib)
                #add our paramater specifying the attribute collection
                $ImportObject = New-Object System.Management.Automation.RuntimeDefinedParameter('ImportObject', [Object], $attributeCollection)
                $ImportObject_Settings = New-Object System.Management.Automation.RuntimeDefinedParameter('ImportObject_Settings', [Object], $attributeCollection)
                #expose the name of our parameter
                $paramDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
                $paramDictionary.Add('ImportObject', $ImportObject)
                $paramDictionary.Add('ImportObject_Settings', $ImportObject_Settings)
                return $paramDictionary 
            }
        }
        
    }

    begin {
        #If the File Param is used, Test the Path to make sure its accessible, If not throw an error. If it does exist set the Import_File Param to the AttributeValue
        IF ($PSBoundParameters.File){
            IF(-not (Test-Path -Path $PSBoundParameters.File)) {
                Throw "Unable to locate $PSBoundParameters.File"
            } else {
                $Import_File = $PSBoundParameters.File
            }
        }
        
        IF (-Not ($BGUAccessToken)) {
            Throw "You must first obtain an access token by running Get-BGUAccessToken, please obtain a token and retry this action"
        } 
        elseif ($BGUAccessToken.ExpiresOn.LocalDateTime -LT $(Get-Date)) {
            Throw "You're access token expired $($BGUAccessToken.ExpiresOn.LocalDateTime), you must obtain a new access token by running Get-BGUAccessToken."
        }
 
         $GraphHeader = @{Authorization = "Bearer $($BGUAccessToken.AccessToken)"}
 
    } 

    #Process The Function
    Process {
        switch ($Type) {
            File { 
                $File_Info = Get-Item $Import_File | Select-Object -Property *

                $ImportSettingsFile = Join-Path -Path $File_Info.DirectoryName -ChildPath ($File_Info.BaseName + "_settings.json")
                if(Test-Path -Path $ImportSettingsFile) {
                    $Settings = (ConvertFrom-Json -InputObject (Get-Content $ImportSettingsFile -Raw))
                }
                $BasePolicyJSON = Get-Content $Import_File | ConvertFrom-Json | Select-Object -Property * -ExcludeProperty Version,LastModifiedTime,CreatedDateTime,id,supportsScopeTags | ConvertTo-Json -Depth 10
            }
            Object {
                $BasePolicyJSON = $PSBoundParameters.ImportObject | Select-Object -Property * -ExcludeProperty Version,LastModifiedTime,CreatedDateTime,id,supportsScopeTags,lastModifiedDateTime | ConvertTo-Json -Depth 10
                $Settings = $PSBoundParameters.ImportObject_Settings
            }
        }
        
        $GraphBasePolicyImportParams = @{
            Method = "POST"
            URI = "$GraphURI/deviceManagement/groupPolicyConfigurations"
            BODY = $BasePolicyJSON
            Headers = $GraphHeader
            CONTENTTYPE = "application/Json"
        }
        $BasePolicyImport_Request = Invoke-RestMethod @GraphBasePolicyImportParams

        IF ($BasePolicyImport_Request){
            foreach ($Setting in $Settings) {
                $Setting.psobject.Properties.Remove('presentation')
                $Setting.psobject.Properties.Remove('ID')
                $Setting.psobject.Properties.Remove('lastModifiedDateTime')
                $Setting.psobject.Properties.Remove('createdDateTime')
                IF ($Setting.presentationValues) {
                    $CurrentSettings = $Setting.presentationValues | Select-Object * -ExcludeProperty presentation,id,lastmodifieddatetime,createddatetime
                    $Setting.presentationValues = @()
                    $Setting.presentationValues += $CurrentSettings
                }
                $GraphImportParams = @{
                    Method = "POST"
                    URI = "$GraphURI/deviceManagement/groupPolicyConfigurations/$($BasePolicyImport_Request.id)/definitionValues"
                    BODY = ($Setting | ConvertTo-Json -Depth 10)
                    Headers = $GraphHeader
                    CONTENTTYPE = "application/Json"
                }
                Invoke-RestMethod @GraphImportParams
            }
        }
    }
}

function Get-AdminTemplate_Settings {
    param(
        [Parameter(Mandatory = $true)]
        $InputObject,
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphVersion = "beta",
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphHost = "graph.microsoft.com",
        [Parameter(DontShow = $true)]
        $GraphURI = "https://$MSGraphHost/$MsGraphVersion"
    )

    begin {
        IF (-Not ($BGUAccessToken)) {
            Throw "You must first obtain an access token by running Get-BGUAccessToken, please obtain a token and retry this action"
        } 
        elseif ($BGUAccessToken.ExpiresOn.LocalDateTime -LT $(Get-Date)) {
            Throw "You're access token expired $($BGUAccessToken.ExpiresOn.LocalDateTime), you must obtain a new access token by running Get-BGUAccessToken."
        }
 
         $GraphHeader = @{Authorization = "Bearer $($BGUAccessToken.AccessToken)"}
 
    }

    Process {
        $adm_settings = @()
        # Get all policies set for the profile
        $GraphDefinitionValuesParam = @{
            METHOD = "GET"
            URI = "$GraphURI/deviceManagement/groupPolicyConfigurations/$($InputObject.id)/definitionValues?`$expand=definition"
            HEADERS = $GraphHeader
        }
        $Definition_Values =  Invoke-RestMethod @GraphDefinitionValuesParam
        #For Each definition value, Get the presentation value with its settings
        foreach($Def in $Definition_Values.value)
        {
            # Get presentation values for the passed in object
            $GraphPresentationValuesParams = @{
                METHOD = "GET"
                URI = "$GraphURI/deviceManagement/groupPolicyConfigurations/$($InputObject.id)/definitionValues/$($Def.id)/presentationValues?`$expand=presentation"
                HEADERS = $GraphHeader
            }
            $presnetation_values =  Invoke-RestMethod @GraphPresentationValuesParams
            
            $adm_obj = @{
                "enabled" = $Def.enabled
                "definition@odata.bind" = "$($GraphURI)/deviceManagement/groupPolicyDefinitions('$($Def.definition.id)')"
            }

            #If presentation_Values is not blank, Get the settings
            if($presnetation_values.value)
            {
                # Policy presentation values
                $adm_obj.presentationValues = @()
                $presnetation = $null
                foreach ($presentation in $presnetation_values.value) 
                {
                    $presentation | Add-Member -MemberType NoteProperty -Name "presentation@odata.bind" -Value "$($GraphURI)/deviceManagement/groupPolicyDefinitions('$($Def.definition.id)')/presentations('$($presentation.presentation.id)')"
                    $adm_obj.presentationValues += $presentation
                }
            }
            $adm_settings += $adm_obj
        }
        $adm_settings
    }
}

function Export-AdminTemplate {
    param(
        [Parameter(Mandatory = $True)]
        $PolicyID, 
        [ValidateSet('Object','File')]
        [Parameter(Mandatory = $True)]
        $Type,
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphVersion = "beta",
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphHost = "graph.microsoft.com",
        [Parameter(DontShow = $true)]
        $GraphURI = "https://$MSGraphHost/$MsGraphVersion"
    )

    DynamicParam {
        #If the Import Param is used, Create the File Param
        switch ($Type) {
            File {
                $FileAttribute = New-Object System.Management.Automation.ParameterAttribute
                $FileAttribute.Mandatory = $true
                #create an attributecollection object for the attribute we just created.
                $attributeCollection = new-object System.Collections.ObjectModel.Collection[System.Attribute]
                #add custom FileAttribute attribute
                $attributeCollection.Add($FileAttribute)
                #add our paramater specifying the attribute collection
                $ExportLocation = New-Object System.Management.Automation.RuntimeDefinedParameter('ExportLocation', [string], $attributeCollection)
                #expose the name of our parameter
                $paramDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
                $paramDictionary.Add('ExportLocation', $ExportLocation)
                return $paramDictionary
            }
        }
    }

    begin {
        IF (-Not ($BGUAccessToken)) {
            Throw "You must first obtain an access token by running Get-BGUAccessToken, please obtain a token and retry this action"
        } 
        elseif ($BGUAccessToken.ExpiresOn.LocalDateTime -LT $(Get-Date)) {
            Throw "You're access token expired $($BGUAccessToken.ExpiresOn.LocalDateTime), you must obtain a new access token by running Get-BGUAccessToken."
        }
 
         $GraphHeader = @{Authorization = "Bearer $($BGUAccessToken.AccessToken)"}
 
    }
    Process {
        $GraphObjectParams = @{
            METHOD = "GET"
            URI = "$GraphURI/deviceManagement/groupPolicyConfigurations/$($PolicyID)"
            HEADERS = $GraphHeader
        }

        $export_obj =  Invoke-RestMethod @GraphObjectParams

        if($export_obj)
        {       
            switch ($Type) {
                Object {
                    $export_obj
                }
                File {
                    # Export The Base Admin Template
                    ConvertTo-Json $export_obj -Depth 10 | Out-File "$ExportLocation\$(($export_obj.displayName)).json" -Force

                    # Export the settings from the Admin Template
                    $adm_settings = Get-AdminTemplate_Settings -InputObject $export_obj
                    ConvertTo-Json $adm_settings -Depth 10 | Out-File "$ExportLocation\$($export_obj.displayName)_Settings.json" -Force
                }
            }     
        }
    }
}
function Copy-AdminTemplate {
    param(
        [string]
        [Parameter(Mandatory = $True)]
        $PolicyID, 
        [Parameter(Mandatory = $True)]
        [ValidateSet('Copy','Test','PreProd','Dev','Prod','Pilot','Custom')]
        $Prefix,
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphVersion = "beta",
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphHost = "graph.microsoft.com",
        [Parameter(DontShow = $true)]
        $GraphURI = "https://$MSGraphHost/$MsGraphVersion"
    )

    DynamicParam {
        #If the Import Param is used, Create the File Param
        switch ($Prefix) {
            Custom {
                $CustomAttrib = New-Object System.Management.Automation.ParameterAttribute
                $CustomAttrib.Mandatory = $true
                #create an attributecollection object for the attribute we just created.
                $attributeCollection = new-object System.Collections.ObjectModel.Collection[System.Attribute]
                #add custom CustomAttrib attribute
                $attributeCollection.Add($CustomAttrib)
                #add our paramater specifying the attribute collection
                $CustomPrefix = New-Object System.Management.Automation.RuntimeDefinedParameter('CustomPrefix', [string], $attributeCollection)
                #expose the name of our parameter
                $paramDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
                $paramDictionary.Add('CustomPrefix', $CustomPrefix)
                return $paramDictionary
            }
        }
    }

    begin {
        IF (-Not ($BGUAccessToken)) {
            Throw "You must first obtain an access token by running Get-BGUAccessToken, please obtain a token and retry this action"
        } 
        elseif ($BGUAccessToken.ExpiresOn.LocalDateTime -LT $(Get-Date)) {
            Throw "You're access token expired $($BGUAccessToken.ExpiresOn.LocalDateTime), you must obtain a new access token by running Get-BGUAccessToken."
        }

        switch ($Prefix) {
            Custom { 
                $PolicyPrefix = $PSBoundParameters.CustomPrefix.ToUpper()
            }
            Default {
                $PolicyPrefix = $Prefix.ToUpper()
            }
        }
    }
    
    process {
        Write-Output "Object iD: $($PolicyID)"

        $BaseObject = Export-AdminTemplate -Type Object $PolicyID
        $BaseObject.displayName = "$PolicyPrefix-$($BaseObject.displayName)"
        $BaseObject_Settings = Get-AdminTemplate_Settings -InputObject $BaseObject
        Import-AdminTemplate -Type Object -ImportObject $BaseObject -ImportObject_Settings $BaseObject_Settings
    }
}

##################################################################################
##################################################################################
# #
# Scripts #
# #
##################################################################################
##################################################################################
function Invoke-Encoder {
    param (
        [Parameter(Mandatory = $true)]
        [ValidateSet('Encode','Decode')]
        $Type,
        [Parameter(Mandatory = $true)]
        [string]
        $Value
    )

    switch ($Type) {
        Encode { 
            [Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($Value))
        }
        Decode {
            [System.Text.Encoding]::ASCII.GetString([System.Convert]::FromBase64String($Value))
        }
    }
}
Function Get-IntuneScript {
    [CmdletBinding()]
    param (
        [ValidateSet('All','FilterQuery')]
        $Type,
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphVersion = "beta",
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphHost = "graph.microsoft.com",
        [Parameter(DontShow = $true)]
        $GraphURI = "https://$MSGraphHost/$MsGraphVersion"
    )

    DynamicParam {
        #If the Import Param is used, Create the File Param
        switch ($Type) {
            FilterQuery {
                $FAttrib = New-Object System.Management.Automation.ParameterAttribute
                $FAttrib.Mandatory = $true
                #create an attributecollection object for the attribute we just created.
                $attributeCollection = new-object System.Collections.ObjectModel.Collection[System.Attribute]
                #add custom FileAttribute attribute
                $attributeCollection.Add($FAttrib)
                #add our paramater specifying the attribute collection
                $FilterID = New-Object System.Management.Automation.RuntimeDefinedParameter('FilterID', [string], $attributeCollection)
                #expose the name of our parameter
                $paramDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
                $paramDictionary.Add('FilterID', $FilterID)
                return $paramDictionary
            }
        }
    }

    begin {
        IF (-Not ($BGUAccessToken)) {
            Throw "You must first obtain an access token by running Get-BGUAccessToken, please obtain a token and retry this action"
        } 
        elseif ($BGUAccessToken.ExpiresOn.LocalDateTime -LT $(Get-Date)) {
            Throw "You're access token expired $($BGUAccessToken.ExpiresOn.LocalDateTime), you must obtain a new access token by running Get-BGUAccessToken."
        }
 
         $GraphHeader = @{Authorization = "Bearer $($BGUAccessToken.AccessToken)"}
 
    } 
    #Process The Function
    Process {
        
        try {
            $GraphParams = @{
                Method = "GET"
                URI = "$GraphURI/deviceManagement/deviceManagementScripts"
                Headers = $GraphHeader
            }
            $GraphRequest = Invoke-RestMethod @GraphParams -ErrorAction Stop
            $global:All_GraphRequest = @()
            $All_GraphRequest += $GraphRequest
            while($GraphRequest.'@odata.nextLink') {
                $GraphRequest_NextLink = @{
                    Method = "GET"
                    URI = $GraphRequest.'@odata.nextLink'
                    Headers = $GraphHeader
                    ContentType = "application/JSON"
                }
                $GraphRequest = Invoke-RestMethod @$GraphRequest_NextLink -ErrorAction Stop
                $All_GraphRequest += $GraphRequest
            }
        }
        catch {
            $Error[0]
            Throw "The Microsoft Graph Query Failed,"
        }
      
        Switch ($Type) {
            Default {
                $All_GraphRequest | Select-Object -ExpandProperty Value
            }
            FilterQuery {
                $All_GraphRequest | Select-Object -ExpandProperty Value | Where-Object id -Match $($PSBoundParameters.FilterID)
            }
        }
    }
}
Function Import-IntuneScript {
    [CmdletBinding()]
    param (
        [ValidateSet('Object','File')]
        $Type,
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphVersion = "beta",
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphHost = "graph.microsoft.com",
        [Parameter(DontShow = $true)]
        $GraphURI = "https://$MSGraphHost/$MsGraphVersion"
    )

    DynamicParam {
        switch ($Type) {
            File { 
                #If the Import Param is used, Create the File Param
                $FileAttribute = New-Object System.Management.Automation.ParameterAttribute
                $FileAttribute.Mandatory = $true
                #create an attributecollection object for the attribute we just created.
                $attributeCollection = new-object System.Collections.ObjectModel.Collection[System.Attribute]
                #add custom FileAttribute attribute
                $attributeCollection.Add($FileAttribute)
                #add our paramater specifying the attribute collection
                $File = New-Object System.Management.Automation.RuntimeDefinedParameter('File', [string], $attributeCollection)
                #expose the name of our parameter
                $paramDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
                $paramDictionary.Add('File', $File)
                return $paramDictionary 
            }
            Object {
                $ObjectAttrib = New-Object System.Management.Automation.ParameterAttribute
                $ObjectAttrib.Mandatory = $true
                #create an attributecollection object for the attribute we just created.
                $attributeCollection = new-object System.Collections.ObjectModel.Collection[System.Attribute]
                #add custom ObjectAttrib attribute
                $attributeCollection.Add($ObjectAttrib)
                #add our paramater specifying the attribute collection
                $ImportObject = New-Object System.Management.Automation.RuntimeDefinedParameter('ImportObject', [Object], $attributeCollection)
                #expose the name of our parameter
                $paramDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
                $paramDictionary.Add('ImportObject', $ImportObject)
                return $paramDictionary 
            }
        }
        
    }

    begin {
        #If the File Param is used, Test the Path to make sure its accessible, If not throw an error. If it does exist set the JSONImport Param to the AttributeValue
        IF ($PSBoundParameters.File){
            IF(-not (Test-Path -Path $PSBoundParameters.File)) {
                Throw "Unable to locate $PSBoundParameters.File"
            } else {
                $Import_File = $PSBoundParameters.File
            }
        }

        IF (-Not ($BGUAccessToken)) {
            Throw "You must first obtain an access token by running Get-BGUAccessToken, please obtain a token and retry this action"
        } 
        elseif ($BGUAccessToken.ExpiresOn.LocalDateTime -LT $(Get-Date)) {
            Throw "You're access token expired $($BGUAccessToken.ExpiresOn.LocalDateTime), you must obtain a new access token by running Get-BGUAccessToken."
        }
 
        $GraphHeader = @{Authorization = "Bearer $($BGUAccessToken.AccessToken)"}
 
    } 

    #Process The Function
    Process {
        switch ($Type) {
            File { 
                $File_Info = Get-Item $Import_File | Select-Object -Property *

                $ImportScript = Join-Path -Path $File_Info.DirectoryName -ChildPath ($File_Info.BaseName + ".ps1")
                
                $ImportObject =  Get-Content $Import_File | ConvertFrom-Json | Select-Object -Property * -ExcludeProperty Version,LastModifiedTime,CreatedDateTime,id,supportsScopeTags
                
                if(Test-Path -Path $ImportScript) {
                    $ImportObject.scriptContent = (Invoke-Encoder -Type Encode (Get-Content $ImportScript -Raw))
                }
                $ImportJSON  = $ImportObject | ConvertTo-Json -Depth 10
            }
            Object {
                $ImportJSON = $PSBoundParameters.ImportObject | Select-Object -Property * -ExcludeProperty Version,LastModifiedTime,CreatedDateTime,id,supportsScopeTags,lastModifiedDateTime | ConvertTo-Json -Depth 10
            }
        }
        
        $GraphImportParams = @{
            Method = "POST"
            URI = "$GraphURI/deviceManagement/deviceManagementScripts"
            BODY = $ImportJSON
            Headers = $GraphHeader
            CONTENTTYPE = "application/Json"
        }
        
        Invoke-RestMethod @GraphImportParams
    }
}
function Export-IntuneScript {
    param(
        [Parameter(Mandatory = $True)]
        $PolicyID, 
        [ValidateSet('Object','File')]
        [Parameter(Mandatory = $True)]
        $Type,
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphVersion = "beta",
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphHost = "graph.microsoft.com",
        [Parameter(DontShow = $true)]
        $GraphURI = "https://$MSGraphHost/$MsGraphVersion"
    )

    DynamicParam {
        #If the Import Param is used, Create the File Param
        switch ($Type) {
            File {
                $FileAttribute = New-Object System.Management.Automation.ParameterAttribute
                $FileAttribute.Mandatory = $true
                #create an attributecollection object for the attribute we just created.
                $attributeCollection = new-object System.Collections.ObjectModel.Collection[System.Attribute]
                #add custom FileAttribute attribute
                $attributeCollection.Add($FileAttribute)
                #add our paramater specifying the attribute collection
                $ExportLocation = New-Object System.Management.Automation.RuntimeDefinedParameter('ExportLocation', [string], $attributeCollection)
                #expose the name of our parameter
                $paramDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
                $paramDictionary.Add('ExportLocation', $ExportLocation)
                return $paramDictionary
            }
        }
    }

    begin {
        IF ($PSBoundParameters.ExportLocation){
            $ExportLocation = $PSBoundParameters.ExportLocation
        }
        IF (-Not ($BGUAccessToken)) {
            Throw "You must first obtain an access token by running Get-BGUAccessToken, please obtain a token and retry this action"
        } 
        elseif ($BGUAccessToken.ExpiresOn.LocalDateTime -LT $(Get-Date)) {
            Throw "You're access token expired $($BGUAccessToken.ExpiresOn.LocalDateTime), you must obtain a new access token by running Get-BGUAccessToken."
        }
 
        $GraphHeader = @{Authorization = "Bearer $($BGUAccessToken.AccessToken)"}
    }
    Process {
        $GraphObjectParams = @{
            METHOD = "GET"
            URI = "$GraphURI/deviceManagement/deviceManagementScripts/$($PolicyID)"
            HEADERS = $GraphHeader
        }

        $export_obj =  Invoke-RestMethod @GraphObjectParams

        if($export_obj)
        {       
            switch ($Type) {
                Object {
                    $export_obj
                }
                File {
                    # Export The Base Admin Template
                    ConvertTo-Json $export_obj -Depth 10 | Out-File "$ExportLocation\$(($export_obj.displayName)).json" -Force
                    Invoke-Encoder -Type Decode -Value $export_obj.ScriptContent | Out-File "$ExportLocation\$(($export_obj.displayName)).PS1" -Force
                }
            }     
        }
    }
}
function Copy-IntuneScript {
    param(
        [string]
        [Parameter(Mandatory = $True)]
        $PolicyID, 
        [Parameter(Mandatory = $True)]
        [ValidateSet('Copy','Test','PreProd','Dev','Prod','Pilot','Custom')]
        $Prefix,
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphVersion = "beta",
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphHost = "graph.microsoft.com",
        [Parameter(DontShow = $true)]
        $GraphURI = "https://$MSGraphHost/$MsGraphVersion"
    )

    DynamicParam {
        #If the Import Param is used, Create the File Param
        switch ($Prefix) {
            Custom {
                $CustomAttrib = New-Object System.Management.Automation.ParameterAttribute
                $CustomAttrib.Mandatory = $true
                #create an attributecollection object for the attribute we just created.
                $attributeCollection = new-object System.Collections.ObjectModel.Collection[System.Attribute]
                #add custom CustomAttrib attribute
                $attributeCollection.Add($CustomAttrib)
                #add our paramater specifying the attribute collection
                $CustomPrefix = New-Object System.Management.Automation.RuntimeDefinedParameter('CustomPrefix', [string], $attributeCollection)
                #expose the name of our parameter
                $paramDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
                $paramDictionary.Add('CustomPrefix', $CustomPrefix)
                return $paramDictionary
            }
        }
    }

    begin {
        IF (-Not ($BGUAccessToken)) {
            Throw "You must first obtain an access token by running Get-BGUAccessToken, please obtain a token and retry this action"
        } 
        elseif ($BGUAccessToken.ExpiresOn.LocalDateTime -LT $(Get-Date)) {
            Throw "You're access token expired $($BGUAccessToken.ExpiresOn.LocalDateTime), you must obtain a new access token by running Get-BGUAccessToken."
        }

        switch ($Prefix) {
            Custom { 
                $PolicyPrefix = $PSBoundParameters.CustomPrefix.ToUpper()
            }
            Default {
                $PolicyPrefix = $Prefix.ToUpper()
            }
        }
    }
    
    
    process {
        Write-Output "Object iD: $($PolicyID)"

        $BaseObject = Export-IntuneScript -Type Object $PolicyID
        $BaseObject.displayName = "$PolicyPrefix-$($BaseObject.displayName)"

        Import-IntuneScript -Type Object -ImportObject $BaseObject
    }
}

function Update-IntuneScript {
    param(
        [string]
        [Parameter(Mandatory = $True)]
        $PolicyID, 
        [Parameter(Mandatory = $True)]
        [ValidateSet('Object','File')]
        $Type,
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphVersion = "beta",
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphHost = "graph.microsoft.com",
        [Parameter(DontShow = $true)]
        $GraphURI = "https://$MSGraphHost/$MsGraphVersion"
    )

    DynamicParam {
        switch ($Type) {
            File { 
                #If the Import Param is used, Create the File Param
                $PSAttrib = New-Object System.Management.Automation.ParameterAttribute
                $PSAttrib.Mandatory = $true
                #create an attributecollection object for the attribute we just created.
                $attributeCollection = new-object System.Collections.ObjectModel.Collection[System.Attribute]
                #add custom PSAttrib attribute
                $attributeCollection.Add($PSAttrib)
                #add our paramater specifying the attribute collection
                $File = New-Object System.Management.Automation.RuntimeDefinedParameter('File', [string], $attributeCollection)
                #expose the name of our parameter
                $paramDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
                $paramDictionary.Add('File', $File)
                return $paramDictionary 
            }
            Object {
                $ObjectAttrib = New-Object System.Management.Automation.ParameterAttribute
                $ObjectAttrib.Mandatory = $true
                #create an attributecollection object for the attribute we just created.
                $attributeCollection = new-object System.Collections.ObjectModel.Collection[System.Attribute]
                #add custom ObjectAttrib attribute
                $attributeCollection.Add($ObjectAttrib)
                #add our paramater specifying the attribute collection
                $ScriptObject = New-Object System.Management.Automation.RuntimeDefinedParameter('ScriptObject', [Object], $attributeCollection)
                #expose the name of our parameter
                $paramDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
                $paramDictionary.Add('ScriptObject', $ScriptObject)
                return $paramDictionary 
            }
        }
        
    }

    begin {
        IF ($PSBoundParameters.File){
            IF(-not (Test-Path -Path $PSBoundParameters.File)) {
                Throw "Unable to locate $PSBoundParameters.File"
            } else {
                $ScriptImport = $PSBoundParameters.File
            }
        }
        IF (-Not ($BGUAccessToken)) {
            Throw "You must first obtain an access token by running Get-BGUAccessToken, please obtain a token and retry this action"
        } 
        elseif ($BGUAccessToken.ExpiresOn.LocalDateTime -LT $(Get-Date)) {
            Throw "You're access token expired $($BGUAccessToken.ExpiresOn.LocalDateTime), you must obtain a new access token by running Get-BGUAccessToken."
        }

        $GraphHeader = @{Authorization = "Bearer $($BGUAccessToken.AccessToken)"}
    } 

    Process {
        Write-Output "Object iD: $($PolicyID)"

        $Policy = Get-IntuneScript -Type FilterQuery -FilterID $PolicyID

        switch ($Type) {
            File { 
                $Policy.ScriptContent = Invoke-Encoder -Type Encode -Value (Get-Content $ScriptImport -Raw)
            }
            Object {
                $Policy.ScriptContent = Invoke-Encoder -Type Encode -Value $ScriptObject
            }
        }

        $GraphImportParams = @{
            Method = "PATCH"
            URI = "$GraphURI/deviceManagement/deviceManagementScripts/$PolicyID"
            BODY = ($Policy | Select-Object -Property * -ExcludeProperty Version,LastModifiedDateTime,CreatedDateTime,id,supportsScopeTags | ConvertTo-Json -Depth 10)
            Headers = $GraphHeader
            CONTENTTYPE = "application/Json"
        }
        
        Invoke-RestMethod @GraphImportParams
        
    }
    
}

##################################################################################
##################################################################################
# #
# AppProtection Policies #
# #
##################################################################################
##################################################################################

Function Get-AppProtectionPolicies {
    [CmdletBinding()]
    param (
        [ValidateSet('All','FilterQuery')]
        $Type,
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphVersion = "beta",
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphHost = "graph.microsoft.com",
        [Parameter(DontShow = $true)]
        $GraphURI = "https://$MSGraphHost/$MsGraphVersion"
    )

    DynamicParam {
        #If the Import Param is used, Create the File Param
        switch ($Type) {
            FilterQuery {
                $FAttrib = New-Object System.Management.Automation.ParameterAttribute
                $FAttrib.Mandatory = $true
                #create an attributecollection object for the attribute we just created.
                $attributeCollection = new-object System.Collections.ObjectModel.Collection[System.Attribute]
                #add custom FileAttribute attribute
                $attributeCollection.Add($FAttrib)
                #add our paramater specifying the attribute collection
                $FilterID = New-Object System.Management.Automation.RuntimeDefinedParameter('FilterID', [string], $attributeCollection)
                #expose the name of our parameter
                $paramDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
                $paramDictionary.Add('FilterID', $FilterID)
                return $paramDictionary
            }
        }
    }

    begin {
        IF (-Not ($BGUAccessToken)) {
            Throw "You must first obtain an access token by running Get-BGUAccessToken, please obtain a token and retry this action"
        } 
        elseif ($BGUAccessToken.ExpiresOn.LocalDateTime -LT $(Get-Date)) {
            Throw "You're access token expired $($BGUAccessToken.ExpiresOn.LocalDateTime), you must obtain a new access token by running Get-BGUAccessToken."
        }
 
         $GraphHeader = @{Authorization = "Bearer $($BGUAccessToken.AccessToken)"}
    } 
    #Process The Function
    Process {
        try {
            $GraphParams = @{
                Method = "GET"
                URI = "$GraphURI/deviceAppManagement/managedAppPolicies"
                Headers = $GraphHeader
            }
            $GraphRequest = Invoke-RestMethod @GraphParams -ErrorAction Stop
            $global:All_GraphRequest = @()
            $All_GraphRequest += $GraphRequest
            while($GraphRequest.'@odata.nextLink') {
                $GraphRequest_NextLink = @{
                    Method = "GET"
                    URI = $GraphRequest.'@odata.nextLink'
                    Headers = $GraphHeader
                    ContentType = "application/JSON"
                }
                $GraphRequest = Invoke-RestMethod @$GraphRequest_NextLink -ErrorAction Stop
                $All_GraphRequest += $GraphRequest
            }
        }
        catch {
            $Error[0]
            Throw "The Microsoft Graph Query Failed,"
        }
      
        Switch ($Type) {
            Default {
                $All_GraphRequest | Select-Object -ExpandProperty Value
            }
            FilterQuery {
                $All_GraphRequest | Select-Object -ExpandProperty Value | Where-Object id -Match $($PSBoundParameters.FilterID)
            }
        }
    }
}
Function Import-AppProtectionPolicies {
    [CmdletBinding()]
    param (
        [ValidateSet('Object','File')]
        $Type,
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphVersion = "beta",
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphHost = "graph.microsoft.com",
        [Parameter(DontShow = $true)]
        $GraphURI = "https://$MSGraphHost/$MsGraphVersion"
    )

    DynamicParam {
        switch ($Type) {
            File { 
                #If the Import Param is used, Create the File Param
                $FileAttribute = New-Object System.Management.Automation.ParameterAttribute
                $FileAttribute.Mandatory = $true
                #create an attributecollection object for the attribute we just created.
                $attributeCollection = new-object System.Collections.ObjectModel.Collection[System.Attribute]
                #add custom FileAttribute attribute
                $attributeCollection.Add($FileAttribute)
                #add our paramater specifying the attribute collection
                $File = New-Object System.Management.Automation.RuntimeDefinedParameter('File', [string], $attributeCollection)
                #expose the name of our parameter
                $paramDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
                $paramDictionary.Add('File', $File)
                return $paramDictionary 
            }
            Object {
                $ObjectAttrib = New-Object System.Management.Automation.ParameterAttribute
                $ObjectAttrib.Mandatory = $true
                #create an attributecollection object for the attribute we just created.
                $attributeCollection = new-object System.Collections.ObjectModel.Collection[System.Attribute]
                #add custom ObjectAttrib attribute
                $attributeCollection.Add($ObjectAttrib)
                #add our paramater specifying the attribute collection
                $ImportObject = New-Object System.Management.Automation.RuntimeDefinedParameter('ImportObject', [Object], $attributeCollection)
                #expose the name of our parameter
                $paramDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
                $paramDictionary.Add('ImportObject', $ImportObject)
                return $paramDictionary 
            }
        }
        
    }

    begin {
        #If the File Param is used, Test the Path to make sure its accessible, If not throw an error. If it does exist set the JSONImport Param to the AttributeValue
        IF ($PSBoundParameters.File){
            IF(-not (Test-Path -Path $PSBoundParameters.File)) {
                Throw "Unable to locate $PSBoundParameters.File"
            } else {
                $JSONImport = $PSBoundParameters.File
            }
        }

        IF (-Not ($BGUAccessToken)) {
            Throw "You must first obtain an access token by running Get-BGUAccessToken, please obtain a token and retry this action"
        } 
        elseif ($BGUAccessToken.ExpiresOn.LocalDateTime -LT $(Get-Date)) {
            Throw "You're access token expired $($BGUAccessToken.ExpiresOn.LocalDateTime), you must obtain a new access token by running Get-BGUAccessToken."
        }
 
        $GraphHeader = @{Authorization = "Bearer $($BGUAccessToken.AccessToken)"}
    } 

    #Process The Function
    Process {

        switch ($Type) {
            File { 
                $ImportBody = Get-Content $JSONImport | ConvertFrom-Json | Select-Object -Property * -ExcludeProperty Version,LastModifiedTime,CreatedDateTime,id | ConvertTo-Json -Depth 10
            }
            Object {
                $ImportBody = $PSBoundParameters.ImportObject | Select-Object -Property * -ExcludeProperty Version,LastModifiedTime,CreatedDateTime,id,supportsScopeTags,lastModifiedDateTime | ConvertTo-Json -Depth 10
            }
        }
        
        $GraphImportParams = @{
            Method = "POST"
            URI = "$GraphURI/deviceAppManagement/managedAppPolicies"
            BODY = $ImportBody
            Headers = $GraphHeader
            CONTENTTYPE = "application/Json"
        }
        
        Invoke-RestMethod @GraphImportParams
    }
}
function Export-AppProtectionPolicies {
    param(
        [Parameter(Mandatory = $True)]
        $PolicyID, 
        [ValidateSet('Object','File')]
        [Parameter(Mandatory = $True)]
        $Type,
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphVersion = "beta",
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphHost = "graph.microsoft.com",
        [Parameter(DontShow = $true)]
        $GraphURI = "https://$MSGraphHost/$MsGraphVersion"
    )

    DynamicParam {
        #If the Import Param is used, Create the File Param
        switch ($Type) {
            File {
                $FileAttribute = New-Object System.Management.Automation.ParameterAttribute
                $FileAttribute.Mandatory = $true
                #create an attributecollection object for the attribute we just created.
                $attributeCollection = new-object System.Collections.ObjectModel.Collection[System.Attribute]
                #add custom FileAttribute attribute
                $attributeCollection.Add($FileAttribute)
                #add our paramater specifying the attribute collection
                $ExportLocation = New-Object System.Management.Automation.RuntimeDefinedParameter('ExportLocation', [string], $attributeCollection)
                #expose the name of our parameter
                $paramDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
                $paramDictionary.Add('ExportLocation', $ExportLocation)
                return $paramDictionary
            }
        }
    }

    begin {
        IF ($PSBoundParameters.ExportLocation){
            $ExportLocation = $PSBoundParameters.ExportLocation
        }
        IF (-Not ($BGUAccessToken)) {
            Throw "You must first obtain an access token by running Get-BGUAccessToken, please obtain a token and retry this action"
        } 
        elseif ($BGUAccessToken.ExpiresOn.LocalDateTime -LT $(Get-Date)) {
            Throw "You're access token expired $($BGUAccessToken.ExpiresOn.LocalDateTime), you must obtain a new access token by running Get-BGUAccessToken."
        }
 
        $GraphHeader = @{Authorization = "Bearer $($BGUAccessToken.AccessToken)"}
    }
    Process {
        $GraphObjectParams = @{
            METHOD = "GET"
            URI = "$GraphURI/deviceAppManagement/managedAppPolicies/$($PolicyID)"
            HEADERS = $GraphHeader
        }

        $export_obj =  Invoke-RestMethod @GraphObjectParams

        if($export_obj)
        {       
            switch ($Type) {
                Object {
                    $export_obj
                }
                File {
                    # Export The Base Admin Template
                    ConvertTo-Json $export_obj -Depth 10 | Out-File "$ExportLocation\$(($export_obj.displayName)).json" -Force
                }
            }     
        }
    }
}
function Copy-AppProtectionPolicies {
    param(
        [string]
        [Parameter(Mandatory = $True)]
        $PolicyID, 
        [Parameter(Mandatory = $True)]
        [ValidateSet('Copy','Test','PreProd','Dev','Prod','Pilot','Custom')]
        $Prefix,
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphVersion = "beta",
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphHost = "graph.microsoft.com",
        [Parameter(DontShow = $true)]
        $GraphURI = "https://$MSGraphHost/$MsGraphVersion"
    )

    DynamicParam {
        #If the Import Param is used, Create the File Param
        switch ($Prefix) {
            Custom {
                $CustomAttrib = New-Object System.Management.Automation.ParameterAttribute
                $CustomAttrib.Mandatory = $true
                #create an attributecollection object for the attribute we just created.
                $attributeCollection = new-object System.Collections.ObjectModel.Collection[System.Attribute]
                #add custom CustomAttrib attribute
                $attributeCollection.Add($CustomAttrib)
                #add our paramater specifying the attribute collection
                $CustomPrefix = New-Object System.Management.Automation.RuntimeDefinedParameter('CustomPrefix', [string], $attributeCollection)
                #expose the name of our parameter
                $paramDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
                $paramDictionary.Add('CustomPrefix', $CustomPrefix)
                return $paramDictionary
            }
        }
    }

    begin {
        IF (-Not ($BGUAccessToken)) {
            Throw "You must first obtain an access token by running Get-BGUAccessToken, please obtain a token and retry this action"
        } 
        elseif ($BGUAccessToken.ExpiresOn.LocalDateTime -LT $(Get-Date)) {
            Throw "You're access token expired $($BGUAccessToken.ExpiresOn.LocalDateTime), you must obtain a new access token by running Get-BGUAccessToken."
        }

        switch ($Prefix) {
            Custom { 
                $PolicyPrefix = $PSBoundParameters.CustomPrefix.ToUpper()
            }
            Default {
                $PolicyPrefix = $Prefix.ToUpper()
            }
        }
    }
        
    process {
        Write-Output "Object iD: $($PolicyID)"

        $BaseObject = Export-AppProtectionPolicies -Type Object $PolicyID
        $BaseObject.displayName = "$PolicyPrefix-$($BaseObject.displayName)"

        Import-AppProtectionPolicies -Type Object -ImportObject $BaseObject
    }
}

##################################################################################
##################################################################################
# #
# Compliance Policies #
# #
##################################################################################
##################################################################################

Function Get-CompliancePolicies {
    [CmdletBinding()]
    param (
        [ValidateSet('All','FilterQuery')]
        $Type,
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphVersion = "beta",
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphHost = "graph.microsoft.com",
        [Parameter(DontShow = $true)]
        $GraphURI = "https://$MSGraphHost/$MsGraphVersion"
    )

    DynamicParam {
        #If the Import Param is used, Create the File Param
        switch ($Type) {
            FilterQuery {
                $FAttrib = New-Object System.Management.Automation.ParameterAttribute
                $FAttrib.Mandatory = $true
                #create an attributecollection object for the attribute we just created.
                $attributeCollection = new-object System.Collections.ObjectModel.Collection[System.Attribute]
                #add custom FileAttribute attribute
                $attributeCollection.Add($FAttrib)
                #add our paramater specifying the attribute collection
                $FilterID = New-Object System.Management.Automation.RuntimeDefinedParameter('FilterID', [string], $attributeCollection)
                #expose the name of our parameter
                $paramDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
                $paramDictionary.Add('FilterID', $FilterID)
                return $paramDictionary
            }
        }
    }

    begin {
        IF (-Not ($BGUAccessToken)) {
            Throw "You must first obtain an access token by running Get-BGUAccessToken, please obtain a token and retry this action"
        } 
        elseif ($BGUAccessToken.ExpiresOn.LocalDateTime -LT $(Get-Date)) {
            Throw "You're access token expired $($BGUAccessToken.ExpiresOn.LocalDateTime), you must obtain a new access token by running Get-BGUAccessToken."
        }
 
        $GraphHeader = @{Authorization = "Bearer $($BGUAccessToken.AccessToken)"}
    } 
    #Process The Function
    Process {
        try {
            $GraphParams = @{
                Method = "GET"
                URI = "$GraphURI/deviceManagement/deviceCompliancePolicies?`$expand=scheduledActionsForRule(`$expand=scheduledActionConfigurations)"
                Headers = $GraphHeader
            }
        
            $GraphRequest = Invoke-RestMethod @GraphParams -ErrorAction Stop
            $global:All_GraphRequest = @()
            $All_GraphRequest += $GraphRequest
            while($GraphRequest.'@odata.nextLink') {
                $GraphRequest_NextLink = @{
                    Method = "GET"
                    URI = $GraphRequest.'@odata.nextLink'
                    Headers = $GraphHeader
                    ContentType = "application/JSON"
                }
                $GraphRequest = Invoke-RestMethod @$GraphRequest_NextLink -ErrorAction Stop
                $All_GraphRequest += $GraphRequest
            }
        }
        catch {
            $Error[0]
            Throw "The Microsoft Graph Query Failed,"
        }
      
        Switch ($Type) {
            Default {
                $All_GraphRequest | Select-Object -ExpandProperty Value
            }
            FilterQuery {
                $All_GraphRequest | Select-Object -ExpandProperty Value | Where-Object id -Match $($PSBoundParameters.FilterID)
            }
        }
    }
}
Function Import-CompliancePolicies {
    [CmdletBinding()]
    param (
        [ValidateSet('Object','File')]
        $Type,
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphVersion = "beta",
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphHost = "graph.microsoft.com",
        [Parameter(DontShow = $true)]
        $GraphURI = "https://$MSGraphHost/$MsGraphVersion"
    )

    DynamicParam {
        switch ($Type) {
            File { 
                #If the Import Param is used, Create the File Param
                $FileAttribute = New-Object System.Management.Automation.ParameterAttribute
                $FileAttribute.Mandatory = $true
                #create an attributecollection object for the attribute we just created.
                $attributeCollection = new-object System.Collections.ObjectModel.Collection[System.Attribute]
                #add custom FileAttribute attribute
                $attributeCollection.Add($FileAttribute)
                #add our paramater specifying the attribute collection
                $File = New-Object System.Management.Automation.RuntimeDefinedParameter('File', [string], $attributeCollection)
                #expose the name of our parameter
                $paramDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
                $paramDictionary.Add('File', $File)
                return $paramDictionary 
            }
            Object {
                $ObjectAttrib = New-Object System.Management.Automation.ParameterAttribute
                $ObjectAttrib.Mandatory = $true
                #create an attributecollection object for the attribute we just created.
                $attributeCollection = new-object System.Collections.ObjectModel.Collection[System.Attribute]
                #add custom ObjectAttrib attribute
                $attributeCollection.Add($ObjectAttrib)
                #add our paramater specifying the attribute collection
                $ImportObject = New-Object System.Management.Automation.RuntimeDefinedParameter('ImportObject', [Object], $attributeCollection)
                #expose the name of our parameter
                $paramDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
                $paramDictionary.Add('ImportObject', $ImportObject)
                return $paramDictionary 
            }
        }
        
    }

    begin {
        IF ($PSBoundParameters.File){
            IF(-not (Test-Path -Path $PSBoundParameters.File)) {
                Throw "Unable to locate $PSBoundParameters.File"
            } else {
                $JSONImport = $PSBoundParameters.File
            }
        }
        IF (-Not ($BGUAccessToken)) {
            Throw "You must first obtain an access token by running Get-BGUAccessToken, please obtain a token and retry this action"
        } 
        elseif ($BGUAccessToken.ExpiresOn.LocalDateTime -LT $(Get-Date)) {
            Throw "You're access token expired $($BGUAccessToken.ExpiresOn.LocalDateTime), you must obtain a new access token by running Get-BGUAccessToken."
        }
 
        $GraphHeader = @{Authorization = "Bearer $($BGUAccessToken.AccessToken)"}
    } 

    #Process The Function
    Process {

        switch ($Type) {
            File { 
                $ImportBody = Get-Content $JSONImport | ConvertFrom-Json | Select-Object -Property * -ExcludeProperty Version,lastModifiedDateTime,CreatedDateTime,id,scheduledActionsForRule@odata.context
                
                IF (-Not ($ImportBody.scheduledActionsForRule)) {
                    $SAFRuleOBJ = @(
                        @{
                            "ruleName" = "PasswordRequired" 
                            "scheduledActionConfigurations" = @(
                                @{
                                    "actionType" = "block"
                                    "gracePeriodHours" = 0
                                    "notificationTemplateId" = ""
                                    "notificationMessageCCList" = @()
                                }
                            )
                        }
                    )
                    $ImportBody | Add-Member -MemberType NoteProperty -Name "scheduledActionsForRule" -Value $SAFRuleOBJ
                } else {
                    $CurrentSettings = $ImportBody.scheduledActionsForRule | Select-Object * -ExcludeProperty id,scheduledActionConfigurations@odata.context
                    $CurrentSettings_SAC = $CurrentSettings.scheduledActionConfigurations | Select-Object * -ExcludeProperty id
                    IF ($CurrentSettings_SAC.notificationTemplateId -match "00000000-0000-0000-0000-000000000000") {
                        $CurrentSettings_SAC.notificationTemplateId = ""
                    }
                    $CurrentSettings.scheduledActionConfigurations = @($CurrentSettings_SAC)
                    $ImportBody.scheduledActionsForRule = @($CurrentSettings)
                    #$ImportBody.scheduledActionsForRule.scheduledActionConfigurations = $CurrentSettings_SAC
                }
            }
            Object {
                $ImportBody = $PSBoundParameters.ImportObject | Select-Object -Property * -ExcludeProperty Version,lastModifiedDateTime,CreatedDateTime,id,supportsScopeTags,lastModifiedDateTime
                IF (-Not ($ImportBody.scheduledActionsForRule)) {
                    $SAFRuleOBJ = @(
                        @{
                            "ruleName" = "PasswordRequired" 
                            "scheduledActionConfigurations" = @(
                                @{
                                    "actionType" = "block"
                                    "gracePeriodHours" = 0
                                    "notificationTemplateId" = ""
                                    "notificationMessageCCList" = @()
                                }
                            )
                        }
                    )
                    $ImportBody | Add-Member -MemberType NoteProperty -Name "scheduledActionsForRule" -Value $SAFRuleOBJ
                } else {
                    $CurrentSettings = $ImportBody.scheduledActionsForRule | Select-Object * -ExcludeProperty id,scheduledActionConfigurations@odata.context
                    $CurrentSettings_SAC = $CurrentSettings.scheduledActionConfigurations | Select-Object * -ExcludeProperty id
                    IF ($CurrentSettings_SAC.notificationTemplateId -match "00000000-0000-0000-0000-000000000000") {
                        $CurrentSettings_SAC.notificationTemplateId = ""
                    }
                    $CurrentSettings.scheduledActionConfigurations = @($CurrentSettings_SAC)
                    $ImportBody.scheduledActionsForRule = @($CurrentSettings)
                }
            }
        }
        
        $GraphImportParams = @{
            Method = "POST"
            URI = "$GraphURI/deviceManagement/deviceCompliancePolicies"
            BODY = ($ImportBody | ConvertTo-Json -Depth 10)
            Headers = $GraphHeader
            CONTENTTYPE = "application/Json"
        }
        
        Invoke-RestMethod @GraphImportParams
    }
}
function Export-CompliancePolicies {
    param(
        [Parameter(Mandatory = $True)]
        $PolicyID, 
        [ValidateSet('Object','File')]
        [Parameter(Mandatory = $True)]
        $Type,
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphVersion = "beta",
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphHost = "graph.microsoft.com",
        [Parameter(DontShow = $true)]
        $GraphURI = "https://$MSGraphHost/$MsGraphVersion"
    )

    DynamicParam {
        #If the Import Param is used, Create the File Param
        switch ($Type) {
            File {
                $FileAttribute = New-Object System.Management.Automation.ParameterAttribute
                $FileAttribute.Mandatory = $true
                #create an attributecollection object for the attribute we just created.
                $attributeCollection = new-object System.Collections.ObjectModel.Collection[System.Attribute]
                #add custom FileAttribute attribute
                $attributeCollection.Add($FileAttribute)
                #add our paramater specifying the attribute collection
                $ExportLocation = New-Object System.Management.Automation.RuntimeDefinedParameter('ExportLocation', [string], $attributeCollection)
                #expose the name of our parameter
                $paramDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
                $paramDictionary.Add('ExportLocation', $ExportLocation)
                return $paramDictionary
            }
        }
    }

    begin {
        IF ($PSBoundParameters.ExportLocation){
            $ExportLocation = $PSBoundParameters.ExportLocation
        }
        IF (-Not ($BGUAccessToken)) {
            Throw "You must first obtain an access token by running Get-BGUAccessToken, please obtain a token and retry this action"
        } 
        elseif ($BGUAccessToken.ExpiresOn.LocalDateTime -LT $(Get-Date)) {
            Throw "You're access token expired $($BGUAccessToken.ExpiresOn.LocalDateTime), you must obtain a new access token by running Get-BGUAccessToken."
        }
 
        $GraphHeader = @{Authorization = "Bearer $($BGUAccessToken.AccessToken)"}
    }
    Process {
        $GraphObjectParams = @{
            METHOD = "GET"
            URI = "$GraphURI/deviceManagement/deviceCompliancePolicies/$($PolicyID)?`$expand=scheduledActionsForRule(`$expand=scheduledActionConfigurations)"
            HEADERS = $GraphHeader
        }

        $export_obj =  Invoke-RestMethod @GraphObjectParams

        if($export_obj)
        {       
            switch ($Type) {
                Object {
                    $export_obj
                }
                File {
                    # Export The Base Admin Template
                    ConvertTo-Json $export_obj -Depth 10 | Out-File "$ExportLocation\$(($export_obj.displayName)).json" -Force
                }
            }     
        }
    }
}
function Copy-CompliancePolicies {
    param(
        [string]
        [Parameter(Mandatory = $True)]
        $PolicyID, 
        [Parameter(Mandatory = $True)]
        [ValidateSet('Copy','Test','PreProd','Dev','Prod','Pilot','Custom')]
        $Prefix,
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphVersion = "beta",
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphHost = "graph.microsoft.com",
        [Parameter(DontShow = $true)]
        $GraphURI = "https://$MSGraphHost/$MsGraphVersion"
    )

    DynamicParam {
        #If the Import Param is used, Create the File Param
        switch ($Prefix) {
            Custom {
                $CustomAttrib = New-Object System.Management.Automation.ParameterAttribute
                $CustomAttrib.Mandatory = $true
                #create an attributecollection object for the attribute we just created.
                $attributeCollection = new-object System.Collections.ObjectModel.Collection[System.Attribute]
                #add custom CustomAttrib attribute
                $attributeCollection.Add($CustomAttrib)
                #add our paramater specifying the attribute collection
                $CustomPrefix = New-Object System.Management.Automation.RuntimeDefinedParameter('CustomPrefix', [string], $attributeCollection)
                #expose the name of our parameter
                $paramDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
                $paramDictionary.Add('CustomPrefix', $CustomPrefix)
                return $paramDictionary
            }
        }
    }

    begin {
        IF (-Not ($BGUAccessToken)) {
            Throw "You must first obtain an access token by running Get-BGUAccessToken, please obtain a token and retry this action"
        } 
        elseif ($BGUAccessToken.ExpiresOn.LocalDateTime -LT $(Get-Date)) {
            Throw "You're access token expired $($BGUAccessToken.ExpiresOn.LocalDateTime), you must obtain a new access token by running Get-BGUAccessToken."
        }

        switch ($Prefix) {
            Custom { 
                $PolicyPrefix = $PSBoundParameters.CustomPrefix.ToUpper()
            }
            Default {
                $PolicyPrefix = $Prefix.ToUpper()
            }
        }
    }
    
    process {
        Write-Output "Object iD: $($PolicyID)"
        $BaseObject = Export-CompliancePolicies -Type Object $PolicyID
        $BaseObject.displayName = "$PolicyPrefix-$($BaseObject.displayName)"

        Import-CompliancePolicies -Type Object -ImportObject $BaseObject
    }
}

##################################################################################
##################################################################################
# #
# Conditional Access Policies #
# #
##################################################################################
##################################################################################

Function Get-ConditionalAccessPolicies {
    [CmdletBinding()]
    param (
        [ValidateSet('All','FilterQuery')]
        $Type,
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphVersion = "beta",
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphHost = "graph.microsoft.com",
        [Parameter(DontShow = $true)]
        $GraphURI = "https://$MSGraphHost/$MsGraphVersion" 
    )

    DynamicParam {
        #If the Import Param is used, Create the File Param
        switch ($Type) {
            FilterQuery {
                $FAttrib = New-Object System.Management.Automation.ParameterAttribute
                $FAttrib.Mandatory = $true
                #create an attributecollection object for the attribute we just created.
                $attributeCollection = new-object System.Collections.ObjectModel.Collection[System.Attribute]
                #add custom FileAttribute attribute
                $attributeCollection.Add($FAttrib)
                #add our paramater specifying the attribute collection
                $FilName = New-Object System.Management.Automation.RuntimeDefinedParameter('FilterID', [string], $attributeCollection)
                #expose the name of our parameter
                $paramDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
                $paramDictionary.Add('FilterID', $FilName)
                return $paramDictionary
            }
        }
    }

    begin {
        IF (-Not ($BGUAccessToken)) {
            Throw "You must first obtain an access token by running Get-BGUAccessToken, please obtain a token and retry this action"
        } 
        elseif ($BGUAccessToken.ExpiresOn.LocalDateTime -LT $(Get-Date)) {
            Throw "You're access token expired $($BGUAccessToken.ExpiresOn.LocalDateTime), you must obtain a new access token by running Get-BGUAccessToken."
        }
 
        $GraphHeader = @{Authorization = "Bearer $($BGUAccessToken.AccessToken)"}
    } 
    #Process The Function
    Process {
        try {
            $GraphParams = @{
                Method = "GET"
                URI = "$GraphURI/identity/conditionalAccess/policies"
                Headers = $GraphHeader
            }
            $GraphRequest = Invoke-RestMethod @GraphParams -ErrorAction Stop
            $global:All_GraphRequest = @()
            $All_GraphRequest += $GraphRequest
            while($GraphRequest.'@odata.nextLink') {
                $GraphRequest_NextLink = @{
                    Method = "GET"
                    URI = $GraphRequest.'@odata.nextLink'
                    Headers = $GraphHeader
                    ContentType = "application/JSON"
                }
                $GraphRequest = Invoke-RestMethod @$GraphRequest_NextLink -ErrorAction Stop
                $All_GraphRequest += $GraphRequest
            }
        }
        catch {
            $Error[0]
            Throw "The Microsoft Graph Query Failed,"
        }

        Switch ($Type) {
            Default {
                $All_GraphRequest | Select-Object -ExpandProperty Value
            }
            FilterQuery {
                $All_GraphRequest | Select-Object -ExpandProperty Value | Where-Object id -Match $($PSBoundParameters.FilterID)
            }
        }
    }
}
Function Import-ConditionalAccessPolicies {
    [CmdletBinding()]
    param (
        [ValidateSet('Object','File')]
        $Type,
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphVersion = "beta",
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphHost = "graph.microsoft.com",
        [Parameter(DontShow = $true)]
        $GraphURI = "https://$MSGraphHost/$MsGraphVersion"
    )

    DynamicParam {
        switch ($Type) {
            File { 
                #If the Import Param is used, Create the File Param
                $FileAttribute = New-Object System.Management.Automation.ParameterAttribute
                $FileAttribute.Mandatory = $true
                #create an attributecollection object for the attribute we just created.
                $attributeCollection = new-object System.Collections.ObjectModel.Collection[System.Attribute]
                #add custom FileAttribute attribute
                $attributeCollection.Add($FileAttribute)
                #add our paramater specifying the attribute collection
                $File = New-Object System.Management.Automation.RuntimeDefinedParameter('File', [string], $attributeCollection)
                #expose the name of our parameter
                $paramDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
                $paramDictionary.Add('File', $File)
                return $paramDictionary 
            }
            Object {
                $ObjectAttrib = New-Object System.Management.Automation.ParameterAttribute
                $ObjectAttrib.Mandatory = $true
                #create an attributecollection object for the attribute we just created.
                $attributeCollection = new-object System.Collections.ObjectModel.Collection[System.Attribute]
                #add custom ObjectAttrib attribute
                $attributeCollection.Add($ObjectAttrib)
                #add our paramater specifying the attribute collection
                $ImportObject = New-Object System.Management.Automation.RuntimeDefinedParameter('ImportObject', [Object], $attributeCollection)
                #expose the name of our parameter
                $paramDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
                $paramDictionary.Add('ImportObject', $ImportObject)
                return $paramDictionary 
            }
        }
        
    }

    begin {
        IF ($PSBoundParameters.File){
            IF(-not (Test-Path -Path $PSBoundParameters.File)) {
                Throw "Unable to locate $PSBoundParameters.File"
            } else {
                $JSONImport = $PSBoundParameters.File
            }
        }
        IF (-Not ($BGUAccessToken)) {
            Throw "You must first obtain an access token by running Get-BGUAccessToken, please obtain a token and retry this action"
        } 
        elseif ($BGUAccessToken.ExpiresOn.LocalDateTime -LT $(Get-Date)) {
            Throw "You're access token expired $($BGUAccessToken.ExpiresOn.LocalDateTime), you must obtain a new access token by running Get-BGUAccessToken."
        }
 
        $GraphHeader = @{Authorization = "Bearer $($BGUAccessToken.AccessToken)"}
    } 
    Process {

        switch ($Type) {
            File { 
                $ImportBody = Get-Content $JSONImport | ConvertFrom-Json | Select-Object -Property * -ExcludeProperty Version,ModifiedDateTime,CreatedDateTime,id,supportsScopeTags
            }
            Object {
                $ImportBody = $PSBoundParameters.ImportObject | Select-Object -Property * -ExcludeProperty Version,ModifiedDateTime,CreatedDateTime,id,supportsScopeTags
            }
        }
        
        $GraphImportParams = @{
            Method = "POST"
            URI = "$GraphURI/identity/conditionalAccess/policies"
            BODY = ($ImportBody | ConvertTo-Json -Depth 10)
            Headers = $GraphHeader
            CONTENTTYPE = "application/Json"
        }
        
        Invoke-RestMethod @GraphImportParams
    }
}
function Export-ConditionalAccessPolicies {
    param(
        [Parameter(Mandatory = $True)]
        $PolicyID, 
        [ValidateSet('Object','File')]
        [Parameter(Mandatory = $True)]
        $Type,
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphVersion = "beta",
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphHost = "graph.microsoft.com",
        [Parameter(DontShow = $true)]
        $GraphURI = "https://$MSGraphHost/$MsGraphVersion"
    )

    DynamicParam {
        #If the Import Param is used, Create the File Param
        switch ($Type) {
            File {
                $FileAttribute = New-Object System.Management.Automation.ParameterAttribute
                $FileAttribute.Mandatory = $true
                #create an attributecollection object for the attribute we just created.
                $attributeCollection = new-object System.Collections.ObjectModel.Collection[System.Attribute]
                #add custom FileAttribute attribute
                $attributeCollection.Add($FileAttribute)
                #add our paramater specifying the attribute collection
                $ExportLocation = New-Object System.Management.Automation.RuntimeDefinedParameter('ExportLocation', [string], $attributeCollection)
                #expose the name of our parameter
                $paramDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
                $paramDictionary.Add('ExportLocation', $ExportLocation)
                return $paramDictionary
            }
        }
    }

    begin {
        IF ($PSBoundParameters.ExportLocation){
            $ExportLocation = $PSBoundParameters.ExportLocation
        }
        IF (-Not ($BGUAccessToken)) {
            Throw "You must first obtain an access token by running Get-BGUAccessToken, please obtain a token and retry this action"
        } 
        elseif ($BGUAccessToken.ExpiresOn.LocalDateTime -LT $(Get-Date)) {
            Throw "You're access token expired $($BGUAccessToken.ExpiresOn.LocalDateTime), you must obtain a new access token by running Get-BGUAccessToken."
        }
 
        $GraphHeader = @{Authorization = "Bearer $($BGUAccessToken.AccessToken)"}
    }
    Process {
        $GraphObjectParams = @{
            METHOD = "GET"
            URI = "$GraphURI/identity/conditionalAccess/policies/$($PolicyID)"
            HEADERS = $GraphHeader
        }

        $export_obj =  Invoke-RestMethod @GraphObjectParams

        if($export_obj)
        {       
            switch ($Type) {
                Object {
                    $export_obj
                }
                File {
                    # Export The Base Admin Template
                    ConvertTo-Json $export_obj -Depth 10 | Out-File "$ExportLocation\$(($export_obj.displayName)).json" -Force
                }
            }     
        }
    }
}
function Copy-ConditionalAccessPolicies {
    param(
        [string]
        [Parameter(Mandatory = $True)]
        $PolicyID, 
        [Parameter(Mandatory = $True)]
        [ValidateSet('Copy','Test','PreProd','Dev','Prod','Pilot','Custom')]
        $Prefix,
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphVersion = "beta",
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphHost = "graph.microsoft.com",
        [Parameter(DontShow = $true)]
        $GraphURI = "https://$MSGraphHost/$MsGraphVersion"
    )

    DynamicParam {
        #If the Import Param is used, Create the File Param
        switch ($Prefix) {
            Custom {
                $CustomAttrib = New-Object System.Management.Automation.ParameterAttribute
                $CustomAttrib.Mandatory = $true
                #create an attributecollection object for the attribute we just created.
                $attributeCollection = new-object System.Collections.ObjectModel.Collection[System.Attribute]
                #add custom CustomAttrib attribute
                $attributeCollection.Add($CustomAttrib)
                #add our paramater specifying the attribute collection
                $CustomPrefix = New-Object System.Management.Automation.RuntimeDefinedParameter('CustomPrefix', [string], $attributeCollection)
                #expose the name of our parameter
                $paramDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
                $paramDictionary.Add('CustomPrefix', $CustomPrefix)
                return $paramDictionary
            }
        }
    }

    begin {
        IF (-Not ($BGUAccessToken)) {
            Throw "You must first obtain an access token by running Get-BGUAccessToken, please obtain a token and retry this action"
        } 
        elseif ($BGUAccessToken.ExpiresOn.LocalDateTime -LT $(Get-Date)) {
            Throw "You're access token expired $($BGUAccessToken.ExpiresOn.LocalDateTime), you must obtain a new access token by running Get-BGUAccessToken."
        }

        switch ($Prefix) {
            Custom { 
                $PolicyPrefix = $PSBoundParameters.CustomPrefix.ToUpper()
            }
            Default {
                $PolicyPrefix = $Prefix.ToUpper()
            }
        }
    }
    
    process {
        Write-Output "Object iD: $($PolicyID)"
        $BaseObject = Export-ConditionalAccessPolicies -Type Object -PolicyID $PolicyID
        $BaseObject.displayName = "$PolicyPrefix-$($BaseObject.displayName)"
        Import-ConditionalAccessPolicies -Type Object -ImportObject $BaseObject
    }
}

##################################################################################
##################################################################################
# #
# Configuration Profiles #
# #
##################################################################################
##################################################################################

Function Get-ConfigurationProfiles {
    [CmdletBinding()]
    param (
        [ValidateSet('All','FilterQuery')]
        $Type,
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphVersion = "beta",
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphHost = "graph.microsoft.com",
        [Parameter(DontShow = $true)]
        $GraphURI = "https://$MSGraphHost/$MsGraphVersion"
    )

    DynamicParam {
        #If the Import Param is used, Create the File Param
        switch ($Type) {
            FilterQuery {
                $FAttrib = New-Object System.Management.Automation.ParameterAttribute
                $FAttrib.Mandatory = $true
                #create an attributecollection object for the attribute we just created.
                $attributeCollection = new-object System.Collections.ObjectModel.Collection[System.Attribute]
                #add custom FileAttribute attribute
                $attributeCollection.Add($FAttrib)
                #add our paramater specifying the attribute collection
                $FilterID = New-Object System.Management.Automation.RuntimeDefinedParameter('FilterID', [string], $attributeCollection)
                #expose the name of our parameter
                $paramDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
                $paramDictionary.Add('FilterID', $FilterID)
                return $paramDictionary
            }
        }
    }

    begin {
        IF (-Not ($BGUAccessToken)) {
            Throw "You must first obtain an access token by running Get-BGUAccessToken, please obtain a token and retry this action"
        } 
        elseif ($BGUAccessToken.ExpiresOn.LocalDateTime -LT $(Get-Date)) {
            Throw "You're access token expired $($BGUAccessToken.ExpiresOn.LocalDateTime), you must obtain a new access token by running Get-BGUAccessToken."
        }
 
        $GraphHeader = @{Authorization = "Bearer $($BGUAccessToken.AccessToken)"}
    } 
    #Process The Function
    Process {
        try {
            $GraphParams = @{
                Method = "GET"
                URI = "$GraphURI/deviceManagement/deviceConfigurations"
                Headers = $GraphHeader
            }
        
            $GraphRequest = Invoke-RestMethod @GraphParams -ErrorAction Stop
            $global:All_GraphRequest = @()
            $All_GraphRequest += $GraphRequest
            while($GraphRequest.'@odata.nextLink') {
                $GraphRequest_NextLink = @{
                    Method = "GET"
                    URI = $GraphRequest.'@odata.nextLink'
                    Headers = $GraphHeader
                    ContentType = "application/JSON"
                }
                $GraphRequest = Invoke-RestMethod @$GraphRequest_NextLink -ErrorAction Stop
                $All_GraphRequest += $GraphRequest
            }
        }
        catch {
            $Error[0]
            Throw "The Microsoft Graph Query Failed,"
        }

        Switch ($Type) {
            Default {
                $All_GraphRequest | Select-Object -ExpandProperty Value
            }
            FilterQuery {
                $All_GraphRequest | Select-Object -ExpandProperty Value | Where-Object id -Match $($PSBoundParameters.FilterID)
            }
        }
    }
}
Function Import-ConfigurationProfiles {
    [CmdletBinding()]
    param (
        [ValidateSet('Object','File')]
        $Type,
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphVersion = "beta",
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphHost = "graph.microsoft.com",
        [Parameter(DontShow = $true)]
        $GraphURI = "https://$MSGraphHost/$MsGraphVersion" 
    )

    DynamicParam {
        switch ($Type) {
            File { 
                #If the Import Param is used, Create the File Param
                $FileAttribute = New-Object System.Management.Automation.ParameterAttribute
                $FileAttribute.Mandatory = $true
                #create an attributecollection object for the attribute we just created.
                $attributeCollection = new-object System.Collections.ObjectModel.Collection[System.Attribute]
                #add custom FileAttribute attribute
                $attributeCollection.Add($FileAttribute)
                #add our paramater specifying the attribute collection
                $File = New-Object System.Management.Automation.RuntimeDefinedParameter('File', [string], $attributeCollection)
                #expose the name of our parameter
                $paramDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
                $paramDictionary.Add('File', $File)
                return $paramDictionary 
            }
            Object {
                $ObjectAttrib = New-Object System.Management.Automation.ParameterAttribute
                $ObjectAttrib.Mandatory = $true
                #create an attributecollection object for the attribute we just created.
                $attributeCollection = new-object System.Collections.ObjectModel.Collection[System.Attribute]
                #add custom ObjectAttrib attribute
                $attributeCollection.Add($ObjectAttrib)
                #add our paramater specifying the attribute collection
                $ImportObject = New-Object System.Management.Automation.RuntimeDefinedParameter('ImportObject', [Object] , $attributeCollection)
                #expose the name of our parameter
                $paramDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
                $paramDictionary.Add('ImportObject', $ImportObject)
                return $paramDictionary 
            }
        }
        
    }

    begin {
        #If the File Param is used, Test the Path to make sure its accessible, If not throw an error. If it does exist set the JSONImport Param to the AttributeValue
        IF ($PSBoundParameters.File){
            IF(-not (Test-Path -Path $PSBoundParameters.File)) {
                Throw "Unable to locate $PSBoundParameters.File"
            } else {
                $JSONImport = $PSBoundParameters.File
            }
        }
        IF (-Not ($BGUAccessToken)) {
            Throw "You must first obtain an access token by running Get-BGUAccessToken, please obtain a token and retry this action"
        } 
        elseif ($BGUAccessToken.ExpiresOn.LocalDateTime -LT $(Get-Date)) {
            Throw "You're access token expired $($BGUAccessToken.ExpiresOn.LocalDateTime), you must obtain a new access token by running Get-BGUAccessToken."
        }
 
        $GraphHeader = @{Authorization = "Bearer $($BGUAccessToken.AccessToken)"}
    } 

    #Process The Function
    Process {

        switch ($Type) {
            File { 
                $ImportBody = Get-Content $JSONImport | ConvertFrom-Json | Select-Object -Property * -ExcludeProperty Version,LastModifiedDateTime,CreatedDateTime,id | ConvertTo-Json -Depth 10
            }
            Object {
                $ImportBody = $PSBoundParameters.ImportObject | Select-Object -Property * -ExcludeProperty Version,LastModifiedDateTime,CreatedDateTime,id,supportsScopeTags,lastModifiedDateTime | ConvertTo-Json -Depth 10
            }
        }
        
        $GraphImportParams = @{
            Method = "POST"
            URI = "$GraphURI/deviceManagement/deviceConfigurations"
            BODY = $ImportBody
            Headers = $GraphHeader
            CONTENTTYPE = "application/Json"
        }
        
        Invoke-RestMethod @GraphImportParams
    }
}

function Export-ConfigurationProfiles {
    param(
        [Parameter(Mandatory = $True)]
        $PolicyID, 
        [ValidateSet('Object','File')]
        [Parameter(Mandatory = $True)]
        $Type,
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphVersion = "beta",
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphHost = "graph.microsoft.com",
        [Parameter(DontShow = $true)]
        $GraphURI = "https://$MSGraphHost/$MsGraphVersion"
    )

    DynamicParam {
        #If the Import Param is used, Create the File Param
        switch ($Type) {
            File {
                $FileAttribute = New-Object System.Management.Automation.ParameterAttribute
                $FileAttribute.Mandatory = $true
                #create an attributecollection object for the attribute we just created.
                $attributeCollection = new-object System.Collections.ObjectModel.Collection[System.Attribute]
                #add custom FileAttribute attribute
                $attributeCollection.Add($FileAttribute)
                #add our paramater specifying the attribute collection
                $ExportLocation = New-Object System.Management.Automation.RuntimeDefinedParameter('ExportLocation', [string], $attributeCollection)
                #expose the name of our parameter
                $paramDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
                $paramDictionary.Add('ExportLocation', $ExportLocation)
                return $paramDictionary
            }
        }
    }

    begin {
        IF ($PSBoundParameters.ExportLocation){
            $ExportLocation = $PSBoundParameters.ExportLocation
        }
        IF (-Not ($BGUAccessToken)) {
            Throw "You must first obtain an access token by running Get-BGUAccessToken, please obtain a token and retry this action"
        } 
        elseif ($BGUAccessToken.ExpiresOn.LocalDateTime -LT $(Get-Date)) {
            Throw "You're access token expired $($BGUAccessToken.ExpiresOn.LocalDateTime), you must obtain a new access token by running Get-BGUAccessToken."
        }
 
        $GraphHeader = @{Authorization = "Bearer $($BGUAccessToken.AccessToken)"}
    }
    Process {
        $GraphObjectParams = @{
            METHOD = "GET"
            URI = "$GraphURI/deviceManagement/deviceConfigurations/$($PolicyID)"
            HEADERS = $GraphHeader
        }

        $export_obj =  Invoke-RestMethod @GraphObjectParams

        if($export_obj)
        {       
            switch ($Type) {
                Object {
                    $export_obj
                }
                File {
                    # Export The Base Admin Template
                    ConvertTo-Json $export_obj -Depth 10 | Out-File "$ExportLocation\$(($export_obj.displayName)).json" -Force
                }
            }     
        }
    }
}
function Copy-ConfigurationProfiles {
    param(
        [string]
        [Parameter(Mandatory = $True)]
        $PolicyID, 
        [Parameter(Mandatory = $True)]
        [ValidateSet('Copy','Test','PreProd','Dev','Prod','Pilot','Custom')]
        $Prefix,
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphVersion = "beta",
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphHost = "graph.microsoft.com",
        [Parameter(DontShow = $true)]
        $GraphURI = "https://$MSGraphHost/$MsGraphVersion"
    )

    DynamicParam {
        #If the Import Param is used, Create the File Param
        switch ($Prefix) {
            Custom {
                $CustomAttrib = New-Object System.Management.Automation.ParameterAttribute
                $CustomAttrib.Mandatory = $true
                #create an attributecollection object for the attribute we just created.
                $attributeCollection = new-object System.Collections.ObjectModel.Collection[System.Attribute]
                #add custom CustomAttrib attribute
                $attributeCollection.Add($CustomAttrib)
                #add our paramater specifying the attribute collection
                $CustomPrefix = New-Object System.Management.Automation.RuntimeDefinedParameter('CustomPrefix', [string], $attributeCollection)
                #expose the name of our parameter
                $paramDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
                $paramDictionary.Add('CustomPrefix', $CustomPrefix)
                return $paramDictionary
            }
        }
    }

    begin {
        IF (-Not ($BGUAccessToken)) {
            Throw "You must first obtain an access token by running Get-BGUAccessToken, please obtain a token and retry this action"
        } 
        elseif ($BGUAccessToken.ExpiresOn.LocalDateTime -LT $(Get-Date)) {
            Throw "You're access token expired $($BGUAccessToken.ExpiresOn.LocalDateTime), you must obtain a new access token by running Get-BGUAccessToken."
        }

        switch ($Prefix) {
            Custom { 
                $PolicyPrefix = $PSBoundParameters.CustomPrefix.ToUpper()
            }
            Default {
                $PolicyPrefix = $Prefix.ToUpper()
            }
        }
    }
    
    process {
        Write-Output "Object iD: $($PolicyID)"
        $BaseObject = Export-ConfigurationProfiles -Type Object $PolicyID
        $BaseObject.displayName = "$PolicyPrefix-$($BaseObject.displayName)"
        Import-ConfigurationProfiles -Type Object -ImportObject $BaseObject
    }
}

##################################################################################
##################################################################################
# #
# Endpoint Security Profiles #
# #
##################################################################################
##################################################################################

Function Get-EndpointSecurityProfiles {
    [CmdletBinding()]
    param (
        [ValidateSet('All','FilterQuery')]
        $Type,
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphVersion = "beta",
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphHost = "graph.microsoft.com",
        [Parameter(DontShow = $true)]
        $GraphURI = "https://$MSGraphHost/$MsGraphVersion"
    )

    DynamicParam {
        #If the Import Param is used, Create the File Param
        switch ($Type) {
            FilterQuery {
                $FAttrib = New-Object System.Management.Automation.ParameterAttribute
                $FAttrib.Mandatory = $true
                #create an attributecollection object for the attribute we just created.
                $attributeCollection = new-object System.Collections.ObjectModel.Collection[System.Attribute]
                #add custom FileAttribute attribute
                $attributeCollection.Add($FAttrib)
                #add our paramater specifying the attribute collection
                $FilterID = New-Object System.Management.Automation.RuntimeDefinedParameter('FilterID', [string], $attributeCollection)
                #expose the name of our parameter
                $paramDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
                $paramDictionary.Add('FilterID', $FilterID)
                return $paramDictionary
            }
        }
    }

    begin {
        IF (-Not ($BGUAccessToken)) {
            Throw "You must first obtain an access token by running Get-BGUAccessToken, please obtain a token and retry this action"
        } 
        elseif ($BGUAccessToken.ExpiresOn.LocalDateTime -LT $(Get-Date)) {
            Throw "You're access token expired $($BGUAccessToken.ExpiresOn.LocalDateTime), you must obtain a new access token by running Get-BGUAccessToken."
        }
 
        $GraphHeader = @{Authorization = "Bearer $($BGUAccessToken.AccessToken)"}
    } 
    #Process The Function
    Process {
        try {
            $GraphParams = @{
                Method = "GET"
                URI = "$GraphURI/deviceManagement/intents"
                Headers = $GraphHeader
            }
        
            $GraphRequest = Invoke-RestMethod @GraphParams -ErrorAction Stop
            $All_GraphRequest = @()
            $All_GraphRequest += $GraphRequest
            while($GraphRequest.'@odata.nextLink') {
                $GraphRequest_NextLink = @{
                    Method = "GET"
                    URI = $GraphRequest.'@odata.nextLink'
                    Headers = $GraphHeader
                    ContentType = "application/JSON"
                }
                $GraphRequest = Invoke-RestMethod @$GraphRequest_NextLink -ErrorAction Stop
                $All_GraphRequest += $GraphRequest
            }
        }
        catch {
            $Error[0]
            Throw "The Microsoft Graph Query Failed,"
        }

        Switch ($Type) {
            Default {
                $All_GraphRequest | Select-Object -ExpandProperty Value
            }
            FilterQuery {
                $All_GraphRequest | Select-Object -ExpandProperty Value | Where-Object id -Match $($PSBoundParameters.FilterID)
            }
        }
    }
}
Function Import-EndpointSecurityProfiles {
    [CmdletBinding()]
    param (
        [ValidateSet('Object','File')]
        $Type,
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphVersion = "beta",
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphHost = "graph.microsoft.com",
        [Parameter(DontShow = $true)]
        $GraphURI = "https://$MSGraphHost/$MsGraphVersion" 
    )

    DynamicParam {
        switch ($Type) {
            File { 
                #If the Import Param is used, Create the File Param
                $FileAttribute = New-Object System.Management.Automation.ParameterAttribute
                $FileAttribute.Mandatory = $true
                #create an attributecollection object for the attribute we just created.
                $attributeCollection = new-object System.Collections.ObjectModel.Collection[System.Attribute]
                #add custom FileAttribute attribute
                $attributeCollection.Add($FileAttribute)
                #add our paramater specifying the attribute collection
                $File = New-Object System.Management.Automation.RuntimeDefinedParameter('File', [string], $attributeCollection)
                #expose the name of our parameter
                $paramDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
                $paramDictionary.Add('File', $File)
                return $paramDictionary 
            }
            Object {
                $ObjectAttrib = New-Object System.Management.Automation.ParameterAttribute
                $ObjectAttrib.Mandatory = $true
                #create an attributecollection object for the attribute we just created.
                $attributeCollection = new-object System.Collections.ObjectModel.Collection[System.Attribute]
                #add custom ObjectAttrib attribute
                $attributeCollection.Add($ObjectAttrib)
                #add our paramater specifying the attribute collection
                $ImportObject = New-Object System.Management.Automation.RuntimeDefinedParameter('ImportObject', [array] ,$attributeCollection)
                #expose the name of our parameter
                $paramDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
                $paramDictionary.Add('ImportObject', $ImportObject)
                return $paramDictionary 
            }
        }
        
    }

    begin {
        #If the File Param is used, Test the Path to make sure its accessible, If not throw an error. If it does exist set the JSONImport Param to the AttributeValue
        IF ($PSBoundParameters.File){
            IF(-not (Test-Path -Path $PSBoundParameters.File)) {
                Throw "Unable to locate $PSBoundParameters.File"
            } else {
                $JSONImport = $PSBoundParameters.File
            }
        }
        IF (-Not ($BGUAccessToken)) {
            Throw "You must first obtain an access token by running Get-BGUAccessToken, please obtain a token and retry this action"
        } 
        elseif ($BGUAccessToken.ExpiresOn.LocalDateTime -LT $(Get-Date)) {
            Throw "You're access token expired $($BGUAccessToken.ExpiresOn.LocalDateTime), you must obtain a new access token by running Get-BGUAccessToken."
        }
 
        $GraphHeader = @{Authorization = "Bearer $($BGUAccessToken.AccessToken)"}
    } 

    #Process The Function
    Process {

        switch ($Type) {
            File { 
                $JSONContent = Get-Content $JSONImport | ConvertFrom-Json
                $TemplateID = $JSONContent.templateID
                $ImportBody = $JSONContent | Select-Object -Property * -ExcludeProperty templateID
            }
            Object {
                $TemplateID = $PSBoundParameters.ImportObject.templateID

                $ImportBody = @{
                    "displayName" = $PSBoundParameters.ImportObject.displayName
                    "description" = $PSBoundParameters.ImportObject.description
                    "settingDelta" = $PSBoundParameters.ImportObject.settingDelta
                    "roleScopeTagIds" = @($PSBoundParameters.ImportObject.roleScopeTagIds)
                }
            }
        }
        
        $GraphImportParams = @{
            Method = "POST"
            URI = "$GraphURI/deviceManagement/templates/$($TemplateID)/createinstance"
            BODY = ($ImportBody | ConvertTo-Json -Depth 10 )
            Headers = $GraphHeader
            CONTENTTYPE = "application/Json"
        }
        
        Invoke-RestMethod @GraphImportParams
    }
}

function Export-EndpointSecurityProfiles {
    param(
        [Parameter(Mandatory = $True)]
        $PolicyID, 
        [ValidateSet('Object','File')]
        [Parameter(Mandatory = $True)]
        $Type,
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphVersion = "beta",
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphHost = "graph.microsoft.com",
        [Parameter(DontShow = $true)]
        $GraphURI = "https://$MSGraphHost/$MsGraphVersion"
    )

    DynamicParam {
        #If the Import Param is used, Create the File Param
        switch ($Type) {
            File {
                $FileAttribute = New-Object System.Management.Automation.ParameterAttribute
                $FileAttribute.Mandatory = $true
                #create an attributecollection object for the attribute we just created.
                $attributeCollection = new-object System.Collections.ObjectModel.Collection[System.Attribute]
                #add custom FileAttribute attribute
                $attributeCollection.Add($FileAttribute)
                #add our paramater specifying the attribute collection
                $ExportLocation = New-Object System.Management.Automation.RuntimeDefinedParameter('ExportLocation', [string], $attributeCollection)
                #expose the name of our parameter
                $paramDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
                $paramDictionary.Add('ExportLocation', $ExportLocation)
                return $paramDictionary
            }
        }
    }

    begin {
        IF ($PSBoundParameters.ExportLocation){
            $ExportLocation = $PSBoundParameters.ExportLocation
        }
        IF (-Not ($BGUAccessToken)) {
            Throw "You must first obtain an access token by running Get-BGUAccessToken, please obtain a token and retry this action"
        } 
        elseif ($BGUAccessToken.ExpiresOn.LocalDateTime -LT $(Get-Date)) {
            Throw "You're access token expired $($BGUAccessToken.ExpiresOn.LocalDateTime), you must obtain a new access token by running Get-BGUAccessToken."
        }
 
        $GraphHeader = @{Authorization = "Bearer $($BGUAccessToken.AccessToken)"}
    }
    Process {

        $GraphDeviceIntentParams = @{
            METHOD = "GET"
            URI = "$GraphURI/deviceManagement/Intents/$($PolicyID)"
            HEADERS = $GraphHeader
        }

        $IntentPolicy =  Invoke-RestMethod @GraphDeviceIntentParams

        if($IntentPolicy){       

            $GraphTemplateCategoriesParams = @{
                METHOD = "GET"
                URI = "$GraphURI/deviceManagement/templates/$($IntentPolicy.templateId)/categories"
                HEADERS = $GraphHeader
            }
            $IntentPolicy_Template_Categories =  Invoke-RestMethod @GraphTemplateCategoriesParams
            $All_IntentPolicy_Template_Categories = @()
            $All_IntentPolicy_Template_Categories += $IntentPolicy_Template_Categories
            while ($IntentPolicy_Template_Categories.'@odata.nextLink') {
                $GraphRequest_NextLink = @{
                    Method = "GET"
                    URI = $IntentPolicy_Template_Categories.'@odata.nextLink'
                    Headers = $GraphHeader
                    ContentType = "application/JSON"
                }
                $IntentPolicy_Template_Categories = Invoke-RestMethod @GraphRequest_NextLink -ErrorAction Stop
                $All_IntentPolicy_Template_Categories += $IntentPolicy_Template_Categories
            }
            
            
            $IntentPolicy_Settings = @()
            FOREACH ($Category in $All_IntentPolicy_Template_Categories.value) {
                $GraphIntentSettingParams = @{
                    METHOD = "GET"
                    URI = "$GraphURI/deviceManagement/intents/$($IntentPolicy.Id)/categories/$($Category.id)/settings"
                    HEADERS = $GraphHeader
                }

                $IntentPolicy_Settings += Invoke-RestMethod @GraphIntentSettingParams
                $All_IntentPolicy_Settings = @()
                $All_IntentPolicy_Settings += $IntentPolicy_Settings
                while($IntentPolicy_Settings.'@odata.nextLink') {
                    $GraphRequest_NextLink = @{
                        Method = "GET"
                        URI = $IntentPolicy_Settings.'@odata.nextLink'
                        Headers = $GraphHeader
                        ContentType = "application/JSON"
                    }
                    $IntentPolicy_Settings = Invoke-RestMethod @GraphRequest_NextLink -ErrorAction Stop
                    $All_IntentPolicy_Settings += $IntentPolicy_Settings
                }
            }
            
            $export_obj = @{
                "displayName" = $IntentPolicy.displayName
                "templateID" = $IntentPolicy.templateId
                "description" = $IntentPolicy.description
                "settingsDelta" = $All_IntentPolicy_Settings.value
                "roleScopeTagIds" = $IntentPolicy.roleScopeTagIds

            }
            switch ($Type) {
                Object {
                    $export_obj
                }
                File {
                    # Export The Base Admin Template
                    ConvertTo-Json $export_obj -Depth 10 | Out-File "$ExportLocation\$(($export_obj.displayName)).json" -Force
                }
            }     
        }
    }
}
function Copy-EndpointSecurityProfiles {
    param(
        [string]
        [Parameter(Mandatory = $True)]
        $PolicyID, 
        [Parameter(Mandatory = $True)]
        [ValidateSet('Copy','Test','PreProd','Dev','Prod','Pilot','Custom')]
        $Prefix,
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphVersion = "beta",
        [Parameter(DontShow = $true)]
        [string]
        $MsGraphHost = "graph.microsoft.com",
        [Parameter(DontShow = $true)]
        $GraphURI = "https://$MSGraphHost/$MsGraphVersion"
    )

    DynamicParam {
        #If the Import Param is used, Create the File Param
        switch ($Prefix) {
            Custom {
                $CustomAttrib = New-Object System.Management.Automation.ParameterAttribute
                $CustomAttrib.Mandatory = $true
                #create an attributecollection object for the attribute we just created.
                $attributeCollection = new-object System.Collections.ObjectModel.Collection[System.Attribute]
                #add custom CustomAttrib attribute
                $attributeCollection.Add($CustomAttrib)
                #add our paramater specifying the attribute collection
                $CustomPrefix = New-Object System.Management.Automation.RuntimeDefinedParameter('CustomPrefix', [string], $attributeCollection)
                #expose the name of our parameter
                $paramDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
                $paramDictionary.Add('CustomPrefix', $CustomPrefix)
                return $paramDictionary
            }
        }
    }

    begin {
        IF (-Not ($BGUAccessToken)) {
            Throw "You must first obtain an access token by running Get-BGUAccessToken, please obtain a token and retry this action"
        } 
        elseif ($BGUAccessToken.ExpiresOn.LocalDateTime -LT $(Get-Date)) {
            Throw "You're access token expired $($BGUAccessToken.ExpiresOn.LocalDateTime), you must obtain a new access token by running Get-BGUAccessToken."
        }

        switch ($Prefix) {
            Custom { 
                $PolicyPrefix = $PSBoundParameters.CustomPrefix.ToUpper()
            }
            Default {
                $PolicyPrefix = $Prefix.ToUpper()
            }
        }
    }
    
    process {
        Write-Output "Object iD: $($PolicyID)"
        $BaseObject = Export-EndpointSecurityProfiles -Type Object $PolicyID
        $BaseObject.displayName = "$PolicyPrefix-$($BaseObject.displayName)"
        Import-EndpointSecurityProfiles -Type Object -ImportObject $BaseObject
    }
}


Export-ModuleMember -Alias * -Function *