Document service account choices for AD-aware hooks
Add a Service account section to PLAN.md and README.md covering LocalSystem, domain user, and gMSA install paths so users running AD PowerShell scripts know which identity to pick. Drop the stale "outbound webhook delivery" out-of-scope bullet now that callbacks are in v1. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -229,6 +229,35 @@ Order in the request pipeline matters: **IP check runs before auth.** That avoid
|
||||
|
||||
This covers GitHub, Stripe, Slack, generic CI patterns by tweaking the four fields.
|
||||
|
||||
## Service account
|
||||
|
||||
The service itself runs fine under any account — this section is about which account makes sense for the **scripts** the service launches, since they inherit its identity.
|
||||
|
||||
| Account | Network identity | When to use |
|
||||
|---|---|---|
|
||||
| `LocalSystem` (default) | Computer account `DOMAIN\MACHINE$` on a domain-joined host; nothing on a workgroup host | Default. Local-only scripts, or read-only AD queries on a domain-joined machine. Most powerful local account — any webhook script effectively runs as SYSTEM. |
|
||||
| `LocalService` | None — no network credentials | **Don't.** Cannot talk to AD or any other remote resource that requires Windows auth. Listed only to rule it out. |
|
||||
| `NetworkService` | Computer account, same as LocalSystem | Slightly less local privilege than LocalSystem; same network identity. Rarely worth the switch. |
|
||||
| Domain user (`DOMAIN\svc-webhookserver`) | That user | Need write/admin operations against AD (password resets, group changes, OU creates). You own password rotation. |
|
||||
| **gMSA** (`DOMAIN\svc-webhookserver$`) | That gMSA | **Recommended for AD-write workloads.** AD generates and rotates the password automatically. Requires domain functional level 2012+ and `Install-ADServiceAccount` on the host. |
|
||||
|
||||
Install commands by account type:
|
||||
|
||||
```powershell
|
||||
# LocalSystem (default)
|
||||
sc.exe create WebhookServer binPath= "C:\path\WebhookServer.Service.exe" start= auto
|
||||
|
||||
# Domain user
|
||||
sc.exe create WebhookServer binPath= "..." obj= "DOMAIN\svc-webhookserver" password= "..." start= auto
|
||||
|
||||
# gMSA — note the trailing $ and no password=
|
||||
sc.exe create WebhookServer binPath= "..." obj= "DOMAIN\svc-webhookserver$" start= auto
|
||||
```
|
||||
|
||||
`scripts/install-service.ps1` will accept a `-ServiceAccount` parameter that defaults to `LocalSystem` and accepts a domain user or gMSA name. README will document the gMSA setup once for users who need AD writes from their hooks.
|
||||
|
||||
The service code itself makes no assumptions about the account — DPAPI uses `LocalMachine` scope so secret decryption works under any local identity.
|
||||
|
||||
## Secret storage (DPAPI)
|
||||
|
||||
Endpoint `Secret` is stored in JSON as `{ "encrypted": "<base64 of ProtectedData.Protect(utf8(secret), null, LocalMachine)>" }`. Decrypt only inside the service when needed. The GUI submits secrets in plaintext over the named pipe (local-machine, ACL-restricted), service encrypts before writing.
|
||||
|
||||
@@ -69,7 +69,31 @@ sc.exe create WebhookServer binPath= "C:\Program Files\WebhookServer\WebhookServ
|
||||
sc.exe start WebhookServer
|
||||
```
|
||||
|
||||
`scripts/install-service.ps1` will wrap this once implemented.
|
||||
`scripts/install-service.ps1` will wrap this once implemented and will accept a `-ServiceAccount` parameter.
|
||||
|
||||
## Service account & Active Directory
|
||||
|
||||
The service runs as `LocalSystem` by default — fine for local-only scripts and read-only AD queries (it authenticates to the domain as the computer account). If your webhook scripts need to **modify** AD (password resets, group changes, etc.), run the service under an account with the right delegated rights:
|
||||
|
||||
- **Recommended: gMSA** — Active Directory generates and rotates the password automatically.
|
||||
```powershell
|
||||
# on a DC, once
|
||||
New-ADServiceAccount -Name svc-webhookserver -DNSHostName host.domain.local `
|
||||
-PrincipalsAllowedToRetrieveManagedPassword "DOMAIN\WebhookHosts"
|
||||
# on the webhook host
|
||||
Install-ADServiceAccount svc-webhookserver
|
||||
sc.exe create WebhookServer binPath= "..." obj= "DOMAIN\svc-webhookserver$" start= auto
|
||||
```
|
||||
Note the trailing `$` and the absence of `password=`.
|
||||
|
||||
- **Plain domain user** — works on older domains, but you own password rotation:
|
||||
```powershell
|
||||
sc.exe create WebhookServer binPath= "..." obj= "DOMAIN\svc-webhookserver" password= "..." start= auto
|
||||
```
|
||||
|
||||
Don't use `LocalService` — it has no network identity and cannot talk to a domain controller.
|
||||
|
||||
> Heads up: any account the service runs under is the account your hook scripts run under. `LocalSystem` is the most powerful local account on the machine — treat webhook script contents as privileged.
|
||||
|
||||
## Configuration
|
||||
|
||||
@@ -78,7 +102,6 @@ The service reads `C:\ProgramData\WebhookServer\config.json`. Edit it through th
|
||||
## Out of scope for v1
|
||||
|
||||
- Importing/exporting config across machines (DPAPI LocalMachine scope ties decryption to the host).
|
||||
- Outbound webhook delivery / retry queues.
|
||||
- Per-endpoint rate limiting.
|
||||
- Multi-user RBAC for the GUI.
|
||||
- Auto-update.
|
||||
|
||||
Reference in New Issue
Block a user