Disclaimer: I recommend utilizing pure-AAD join in 99% of use Autopilot use cases. Hybrid join is excellent for getting existing domain-joined devices into Intune, with future replacement with an AADJ-only device. That being said, there are still use cases where hybrid Autopilot is desired. This post delves into me learning how it works so I better understand it and can speak knowledgeably about it with others.
Hello all, and Happy Holidays! I’m back with one more post for the year, to talk a bit about my recent experience with getting Autopilot & hybrid join to function, specifically regarding the Offline Domain Join (ODJ) connector. When I started down this path in my lab, I will admit that I found the docs to be a little lacking (Deploy hybrid Azure AD-joined devices by using Intune and Windows Autopilot). Specifically, the steps regarding installing and configuring the ODJ connector. Two specific questions came to my mind:
- Can this be installed and configured on Server Core?
- What permissions does the service account require?
Server Core?
Short answer to question one: no, it cannot.
Long answer to question one: since it isn’t documented, I decided to try it. After spinning up a Server 2022 Core server, I downloaded the latest ODJConnectorBootstrapper.exe via the MEM Admin Center and attempted to install it. Issue number one:
Interesting, Server 2022 is definitely later than 2016. In looking at the installation log, I found these two lines:
1 2 3 |
MSI (s) (FC:FC) [08:18:07:525]: PROPERTY CHANGE: Adding WINDOWSINSTALLATIONTYPE property. Its value is 'Server Core'. MSI (s) (FC:FC) [08:22:11:187]: Product: Intune Connector for Active Directory -- Windows Server 2016 or later is required for this setup to complete. |
OK, so it’s most likely looking at the value of InstallationType in the registry. For my own personal amusement, as this is now entering unsupported territory, I modified this registry value and tried again.
1 |
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\' -Name InstallationType -Value Server -Force |
And we have success!
1 2 |
MSI (s) (FC:6C) [08:26:50:290]: Windows Installer installed the product. Product Name: Intune Connector for Active Directory. Product Version: 6.1810.101.7. Product Language: 1033. Manufacturer: Microsoft Corporation. Installation success or error status: 0. |
Except, when you launch the configuration tool, and click “Sign In”, the application crashed. Womp womp.
Alright, so this was mostly expected. As I mentioned earlier, diving this deep entered unsupported territory, but I “needed” to know.
Permissions?
Next, I wanted to know what permissions I could get away with when running multiple connectors. The documentation only states that all connectors must run via a service account that has the necessary permissions within Active Directory, but it makes no mention of the permissions required on the server itself. By default, the ODJConnectorSvc service will be configured to run as SYSTEM after installation. In my mind, this is not ideal. I’d prefer the service to run with as few permissions as possible.
The first step I took was to prepare a group Managed Service Account for the service to run as:
1 2 3 4 5 6 7 8 |
# Create a gMSA New-ADServiceAccount -Name svc_ODJ_Con -PrincipalsAllowedToRetrieveManagedPassword (Get-ADGroup -Identity ODJ_Connectors) -DNSHostName odjcon.corp.ajf8729.com -KerberosEncryptionType AES128,AES128 -Path 'OU=ODJCON,OU=T0,DC=corp,DC=ajf8729,DC=com' -Verbose # Install it on each server Install-WindowsFeature -Name RSAT-AD-PowerShell Install-ADServiceAccount -Identity svc_ODJ_Con Test-ADServiceAccount -Identity svc_ODJ_Con Restart-Computer |
This gMSA will also need to be granted permissions within Active Directory to create computer objects; in my lab, I added it to an existing group that granted the necessary permissions to a specific OU for hybrid Autopilot devices to be created.
Next up is to configure a GPO to grant the above gMSA the “Log on as a service” right and link it to the OU containing the servers:
Finally, install the connector, configure it, then change it to run as the previously configured gMSA (be sure to disable IE ESC for Administrators so you are able to sign in):
1 2 |
Start-Process -FilePath 'sc.exe' -ArgumentList 'config', 'ODJConnectorSvc', 'obj=', 'CORP\svc_ODJ_Con$' Restart-Service -Name ODJConnectorSvc |
Now, let’s take a look at the connector status in MEM Admin Center:
While this initially looks good, eventually, they will all go into an Error state. If we poke at the event logs, we’ll find the following:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
# ODJ Connector Service Log { "Metric":{ "Dimensions":{ "InstanceId":"F980D4AC-357B-45A2-8BEE-82C43C0801E2", "DiagnosticCode":"0x0FFFFFFF", "DiagnosticText":"We are unable to complete your request because a server-side error occurred. Please try again. [Exception Message: \"DiagnosticException: 0x0FFFFFFF. We are unable to complete your request because a server-side error occurred. Please try again.\"] [Exception Message: \"Failed to get a value for Key: OdjServiceBaseUrl\"] [Exception Message: \"The given key was not present in the dictionary.\"]" }, "Name":"RequestHandlingPipeline_DownloadFailure", "Value":0 } } # Security Log Cryptographic operation. Subject: Security ID: CORP\svc_ODJ_Con$ Account Name: svc_ODJ_Con$ Account Domain: CORP Logon ID: 0x22AD56 Cryptographic Parameters: Provider Name: Microsoft Software Key Storage Provider Algorithm Name: UNKNOWN Key Name: b686a2307d6f00e79a260b740fd27691_1a3cdda4-ea72-467c-8f01-8b4b796110a2 Key Type: Machine key. Cryptographic Operation: Operation: Open Key. Return Code: 0x80090016 |
If we switch the connector server back to running as SYSTEM, these errors will go away, and the status will return green. The problem is that when enrolling the connector, it enrolls a certificate that the service uses to authenticate to Intune, and the gMSA does not have permissions to this certificate’s private key. In order to fix this, we need to modify these permissions via certlm.msc by managing the private key:
Once the gMSA is granted read permissions to this certificate’s private key, and the connector service restarted, the connector status should return to green.
In order to update this on multiple connectors, I put together a short PowerShell script to configure the private key permissions and the service runas account, which can be found in my GitHub (https://github.com/ajf8729/Toolbox/blob/main/Active%20Directory/Set-ODJConnectorPermissions.ps1)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
[CmdletBinding()] Param( [Parameter(Mandatory = $True)] [string]$ServiceAccount ) $FileSystemAccessRule = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule($ServiceAccount, 'Read', 'Allow') $Certificate = Get-ChildItem 'Cert:\LocalMachine\My\' | Where-Object {$_.Issuer -eq 'CN=Microsoft Intune ODJ Connector CA'} $PrivateKey = [System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($Certificate) $PrivateKeyFilename = $PrivateKey.key.UniqueName $PrivateKeyPath = "$env:ProgramData\Microsoft\Crypto\RSA\MachineKeys\$PrivateKeyFilename" $PrivateKeyPermissions = Get-Acl -Path $PrivateKeyPath $PrivateKeyPermissions.AddAccessRule($FileSystemAccessRule) Set-Acl -Path $PrivateKeyPath -AclObject $PrivateKeyPermissions Stop-Service -Name ODJConnectorSvc Start-Process -FilePath 'sc.exe' -ArgumentList 'config', 'ODJConnectorSvc', 'obj=', $ServiceAccount -NoNewWindow Start-Service -Name ODJConnectorSvc |
The above script accepts a parameter to specify the service account (in the form “DOMAIN\gMSA_name$”), configure the private key permissions, configure the connector service to run as the gMSA, and finally restart the service.
Hooray, we now have our ODJ connectors successfully running as a gMSA and without administrator rights!
Finally, in testing Hybrid Autopilot now…
Happy Holidays Everyone!
This is wonderful. Thanks so much for your detailed write up. I, too, didn’t like the idea of using SYSTEM for permissions on this function and gMSAs are definitely the way to go.
Thanks! I agree, service accounts always seem better, just be forewarned that this might not be a 100% supported configuration 😇