{"id":485,"date":"2021-12-20T10:07:20","date_gmt":"2021-12-20T15:07:20","guid":{"rendered":"https:\/\/anthonyfontanez.com\/?p=485"},"modified":"2025-02-27T15:06:13","modified_gmt":"2025-02-27T20:06:13","slug":"hybrid-autopilot-and-odj-connector-permissions","status":"publish","type":"post","link":"https:\/\/anthonyfontanez.com\/index.php\/2021\/12\/20\/hybrid-autopilot-and-odj-connector-permissions\/","title":{"rendered":"Hybrid Autopilot &#038; ODJ Connector Permissions"},"content":{"rendered":"\n<p>2025-02-27 Update: This entire post is now irrelevant, see <a href=\"https:\/\/techcommunity.microsoft.com\/blog\/intunecustomersuccess\/microsoft-intune-connector-for-active-directory-security-update\/4386898\">https:\/\/techcommunity.microsoft.com\/blog\/intunecustomersuccess\/microsoft-intune-connector-for-active-directory-security-update\/4386898<\/a> for more information.<\/p>\n\n\n\n<p style=\"font-size:12px\"><em>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.<\/em><\/p>\n\n\n\n<p>Hello all, and Happy Holidays! I&#8217;m back with one more post for the year, to talk a bit about my recent experience with getting Autopilot &amp; 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 (<a rel=\"noreferrer noopener\" href=\"https:\/\/docs.microsoft.com\/mem\/autopilot\/windows-autopilot-hybrid\" data-type=\"URL\" data-id=\"https:\/\/docs.microsoft.com\/mem\/autopilot\/windows-autopilot-hybrid\" target=\"_blank\">Deploy hybrid Azure AD-joined devices by using Intune and Windows Autopilot<\/a>). Specifically, the steps regarding installing and configuring the ODJ connector. Two specific questions came to my mind:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Can this be installed and configured on Server Core?<\/li>\n\n\n\n<li>What permissions does the service account require?<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"server-core\">Server Core?<\/h2>\n\n\n\n<p><\/p>\n\n\n\n<p>Short answer to question one: no, it cannot.<\/p>\n\n\n\n<p>Long answer to question one: since it isn&#8217;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:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"483\" height=\"298\" src=\"https:\/\/anthonyfontanez.com\/wp-content\/uploads\/2021\/12\/image.png\" alt=\"\" class=\"wp-image-487\" srcset=\"https:\/\/anthonyfontanez.com\/wp-content\/uploads\/2021\/12\/image.png 483w, https:\/\/anthonyfontanez.com\/wp-content\/uploads\/2021\/12\/image-300x185.png 300w\" sizes=\"auto, (max-width: 483px) 100vw, 483px\" \/><figcaption class=\"wp-element-caption\">Attempting to install the ODJ connector on Server 2022 Core<\/figcaption><\/figure>\n<\/div>\n\n\n<p>Interesting, Server 2022 is definitely later than 2016. In looking at the installation log, I found these two lines:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>MSI (s) (FC:FC) &#91;08:18:07:525]: PROPERTY CHANGE: Adding WINDOWSINSTALLATIONTYPE property. Its value is 'Server Core'.\nMSI (s) (FC:FC) &#91;08:22:11:187]: Product: Intune Connector for Active Directory -- Windows Server 2016 or later is required for this setup to complete.\n<\/code><\/pre>\n\n\n\n<p>OK, so it&#8217;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.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Set-ItemProperty -Path 'HKLM:\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\' -Name InstallationType -Value Server -Force<\/code><\/pre>\n\n\n\n<p>And we have success!<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>MSI (s) (FC:6C) &#91;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.\n<\/code><\/pre>\n\n\n\n<p>Except, when you launch the configuration tool, and click &#8220;Sign In&#8221;, the application crashed. Womp womp.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"477\" height=\"81\" src=\"https:\/\/anthonyfontanez.com\/wp-content\/uploads\/2021\/12\/image-1.png\" alt=\"\" class=\"wp-image-488\" srcset=\"https:\/\/anthonyfontanez.com\/wp-content\/uploads\/2021\/12\/image-1.png 477w, https:\/\/anthonyfontanez.com\/wp-content\/uploads\/2021\/12\/image-1-300x51.png 300w\" sizes=\"auto, (max-width: 477px) 100vw, 477px\" \/><figcaption class=\"wp-element-caption\">ODJConnectorUI.exe crashes after clicking Sign In<\/figcaption><\/figure>\n<\/div>\n\n\n<p>Alright, so this was mostly expected. As I mentioned earlier, diving this deep entered unsupported territory, but I &#8220;needed&#8221; to know.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"permissions\">Permissions?<\/h2>\n\n\n\n<p><\/p>\n\n\n\n<p>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&#8217;d prefer the service to run with as few permissions as possible.<\/p>\n\n\n\n<p>The first step I took was to prepare a group Managed Service Account for the service to run as:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Create a gMSA\nNew-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\n\n# Install it on each server\nInstall-WindowsFeature -Name RSAT-AD-PowerShell\nInstall-ADServiceAccount -Identity svc_ODJ_Con\nTest-ADServiceAccount -Identity svc_ODJ_Con\nRestart-Computer<\/code><\/pre>\n\n\n\n<p>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.<\/p>\n\n\n\n<p>Next up is to configure a GPO to grant the above gMSA the &#8220;Log on as a service&#8221; right and link it to the OU containing the servers:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"435\" height=\"204\" src=\"https:\/\/anthonyfontanez.com\/wp-content\/uploads\/2021\/12\/image-2.png\" alt=\"\" class=\"wp-image-489\" srcset=\"https:\/\/anthonyfontanez.com\/wp-content\/uploads\/2021\/12\/image-2.png 435w, https:\/\/anthonyfontanez.com\/wp-content\/uploads\/2021\/12\/image-2-300x141.png 300w\" sizes=\"auto, (max-width: 435px) 100vw, 435px\" \/><figcaption class=\"wp-element-caption\">Granting &#8220;Log on as a service&#8221; rights<\/figcaption><\/figure>\n<\/div>\n\n\n<p>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):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Start-Process -FilePath 'sc.exe' -ArgumentList 'config', 'ODJConnectorSvc', 'obj=', 'CORP\\svc_ODJ_Con$'\nRestart-Service -Name ODJConnectorSvc<\/code><\/pre>\n\n\n\n<p>Now, let&#8217;s take a look at the connector status in MEM Admin Center:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"537\" height=\"236\" src=\"https:\/\/anthonyfontanez.com\/wp-content\/uploads\/2021\/12\/image-3.png\" alt=\"\" class=\"wp-image-493\" srcset=\"https:\/\/anthonyfontanez.com\/wp-content\/uploads\/2021\/12\/image-3.png 537w, https:\/\/anthonyfontanez.com\/wp-content\/uploads\/2021\/12\/image-3-300x132.png 300w\" sizes=\"auto, (max-width: 537px) 100vw, 537px\" \/><figcaption class=\"wp-element-caption\">ODJ Connector Status<\/figcaption><\/figure>\n<\/div>\n\n\n<p>While this initially looks good, eventually, they will all go into an Error state. If we poke at the event logs, we&#8217;ll find the following:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># ODJ Connector Service Log\n{\n\t\"Metric\":{\n\t\t\"Dimensions\":{\n\t\t\t\"InstanceId\":\"F980D4AC-357B-45A2-8BEE-82C43C0801E2\",\n\t\t\t\"DiagnosticCode\":\"0x0FFFFFFF\",\n\t\t\t\"DiagnosticText\":\"We are unable to complete your request because a server-side error occurred. Please try again. &#91;Exception Message: \\\"DiagnosticException: 0x0FFFFFFF. We are unable to complete your request because a server-side error occurred. Please try again.\\\"] &#91;Exception Message: \\\"Failed to get a value for Key: OdjServiceBaseUrl\\\"] &#91;Exception Message: \\\"The given key was not present in the dictionary.\\\"]\"\n\t\t},\n\t\t\"Name\":\"RequestHandlingPipeline_DownloadFailure\",\n\t\t\"Value\":0\n\t}\n}\n\n# Security Log\nCryptographic operation.\n\nSubject:\n\tSecurity ID:\t\tCORP\\svc_ODJ_Con$\n\tAccount Name:\t\tsvc_ODJ_Con$\n\tAccount Domain:\t\tCORP\n\tLogon ID:\t\t0x22AD56\n\nCryptographic Parameters:\n\tProvider Name:\tMicrosoft Software Key Storage Provider\n\tAlgorithm Name:\tUNKNOWN\n\tKey Name:\tb686a2307d6f00e79a260b740fd27691_1a3cdda4-ea72-467c-8f01-8b4b796110a2\n\tKey Type:\tMachine key.\n\nCryptographic Operation:\n\tOperation:\tOpen Key.\n\tReturn Code:\t0x80090016<\/code><\/pre>\n\n\n\n<p>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&#8217;s private key. In order to fix this, we need to modify these permissions via certlm.msc by managing the private key:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"690\" src=\"https:\/\/anthonyfontanez.com\/wp-content\/uploads\/2021\/12\/image-4-1024x690.png\" alt=\"\" class=\"wp-image-494\" srcset=\"https:\/\/anthonyfontanez.com\/wp-content\/uploads\/2021\/12\/image-4-1024x690.png 1024w, https:\/\/anthonyfontanez.com\/wp-content\/uploads\/2021\/12\/image-4-300x202.png 300w, https:\/\/anthonyfontanez.com\/wp-content\/uploads\/2021\/12\/image-4-768x518.png 768w, https:\/\/anthonyfontanez.com\/wp-content\/uploads\/2021\/12\/image-4.png 1049w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Manage Private Key Permissions<\/figcaption><\/figure>\n<\/div>\n\n\n<p>Once the gMSA is granted read permissions to this certificate&#8217;s private key, and the connector service restarted, the connector status should return to green.<\/p>\n\n\n\n<p>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 (<a href=\"https:\/\/github.com\/ajf8729\/Toolbox\/blob\/main\/Active%20Directory\/Set-ODJConnectorPermissions.ps1\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/github.com\/ajf8729\/Toolbox\/blob\/main\/Active%20Directory\/Set-ODJConnectorPermissions.ps1<\/a>)<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">[CmdletBinding()]\nParam(\n    [Parameter(Mandatory = $True)]\n    [string]$ServiceAccount\n)\n\n$FileSystemAccessRule = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule($ServiceAccount, 'Read', 'Allow')\n\n$Certificate = Get-ChildItem 'Cert:\\LocalMachine\\My\\' | Where-Object {$_.Issuer -eq 'CN=Microsoft Intune ODJ Connector CA'}\n$PrivateKey = [System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($Certificate)\n$PrivateKeyFilename = $PrivateKey.key.UniqueName\n$PrivateKeyPath = \"$env:ProgramData\\Microsoft\\Crypto\\RSA\\MachineKeys\\$PrivateKeyFilename\"\n$PrivateKeyPermissions = Get-Acl -Path $PrivateKeyPath\n$PrivateKeyPermissions.AddAccessRule($FileSystemAccessRule)\nSet-Acl -Path $PrivateKeyPath -AclObject $PrivateKeyPermissions\n\nStop-Service -Name ODJConnectorSvc\nStart-Process -FilePath 'sc.exe' -ArgumentList 'config', 'ODJConnectorSvc', 'obj=', $ServiceAccount -NoNewWindow\nStart-Service -Name ODJConnectorSvc<\/pre>\n\n\n\n<p>The above script accepts a parameter to specify the service account (in the form &#8220;DOMAIN\\gMSA_name$&#8221;), configure the private key permissions, configure the connector service to run as the gMSA, and finally restart the service.<\/p>\n\n\n\n<p>Hooray, we now have our ODJ connectors successfully running as a gMSA and without administrator rights!<\/p>\n\n\n\n<p>Finally, in testing Hybrid Autopilot now&#8230;<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"387\" height=\"262\" src=\"https:\/\/anthonyfontanez.com\/wp-content\/uploads\/2021\/12\/image-5.png\" alt=\"\" class=\"wp-image-496\" srcset=\"https:\/\/anthonyfontanez.com\/wp-content\/uploads\/2021\/12\/image-5.png 387w, https:\/\/anthonyfontanez.com\/wp-content\/uploads\/2021\/12\/image-5-300x203.png 300w\" sizes=\"auto, (max-width: 387px) 100vw, 387px\" \/><figcaption class=\"wp-element-caption\">Computer Account Created Successfully!<\/figcaption><\/figure>\n<\/div>\n\n\n<p>Happy Holidays Everyone!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>2025-02-27 Update: This entire post is now irrelevant, see https:\/\/techcommunity.microsoft.com\/blog\/intunecustomersuccess\/microsoft-intune-connector-for-active-directory-security-update\/4386898 for more information. Disclaimer: I recommend utilizing pure-AAD join in 99% of use Autopilot use<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[21,20],"tags":[23,22],"class_list":["post-485","post","type-post","status-publish","format-standard","hentry","category-autopilot","category-intune","tag-autopilot","tag-intune"],"jetpack_featured_media_url":"","jetpack_likes_enabled":true,"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/anthonyfontanez.com\/index.php\/wp-json\/wp\/v2\/posts\/485","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/anthonyfontanez.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/anthonyfontanez.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/anthonyfontanez.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/anthonyfontanez.com\/index.php\/wp-json\/wp\/v2\/comments?post=485"}],"version-history":[{"count":11,"href":"https:\/\/anthonyfontanez.com\/index.php\/wp-json\/wp\/v2\/posts\/485\/revisions"}],"predecessor-version":[{"id":980,"href":"https:\/\/anthonyfontanez.com\/index.php\/wp-json\/wp\/v2\/posts\/485\/revisions\/980"}],"wp:attachment":[{"href":"https:\/\/anthonyfontanez.com\/index.php\/wp-json\/wp\/v2\/media?parent=485"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/anthonyfontanez.com\/index.php\/wp-json\/wp\/v2\/categories?post=485"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/anthonyfontanez.com\/index.php\/wp-json\/wp\/v2\/tags?post=485"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}