Summary
dbatools can audit Windows privileges (Get-DbaPrivilege) and grant them (Set-DbaPrivilege), but it cannot revoke one. There is no Remove-DbaPrivilege, so undoing a grant - a wrongly targeted LPIM, an IFI grant that a security review wants gone, a service account that changed - currently means exporting the local security policy with secedit /export, hand-editing the SID out of the right's line, and re-importing with secedit /configure. That is exactly the manual work the Get/Set pair was written to remove.
Looking through the history, the gap seems to be nobody-asked rather than a decision: the pair arrived as bare initial commits, no issue or PR for a remove has ever existed, and the closest discussion (#7433) was about process token privileges, which the maintainers correctly identified as a different problem.
Proposed command
Remove-DbaPrivilege, mirroring Set-DbaPrivilege:
Remove-DbaPrivilege -ComputerName sql1 -Type LPIM,IFI # revoke from SQL service accounts / per-service SIDs
Remove-DbaPrivilege -ComputerName sql1 -Type IFI -User "CONTOSO\OldSvc" # revoke from a specific account
Same -Type set (IFI, LPIM, BatchLogon, SecAudit, ServiceLogon, CreateGlobalObjects), same automatic service-account discovery when -User is not given (including the NT SERVICE\<ServiceName> per-service SIDs that Set-DbaPrivilege uses for IFI/LPIM/SecAudit), SupportsShouldProcess, and a warning when the account does not hold the privilege.
Two implementation shapes
-
Reuse the secedit machinery. Set-DbaPrivilege already exports the policy, edits the SeXxx = *SID,*SID line, and runs secedit /configure /areas USER_RIGHTS. Removing is the inverse edit: strip the SID position-independently from the line and re-apply. Smallest possible diff, consistent with the existing pair, inherits its remoting/credential behavior.
-
Use the LSA API. LsaRemoveAccountRights (with LsaAddAccountRights / LsaEnumerateAccountsWithUserRight for the rest of the family) is the API that secedit itself sits on: no temp files, no cfg parsing, no fixed-offset Substring() calls. Verified working remotely over RPC/SMB, including with alternate credentials via LogonUser/LOGON32_LOGON_NEW_CREDENTIALS impersonation - but that is a bigger P/Invoke investment and changes the transport (port 445 instead of WinRM), so it would make more sense as a later reimplementation of the whole privilege family than as the price of admission for a remove command.
Shape 1 gets users unblocked; shape 2 is the better long-term home. I am happy to contribute shape 1 if there is interest.
Related: #10616 fixes the credential handling of the existing pair.
created by Claude and reviewed by Andreas Jordan
Summary
dbatools can audit Windows privileges (
Get-DbaPrivilege) and grant them (Set-DbaPrivilege), but it cannot revoke one. There is noRemove-DbaPrivilege, so undoing a grant - a wrongly targeted LPIM, an IFI grant that a security review wants gone, a service account that changed - currently means exporting the local security policy withsecedit /export, hand-editing the SID out of the right's line, and re-importing withsecedit /configure. That is exactly the manual work the Get/Set pair was written to remove.Looking through the history, the gap seems to be nobody-asked rather than a decision: the pair arrived as bare initial commits, no issue or PR for a remove has ever existed, and the closest discussion (#7433) was about process token privileges, which the maintainers correctly identified as a different problem.
Proposed command
Remove-DbaPrivilege, mirroringSet-DbaPrivilege:Same
-Typeset (IFI,LPIM,BatchLogon,SecAudit,ServiceLogon,CreateGlobalObjects), same automatic service-account discovery when-Useris not given (including theNT SERVICE\<ServiceName>per-service SIDs thatSet-DbaPrivilegeuses for IFI/LPIM/SecAudit),SupportsShouldProcess, and a warning when the account does not hold the privilege.Two implementation shapes
Reuse the secedit machinery.
Set-DbaPrivilegealready exports the policy, edits theSeXxx = *SID,*SIDline, and runssecedit /configure /areas USER_RIGHTS. Removing is the inverse edit: strip the SID position-independently from the line and re-apply. Smallest possible diff, consistent with the existing pair, inherits its remoting/credential behavior.Use the LSA API.
LsaRemoveAccountRights(withLsaAddAccountRights/LsaEnumerateAccountsWithUserRightfor the rest of the family) is the API that secedit itself sits on: no temp files, no cfg parsing, no fixed-offsetSubstring()calls. Verified working remotely over RPC/SMB, including with alternate credentials viaLogonUser/LOGON32_LOGON_NEW_CREDENTIALSimpersonation - but that is a bigger P/Invoke investment and changes the transport (port 445 instead of WinRM), so it would make more sense as a later reimplementation of the whole privilege family than as the price of admission for a remove command.Shape 1 gets users unblocked; shape 2 is the better long-term home. I am happy to contribute shape 1 if there is interest.
Related: #10616 fixes the credential handling of the existing pair.
created by Claude and reviewed by Andreas Jordan