In the final part of the series, we will look at the newest means of controlling settings, Administrative Templates (ADMX). We will also look at working around some limitations with exported pre-created group policies.

Series Links:
Managing Windows 10 with Microsoft Intune – Part 1 (MDM Profiles)
Managing Windows 10 with Microsoft Intune – Part 2 (CSP Policies)
Managing Windows 10 with Microsoft Intune – Part 3 (Administrative Templates & Workarounds)

Administrative Template (aka ADMX) Settings

This is the latest addition to Intune’s management capability, something which people have been crying out for over the past couple of years. Introduced at Microsoft Ignite in 2018, I had previously blogged about how to configure settings using this new “preview” feature (https://www.scconfigmgr.com/2018/10/17/configure-admx-settings-with-microsoft-intune-administrative-templates) in October.

At present there are a total of 278 settings which can be applied, focusing on the following technologies;

  • Internet Explorer
  • Office 2016
  • OneDrive

Given that little has changed in the current preview release, please refer to the post for a step by step guide. I’m sure in time we will see future improvements in this area, I will update this post as / when they happen.

Group Policy Settings – A Workaround Solution

So what happens when all else fails and you need a work around? Well thankfully there is a fallback, which many of you might be more familiar with. This of course is the ability to control settings in Windows through good old group policy objects, although this requires some creative solutions in order to apply the settings.

I have blogged about using local non-administrator group policy objects through Intune previously, see my post about building kiosks through the use of shared pc mode (https://www.scconfigmgr.com/2018/10/27/building-a-shared-pc-mode-kiosk-with-microsoft-intune) and how you can deploy these settings via a custom MSI.

This process could also be achieved through packaging the exported objects into a Win32 application using a PowerShell script to deliver the content, as an alternative for those who do not have access to application packaging software. Let us explore how this would work and how to review the logs and content location in order to understand the background processes;

Let us start with configuring the package.

  • First of you will need to download the Win32 app packaging tool from https://github.com/Microsoft/Intune-Win32-App-Packaging-Tool.
  • Now we create a non-local admin GPO, for test purposes just to block access to the control panel;

  • The GPO settings are written to “C:\Windows\System32\GroupPolicyUsers\S-1-5-32-545
  • Next we will need two PowerShell scripts, the first will install the GPO and the second will remove it;Name: Add-LocalGPOPolicy.ps1
    Content;

    #region Functions
    
    # Functions defined here
    function Write-LogEntry
    {
      param (
        [parameter(Mandatory = $true, HelpMessage = "Value added to the log file.")]
        [ValidateNotNullOrEmpty()]
        [string]$Value,
        [parameter(Mandatory = $true, HelpMessage = "Severity for the log entry. 1 for Informational, 2 for Warning and 3 for Error.")]
        [ValidateNotNullOrEmpty()]
        [ValidateSet("1", "2", "3")]
        [string]$Severity,
        [parameter(Mandatory = $false, HelpMessage = "Name of the log file that the entry will written to.")]
        [ValidateNotNullOrEmpty()]
        [string]$FileName = "Apply-LocalGPOPolicy.log"
      )
      # Determine log file location
      $LogFilePath = Join-Path -Path $env:Temp -ChildPath $FileName
      
      # Construct time stamp for log entry
      $Time = -join @((Get-Date -Format "HH:mm:ss.fff"), " ", (Get-WmiObject -Class Win32_TimeZone | Select-Object -ExpandProperty Bias))
      
      # Construct date for log entry
      $Date = (Get-Date -Format "MM-dd-yyyy")
      
      # Construct context for log entry
      $Context = $([System.Security.Principal.WindowsIdentity]::GetCurrent().Name)
      
      # Construct final log entry
      $LogText = "<![LOG[$($Value)]LOG]!><time=""$($Time)"" date=""$($Date)"" component=""LocalGPOInstall"" context=""$($Context)"" type=""$($Severity)"" thread=""$($PID)"" file="""">"
      
      # Add value to log file
      try
      {
        Out-File -InputObject $LogText -Append -NoClobber -Encoding Default -FilePath $LogFilePath -ErrorAction Stop
        if ($Severity -eq 1)
        {
          Write-Verbose -Message $Value
        }
        elseif ($Severity -eq 3)
        {
          Write-Warning -Message $Value
        }
      }
      catch [System.Exception] {
        Write-Warning -Message "Unable to append log entry to LogCollection.log file. Error message at line $($_.InvocationInfo.ScriptLineNumber): $($_.Exception.Message)"
      }
    }
    
    #endregion Functions
    
    Write-LogEntry -Value "Running from directory - $($PSScriptRoot)" -Severity 1
    Write-LogEntry -Value "Copying folder to C:\Windows\System32\GroupPolicyUsers" -Severity 1
    $RunningContext = Whoami
    Write-LogEntry -Value "Running under $RunningContext account" -Severity 1
    $CopyProgress = Copy-Item -Path (Join-Path -Path $PSScriptRoot -ChildPath "S-1-5-32-545") -Destination "C:\Windows\Sysnative\GroupPolicyUsers" -Container -Recurse -Force -Verbose -PassThru
    Write-LogEntry -Value "Copying items - $CopyProgress" -Severity 1
    Start-Sleep -Seconds 5
    if ((Test-Path -Path "C:\Windows\Sysnative\GroupPolicyusers\S-1-5-32-545") -eq $true)
    {
      Write-LogEntry -Value "S-1-5-32-545 folder exists" -Severity 1
      Write-LogEntry -Value "Hiding folder S-1-5-32-545" -Severity 1
      #Hide local non-admin folder
      (Get-Item -Path "C:\Windows\Sysnative\GroupPolicyUsers\S-1-5-32-545").Attributes = "Hidden"
    }
    Return 0

     

    Name: Remove-LocalGPOPolicy.ps1
    Content;

    If ((Test-Path -Path "C:\Windows\Sysnative\GroupPolicyUsers\S-1-5-32-545") -eq $true){
      Set-Location -Path "C:\Windows\Sysnative\GroupPolicyUsers\"
      Get-ChildItem | Where-Object {$_.Name -match "S-1-5-32-545"} | Remove-Item -Recurse -Force
    }
    Return 0

     

  • Now we can take the local GPO folder and PowerShell scripts to package them using the Win32 app packaging tool
  • Create a source folder and place the scripts and GPO folder inside
  • Run the Win32 app tool;

  • Now we can create the package and assign it
  • Create a new package and use the following installation settings;

    Install Command – C:\Windows\syswow64\WindowsPowerShell\v1.0\powershell.exe -executionpolicy bypass -file Add-LocalGPOPolicy.ps1
    Uninstall Command – C:\Windows\syswow64\WindowsPowerShell\v1.0\powershell.exe -executionpolicy bypass -file Remove-LocalGPOPolicy.ps1

    Note: The reason we are specifying the path of PowerShell.exe is to avoid 64 bit variable mapping as we need to use the SysNative (System32) folder. More information on file system redirection can be found here – https://docs.microsoft.com/en-us/windows/desktop/winprog64/file-system-redirector

  • Use the following detection logic;

  • Deploy your application to a device collection
  • Now let us run the install and look at the background processes
  • Open the Company Portal and run the install;

  • At this point the content will be downloaded first of all downloaded in its packaged format, this can be viewed by looking at the IntuneManagementExtension log found at – “C:\ProgramData\Microsoft\IntuneManagementExtension”;

  • The content will be then unzipped, copied to and then run from a cache directory. You can see the contents of this by opening the “C:\Windows\IMECache” folder;

  • Once the application install command has run, the detection rule runs to check if the install was successful;

  • The company portal is updated to reflect the successful installation;

  • Here we can see that the GPO folder has been created in the “C:\Windows\System32” folder
  • By logging on as a non-local admin, we can now verify that the control panel is blocked;

Conclusion

The example here is of course basic as we are only blocking the control panel, but you could include additional ADMX templates and pick from thousands of configuration options, just as you would have done previously with Group Policy.

One of the things you often hear is that Intune application install are a bit of a black-box, hopefully here you will be able to understand the processes that run in the background and where to locate both the content and logs files. With development in the Administrative Template (ADMX) feature within Intune, I would foresee that work-around’s like the above will be a thing of a the past in the future, but for now they are useful to “get the job done”.

Thanks for reading.

(2160)

There are no comments.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.