I wanted to initiate a remote sync of Azure AD connect via Remote PowerShell. The cmdlet is simple – Start-ADSyncSyncCycle -PolicyType Delta
– but by default you can’t remove PowerShell unless you are an admin, and I didn’t want to open up admin access to a service account. Moreover I wanted to limit what the service account can do.
The solution for this is simple, and something I found via Google.
Step 1 – Create your service account
Step 2- Create a session configuration file on your Azure AD server.
For this, open an admin PowerShell window. And type the following:
1 2 3 4 5 6 |
New-PSSessionConfigurationFile ` -ModulesToImport "C:\Program Files\Microsoft Azure AD Sync\Bin\ADSync" ` -VisibleCmdLets ('Start-ADSyncSyncCycle') ` -LanguageMode 'NoLanguage' ` -SessionType 'RestrictedRemoteServer' ` -Path 'c:\PSSessionConfigurationFile\limited-aad-sync.pssc' |
This includes the AAD Sync module, and limits the visible cmdlets to a single one. The file is stored in the path given.
Step 3 – Register this session
In the same PowerShell window do:
1 2 3 |
Register-PSSessionConfiguration ` -Name 'Limited AAD Sync' -ShowSecurityDescriptorUI ` -Path 'c:\PSSessionConfigurationFile\limited-aad-sync.pssc' |
This opens up a dialog box, wherein you can search and select the service account previously created. Give this Full Control rights. This is what allows the service account to connect using this session configuration. You could select a group too, but I prefer usernames so no one else can make changes unless they are on the Azure AD connect server.
And that’s it really!
From a client side if I were to now try and connect it would fail with an access denied message:
1 |
New-PSSession -ComputerName $server -Credential $creds |
That’s because the service account isn’t a local admin. Try with the session configuration created above instead:
1 |
New-PSSession -ComputerName $server -Credential $creds -ConfigurationName "Limited AAD Sync" |
This works! If I were to store the session in a variable, I can now run the sync cmdlet:
1 |
Invoke-Command -Session $session -ScriptBlock { Start-ADSyncSyncCycle -PolicyType delta } |
Try any other cmdlet, and it will error out.
The above cmdlet too needs the service account to be in the “ADSyncOperators” groups on the Azure AD server. Else it will succeed but give the following error: Start-ADSyncSyncCycle: Retrieving the COM class factory for remote component with CLSID {835BEE60-8731-4159-8BFF-941301D76D05} from machine XXXX failed due to the following error: 80070005 XXXX.
That’s it! Easy peasy. Thanks to this Petri article for pointing me the right way.
Updates:
What if I want to modify things?
If I want to add a new account to the already created session configuration I should do:
1 |
Set-PSSessionConfiguration -Name 'Limited AAD Sync' -ShowSecurityDescriptorUI |
And what about adding new cmdlets to the configuration file? Thanks to this doc:
When you use a session configuration file in a session configuration, PowerShell creates an active copy of the session configuration file and stores it in the $pshome\SessionConfig directory on the local computer.
The location of the active copy of a session configuration file is stored in the ConfigFilePath property of the session configuration object.
So I do:
1 |
(Get-PSSessionConfiguration -Name 'Limited AAD Sync').ConfigFilePath |
Edit that in notepad or whatever. Currently it has:
1 2 |
# Cmdlets to make visible when applied to a session VisibleCmdlets = 'Start-ADSyncSyncCycle' |
This needs to be an Array, so I change to (adding the 2nd cmdlet):
1 2 |
# Cmdlets to make visible when applied to a session VisibleCmdlets = 'Start-ADSyncSyncCycle', 'Get-ADSyncScheduler' |
After that, test the file for any errors:
1 |
Test-PSSessionConfigurationFile -Path (Get-PSSessionConfiguration -Name 'Limited AAD Sync').ConfigFilePath |
That’s all! Any new sessions to that endpoint will have the additional cmdlet visible. I added the additional cmdlet so I can also get the current sync status etc (is the scheduler paused; is it already running; and so on).