Configuring Windows Defender Credential Guard with Intune

The Windows Defender Credential Guard is a feature to protect NTLM, Kerberos and Sign-on credentials. Windows 10 Enterprise provides the capability to isolate certain Operating System (OS) pieces via so called virtualization-based security (VBS). NTLM and Kerberos credentials are normally stored in the Local Security Authority (LSA). Once VBS is enabled the LSASS process will be split into an isolated process (protected by virtualization based security)  called LSAiso and the LSASS process. The LSAiso process can not be accessed by other OS components than the LSASS. This approach protects credentials from malicious tools which gained system context access. A well known tool to accomplish extraction of credentials from LSASS in system context is Mimikatz. This will not work after enabling Windows Defender Credential Guard as the only process validated to gain access to LSAiso process is LSASS.

With that in mind Credential Guard can protect an attack vector used by a lot of bad guys trying to steal sensitive information. It’s really worth considering to turn this protection on for Windows 10 Enterprise x64 (no support for x86) devices.

CredentialGuardDesign

Further information of Credential Guard:
https://docs.microsoft.com/en-us/windows/access-protection/credential-guard/credential-guard-how-it-works

 

How do we configure this via Modern Management in Intune?

Since Windows 10 Version 1709 Microsoft provides Policy CSP support to configure Credential Guard via custom OMA-URIs. We can create a custom device profile:

CreateDeviceProfile

and then choose Profile type: custom

CredentialGuardDeviceProfile

Here we add the following OMA-URIs to configure Credential Guard with default settings and additional DMA Protection:

Name: DeviceGuard/EnableVirtualizationBasedSecurity
OMA-URI: ./Vendor/MSFT/Policy/Config/DeviceGuard/EnableVirtualizationBasedSecurity
Data type: integer
Value: 1 (enable virtualization based security)

Name: DeviceGuard/LsaCfgFlags
OMA-URI: ./Vendor/MSFT/Policy/Config/DeviceGuard/LsaCfgFlags
Data type: integer
Value: 1 (Enabled with UEFI lock)

Name: DeviceGuard/RequirePlatformSecurityFeatures
OMA-URI: ./Vendor/MSFT/Policy/Config/DeviceGuard/RequirePlatformSecurityFeatures
Data type: integer
Value: 3 (Turns on VBS with Secure Boot and direct memory access (DMA). DMA requires hardware support.)

Further information regarding Policy CSP values:
https://docs.microsoft.com/en-us/windows/client-management/mdm/policy-csp-deviceguard

As a last step we assign the new device configuration profile to our user group we want to provide the additional Credential Guard protection.

 

How to verify successful configuration?

First of all we verify if Intune applied the configuration successfully:

CredentialGuardDeploymentStatus

Then you can verify the applied registry settings on the target device of the user:

CredentialGuardRegistrySettings

Further information regarding registry settings:
https://docs.microsoft.com/en-us/windows/access-protection/credential-guard/credential-guard-manage

Make sure the device was restarted after successful configuration! This is needed as Credential Guard relies on Hyper-V technology for virtualization-based security and therefore it will enable the feature Hyper-V Hypervisor component.

We can have a look for the LsaIso.exe process in task manager:

CredentialGuardProcess

Finally we open up msinfo32.exe and verify if virtualization-based security is running and Credential Guard is activated:

CredentialGuardMsinfo32

If everything went well your machine is now protected against stealing of password secrets (hashes) which can be used by attackers for Pass-The-Hash (PTH) attacks. Keep in mind that this will not protect against attacks like key loggers. The solution is an effective way to protect credential stealing from memory.

 

How to test this in a Hyper-V Virtual Machine?

When using Microsoft Hyper-V you can enable nested virtualization on the VM and enable the Trusted Platform Module. Now you can test Credential Guard in your Hyper-V VM.

Enabling nested virtualization on Hyper-V VM:

Set-VMProcessor -VMName <VMName> -ExposeVirtualizationExtensions $true

Further information on nested virtualization:
https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/user-guide/nested-virtualization

Enabling the TPM on Hyper-V VM:

HyperVTPM

 

Additional things to consider?

The target hardware must support Credential Guard
https://docs.microsoft.com/en-us/windows/access-protection/credential-guard/credential-guard-requirements

Compatibility problems
https://docs.microsoft.com/en-us/windows/access-protection/credential-guard/credential-guard-considerations

Limitation in protection
https://docs.microsoft.com/en-us/windows/access-protection/credential-guard/credential-guard-protection-limits

 

UPDATE

Virtualization based security (VBS) will be available for non-Enterprise SKUs and starting with RS4+ VBS will be automatically enabled for clean installs!

 

If you are using Windows 10 please try Credential Guard in your environment as it is a really big security enhancement of Windows 10 Enterprise.

Deep dive Microsoft Intune Management Extension – PowerShell Scripts

Microsoft made a big step forward in the Modern Management field. Limitations like custom configurations or even Win32 App installs can be addressed now. Microsoft developed an EMS agent (aka SideCar) and released it as a new Intune feature called Intune Management Extension. This agent is able to manage and execute PowerShell scripts on Windows 10 devices and it does this quite well.

IntuneManagementExtensionMSIProperties

We can simply upload our own PowerShell scripts for device configuration:

PowerShellScriptsIntune

Part 2 of this article answers common questions I’ve seen, when working with the Intune Management Extension – Part 2, Deep dive Microsoft Intune Management Extension – PowerShell Scripts.

 

How do we get the agent installed on the devices?

The ability to deploy basic MSI packages via MDM OMA-DM channel, is provided by Microsoft since the beginning of Windows 10. This is achieved by using the EnterpriseDesktopAppManagement CSP.

Microsoft is using this mechanism to deploy the agent to Windows 10 devices. Beginning with Windows 10 Version 1607 we have support of the Intune Management Extension now. The device must be AAD joined and the automatic MDM enrollment must be enabled (see Prerequisites).

The workflow is basically like this. If a PowerShell script is assigned to a user group (device groups are not supported) and the agent is not installed, it will be pushed down automatically to the device via EnterpriseDesktopAppManagement CSP by Intune. This can be verified and traced in the “Advanced Diagnostics Report” of the MDM management.

Open Settings > Accounts > Access work or school > Connected to TenantName’s Azure AD > Info > scroll down to the bottom and click “Create report”

AdvancedDiagnosticsReportNow you get an report about all MDM configurations including the desktop app installations. Here we can see the EnterpriseDesktopAppManagement msi install of the EMSAgent with the ProductCode: {25212568-E605-43D5-9AA2-7AE8DB2C3D09}

EMSAgentInstallReport

./device/Vendor/MSFT/EnterpriseDesktopAppManagement/MSI/%7B25212568-E605-43D5-9AA2-7AE8DB2C3D09%7D

The instruction can be translated into more human readable form with ProductCode and curly brackets, as the yellow marked resource uses URL encoding and here %7B = { and %7D = }

./device/Vendor/MSFT/EnterpriseDesktopAppManagement/MSI/{25212568-E605-43D5-9AA2-7AE8DB2C3D09}

If the device encounters any error during installation of the agent, we can troubleshoot this with the eventlog:

Start event viewer > Applications and Services Logs > Microsoft > Windows > DeviceManagement-Enterprise-Diagnostics-Provider > Admin

An example where the agent installation went wrong with an error event id 1924 looks like this:

Event ID 1924, Error

EnterpriseDesktopAppManagement CSP: An application install has failed. 
Examine the MSI log (C:\Windows\system32\config\systemprofile\AppData\
Local\mdm\{25212568-E605-43D5-9AA2-7AE8DB2C3D09}.log) for more details. 
Install command: ("C:\Windows\system32\msiexec.exe" /quiet /l*v 
C:\Windows\system32\config\systemprofile\AppData\Local\mdm\
{25212568-E605-43D5-9AA2-7AE8DB2C3D09}.log /qn /i "C:\Windows\system32\
config\systemprofile\AppData\Local\mdm\
{BD19E4D8-D6C9-48B2-A53C-579D03B29FE9}.msi" ), 
MSI ProductCode: {25212568-E605-43D5-9AA2-7AE8DB2C3D09}, 
User SID: (S-0-0-00-0000000000-0000000000-000000000-000), 
Result: (User cancelled installation.).

Here we can see the original MSI install command including logfile path for further analysis:

C:\Windows\system32\config\systemprofile\AppData\Local\mdm\ {25212568-E605-43D5-9AA2-7AE8DB2C3D09}.log

The agent will get installed in the 32-bit Program Files path:

C:\Program Files (x86)\Microsoft Intune Managment Extension

IntuneManagementExtension

 

How does the agent gets it’s policy?

The agent will start to figure out the service endpoint via Service Discovery. A common approach in Microservices architecture in modern cloud platforms. After getting the Intune Service URL (https://somemssubdomain.manage.microsoft.com/SideCar/StatelessSideCarGatewayService) the agent can start to communicate and will receive its assigned policies.

All this can be traced in the logfiles here:

C:\ProgramData\Microsoft\IntuneManagementExtension\Logs

IntuneManagementExtensionLogs

The agent will start to download and execute the assigned PowerShell script here:

C:\Program Files (x86)\Microsoft Intune Managment Extension\Policies\Scripts\UserGUID_ScriptGUID.ps1

and the results are written here:

C:\Program Files (x86)\Microsoft Intune Managment Extension\Policies\Results\UserGUID_ScriptGUID.output|.error|.timeout

After successful execution the script and results are cleaned up and nothing is left on the device. Corresponding registry entries for the assigned scripts and execution results are here:

HKLM\SOFTWARE\Microsoft\IntuneManagementExtension\Policies\UserGUID\ScriptGUID

IntuneManagementExtensionRegistry

 

How often does the agent check for new policies?

The default is every 60 minutes.

 

What are the PowerShell script execution options?

We can execute scripts in system context or user context. Optional we can enforce a signature check.

ScriptSettings

The current file size limit is 10KB for ASCII scripts and 5KB for unicode scripts. The current file size limit is max. 200KB.

 

How do I enforce next agent check for policies?

Simply restart the Windows Service “Microsoft Intune Management Extension”.

IntuneManagementExtensionWindowsService

 

Is there a particular order in which multiple scripts are executed?

No, they are executed in random order.

 

What can be done with the PowerShell script execution?

Some examples and potentially pitfalls with the usage of the Intune Management Extension are listed below:

Install Win32 application

Install Win32 applications can be done easily by using a web request to get sources for the installation and finally execution of the sources. This technique is used a lot in the Chocolatey space. A simple example with 7-zip is shown below and can be modified to your needs:

# Author: Oliver Kieselbach
# Date: 11/28/2017
# Description: Download executable or msi and execute to install.

# The script is provided "AS IS" with no warranties.
$url = "http://www.7-zip.org/a/7z1701-x64.msi"
$filePath = "c:\windows\temp\7z1701-x64.msi"
$ProgressPreference = 0
Invoke-WebRequest $url -OutFile $filePath -UseBasicParsing
& $filePath /quiet

To use Chocolatey you should follow the install instructions from the Chocolatey website:

iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))

After Chocolatey Framework installation you can use choco.exe install Package in additional PS scripts to install Chocolatey software. An excellent post from Peter van der Woude regarding Chocolatey and Intune Management Extension can be found here: Combining the powers of the Intune Management Extension and Chocolatey

 

Write registry keys in x64 hive and not WOW6432Node

As the agent is an 32-bit agent every PowerShell script execution will be in the 32-bit agent process. If we write a registry key on a x64 device from a 32-bit process it will be redirected to the WOW6432Node in the registry. This is often not the desired behavior. To solve this we can restart the script as a 64-bit process for script execution. An example to write a registry key to the x64 hive with this technique is shown below:

# Author: Oliver Kieselbach
# Date: 11/28/2017
# Description: Write to registry and ensure execution from x64 process environment.

# The script is provided "AS IS" with no warranties.

Param([switch]$Is64Bit = $false)

Function Restart-As64BitProcess
{
 If ([System.Environment]::Is64BitProcess) { return }
 $Invocation = $($MyInvocation.PSCommandPath)
 if ($Invocation -eq $null) { return }
 $sysNativePath = $psHome.ToLower().Replace("syswow64", "sysnative")
 Start-Process "$sysNativePath\powershell.exe" -ArgumentList "-ex bypass -file `"$Invocation`" -Is64Bit" -WindowStyle Hidden -Wait
}

Function New-RegistryKey
{
 Param([Parameter(Mandatory = $true)]
 [string]$Key,
 [Parameter(Mandatory = $true)]
 [string]$Name,
 [Parameter(Mandatory = $true)]
 [string]$Value,
 [ValidateSet("String", "ExpandString", "Binary", "DWord", "Multistring", "QWord", ignorecase=$true)]
 [string]$Type = "String")
 try
 {
 $subkeys = $Key.split("\")

foreach ($subkey in $subkeys)
 {
 $currentkey += ($subkey + '\')
 if (!(Test-Path $currentkey))
 {
 New-Item -Type String -Path $currentkey | Out-Null
 }
 }

Set-ItemProperty -Path $currentkey -Name $Name -Value $Value -Type $Type -ErrorAction SilentlyContinue
 }
 catch [system.exception]
 {
 $message = "{0} threw an exception: `n{0}" -f $MyInvocation.MyCommand, $_.Exception.ToString()
 Write-Host $message
 }
}

if (!$Is64Bit) { Restart-As64BitProcess }
else
{
 # Enable Potentially Unwanted Application protection
 New-RegistryKey -Key "hklm:\SOFTWARE\Microsoft\Windows Defender" -Name "PUAProtection" -Value "1" -Type DWord
}

Please see my GitHub account for Intune Management Extension Samples for a enhanced and maintained PowerShell Template (IntunePSTemplate.ps1) which takes care of x64 restarting, logging and so on!

 

Execute in user context and show dialog

To show a simple example to execute scripts in user context we can use the following script to present a Message Box to the user:

 Add-Type -AssemblyName PresentationFramework
 [System.Windows.MessageBox]::Show('Hello World from Sid-Car!')

HelloSideCar

 

I hope this explains the technical implementation of the Microsoft Intune Management Extension and the extension addresses some road blockers you might have in the past with Intune regarding advanced configurations.

See also my follow up post Part 2, Deep dive Microsoft Intune Management Extension – PowerShell Scripts for even more details and common questions around architecture and troubleshooting.

Gather Windows 10 Autopilot info in Azure Blob Storage during wipe and reload

UPDATE 22/07/2018: New blog post Automation of gathering and importing Windows Autopilot information

The Modern Management strategy is based on Enterprise Mobility + Security and additional services like Office 365. Microsoft created a new SKU called Microsoft 365 for this. To complete the big picture we need some additional services:

The idea is clear, manage the Windows 10 devices like mobile phones. No more Operating System Deployment (OSD) just provisioning and management from everywhere. Everything is powered by the cloud.

A new member in this story is a feature called Windows Autopilot. You can compare this with the Device Enrollment Program as you might know from Apple. It provides a managed way of provisioning with near zero touch. IT is able to control the experience the end user will have during enrollment process. To make all this work we need to gather some properties of the device to identify it clearly. The Autopilot needs the Device Serial Number, Windows Product ID and the Hardware Hash. This information is uploaded to the Autopilot service and then the device will be recognized during OOBE as an Autopilot device, and will show a customized enrollment experience.

The Problem

Many organizations are still using Windows 7 and are on it’s way to Windows 10.  Windows 10 is the new “baseline” in this story. It’s aligned with the complete modern management story. It provides the capability to join Azure AD and the usage of a Windows as a Service model.

How do we get to the new baseline?

If we purchase a new device, the OEM vendor takes care of installing Windows 10 with a signature edition and all necessary drivers. In future the hardware information will be synced into our tenant from the OEM vendor. We will get the device information in Intune and we can start to assign an Autopilot Deployment Profile and start to enroll the device.

DeviceEnrollment

What if we have a bunch of Windows 7 devices in the environment?

A way to handle this is that we are playing the role of the OEM vendor and do the install of a Windows 10 signature edition on the existing Windows 7 devices. Depending what is available we can use ConfigMgr or MDT. In the context of modern management I like to keep on-premises software as low as possible. I use MDT for that simple task now. If ConfigMgr is available we can build the following the same way.

I use MDT to create a Deployment USB media (removable drive) for that and build up a Standard Task Sequence to deploy Windows 10 for this. We take care of the right drivers and in the end we let the device start the OOBE again (sysprep.exe /oobe /reboot|shutdown). Now we have the same situation like a newly delivered device by the OEM vendor. But we can’t deliver the hardware information directly into our tenant like the OEM vendor will do in the future. Good to know that we can get the hardware information with the PowerShell Script Get-WindowsAutoPilotInfo and upload the information provided via a .csv file our self.

Now imagine a situation where a rollout team is preparing a lot of machines. We would end up in a lot of .csv files on different USB removable drives. To make this a little easier for IT to import the hardware information of new devices to Autopilot, we build up the following logic:

 

First of all we prepare the Blob Storage for easy csv file storage.

Login to Azure portal and click on “Storage accounts

StorageAccount

Click Add

StorageAccountAdd

fill out name, Account kind: Blob storage

StorageAccountCreation

after creation you should see the storage account

StorageAccountOverview

create a container called hashes

StorageAccountContainer

create a shared access signature for Blob | Write | an extended expiry date/time | HTTPS only and create a SAS token. Shared Access Signature is used to limit the permission and the limit the period of time to access the account. See Delegating Access with a Shared Access Signature

StorageAccountSAS

Copy the SAS token as we need it in the following script.

Download PowerShell Script Get-WindowsAutoPilotInfo and AzCopy. Install AzCopy and get the files from here: C:\Program Files (x86)\Microsoft SDKs\Azure\AzCopy

Copy AzCopy files and Get-WindowsAutoPilotInfo.ps1 into MDT share e.g. C:\DeploymentShare\Scripts\CUSTOM\HardwareInfo

Create PowerShell script: Get-HardwareInformation.ps1 and copy to the MDT folder HardwareInfo as well. Replace the SAS token (ending with XXXX) in the script example with the newly created one. Replace ZZZZ with your Storage account name.

The script will look for the Get-WindowsAutoPilotInfo.ps1 script, executes it and creates a computername.csv file in C:\Windows\Temp. From here it will be copied to the blob storage account and copied to the USB removable drive folder autopilot-script-success or autopilot-script-failed. This provides the chance in case of failure (missing internet access during deployment) that the computername.csv can be gathered from the USB drive as well.

hardwareinfocsv


# Author: Oliver Kieselbach
# Date: 11/15/2017
# Description: Generate AutoPilot .csv file and upload to Azure Blob Storage.

# The script is provided "AS IS" with no warranties.

# Downlaod URL for AzCopy:
# http://aka.ms/downloadazcopy

# Downlaod URL for Get-WindowsAutoPilotInfo:
# https://www.powershellgallery.com/packages/Get-WindowsAutoPilotInfo

Function Execute-Command
{
 Param([Parameter (Mandatory=$true)]
 [string]$Command,
 [Parameter (Mandatory=$false)]
 [string]$Arguments)

$pinfo = New-Object System.Diagnostics.ProcessStartInfo
 $pinfo.FileName = $Command
 $pinfo.RedirectStandardError = $true
 $pinfo.RedirectStandardOutput = $true
 $pinfo.CreateNoWindow = $true
 $pinfo.UseShellExecute = $false
 $pinfo.Arguments = $Arguments
 $p = New-Object System.Diagnostics.Process
 $p.StartInfo = $pinfo
 $p.Start() | Out-Null
 $p.WaitForExit()
 [pscustomobject]@{
 stdout = $p.StandardOutput.ReadToEnd()
 stderr = $p.StandardError.ReadToEnd()
 ExitCode = $p.ExitCode
 }
}

$scriptPath = [System.IO.Path]::GetDirectoryName($MyInvocation.MyCommand.Path)
$fileName = "$env:computername.csv"
$outputPath = Join-Path $env:windir "temp"
$outputFile = Join-Path $outputPath $fileName
$autoPilotScript = Join-Path $scriptPath "Get-WindowsAutoPilotInfo.ps1"

Execute-Command -Command "$psHome\powershell.exe" -Arguments "-ex bypass -file `"$autoPilotScript`" -ComputerName $env:computername -OutputFile `"$outputFile`"" | Out-Null

$url = "https://ZZZZ.blob.core.windows.net/hashes"
$sasToken = "?sv=2017-04-17&ss=b&srt=o&sp=w&se=2019-10-16T19:47:51Z&st=2017-10-15T11:47:51Z&spr=https&sig=XXXX"
$result = Execute-Command -Command "`"$scriptPath\azcopy.exe`"" -Arguments "/Source:`"$outputPath`" /Dest:$url /Pattern:$fileName /Y /Z:`"$outputPath`" /DestSAS:`"$sasToken`""

if ($result.stdout.Contains("Transfer successfully:  1"))
{
 if (-not (Test-Path $(Join-Path $scriptPath "autopilot-script-success")))
 {
 New-Item -Path $(Join-Path $scriptPath "autopilot-script-success") -ItemType Directory | Out-Null
 }
 Copy-Item -Path $outputFile -Destination $(Join-Path $scriptPath "autopilot-script-success") -Force -ErrorAction SilentlyContinue | Out-Null
}
else
{
 if (-not (Test-Path $(Join-Path $scriptPath "autopilot-script-failed")))
 {
 New-Item -Path $(Join-Path $scriptPath "autopilot-script-failed") -ItemType Directory | Out-Null
 }
 Copy-Item -Path $outputFile -Destination $(Join-Path $scriptPath "autopilot-script-failed") -Force -ErrorAction SilentlyContinue | Out-Null
}

UPDATE 22/07/2018: I have an enhanced version of the gather script now which can be found on my GitHub account. The enhanced version does not have the dependency on AzCopy.exe (incl. dependency files) and Get-WindowsAutoPilotInfo.ps1 in the script directory. If they are not available, they are downloaded from an additional Blob Storage container named resources. The additional container resources must be created and the AzCopy.zip and Get-WindowsAutoPilotInfo.ps1 must be uploaded there to successfully run the script. The scrip is part of a complete automation solution – Automation of gathering and importing Windows Autopilot information

Create another PowerShell script: Download-HardwareInformation.ps1
This can be used later on to download all the .csv files from Azure Blob Storage and create the combined .csv for easy upload to Autopilot. Leave this script on your admin workstation. Replace the StorageAccountKey XXXX with one of your storage account access keys! Replace ZZZZ with your Storage account name.

StorageAccountAccessKey


# Author: Oliver Kieselbach
# Date: 11/15/2017
# Description: Gather AutoPilot .csv file from Azure Blob Storage, delete them and combine into single .csv file.

# The script is provided "AS IS" with no warranties.

#Install-Module AzureRM

$ctx = New-AzureStorageContext -StorageAccountName ZZZZ -StorageAccountKey XXXX
$path = "C:\temp"
$combinedOutput = "C:\temp\combined.csv"

$count = $(Get-AzureStorageContainer -Container hashes -Context $ctx | Get-AzureStorageBlob |measure).Count
if ($count -gt 0)
{
 Get-AzureStorageContainer -Container hashes -Context $ctx | Get-AzureStorageBlob | Get-AzureStorageBlobContent -Force -Destination $path
 $downloadCount = $(Get-ChildItem -Path $path -Filter *.csv | measure).Count
 if ($downloadCount -eq $count)
 {
 Get-AzureStorageContainer -Container hashes -Context $ctx | Get-AzureStorageBlob | Remove-AzureStorageBlob
 }
 # parse all .csv files and combine to single one for easy upload!
 Set-Content -Path $combinedOutput -Value "Device Serial Number,Windows Product ID,Hardware Hash" -Encoding Unicode
 Get-ChildItem -Path $path -Filter "*.csv" | % { Get-Content $_.FullName | Select -Index 1 } | Add-Content -Path $combinedOutput -Encoding Unicode
}

I assume the MDT share is build and a Standard Task Sequence for a vanilla Windows 10 installation is available. Then we add a task sequence step “Run PowerShell Script” to the folder “Custom Tasks“:

RunPowerShellScriptStep

and configure the Get-HardwareInformation.ps1 script:

GetHardwareInformation

Now you are ready to run a MDT deployment of a Windows 10 with an automatic upload of the hardware information to the Azure Blob Storage.

After deployment of the devices you can use the Download-HardwareInformation.ps1 Script to get the combined.csv file and upload it to Microsoft Store for Business (MSfB) or Intune Portal. The upload is currently available in this portal only.

MSfBAutoPilotUpload

I recommend to use the MSfB to upload the combined.csv only! Management of the devices and profiles should be done in Intune. Currently the portals do not completely share their information. For example a profile created in MSfB will not be shown in Intune and vice versa. With Modern Management where Intune is used I suggest to use MSfB to upload devices and Intune for management of profiles (creation and assignment).

In the meantime you have the full functionality in Intune, see more here: Autopilot profile assignment using Intune

 

Happy Autopiloting!

There is another great article from Per Larsen (MVP):
How to collect hardware hash to use in AutoPilot as part of MDT OSD

Deep dive ADMX ingestion to configure SilentAccountConfig with OneDrive

Since Windows 10 1703 you can use a feature called ADMX ingestion to extend policy settings in Intune. What it basically does is to parse an ADMX file and build a MDM policy of it. In the end you can configure the ADMX settings via OMA-URIs in Intune.

More details about ADMX ingestion can be read here Win32 and Desktop Bridge app policy configuration.

During the last time I’m working a lot in the field of Modern IT and Modern Workplace. In the Modern Workplace scenario I like to have Windows 10 clients joined to Azure Active Directory and auto enrolled into Intune (preferred as an AutoPilot enrollment). The nice thing here is, the device gets configured right after the Azure Active Directory join. In this scenario we typically configure necessary system settings. In addition to that I want to drive the user experience and I want to present the files in OneDrive without further sign-in by the user. Normally the user needs to sign-in with his email address to accomplish this.

OneDrivePrompt

To solve this we need to configure OneDrive to silently setup the user account information from the Windows signed-in user. According the article Use Group Policy to control OneDrive sync client settings we can use the following two registry keys for that:

HKCU\SOFTWARE\Microsoft\OneDrive\EnableADAL=1 (dword)
HKLM\SOFTWARE\Policies\Microsoft\OneDrive\SilentAccountConfig=1 (dword)

As we do not have a native Configuration service provider for OneDrive right now we need to configure these settings via ADMX ingestion policy. We can get the OneDrive ADMX from here:

%LocalAppData%\Microsoft\OneDrive\-build-version-\adm\OneDrive.admx

We need the original OnDrive.admx file as a template and we copy the complete policyDefinitions node to a new file. Then we remove every policy node except the policy node with SilentAccountConfig. As we have no node for EnableADAL in the ADMX file we duplicate policy node SilentAccountConfig as additional node under the policies node. In this new node we rename the attribute values “name” and “valueName” to EnableADAL. As last step we replace SOFTWARE\Policies\Microsoft\OneDrive with SOFTWARE\Microsoft\OneDrive.

The result is the following xml file:

<policyDefinitions xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" revision="1.0" schemaVersion="1.0" xmlns="http://schemas.microsoft.com/GroupPolicy/2006/07/PolicyDefinitions">
 <policyNamespaces>
 <target prefix="OneDriveNGSC" namespace="Microsoft.Policies.OneDriveNGSC" />
 <using prefix="windows" namespace="Microsoft.Policies.Windows" />
 </policyNamespaces>
 <resources minRequiredRevision="1.0" />
 <categories>
 <category name="OneDriveNGSC" displayName="$(string.OneDriveNGSCSettingCategory)">
 <parentCategory ref="windows:Software" />
 </category>
 </categories>
 <policies>
 <policy name="EnableADAL" class="User" displayName="$(string.EnableADAL)" explainText="$(string.EnableADAL_Help)" key="SOFTWARE\Microsoft\OneDrive" valueName="EnableADAL">
 <parentCategory ref="OneDriveNGSC" />
 <supportedOn ref="windows:SUPPORTED_Windows7" />
 <enabledValue>
 <decimal value="1" />
 </enabledValue>
 <disabledValue>
 <decimal value="0" />
 </disabledValue>
 </policy>
 <policy name="SilentAccountConfig" class="Machine" displayName="$(string.SilentAccountConfig)" explainText="$(string.SilentAccountConfig_help)" key="SOFTWARE\Microsoft\OneDrive" valueName="SilentAccountConfig">
 <parentCategory ref="OneDriveNGSC" />
 <supportedOn ref="windows:SUPPORTED_Windows7" />
 <enabledValue>
 <decimal value="1" />
 </enabledValue>
 <disabledValue>
 <decimal value="0" />
 </disabledValue>
 </policy>
 </policies>
</policyDefinitions>

Why the replacement of \Policies\ in the registry path?

Excerpt from Win32 and Desktop Bridge app policy configuration

Currently, the ingested policies are not allowed to write to locations within the System, Software\Microsoft, and Software\Policies\Microsoft keys, except for the following locations:

  • software\microsoft\onedrive

Because of this exception we can use SOFTWARE\Microsoft\OneDrive to configure the both keys. EnableADAL is listed under the registry key without \Policies\ but SilentAccountConfig is listed under \Policies\ path.

The path \Policies\ is based on the group policy technique where the sub key is used to overlap the default settings of an application. For example: SOFTWARE\Policies\Microsoft\OneDrive\SilentAccountConfig will overlap an application setting SOFTWARE\Microsoft\OneDrive\SilentAccountConfig. With the xml file above we target the application setting of OneDrive and not the policy setting of OneDrive (keep in mind the default value of OneDrive is overwritten then).

Why not using the whole OneDrive.admx file without \Policies? I’m not sure which of the settings all work without \Policies\ in the path. It depends on the targeted application. With further testing you may find settings working successfully like SilentAccountConfig with OneDrive. For me it was enough for now to have the EnableADAL and SilentAccountConfig settings configured.

In Intune we configure a Device Configuration Profile for Windows 10 as a Custom policy. We need to construct the OMA-URI for ADMX ingestion as described here: Win32 and Desktop Bridge app policy configuration

./Vendor/MSFT/Policy/ConfigOperations/ADMXInstall/{AppName}/{SettingType}/{FileUid or AdmxFileName}

Device Configuration Profile: ADMX Ingestion – CustomOneDrive.admx

DeviceConfigurationProfilesADMX

Name: CustomOneDrive.admx
OMA-URI:
./Vendor/MSFT/Policy/ConfigOperations/ADMXInstall/OneDriveNGSC/Policy/OneDriveAdmx
Data type: string
Value: <xml content from above>

ADMXIngestion

The next step is to configure the ADMX ingested settings:

Again we follow the article Win32 and Desktop Bridge app policy configuration. Excerpt how to configure user or device policy:

In the policy class, the attribute is defined as “User” and the URI is prefixed with ./user. If the attribute value is “Machine”, the URI is prefixed with ./device. If the attribute value is “Both”, the policy can be configured either as a user or a device policy. 

The policy {AreaName} format is {AppName}~{SettingType}~{CategoryPathFromAdmx}. {AppName} and {SettingType} are derived from the URI that is used to import the ADMX file. In this example, the URI is: ./Vendor/MSFT/Policy/ConfigOperations/ADMXInstall/ContosoCompanyApp/Policy/AppAdmxFile01.

{CategoryPathFromAdmx} is derived by traversing the parentCategory parameter. In this example, {CategoryPathFromAdmx} is ParentCategoryArea~Category2~Category3. Therefore, {AreaName} is ContosoCompanyApp~ Policy~ ParentCategoryArea~Category2~Category3. 

Therefore, from the example: 

  • Class: User
  • Policy name: L_PolicyPreventRun_1
  • Policy area name: ContosoCompanyApp~Policy~ParentCategoryArea~Category2~Category3
  • URI: ./user/Vendor/MSFT/Policy/Config/ContosoCompanyApp~Policy~ParentCategoryArea~Category2~Category3/L_PolicyPreventRun_1

In Intune we configure a Device Configuration Profile for Windows 10 as a Custom policy with two custom settings. Important we need to specify EnableADAL as ./User to map it to HKCU and SilentAccountConfig as ./Device to map it to HKLM.

Device Configuration Profile: ADMX Config – CustomOneDrive.admx

DeviceConfigurationProfilesADMX

OMA URI Settings:

Name: EnableADAL
OMA-URI: ./User/Vendor/MSFT/Policy/Config/OneDriveNGSC~Policy~OneDriveNGSC/EnableADAL
Data type: string
Value: <enabled/>

EnableADAL

Name: SilentAccountConfig
OMA-URI:
./Device/Vendor/MSFT/Policy/Config/OneDriveNGSC~Policy~OneDriveNGSC/SilentAccountConfig
Data type: string
Value: <enabled/>

SilentAccountConfig

In the end we assign the device configuration profile to a user group and if applied successfully we will see OneDrive singed-in shortly after the Desktop appears:

OneDriveTaskbar

If you look into Start > Settings > Accounts > Access work or school > your Tenant > Info your should see Policy listed as: OneDriveNGSC~Policy~OneDriveNGSC as defined above.

CustomOneDriveConfigSettingsMenu

Special thanks to Mark for inspiring me to write about that topic my very first blogpost here.

Peter van der Woude has a good article about ADMX ingestion to configure Google Chrome site isolation.

UPDATE May 25th: Senthil’s Blog has a great article about it, I can truly recommend to read: Intune: Deploying ADMX-Backed policies using Microsoft Intune.