-
Notifications
You must be signed in to change notification settings - Fork 0
Service Account and AD
The service runs as LocalSystem out of the box. That's right for local-only scripts and read-only AD queries (LocalSystem authenticates to the network as the machine account, which Authenticated Users includes by default). It is wrong for hooks that need to modify AD — passwords, group memberships, computer objects.
This page covers the four real-world choices and how to switch.
| Account | Network identity | When to use |
|---|---|---|
LocalSystem (default)
|
Computer account DOMAIN\MACHINE$ on a domain-joined host; nothing on a workgroup host |
Default. Local file ops, simple PowerShell, read-only AD queries. Most powerful local account — any hook running under it has full local rights. |
LocalService |
None | Don't. Cannot talk to a domain controller. Listed only to rule it out. |
NetworkService |
Same machine account as LocalSystem | Slightly less local privilege than LocalSystem, same network identity. Rarely the right pick. |
Domain user (DOMAIN\svc-webhookserver) |
That user | Use when hooks need write access to AD and you can't use a gMSA. You own password rotation. |
gMSA (DOMAIN\svc-webhookserver$) |
That gMSA | Recommended for AD-write workloads. AD generates and rotates the password automatically every 30 days. Requires domain functional level 2012+. |
Pass -ServiceAccount to install-service.ps1 (or to the deploy / dev launcher):
# Domain user
& "C:\Program Files\WebhookServer\scripts\install-service.ps1" `
-BinaryPath "C:\Program Files\WebhookServer\WebhookServer.Service.exe" `
-ServiceAccount "CONTOSO\svc-webhookserver" -Password "..."
# gMSA - note trailing $ and no -Password
& "C:\Program Files\WebhookServer\scripts\install-service.ps1" `
-BinaryPath "C:\Program Files\WebhookServer\WebhookServer.Service.exe" `
-ServiceAccount 'CONTOSO\svc-webhookserver$'Or do it manually with sc.exe if the service is already installed:
sc.exe stop WebhookServer
sc.exe config WebhookServer obj= 'CONTOSO\svc-webhookserver$'
sc.exe start WebhookServerA gMSA is a Group Managed Service Account. Active Directory generates and stores its password and rotates it every 30 days; the host machine account retrieves the password as needed. You never see or store it. This is the cleanest pattern for production.
If your domain has never used gMSAs, create the KDS root key (only needed once per domain):
# from a Domain Admin PowerShell, on any DC
Add-KdsRootKey -EffectiveImmediately
# in production wait 10 hours for replication; in a lab, override:
# Add-KdsRootKey -EffectiveTime ((Get-Date).AddHours(-10))# from a DC, with AD PowerShell module loaded
New-ADServiceAccount -Name svc-webhookserver `
-DNSHostName webhook01.contoso.local `
-PrincipalsAllowedToRetrieveManagedPassword "DOMAIN\WebhookHosts"PrincipalsAllowedToRetrieveManagedPassword is the security group containing the computer accounts allowed to use the gMSA. Add your webhook host(s) to that group:
Add-ADGroupMember -Identity 'WebhookHosts' -Members 'WEBHOOK01$'
# the host needs to reboot OR have its kerberos ticket flushed for the new group membership to applyOn the webhook server machine itself:
# from elevated PowerShell, AD PowerShell module installed (RSAT)
Install-ADServiceAccount svc-webhookserver
Test-ADServiceAccount svc-webhookserver # should return TrueIf Test-ADServiceAccount returns False, check:
- Host is in the
WebhookHostsgroup (or whoever's inPrincipalsAllowedToRetrieveManagedPassword) - Host has been rebooted since being added to the group
- KDS root key has had time to propagate (10 hours by default)
# from elevated PowerShell on the webhook host
sc.exe stop WebhookServer
sc.exe config WebhookServer obj= 'CONTOSO\svc-webhookserver$'
sc.exe start WebhookServerNote the trailing $. There is no password parameter for gMSAs. The trailing $ is what tells the SCM "look up this account in AD as a managed service account, retrieve its password automatically."
Give the gMSA only what it needs. For a typical "reset user passwords" workload:
# Delegate "Reset password and force change at next logon" on a specific OU
$ou = "OU=Standard Users,DC=contoso,DC=local"
dsacls $ou /I:S /G "CONTOSO\svc-webhookserver$:CA;Reset Password;user"
dsacls $ou /I:S /G "CONTOSO\svc-webhookserver$:WP;pwdLastSet;user"…or use the GUI Delegation of Control wizard in Active Directory Users and Computers.
# 1. Create the user (one time)
New-ADUser -Name "svc-webhookserver" -SamAccountName "svc-webhookserver" `
-AccountPassword (Read-Host -AsSecureString "password") -Enabled $true `
-PasswordNeverExpires $true -CannotChangePassword $true
# 2. Grant "Log on as a service" right on the host:
# secpol.msc -> Local Policies -> User Rights Assignment -> Log on as a service
# Add CONTOSO\svc-webhookserver
# 3. Configure the service:
sc.exe config WebhookServer obj= "CONTOSO\svc-webhookserver" password= "..."You own password rotation. When you change the password in AD, also update the service via sc.exe config WebhookServer password= "newpw" and restart it.
-
Service mode hooks now run as the new account. PowerShell
whoamifrom inside a hook will show the new identity. -
InteractiveUser hooks stop working if you switch off LocalSystem. Only SYSTEM can call
WTSQueryUserToken. If you need both AD-write hooks and UI-on-desktop hooks, pick one of:- Keep service as LocalSystem and use SpecificUser mode for AD-write hooks
- Switch service to a gMSA / domain user and drop UI hooks (or move them to a separate Webhook Server instance running as LocalSystem)
-
SpecificUser hooks continue to work regardless. They use a separate
LogonUsertoken per call.
After changing the service account, restart the service and add a quick diagnostic endpoint:
slug: whoami
auth: none
executor: Windows PowerShell
inline command: whoami; whoami /groups
Hit it and verify the output matches the account you configured. The first line should be domain\svc-webhookserver (or domain\machine$ for LocalSystem on a domain-joined host).