Skip to content

Instantly share code, notes, and snippets.

@jeffpatton1971
Last active September 12, 2021 16:07
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jeffpatton1971/354c4c0948a93ea5b9e0 to your computer and use it in GitHub Desktop.
Save jeffpatton1971/354c4c0948a93ea5b9e0 to your computer and use it in GitHub Desktop.
Configure the SQL LowPriv Environment.
<#
This script will configure the local machine for the SQL MP
Low Privilege Environment
We need to set the following items on the server
Add SQLDefaultAction account and SQLMonitor account to
Performance Monitor Users
Add SQLDefaultAction account and SQLMonitor account to
EventLog Readers
Add SQLDefaultAction account and SQLMPLowPriv group to
Users
Grant SQLDefaultAction account and SQLMPLowPriv group
Logon Locally User Right
Grant SQLDefaultAction account and SQLMPLowPriv group
Read Permission
HKLM:\Software\Microsoft\Microsoft SQL Server\
Grant SQLMPLowPriv group
Read Permission
HKLM:\Software\Microsoft\Microsoft SQL Server\$INSTANCEID\MSSQLServer\Parameters
Grant SQLDefaultAction account and SQLMPLowPriv group
Execute Methods, Enable Account, Remote Enable, Read Security Permission
WMI:\root\cimv2
WMI:\root\default
WMI:\root\Microsoft\SqlServer\ComputerManagement
For each item we need to test if true, and if false
perform the required item.
This may be able to be turned into a DSC flow.
#>
Param
(
$Computername = $env:COMPUTERNAME,
[string] $ActionAccount,
[string] $LowPrivGroup
)
Import-Module C:\temp\SqlManagement.psm1
Import-Module C:\temp\ActiveDirectoryManagement.psm1
[System.Management.Automation.PSCredential] $SqlDefaultAction = (New-Object System.Management.Automation.PSCredential($ActionAccount,(New-Object System.Security.SecureString($null))))
[System.Security.Principal.NTAccount]$Account = New-Object System.Security.Principal.NTAccount($SqlDefaultAction.UserName);
[string]$sqlDaSid = $Account.Translate([System.Security.Principal.SecurityIdentifier]).ToString();
[System.Management.Automation.PSCredential] $SQLMPLowPriv = (New-Object System.Management.Automation.PSCredential($LowPrivGroup,(New-Object System.Security.SecureString($null))))
[System.Security.Principal.NTAccount]$Account = New-Object System.Security.Principal.NTAccount($SQLMPLowPriv.UserName);
[string]$sqlLpSid = $Account.Translate([System.Security.Principal.SecurityIdentifier]).ToString();
#
# Test group membership for the following groups
# Performance Monitor Users
# EventLog Readers
# Users
#
$Groups = @("Performance Monitor Users","Event Log Readers","Users");
foreach ($Group in $Groups)
{
$Members = Get-LocalGroupMembers -ComputerName $Computername -GroupName $Group;
if (!($Members |Where-Object {$_.Name -eq $SqlDefaultAction.GetNetworkCredential().UserName}))
{
#
# Account not found
#
Add-UserToLocalGroup -ComputerName $Computername -UserName $SqlDefaultAction.GetNetworkCredential().UserName -LocalGroup $Group -UserDomain $SqlDefaultAction.GetNetworkCredential().Domain;
}
if (!($Members |Where-Object {$_.Name -eq $SQLMPLowPriv.GetNetworkCredential().UserName}))
{
#
# Account not found
#
Add-UserToLocalGroup -ComputerName $Computername -UserName $SQLMPLowPriv.GetNetworkCredential().UserName -LocalGroup $Group -UserDomain $SQLMPLowPriv.GetNetworkCredential().Domain;
}
}
#
# Test logon locally right for the following accounts
# SQLDefaultAction
# SQLMPLowPriv
#
# http://gallery.technet.microsoft.com/PowerShell-script-to-add-b005e0f6#content
#
$tmp = [System.IO.Path]::GetTempFileName()
secedit.exe /export /cfg "$($tmp)"
$Configuration = Get-Content -Path $tmp
$currentSetting = ""
foreach($Line in $Configuration)
{
if( $Line -like "SeInteractiveLogonRight*")
{
$x = $Line.split("=",[System.StringSplitOptions]::RemoveEmptyEntries)
$currentSetting = $x[1].Trim()
}
}
Remove-Item $tmp;
if (!(($currentSetting.Contains($sqlDaSid)) -and ($currentSetting.Contains($sqlLpSid))))
{
if (!($currentSetting.Contains($sqlDaSid)))
{
$currentSetting += ",*$($sqlDaSid)";
}
if (!($currentSetting.Contains($sqlLpSid)))
{
$currentSetting += ",*$($sqlLpSid)";
}
Write-Host $currentSetting
$outFile = @"
[Unicode]
Unicode=yes
[Version]
signature="`$CHICAGO`$"
Revision=1
[Privilege Rights]
SeInteractiveLogonRight = $($currentSetting)
"@
$tmp = [System.IO.Path]::GetTempFileName()
$outFile | Set-Content -Path $tmp -Encoding Unicode -Force
Push-Location (Split-Path $tmp);
try
{
secedit.exe /configure /db "secedit.sdb" /cfg "$($tmp)" /areas USER_RIGHTS
}
finally
{
Pop-Location
Remove-Item $tmp
}
}
else
{
Write-Host "NO ACTIONS REQUIRED! Account already in ""Allow Logon Locally"""
}
#
# http://msdn.microsoft.com/en-us/library/ms147899(v=vs.110).aspx
#
# Test Read Permission for the following registry entries
# HKLM:\Software\Microsoft\Microsoft SQL Server\
#
# Will need to get each instance first
#
# HKLM:\Software\Microsoft\Microsoft SQL Server\$INSTANCEID\MSSQLServer\Parameters
#
$Registry = "HKLM:\Software\Microsoft\Microsoft SQL Server\";
try
{
$Acl = Get-Acl $Registry -ErrorAction SilentlyContinue;
$Aces = ($Acl |Select-Object -Property Access).Access;
if (!($Aces |Where-Object {$_.IdentityReference -eq $SqlDefaultAction.UserName}))
{
#
Write-Host "Missing permission for SqlDefaultAction"
#
$Ace = New-Object System.Security.AccessControl.RegistryAccessRule(
$SqlDefaultAction.UserName,
[System.Security.AccessControl.RegistryRights]::ReadKey,
[System.Security.AccessControl.InheritanceFlags]::ContainerInherit,
[System.Security.AccessControl.PropagationFlags]::None,
[System.Security.AccessControl.AccessControlType]::Allow);
$Acl.SetAccessRule($Ace);
}
if (!($Aces |Where-Object {$_.IdentityReference -eq $SQLMPLowPriv.UserName}))
{
#
write-host "Missing permission for SQLMPLowPriv"
#
$Ace = New-Object System.Security.AccessControl.RegistryAccessRule(
$SQLMPLowPriv.UserName,
[System.Security.AccessControl.RegistryRights]::ReadKey,
[System.Security.AccessControl.InheritanceFlags]::ContainerInherit,
[System.Security.AccessControl.PropagationFlags]::None,
[System.Security.AccessControl.AccessControlType]::Allow);
$Acl.SetAccessRule($Ace);
}
$Instances = Get-SQLInstance;
foreach ($Instance in $Instances)
{
$InstanceReg = "$($Registry)$($Instance.InstanceID)\MSSQLServer\Parameters";
Write-Host $InstanceReg
$Acl = Get-Acl $InstanceReg;
$Aces = (Acl |Select-Object -Property Access).Access;
if (!($Aces |Where-Object {$_.IdentityReference -eq $SQLMPLowPriv.UserName}))
{
#
Write-Host "Missing permission for SQLMPLowPriv"
#
$Ace = New-Object System.Security.AccessControl.RegistryAccessRule(
$SQLMPLowPriv.UserName,
[System.Security.AccessControl.RegistryRights]::ReadKey,
[System.Security.AccessControl.InheritanceFlags]::ContainerInherit,
[System.Security.AccessControl.PropagationFlags]::None,
[System.Security.AccessControl.AccessControlType]::Allow);
$Acl.SetAccessRule($Ace);
}
}
}
catch
{
Write-Host "SQL Not Installed"
}
#
# Test Execute Methods, Enable Account, Remote Enable, Read Security Permission on WMI entries
# WMI:\root\cimv2
# WMI:\root\default
#
# This entry depends on the sql version installed, so we just need to match ComputerManagement
#
# WMI:\root\Microsoft\SqlServer\ComputerManagement
#
#
$Namespaces = @("root\cimv2","root\default","root\Microsoft\SqlServer\ComputerManagement10","root\Microsoft\SqlServer\ComputerManagement11");
Write-Host $Namespaces
foreach ($Namespace in $Namespaces)
{
try
{
$Error.Clear()
$Security = Get-WmiObject -Class __SystemSecurity -Namespace $Namespace -ErrorAction SilentlyContinue
$Descriptor = @($null);
$Result = $Security.PsBase.InvokeMethod("GetSD",$Descriptor)
if ($Result -eq 0)
{
$daSDDL = "(A;;CCDCWPRC;;;$($sqlDaSid))";
$converter = New-Object System.Management.ManagementClass Win32_SecurityDescriptorHelper;
$rootSDDL = $converter.BinarySDToSDDL($Descriptor[0]);
if (!($rootSDDL.SDDL.Contains($sqlDaSid)))
{
$NewSDDL = $rootSDDL.SDDL += $daSDDL;
$WMIbinarySD = $converter.SDDLToBinarySD($NewSDDL);
$WMIconvertedPermissions = ,$WMIbinarySD.BinarySD;
$Result = $security.PsBase.InvokeMethod("SetSD",$WMIconvertedPermissions);
}
$lpSDDL = "(A;;CCDCWPRC;;;$($sqlLpSid))";
if (!($rootSDDL.SDDL.Contains($sqlLpSid)))
{
$NewSDDL = $rootSDDL.SDDL += $lpSDDL;
$WMIbinarySD = $converter.SDDLToBinarySD($NewSDDL);
$WMIconvertedPermissions = ,$WMIbinarySD.BinarySD;
$Result = $security.PsBase.InvokeMethod("SetSD",$WMIconvertedPermissions);
}
}
else
{
Write-Error "An error occurred retreiving Security Definitions from WMI.`r`nError Number : $($Result)";
break;
}
}
catch
{
$_
}
}
#
# http://msdn.microsoft.com/en-us/library/aa394063(v=vs.85).aspx
#
# Don't need these, but don't want to lose them
#
$amFlags = @{1="FILE_READ_DATA";2="FILE_WRITE_DATA";4="FILE_APPEND_DATA";8="FILE_READ_EA";16="FILE_WRITE_EA";32="FILE_EXECUTE";64="FILE_DELETE_CHILD";128="FILE_READ_ATTRIBUTES";256="FILE_WRITE_ATTRIBUTES";65536="DELETE";131072="READ_CONTROL";262144="WRITE_DAC";524288="WRITE_OWNER";1048576="SYNCHRONIZE"}
$afFlags = @{1="OBJECT_INHERIT_ACE"; 2="CONTAINER_INHERIT_ACE";4="NO_PROPAGATE_INHERIT_ACE";8="INHERIT_ONLY_ACE";16="INHERITED_ACE"}
<#
This script will configure the SQL Server for the SQL MP
Low Privilege Environment
#>
@RoelJanssens
Copy link

When I try to run this script I get a lot of errors. What is the command line I should use? This is what I tried:

PS C:\Scripts\LowPriv> .\Setup-SQL-Server.ps1 "DOMAIN\ActionAccount" "DOMAIN\GroupName"

But then I get errors like this:

New-Object : Exception calling ".ctor" with "2" argument(s): "Cannot process argument because the value of argument "userName" is invalid. Change the value of the "userName" argument and run the operation again."

At C:\Scripts\LowPriv\Setup-SQL-Server.ps1:46 char:76

  • [System.Management.Automation.PSCredential] $SqlDefaultAction = (New-Object <<<< System.Management.Automation.PSCredential($ActionAccount,(New-Object System.Security.SecureString($null))))
    • CategoryInfo : InvalidOperation: (:) [New-Object], MethodInvocationException
    • FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommand

New-Object : Constructor not found. Cannot find an appropriate constructor for type System.Security.Principal.NTAccount
.

Please help, I'm not a PowerShell expert :(

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment