Have you ever wondered how to seamlessly connect your on-premises Active Directory with Entra ID? Well, you’re in the right place because today, I’m diving into Entra Connect, formerly known as Azure AD Connect. But hold on tight, because we’re not just talking about the basics; we’re here to make sure you install and configure it like a security pro!

So, what exactly is Entra Connect, you ask? Picture this: You’ve got your company’s user accounts, groups, and all that good stuff living happily in your on-premises Active Directory. But in today’s cloud-driven world, you also want them to play nice with Entra ID, Microsoft’s cloud-based identity and access management service. That’s where Entra Connect comes in – it’s the bridge that makes sure your on-premises and cloud identities sync up seamlessly.

But, here’s the kicker – during many security assessments, I’ve seen something that might make you cringe a bit: excessive permissions handed out to the account responsible for syncing data between Active Directory and Entra Connect. We’re talking even domain admin credentials here! Now, that’s a red flag when it comes to security.

Fear not, because this blog post is your guide to doing it right. We’re all about secure installation and configuration. Say goodbye to risky practices and hello to a setup that keeps your data locked down tighter than Fort Knox.

Setting your UPN (User Principle Name)

Before I dive deep into securing the Entra Connect setup, let’s talk about a crucial requirement: User Principal Names (UPNs). These are like digital identifiers for your users, and they need to be ready for a journey to the cloud. Here’s the deal: your users’ UPNs must be routable on the internet, a.k.a. be able to be located by others.

Why Is This Important?
Well, Entra Connect is all about connecting your on-premises Active Directory with Entra ID in the cloud. To do this, it needs to identify your users uniquely. That’s where the UPN comes into play. It’s the user’s login name, and it should look something like “user@yourdomain.com” – notice that “yourdomain.com” part? That’s the key.

Now, what if your users’ UPNs look like something from your local network, like “user@internal.local“? That won’t fly when you’re taking things to the cloud. Entra Connect needs a UPN that’s ready to party on the internet.

How to Make Your UPNs Internet-Ready:
Here’s how you can change your UPNs to make them internet-friendly:

  • Open “Active Directory Domains and Trusts” You can usually find this in your Windows Server admin tools.
  • Right-click on “Active Directory Domains and Trusts” and select “Properties.”
  • In the “UPN Suffixes” dialog, add the additional UPN suffix you want. In Entra Connect, this is represented by a custom domain name.
  • Click “Add” to add your custom UPN suffix, and then exit the “Active Directory Domains and Trusts” console.

PowerShell example:

#Get the UPN suffix 
Get-ADForest | Format-List UPNSuffixes 

#Set the UPN Suffix 
Get-ADForest | Set-ADForest -UPNSuffixes @{add="zwbhx.onmicrosoft.com"} 

Update the users with PowerShell

Now, if you’re a fan of PowerShell (who isn’t, right?), here’s a quick code snippet to make the change to all your users so they can be synced and use their new login in the Cloud.

Import-Module ActiveDirectory

$AddsUPN = "sandbox.lab" 
$EntraUPN = "zwbhx.onmicrosoft.com" 
$SearchBase = "OU=Users,OU=Management,DC=sandbox,DC=lab" 
$UPNFilter = "'*$($AddsUPN)'" 

$UsersInScope = Get-ADUser -Filter "UserPrincipalName -like $($UPNFilter)" -Properties userPrincipalName -ResultSetSize $null -SearchBase $SearchBase 

$UsersInScope | foreach {$NewUpn = $_.UserPrincipalName.Replace("@$($AddsUPN)","@$($EntraUPN)"); $_ | Set-ADUser -UserPrincipalName $NewUpn} 

IDFix: Ensuring smooth user sync

The journey from an on-premises Active Directory to Entra ID can be a challenging one. But, like any step, it’s best to ensure you’re prepared. Enter the IDFix tool, your trusty tool for a clean sync experience.

What is IDFix?
IDFix, a nifty tool offered by Microsoft, plays a crucial role in the prelude to syncing user identities from your on-premises Active Directory to Azure AD. It’s like a diligent gatekeeper, ensuring that your user identities are ready for the cloud transition.

Download it here: https://github.com/microsoft/idfix

Why Does it Matter?
Picture this scenario: you’re all set to sync your users to Azure AD, but unknown to you, there are quirks in your user identities that might cause hiccups down the road. These quirks could include illegal characters, duplicate attributes, reserved words, or even empty attributes within your Active Directory.

How IDFix Comes to the Rescue:
IDFix scans your Active Directory, hunting down these identity anomalies with precision. It flags issues like illegal characters in usernames, ensures attribute values are unique, and makes sure you’re not using reserved terms that could spell trouble in the cloud.

The tool is really self explanatory, first click the “Query” button, for any identity that is found, evaluate the needed action. Any additional search parameters are located under the gear icon. More information about the tool can be found here:

https://microsoft.github.io/idfix/

Enable TLS 1.2 on the CloudIDP

Enabling TLS 1.2 on the Cloud Identity Provider (CloudIDP) server, which hosts the Entra Connect tool, is crucial for securing data transmission between the Entra Connect tool and external systems. This security measure helps encrypt sensitive information during communication and ensures compliance with regulatory standards.

Open “Registry Editor” and add the following values:

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Client]
"DisabledByDefault"=dword:00000000
"Enabled"=dword:00000001

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft.NETFramework\v4.0.30319]
"SchUseStrongCrypto"=dword:00000001

Reboot the server after applying the settings before continuing.

Creating a gMSA for Entra Connect

Creating a Group Managed Service Account (gMSA) is an important step in enhancing security for services like Entra Connect. Here’s a brief overview of how to create a gMSA:

Install Active Directory tools on the CloudIDP

Install-WindowsFeature -Name RSAT-AD-PowerShell,RSAT-ADDS –IncludeAllSubFeature 

Check the presence of a KDS Root Key

A Key Distribution Service (KDS) Root Key is a cryptographic key used within Active Directory to secure the distribution of Group Managed Service Account (gMSA) passwords. It serves as the foundation for generating and managing gMSA passwords, ensuring their security and integrity. The KDS Root Key is a critical component in the secure operation of gMSAs, helping protect against unauthorized access to service accounts and their associated privileges.

Get-KdsRootKey 

If there’s no result, there’s no KDS Root Key present in Active Directory and one needs to be created before continuing. Use the following code to create a key:

Add-KdsRootKey

# Add a KDS Root Key for a LAB
Add-KdsRootKey -EffectiveTime (Get-Date).AddHours(-10) 

Note! It will take 10 hours before the key becomes available, allow replication to provide the key to all domain controllers. 

Create the gMSA account with PowerShell

$Hostname = 'CloudIDP'   

New-ADServiceAccount -Name 'gMSA-MSEC' `
                     -PrincipalsAllowedToRetrieveManagedPassword ('{0}$' -f $Hostname) ` #This can also be a security group * 
                     -DNSHostName ('{0}.{1}' -f $Hostname, (Get-ADDomain).DNSRoot) `
                     -Description "gMSA For Entra Connect" 

Install the gMSA on the CloudIDP

Open an elevated PowerShell console and use the following code:

Install-ADServiceAccount -Identity gMSA-MSEC$ 

Note! No feedback is provided on success. 

In the same PowerShell console, test the account with the following code:

Test-ADServiceAccount -Identity gMSA-MSEC$ 

Note! Successful installation will output “True” 

Create Synchronization Account

The Synchronization Account acts as the bridge between your on-premises Active Directory and the Entra Connect tool. It’s responsible for syncing user identities, groups, and more, ensuring that your cloud identity management is smooth and up-to-date. Use the following PowerShell code to create the account, adjust to your situation:

$Passwordlength = 20
$amountOfNonAlphanumeric = 2
$OU = "OU=Service Accounts,OU=Tier 0,OU=Admin,DC=sandbox,DC=lab"
$AccountName = "srv-msec-sync"
$DisplayName = "Microsoft Entra Connect Sync"

# Generate Password
Add-Type -AssemblyName 'System.Web'
$PasswordClearText = [System.Web.Security.Membership]::GeneratePassword($Passwordlength, $amountOfNonAlphanumeric)
$PasswordClearText | Set-Clipboard
$Password = $PasswordClearText | ConvertTo-SecureString -AsPlainText -Force

New-ADUser -Name $AccountName `
           -DisplayName $DisplayName `
           -SamAccountName $AccountName ` 
           -Path "$OU" `
           -AccountPassword $Password `
           -Enabled $true

Note! The password for this account is copied to the clipboard. Store the password in a secure location (password vault) afterwards.

Delegated Permissions

To empower the Synchronization Account to perform its duties, you’ll need to delegate the appropriate permissions within your Active Directory. This involves carefully configuring access rights to specific directory objects and attributes, allowing the account to carry out its synchronization tasks securely and efficiently.

Here’s what the script can do:

  • Creates default groups for Entra Connect features, ensuring organized and streamlined synchronization.
  • Delegates permissions per Entra Connect feature, so the Synchronization Account can perform its duties without a hitch.

The script can be found here:

https://github.com/mfgjwaterman/Powershell/blob/master/Scripts/New-ADEntraConnectDelegation.ps1

Please note that this script is based on the work provided by Sander Berkouwer of DirTeam, I’ve just converted it to PowerShell. His blog post can be found here:

https://dirteam.com/sander/2019/11/12/howto-properly-delegate-directory-access-to-azure-ad-connect-service-accounts/

#Requires -Version 5.1
#Requires -RunAsAdministrator
#Requires -modules ActiveDirectory

<#PSScriptInfo
    .VERSION 1.0
    .GUID c0621a14-da1d-4227-99c9-2ba91ebadde2
    .AUTHOR Michael Waterman
    .COMPANYNAME None
    .COPYRIGHT
    .TAGS Entra Connect, Delegation, Active Directory
#>

<#
    .SYNOPSIS
    Delegates specific security group rights to be used with Entra Connect 

    .DESCRIPTION
    This script can create security groups and delegate them appropriatly 
    to facilitate a delegation model for Entra ID connect. The initial 
    delegation permissions are from a DIRTEAM blogpost, converted to PowerShell:
    https://dirteam.com/sander/2019/11/12/howto-properly-delegate-directory-access-to-azure-ad-connect-service-accounts/

    .EXAMPLE
    New-ADEntraConnectDelegation.ps1
    

    .EXAMPLE
    New-ADEntraConnectDelegation.ps1 -CreateDefaultGroups -OU "OU=Groups,OU=Tier 0,OU=Admin,DC=sandbox,DC=lab"
    Creates default groups in a designated Organizational Unit.

    .EXAMPLE
    New-ADEntraConnectDelegation.ps1 -PasswordHashSync -SecurityGroup "MSEC - Password Hash Sync"
    Delegates the Password Hash Sync funtionality to the given security group.

    .EXAMPLE
    New-ADEntraConnectDelegation.ps1 -EntraConnectFeature 'Group Writeback' -OU OU=test,DC=sandbox,DC=lab -SecurityGroup "MSEC - Group Writeback"
    Delegates 'Group Writeback' for the security group "MSEC - Group Writeback" to the designated Organizational Unit.
    Options for EntraConnectFeature are: "Base Active Directory", "Device Writeback", "Group Writeback", "Hybrid Exchange", "Password Reset",
    "Password Writeback"
   
    .NOTES
    AUTHOR: Michael Waterman
    Blog: https://michaelwaterman.nl
    LASTEDIT: 2023.12.24
#>



[CmdletBinding(DefaultParameterSetName="Default")]
param(
[Parameter(
    Mandatory=$True,
    ParameterSetName = 'Default')]
[Parameter(
    Mandatory=$True, 
    ParameterSetName = 'CreateDefaultGroups')]
[string]$OU,
[Parameter(
    Mandatory=$True,
    ParameterSetName = 'CreateDefaultGroups'
    )]
[switch]$CreateDefaultGroups=$True,
[Parameter(
    Mandatory=$True,
    ParameterSetName = 'PasswordHashSync'
    )]
[switch]$PasswordHashSync,
[Parameter(
    Mandatory=$True, 
    ParameterSetName = 'Default')]
[Parameter(
    Mandatory=$True, 
    ParameterSetName = 'PasswordHashSync')]
[string]$SecurityGroup,
[Parameter(
    Mandatory=$true,
    ParameterSetName = 'Default'
    )]
[ValidateSet(
    "Base Active Directory",
    "Device Writeback",
    "Group Writeback",
    "Hybrid Exchange",
    "Password Reset",
    "Password Writeback"
    )]
[string]$EntraConnectFeature
)


#AD Security Group Function
##############################################################################################
Function Test-ADGroup ($ADSecurityGroup) {
    Try{
        Get-ADGroup -Identity $ADSecurityGroup | Out-Null
       }
    Catch [Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException]{
       throw $_.Exception.Message
    }
}
##############################################################################################


#Check OU existance
##############################################################################################
If ( -not ( Test-Path "AD:${OU}")){
    Write-Error "Organizational Unit Not Found, make sure you type the correct DN"
    Return
}
##############################################################################################


#Create Security Groups
##############################################################################################
if($CreateDefaultGroups){

    # Array with all the groups
    $Groups = @(
        "MSEC - Password Hash Sync",
        "MSEC - Base Active Directory",
        "MSEC - Password Reset",
        "MSEC - Password Writeback",
        "MSEC - Group Writeback",
        "MSEC - Device Writeback",
        "MSEC - Hybrid Exchange"
    )

    #Create the Groups
    ForEach($Group in $Groups){
        if(!(Get-ADGroup -LDAPFilter "(SAMAccountName=$Group)")){
            New-ADGroup -Name $Group -Path $OU -GroupScope Global
        }
    }
}
##############################################################################################


#ACL for Password Hash Sync
##############################################################################################
If($PasswordHashSync){

    Test-ADGroup -ADSecurityGroup $SecurityGroup

    #ACL for Hash Sync
    $SIDPWHashSync = (Get-ADGroup -Identity $SecurityGroup).SID
    $objRootACL = Get-ACL "AD:$((Get-ADDomain).DistinguishedName)"
    $objRootACL.AddAccessRule((New-Object System.DirectoryServices.ActiveDirectoryAccessRule `
        ($SIDPWHashSync, `
         "ExtendedRight", `
         "Allow", `
         [guid]'1131f6aa-9c07-11d1-f79f-00c04fc2dcd2', `
         'None', `
         [guid]'00000000-0000-0000-0000-000000000000')))
    $objRootACL.AddAccessRule((New-Object System.DirectoryServices.ActiveDirectoryAccessRule `
        ($SIDPWHashSync, `
         "ExtendedRight", `
         "Allow", `
         [guid]'1131f6ad-9c07-11d1-f79f-00c04fc2dcd2', `
         'None', `
         [guid]'00000000-0000-0000-0000-000000000000')))
    Set-acl -AclObject $objRootACL "AD:$((Get-ADDomain).DistinguishedName)"
}
##############################################################################################


#ACL for Base Active Directory
##############################################################################################
If($EntraConnectFeature -eq "Base Active Directory"){

    Test-ADGroup -ADSecurityGroup $SecurityGroup

    $SIDBaseAD = (Get-ADGroup -Identity $SecurityGroup).SID  
    $objACL = Get-ACL "AD:${OU}"
    $objACL.AddAccessRule((New-Object System.DirectoryServices.ActiveDirectoryAccessRule `
        ($SIDBaseAD, `
         "WriteProperty", `
         "Allow", `
         [guid]'23773dc2-b63a-11d2-90e1-00c04fd91ab1', `
         'Descendents', `
         [guid]'bf967aba-0de6-11d0-a285-00aa003049e2')))
    $objACL.AddAccessRule((New-Object System.DirectoryServices.ActiveDirectoryAccessRule `
        ($SIDBaseAD, `
         "WriteProperty", `
         "Allow", `
         [guid]'5b47d60f-6090-40b2-9f37-2a4de88f3063', `
         'Descendents', `
         [guid]'bf967aba-0de6-11d0-a285-00aa003049e2')))
    $objACL.AddAccessRule((New-Object System.DirectoryServices.ActiveDirectoryAccessRule `
        ($SIDBaseAD, `
         "WriteProperty", `
         "Allow", `
         [guid]'5b47d60f-6090-40b2-9f37-2a4de88f3063', `
         'Descendents', `
         [guid]'bf967a9c-0de6-11d0-a285-00aa003049e2')))
    Set-acl -AclObject $objACL "AD:${OU}"
}
##############################################################################################


#ACL For Password Reset
##############################################################################################
If($EntraConnectFeature -eq "Password Reset"){

    Test-ADGroup -ADSecurityGroup $SecurityGroup

    $SIDPWReset = (Get-ADGroup -Identity $SecurityGroup).SID
    $objACL = Get-ACL "AD:${OU}"
    $objACL.AddAccessRule((New-Object System.DirectoryServices.ActiveDirectoryAccessRule `
        ($SIDPWReset, `
         "WriteProperty", `
         "Allow", `
         [guid]'28630ebf-41d5-11d1-a9c1-0000f80367c1', `
         'Descendents', `
         [guid]'bf967aba-0de6-11d0-a285-00aa003049e2')))
    $objACL.AddAccessRule((New-Object System.DirectoryServices.ActiveDirectoryAccessRule `
        ($SIDPWReset, `
         "WriteProperty", `
         "Allow", `
         [guid]'bf967a0a-0de6-11d0-a285-00aa003049e2', `
         'Descendents', `
         [guid]'bf967aba-0de6-11d0-a285-00aa003049e2')))
    $objACL.AddAccessRule((New-Object System.DirectoryServices.ActiveDirectoryAccessRule `
        ($SIDPWReset, `
         "ExtendedRight", `
         "Allow", `
         [guid]'ccc2dc7d-a6ad-4a7a-8846-c04e3cc53501', `
         'Descendents', `
         [guid]'bf967aba-0de6-11d0-a285-00aa003049e2')))
    $objACL.AddAccessRule((New-Object System.DirectoryServices.ActiveDirectoryAccessRule `
        ($SIDPWReset, `
         "ExtendedRight", `
         "Allow", `
         [guid]'00299570-246d-11d0-a768-00aa006e0529', `
         'Descendents', `
         [guid]'bf967aba-0de6-11d0-a285-00aa003049e2')))
    $objACL.AddAccessRule((New-Object System.DirectoryServices.ActiveDirectoryAccessRule `
        ($SIDPWReset, `
         "ExtendedRight", `
         "Allow", `
         [guid]'ab721a53-1e2f-11d0-9819-00aa0040529b', `
         'Descendents', `
         [guid]'bf967aba-0de6-11d0-a285-00aa003049e2')))
    Set-acl -AclObject $objACL "AD:${OU}"
}
##############################################################################################


#ACL For Password Writeback
##############################################################################################
If($EntraConnectFeature -eq "Password Writeback"){

    Test-ADGroup -ADSecurityGroup $SecurityGroup

    $SIDPWWriteback = (Get-ADGroup -Identity $SecurityGroup).SID
    $objACL = Get-ACL "AD:${OU}"
    $objACL.AddAccessRule((New-Object System.DirectoryServices.ActiveDirectoryAccessRule `
        ($SIDPWWriteback, `
         "WriteProperty", `
         "Allow", `
         [guid]'28630ebf-41d5-11d1-a9c1-0000f80367c1', `
         'Descendents', `
         [guid]'bf967aba-0de6-11d0-a285-00aa003049e2')))
    $objACL.AddAccessRule((New-Object System.DirectoryServices.ActiveDirectoryAccessRule `
        ($SIDPWWriteback, `
         "WriteProperty", `
         "Allow", `
         [guid]'bf967a0a-0de6-11d0-a285-00aa003049e2', `
         'Descendents', `
         [guid]'bf967aba-0de6-11d0-a285-00aa003049e2')))
    $objACL.AddAccessRule((New-Object System.DirectoryServices.ActiveDirectoryAccessRule `
        ($SIDPWWriteback, `
         "ExtendedRight", `
         "Allow", `
         [guid]'00299570-246d-11d0-a768-00aa006e0529', `
         'Descendents', `
         [guid]'bf967aba-0de6-11d0-a285-00aa003049e2')))
    $objACL.AddAccessRule((New-Object System.DirectoryServices.ActiveDirectoryAccessRule `
        ($SIDPWWriteback, `
         "ExtendedRight", `
         "Allow", `
         [guid]'ab721a53-1e2f-11d0-9819-00aa0040529b', `
         'Descendents', `
         [guid]'bf967aba-0de6-11d0-a285-00aa003049e2')))
    Set-acl -AclObject $objACL "AD:${OU}"
}
##############################################################################################


#ACL For Device Writeback
##############################################################################################
If($EntraConnectFeature -eq "Device Writeback"){

    Test-ADGroup -ADSecurityGroup $SecurityGroup

    $SIDDevWriteback = (Get-ADGroup -Identity $SecurityGroup).SID
    $objACL = Get-ACL "AD:${OU}"
    $objACL.AddAccessRule((New-Object System.DirectoryServices.ActiveDirectoryAccessRule `
        ($SIDDevWriteback, `
         "CreateChild, DeleteChild, ReadProperty, WriteProperty", `
         "Allow", `
         [guid]'00000000-0000-0000-0000-000000000000', `
         'Descendents', `
         [guid]'bf967a86-0de6-11d0-a285-00aa003049e2')))
    Set-acl -AclObject $objACL "AD:${OU}"
}
##############################################################################################


#ACL For Group Writeback
##############################################################################################
If($EntraConnectFeature -eq "Group Writeback"){

    Test-ADGroup -ADSecurityGroup $SecurityGroup

    $SIDGrpWriteback = (Get-ADGroup -Identity $SecurityGroup).SID
    $objACL = Get-ACL "AD:${OU}"
    $objACL.AddAccessRule((New-Object System.DirectoryServices.ActiveDirectoryAccessRule `
        ($SIDGrpWriteback, `
         "CreateChild, DeleteChild", `
         "Allow", `
         [guid]'bf967a9c-0de6-11d0-a285-00aa003049e2', `
         'Descendents', `
         [guid]'00000000-0000-0000-0000-000000000000')))
    $objACL.AddAccessRule((New-Object System.DirectoryServices.ActiveDirectoryAccessRule `
        ($SIDGrpWriteback, `
         "WriteProperty", `
         "Allow", `
         [guid]'bf9679c0-0de6-11d0-a285-00aa003049e2', `
         'Descendents', `
         [guid]'bf967a9c-0de6-11d0-a285-00aa003049e2')))
    Set-acl -AclObject $objACL "AD:${OU}"
}
##############################################################################################


#ACL For Hybrid Exchange
##############################################################################################
If($EntraConnectFeature -eq "Hybrid Exchange"){

    Test-ADGroup -ADSecurityGroup $SecurityGroup
    
    $SIDHybridExch = (Get-ADGroup -Identity $SecurityGroup).SID
    $objACL = Get-ACL "AD:${OU}"
    $objACL.AddAccessRule((New-Object System.DirectoryServices.ActiveDirectoryAccessRule `
        ($SIDHybridExch, `
         "WriteProperty", `
         "Allow", `
         [guid]'6f606079-3a82-4c1b-8efb-dcc8c91d26fe', `
         'Descendents', `
         [guid]'bf967aba-0de6-11d0-a285-00aa003049e2')))
    $objACL.AddAccessRule((New-Object System.DirectoryServices.ActiveDirectoryAccessRule `
        ($SIDHybridExch, `
         "WriteProperty", `
         "Allow", `
         [guid]'2432acdb-71c4-4d45-b5aa-9beee36630fe', `
         'Descendents', `
         [guid]'bf967aba-0de6-11d0-a285-00aa003049e2')))
    $objACL.AddAccessRule((New-Object System.DirectoryServices.ActiveDirectoryAccessRule `
        ($SIDHybridExch, `
         "WriteProperty", `
         "Allow", `
         [guid]'b1d6bdd0-2a3d-4aba-8c72-40640a999566', `
         'Descendents', `
         [guid]'bf967aba-0de6-11d0-a285-00aa003049e2')))
    $objACL.AddAccessRule((New-Object System.DirectoryServices.ActiveDirectoryAccessRule `
        ($SIDHybridExch, `
         "WriteProperty", `
         "Allow", `
         [guid]'66437984-c3c5-498f-b269-987819ef484b', `
         'Descendents', `
         [guid]'bf967aba-0de6-11d0-a285-00aa003049e2')))
    $objACL.AddAccessRule((New-Object System.DirectoryServices.ActiveDirectoryAccessRule `
        ($SIDHybridExch, ` 
         "WriteProperty", `
         "Allow", `
         [guid]'b17c00b8-46b9-484e-b053-d5c26835f11e', `
         'Descendents', `
         [guid]'bf967aba-0de6-11d0-a285-00aa003049e2')))
    $objACL.AddAccessRule((New-Object System.DirectoryServices.ActiveDirectoryAccessRule `
        ($SIDHybridExch, `
         "WriteProperty", `
         "Allow", `
         [guid]'f0f8ff9a-1191-11d0-a060-00aa006c33ed', `
         'Descendents', `
         [guid]'bf967aba-0de6-11d0-a285-00aa003049e2')))
    $objACL.AddAccessRule((New-Object System.DirectoryServices.ActiveDirectoryAccessRule `
        ($SIDHybridExch, `
         "WriteProperty", `
         "Allow", `
         [guid]'bd29bf90-66ad-40e1-887b-10df070419a6', `
         'Descendents', `
         [guid]'bf967aba-0de6-11d0-a285-00aa003049e2')))
    $objACL.AddAccessRule((New-Object System.DirectoryServices.ActiveDirectoryAccessRule `
        ($SIDHybridExch, `
         "WriteProperty", `
         "Allow", `
         [guid]'bf967a06-0de6-11d0-a285-00aa003049e2', `
         'Descendents', `
         [guid]'bf967aba-0de6-11d0-a285-00aa003049e2')))
    Set-acl -AclObject $objACL "AD:${OU}"
}
##############################################################################################

Create default groups

The script can create default groups that can be used with Entra Connect, you really don’t have to use these and it’s perfectly fine to use your own, this functionality is just here for your convenience.

New-ADEntraConnectDelegation.ps1 -CreateDefaultGroups -OU "OU=Groups,OU=Tier 0,OU=Admin,DC=sandbox,DC=lab"

Note! Don’t forget to add the synchronisation account we created earlier to the appropriate security groups.

Password Hash Sync

Delegates the Password Hash Sync funtionality to the given security group.

New-ADEntraConnectDelegation.ps1 -PasswordHashSync -SecurityGroup "MSEC - Password Hash Sync"

Base Sync

Delegates ‘Base Active Directory’ synchronization for the security group “MSEC – Base Active Directory” to the designated Organizational Unit. Options for Entra Connect Features are:

  • Base Active Directory
  • Device Writeback
  • Group Writeback
  • Hybrid Exchange
  • Password Reset
  • Password Writeback
New-ADEntraConnectDelegation.ps1 -EntraConnectFeature 'Base Active Directory' -OU OU=test,DC=sandbox,DC=lab -SecurityGroup "MSEC - Base Active Directory"

Note! If you want to query the Active Diretory Schema for the identifiers reagrding the used attribute and extended rights, I’ve got your back! During the creation of the above script I’ve created two additional scripts that can help you locating the identifiers of the attributes and extended rights. These scripts are in my GitHub repository:

https://github.com/mfgjwaterman/Powershell/blob/master/Scripts/Get-ADSchemaClassAndAttributes.ps1

https://github.com/mfgjwaterman/Powershell/blob/master/Scripts/Get-ADExtendedRights.ps1

Active Directory Recycle bin

Enabling the Active Directory Recycle Bin is a highly recommended step in enhancing your Active Directory’s data recovery capabilities. This feature acts as a safety net, allowing you to easily restore deleted objects, such as user accounts, groups, and organizational units, without the need for complex restoration processes. By enabling the AD Recycle Bin, you significantly reduce the risk of accidental data loss and streamline your Active Directory management, ensuring that critical objects can be quickly and efficiently recovered when needed. Use the following PowerShell command to enable the feature:

Enable-ADOptionalFeature "Recycle Bin Feature" -server ((Get-ADForest -Current LocalComputer).DomainNamingMaster) -Scope ForestOrConfigurationSet -Target (Get-ADForest -Current LocalComputer) -Confirm:$false 

Use the following PowerShell command to check if the recycle bin is succesfully enabled:

Get-ADOptionalFeature -filter * | Select EnabledScopes 

Adding Trusted Sites for Entra ID Connectivity

When it comes to connecting securely with Entra ID, ensuring that your server can establish reliable connections is essential. However, servers often come with strict security measures in place, and accessing external resources can sometimes be a challenge.

I’ll address a common hurdle: configuring trusted sites on your server. By adding specific sites to your server’s trusted sites list, you pave the way for seamless and secure connections to Entra ID. Use the following registry keys to add the appropriate sites:

[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap\EscDomains\microsoftonline.com\login] 
"https"=dword:00000002

[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap\EscDomains\msftauth.net\aadcdn] 
"https"=dword:00000002

Note! IE Enhanced Security configuration needs to be enabled for these settings to work.

Entra Connect

With the groundwork laid, it’s time to take the next step – the installation of Entra Connect. This is where the rubber meets the road, and your Active Directory and Entra ID start working together seamlessly.

In this paragraph, I’ll guide you through the installation process, ensuring that you set up Entra Connect securely and efficiently.

Download

Go to the Entra ID Portal:

https://entra.microsoft.com/

Identity -> Hybrid Management -> Microsoft Entra Connect and download the tool, or directly on the Microsoft download site:

https://www.microsoft.com/en-us/download/details.aspx?id=47594

Once the tool is downloaded, install it on the CloudIDP, follow the next steps to install and configure:

Select: “I Agree…“, Click “Continue“.

Click “Customize“.

Note! Never ever use the express settings!

Select “Use an existing service account“, select “Managed Service Account“. Add the previously created Group Managed Service Account. Add the $ sign at the end. Click “Install“. it will take a while before you can continue.  

Select “Password Hash Synchronization“, click “Next“. 

Note! When your systems are Hybrid or domain joined, select “Enable single-sign on“. There’s no need to click this option when your clients are Cloud only.  

Enter the name of a Global Admin/Password account in Entra ID and click “Next“.

Authenticate to Entra ID with global admin credentials.

Click “Add Directory“. 

Click “Use existing AD account“, add the synchronisation account we created earlier, add the password and click “OK“. 

The added credentials are checked and the domain is added. Click “Next“. 

Click “Continue without matching all UPN suffixes to verified domain“, click “Next“. 

Select, “Sync selected domain and OUs“. Select only the Organizational Unit(s) than need to be syned to Entra ID. Click “Next“. 

Accept the defaults and click “Next“.  

Note! If the ms-ds-ConsitancyGUID is currently not in use by the directory (AKA, no data is in the attribute) this attribute will be used to uniquely identify an object. If this attribute is used the ObjectGUID will be used. Please note that the latter is a read-only object and cannot be changed. 

Accept the defaults and click “Next“. Please note that a single object can be selected on this page to do a test sync to Entra ID. 

Accept the default and click “Next“. 

Click “Install” to start the synchronization.  

Note! If you see this on the last screen: 

You need to delegate the permissions for the sync account. See the delegating permissions chapter.  

Note! If the installation seems to take a while on the “Creating the Azure Active Directory Synchronization Account“, you need to make sure that this account is exempt from any “Conditional Access” policy. 

Click “Exit“. This concludes the installation and configuration.

Administrating and Troubleshooting

Now that the synchronization engine is up and running, it’s time to put on your administrator’s hat and ensure everything stays in tip-top shape.

In this chapter, I’ll explore the ins and outs of administrating and troubleshooting Entra Connect. You’ll learn how to manage the ongoing synchronization process, keep an eye on performance, troubleshoot common issues, and implement best practices to ensure your identity synchronization remains secure, reliable, and efficient. Basically all the stuff I had to figure out.

Start a manual sync

In PowerShell:

Start-ADSyncSyncCycle 

Note! Passwords are synced every 2 minutes 

Open the “Synchronization Service Manager“, check the synchronization status:

Start a full sync

Start-ADSyncSyncCycle -PolicyType Initial

Deleting a user

Before deleting a user permanently, leave it in the “AD Recycle bin“, the sync will pick up the deletion. If you however permanently delete and a user and an error pops-up a full sync needs to be done to correct the error.

Note! The sync account security group for base operations needs to be delegated on the Organizational Unit it needs to sync. 

E.G:

New-ADEntraConnectDelegation.ps1 -EntraConnectFeature Base Active Directory -OU OU=Users,OU=Management,DC=sandbox,DC=lab -SecurityGroup MSEC – Base Active Directory

List the Entra Connect configuration

Get-ADSyncGlobalSettingsParameter | Select-Object * | Sort-Object -Property Name | Out-GridView 

Get enabled Entra Connect features

Get-ADSyncAADCompanyFeature

Get Sync Connectors

Get-ADSyncAADPasswordSyncConfiguration -SourceConnector "sandbox.lab"

Set the Sync Schedule

Set-ADSyncScheduler -CustomizedSyncCycleInterval d.HH:mm:ss

E.G. every 40 minutes 

Set-ADSyncScheduler -CustomizedSyncCycleInterval 00:40:00 

Note! Although you can set the time to something less than 30 minutes, the sync will not run on that set time and will use the default of 30 minutes.

Disable the Sync

Set-ADSyncScheduler -SyncCycleEnabled $False

Conclusion: Navigating a Secure and Efficient Entra Connect Journey

As I wrap up the journey through the world of Entra Connect, I’ve covered a range of essential topics aimed at ensuring your synchronization process is not only efficient but also rock-solid in terms of security. Let’s recap the key takeaways:

  • User Principal Names (UPNs): I emphasized the importance of having internet-routable UPNs for your users, ensuring seamless integration between your on-premises Active Directory and Azure AD.
  • IDFix Tool: I introduced you to the IDFix tool, your trusty companion for identifying and resolving issues with user identities before they’re synchronized to Azure AD. It’s the first line of defense against potential synchronization hiccups.
  • TLS 1.2 Configuration: Enabling TLS 1.2 on your Entra Connect server is vital for securing data transmission, protecting against vulnerabilities, and maintaining regulatory compliance.
  • Creating a gMSA: I explored the creation of a Group Managed Service Account (gMSA), a critical element in safeguarding your Entra Connect service with automatically managed passwords.
  • Synchronization Account: I highlighted the importance of a dedicated Synchronization Account, which facilitates the synchronization of identities between your Active Directory and Entra Connect. I even made it easy with PowerShell code!
  • Adding Trusted Sites: I addressed the challenge of server security by guiding you through the process of adding trusted sites, ensuring secure connectivity to Entra ID.
  • Entra Connect Installation: I took the plunge and successfully installed Entra Connect, setting the stage for seamless identity synchronization.
  • Administrating and Troubleshooting: You gained insights into ongoing administration and troubleshooting techniques, essential for maintaining a smooth-running Entra Connect environment.

Now, armed with this knowledge, you’re well-prepared to navigate the Entra Connect landscape with confidence.

Thank you for reading this blog post (Yes I realize it’s a lot of information) and as always, please provide feedback or simply ask a question if you have any!