Showing posts with label HAADJ. Show all posts
Showing posts with label HAADJ. Show all posts

Saturday, 24 June 2023

What do you mean, no GPOs?

I hear this question a lot from customers, usually when I tell them that I don't recommend implementing a hybrid Azure AD join solution with Autopilot. It can be a challenge explaining that they don't actually need an Active Directory domain to manage their endpoint devices and that we can usually match the GPO functionality using cloud management only with Intune. It's not always easy and you have to be creative 😀😀😀. We accomplished that in our most recent Autopilot project.

First and foremost, I try not to fall into the trap of analyzing 20 years of GPOs and attempting to re-create them all verbatim in Intune. Rather I agree the requirements with the customer in advance. I've just successfully delivered one of these projects and I wanted to highlight the more difficult areas. I won't get into the specific details of the configurations, rather I will explain the high level approach in each case. Some things worked well, others didn't, so I had to change my approach as I progressed.

Certificates

It's very easy to deploy user certificates on endpoint devices via autoenrollment GPO and the Certificate Authority. It's not as straightforward to do this via Intune, but it's not too bad either.

We used the following approach to deploy PKCS certificates:

  • Exported the root certificate and created a Trusted Certificate configuration profile, assigned to the Autopilot devices.
  • Added and configured the Intune connector to an on-premises server.
  • Configured a certificate template on the Certificate Authority.
  • Created a PKCS certificate profile. This is where it got interesting. The user certificate had to be of a very specific format to be authenticated by Cisco ISE policies, to allow network access. We achieved this by configuring the Subject name format as follows: CN={{OnPrem_Distinguished_Name}},E={{EmailAddress}}

Thanks to my colleague Mark Doyle for working on this piece.

802.1x

Now that the certificates were deployed to the devices, we turned our hand to the 802.1x configuration required for network authentication by Cisco ISE.

I configured a workstation manually with the settings I needed.


On the properties of the network card I enabled 802.1x authentication. This started the Wired AutoConfig service and set it to automatic.  


I chose Smart card or other certificate as the authentication method and selected the Trusted Root certificates. There were a few other settings to configure also.

At a command prompt, I executed the following:

netsh lan show profiles

This told me the interface name. Then I exported the configuration to a profile:

netsh lan export profile folder=PATH_TO_FOLDER interface="INTERFACE_NAME"

This created an XML file in the specified folder, named by the interface name. Then I created a custom configuration profile using the OMA-URI setting and the String (XML file) data type.
 
./Device/Vendor/MSFT/WiredNetwork/LanXML

Two important lines from the XML file were as follows:

<OneXEnforced>false</OneXEnforced>
<OneXEnabled>true</OneXEnabled>

I wanted 802.1x to be enabled and used when it was needed. If it was enforced then users would not be able to work at home.

The approach for the Wi-Fi network was similar but in this case the OMA-URI setting was different:

./Vendor/MSFT/WiFi/Profile/WS-CORP/WlanXml

I assigned the profiles to the Autopilot devices.

Printing

I struggled a bit with printing. As a result of Print Nightmare, non-administrators are no longer able to do the following using Point and Print without an elevation of privilege to administrator:

  • Install new printers using drivers on a remote computer or server
  • Update existing printer drivers using drivers from remote computer or server

You can read more about this in KB5005652. Now when you manually browse to a printer and try to add the print queue, you are prompted for elevated privileges to install the printer driver. This plays havoc when you are trying to automate the solution with Intune.

You could just disable Point and Print restrictions. However this is very insecure and not recommended. There is a compromise. You should be able to remove the drivers installation restrictions based on printer class GUIDs. 

You need this policy which you can create with an Intune configuration profile (Administrative template):

Computer Configuration > Policies > Administrative Templates > System > Driver Installation > Allow non-administrators to install drivers for these device setup classes.


Enter the following GUIDs:

  • Class = Printer {4658ee7e-f050-11d1-b6bd-00c04fa372a7}
  • Class = PNPPrinters {4d36e979-e325-11ce-bfc1-08002be10318}

However this still didn't work as expected for me and I was still not able to install the print driers without the prompt for elevation. 


Installing the printer driver manually, I was able to look at the properties of the printer and this exposed a class GUID that I was previously unaware of {1ed2bbf9-11f0-4084-b21f-ad83a8e6dcdc}. I now know that this is for Local Print Queue. I added it to my policy but unfortunately it still didn't work.

Running out of time I changed my approach and decided to pre-install the drivers using a script and Win32 app. Thanks to Rahul Jindal for helping with prndrvr.vbs.

@echo off

mkdir c:\PrinterDrivers\Kyocera

xcopy *.* /h /c /k /e /r /y c:\PrinterDrivers\Kyocera

cscript "C:\Windows\System32\Printing_Admin_Scripts\en-US\prndrvr.vbs" -a -m "Kyocera TASKalfa 6004i KX" -i "C:\PrinterDrivers\Kyocera\OEMSETUP.inf"

The next step was to add the print queues. W32 app to the rescue again. I was aware that many of the users would be provisioning their devices at home using Autopilot. However the device needed line of sight to the printer in order to add the queue. Therefore I didn't want to add it as a Required app. I made the available app via Company Portal and noted in the description that it should only be installed when in the office. 

Add-Printer -ConnectionName \\PrintServer.domain.local\PrinterName

The script added the print queue.

$printerExists = Get-CimInstance -Class Win32_Printer | Where-Object {$_.Name -like "\\PrintServer.domain.local\PrinterName"}

if($printerExists) {

  Write-Host "Success"

  Exit 0

} else {

  Exit 1

}

The Win32 app allowed me to configured the detection script.

Thanks to Rahul for working on this with me.

Mapped drives

Anoop has a good solution to create mapped network drives without requiring network connectivity to the remote path. This is particularly useful in a scenario where users are provisioning devices at home without any connectivity to the on-premises network or with a VPN connection that may not be available immediately after enrolment. The mapped drives switch from “offline” to “online” when connectivity to the remote path is available. It works really well. 

Try it out.

Anoop has created an ADMX template that can be ingested into Intune using a custom configuration profile and this OMA-URI: 

./Device/Vendor/MSFT/Policy/ConfigOperations/ADMXInstall/DriveMapping/Policy/DriveMappingAdmx

Launch the local group policy editor and you will find the settings under User Configuration\Administrative Templates\Network Drive Mappings.


Then use another custom configuration profile to
actually map the drives using this OMA-URI:

./user/Vendor/MSFT/Policy/Config/DriveMapping~Policy~DriveMapping/Drive_K

You can't control the order in which policies apply. Therefore the network drives are not always available directly after Autopilot. This is solved by a reboot. 

Applications

It's generally straightforward to configure applications to be installed during Autopilot. I always use Win32 apps exclusively as mixing app types in Autopilot can lead to failures. This is well documented. However the configuration of apps is not always easy. The customer had a GPO for configuring SafeSend. This is an add-in for Outlook that helps prevent misaddressed email or inadvertent sharing of sensitive information. You can download an ADMX template where you can configure the application and license key and that seems to work very well with devices that are domain-joined.

Fortunately Intune provides a method of importing our own custom ADMX files, which were provided to me by SafeSend. Of course my first attempt at importing the ADMX file failed. 

"The upload of this ADMX file has failed. To continue, you need to delete this upload, address the action in the error details and try again".

Error Details 

"ADMX file referenced not found. NamespaceMissing:Microsoft.Policies.Windows. Please upload it first".

If you upload an ADMX file without the dependency, an error message will list the missing namespace. 

To see any namespace dependencies, open the ADMX file and search for "using prefix". Any dependencies will be listed. This is quite common and it's often because Windows.admx is missing. Download the latest administrative template for Windows 10, extract Windows.admx and import that.


That worked and I was able to import SafeSend.admx.

This allowed me to create a SafeSend configuration profile using Imported Administrative templates.


I could configure and deploy the SafeSend settings. This worked and I could see the applied setting on my Windows 10 and Windows 11 test devices.


However the success was short-lived. The policy started to fail on Windows 10 only.

  • Error code: 0x20101
  • Error details: The administrative template file failed to be sent to the device  

Rudy Ooms has a great post for troubleshooting ADMX imports but I had project deadlines so I decided on another approach and kept it simple.

I noticed that all SafeSend configurations were written to the registry at [HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\SafeSend]. I exported this key to a .reg file and used regedit.xe and Win32 app to import the registry key to the Autopilot devices.

MD C:\Windows\Temp\Safesend

Copy "%~dp0*.reg" C:\Windows\Temp\Safesend /Y

Copy "%~dp0*.txt" C:\Windows\Temp\Safesend /Y

PUSHD C:\Windows\Temp\Safesend

regedit.exe /s Safesend.reg


The reference to .txt was to create a detection method for the Win32 app using a "detection file". I didn't want to use the SafeSend registry key as my detection method as I was told that I'd have to make a change in the near future.


The moral of the story 

"Win32 apps are your friend" and "friends don't let friends do hybrid". 😄😄

 I hope this helps. Until next time.......


Wednesday, 11 August 2021

Troubleshooting Hybrid Azure AD Join issue

I've been working with a customer this week to configure Hybrid Azure AD Join and co-management. In the first phase (HAADJ), most of my test devices successfully registered in Azure AD. However there were some stragglers. These devices didn't even show up as "Pending" in Azure AD. They just didn't appear at all.

It was time for troubleshooting. What is the best way to find out what is wrong? There are many things you can check.

Service Connection Point

As some of the domain joined devices had successfully registered in Azure AD already, it seemed unlikely that there was a problem with the Service Connection Point. However I had a look at it.

Beginning with version 1.1.819.0, Azure AD Connect provides you with a wizard to configure hybrid Azure AD join. Azure AD Connect deploys a Service Connection Point (SCP) into your Active Directory environment. A service connection point in AD is essentially an object that points to a specific service. The Azure AD Service Connection Point includes information on the following items in its keywords attribute:

  • azureADId; The Azure Active Directory tenant ID
  • azureADName; The Azure Active Directory tenant’s verified custom DNS domain name, or the *.onmicrosoft.com DNS domain name if no verified custom DNS domain name exists for the Azure AD tenant

 The Service Connection Point format is as follows:

CN=62a0ff2e-97b9-4513-943f-0d221bd30080,CN=Device Registration Configuration, CN=Services, CN=Configuration,DC=domain,DC=tld

 Follow this procedure to verify the Service Connection Point in Active Directory.

  • Launch ADSI Edit as an Enterprise Administrator.
  • Connect to the Configuration Naming Context of the domain.
  • Browse to CN=Configuration,DC=contoso,DC=com > CN=Services > CN=Device Registration Configuration
  • Verify that the leaf object CN=62a0ff2e-97b9-4513-943f-0d221bd30080 exists (this is the same CN value for every organization)
  • Select Properties
  • Select keywords from the Attribute Editor window and click Edit
  • Verify the value of azureADId
  • Verify the value of azureADName

This was all good for me.

OU Sync

The next step is to check that the device is in an OU which is synchronized to Azure AD. This is a configuration in Azure AD Connect. 


Navigate to the Domain and OU filtering screen and verify that the OU is selected for sync. I didn't find any problem here.

DSREGCMD

The next step was to have a look at one of the devices. You can get a lot of information using the DSREGCMD /STATUS cmdlet


In the Device State section I could see AzureADJoined = No. However the Diagnostics Data section gave me valuable information.

Failed to schedule Diagnostics Task. Error: 0x80041326

DSREGCMD /DEBUG /JOIN is also useful.


Cannot start Task: 0x80041326

Failed to schedule Join Task. Error: 0x80041326

This told me exactly where to find the problem. The issue was with the Workplace Join scheduled task.

Task Scheduler


Sure enough, I launched Task Scheduler and navigated to Microsoft > Windows > Workplace Join. I could see that all the tasks were disabled. In my experience some external configuration was preventing Azure AD registration on the device.

SCCM


ConfigMgr client settings was a good place to start. However automatic Azure AD registration was allowed (Cloud Services).

Group Policy

The next place to look was group policy, it's always a GPO, right?


A Resultant Set of Policy query showed me exactly where the problem was.

Computer Configuration > Administrative Templates > Windows Components > Device Registration > Register domain joined computers as devices was disabled.


What did this setting do? The description showed that this setting allowed devices to be silently registered in Azure AD. Disabling it obviously had the reverse effect and prevented the registration.

Solution

The solution was to remove this GPO setting from the affected devices.

I hope this helps. Until next time.....


Wednesday, 24 March 2021

Implementing hybrid AAD join over a VPN - the userCertificate attribute saga

Do you know what the userCertificate attribute is? If you don't then keep on reading.

This was fun. Once I learned more about how hybrid Azure AD join worked, I understood the behavior and was able to figure out how to make this work.

First, a little bit about the basics of HAADJ. What is a HAADJ device? This is a device that is joined to AD and registered with Azure AD. You can't be joined to both directories at the same time. Also you can't sign into a HAADJ device with Azure AD credentials. 

We know that we need an Azure AD Connect server. 

Version 1.1.819.0 and later of Azure AD Connect includes an option to configure Hybrid AAD Join. But what does that mean? When you choose this option the wizard creates a Service Connection Point in AD. The SCP contains all the information that a workstation needs to perform the HAADJ process.  

This isn't just a notional thing. You can actually see the SCP in AD using ADSIEDIT and connecting to the domain in the Configuration context. This is the SCP. The GUID (62a0ff2e-97b9-4513-943f-0d221bd30080) is what Windows 10 devices search for using an LDAP query, and is the same from organization to organization.

Have a look at the keywords and you will see the details of the specific organization's Azure AD domain and directory ID.

The next thing we do is to synchronize the workstations with AAD. Again we do this using Azure AD Connect. 

Check the box for the OU you need. The AAD Connect synchronization service runs on a schedule and creates computer objects in AAD for your workstations.


That's only the behind-the-scenes prep work though. On the workstation a scheduled task runs (Microsoft>Windows>WorkPlace Join). This task actually implements the Workplace join element. The device must have already synced to AAD for this to be successful.

That's it, that's all you need to do to implement HAADJ for an organization and to be fair, it just works. However there are some complications when most of the devices are remote and connect to the VPN infrequently. Then the process doesn't work and you need to understand the process and behavior a little more in order to make it work.

The first thing to understand is that the scheduled task really only runs when the user logs on to the workstation. That's the first trigger associated with the task.

There is a second trigger for this task. It runs whenever it detects Event ID 4096 in the event logs. In my experience though, this doesn't make any difference, and the task doesn't run again after the logon.


"Automatic device join pre-check tasks completed. The device can NOT be joined because a domain controller could not be located. The device must be connected to a network with connectivity to an Active Directory domain controller".

In the event log we get this continual error. We can see that workplace join fails as the device does not have line of sight to a domain controller. Unfortunately we are not connected to the VPN at that stage. The user may then connect to the VPN but at that stage it's too late, the scheduled task doesn't run again. You can see why this works seamlessly on the LAN, as the workstation is authenticating with a domain controller on log on and not using cached credentials.

OK, what if I run a script to run that scheduled task after the user connects to the VPN? I should be able to figure that out, right.

schtasks /Run /TN “Microsoft\Windows\Workplace Join\Automatic-Device-Join”

This is the command you need to run to kick that off.

However I found that it is not that simple. There are several steps involved to workplace join a device and you have to wait for the various schedules to see that in action. I'll explain the steps and introduce a new concept - the userCertificate attribute.


Azure AD Connect is configured to only synchronize devices that have the userCertificate attribute configured. AAD Connect does its job well and just filters out any devices that don't have this attribute set. You don't get an error or a warning to say that they are missing, which is a real nuisance.

So where does the attribute come from? These are two computers from the same organization, computer A has it and computer B doesn't. Computer A has synchronized with AAD but computer B has not. So how does that happen?

The science bit

Whenever the workplace join scheduled task runs it checks for a direct connection to a domain controller. When it finds one it looks for the Service Connection Point in AD using an LDAP query. The SCP has information on which AAD tenant the device should join. At that point the computer generates a self-signed certificate and the userCertificate attribute is added to the computer properties in AD. All is well at that stage and the computer will workplace join. Well, not really, quite a bit has to happen yet. If we run the workplace join scheduled task again at that point it will fail.

Automatic registration failed at join phase. Exit code: Unknown HResult Error code: 0x801c03f2. Server error: The device object by the given id (876df222-8565-4118-8193-f1d051d12e19) is not found.

It will tell us that the directory object cannot be found. Of course that makes sense. The device did not synchronize with AAD because of the missing userCertificate attribute. Now that we have forced that to happen, we must wait for the AAD Connect sync service to run again and this time the device sync successfully to AAD.

Now we must wait for the workplace join scheduled task to run again and this time, all the elements are in place and the workplace join is successful. This all works seamlessly for computers on the LAN but it does not work very well for VPN connected computers.


I created a task sequence that executes the workplace join scheduled task and I deployed it to VPN connected devices.

The script will execute the scheduled task every 10 mins. Then I encourage users to connect to the VPN and the magic happens.

  • Script executes #1 (needs to have line of sight to DC) - scheduled task runs and finds SCP in AD with LDAP query. The computer generates a self-signed certificate and the userCertificate Attribute is updated in computer properties.
  • AAD Connect sync service runs on a schedule - sync computer object to AAD
  • Script executes #2 (needs to have line of sight to DC) - scheduled task runs and finds SCP in AD with LDAP query. Device is workplace joined.
  • User that signs into the device will get an Azure AD user token that can be used to authenticate with Azure AD-based services

Don't forget to remove the deployment afterwards.

You can search AD to get a list of computers that are missing the userCertificate attribute.

Get-ADComputer -LDAPFilter '(!(userCertificate=*))' | Select Name,DNSHostName | export-csv -path C:\GH\Emptyattrib.csv

This will get you started but will include servers. You can filter them out.


You can also do a custom search on a specific OU using the LDAP query: 

(!(userCertificate=*))

I hope this helps you to understand what is going on with HAADJ. Until next time……..