Get-Set-LocalPolicies.ps1 (zpäť na zoznam) Zisťovanie a zmena niektorých lokálnych politík.
			#ISSUES
#
# -- 1 -- for servers running 2008R1 and with MSSQL, there's issue with importing .inf file and service accounts for these applications
#         secedit doesn't know how to import these accounts if there is not "NT SERVICE\" prefix before account names
#         possible fix is to search for instance names and add this prefix for every occurence in privileges section in .inf file, part of account name is the name of SQL instance so it is searchable
#         possible issue also for IIS, not yet investigated/no issue reported yet
#         actuall fix is to skip import for every 2008R1 with MSSQL and IIS, hovewer policies to replace and alert message are written to log to be able to check those servers manually


$secpolDbPath = "c:\temp\secpol.sdb" #security database location
$secpolBkpPath = "c:\windows\security\templates\secpol.bkp.inf" #path to backup configuration file
$secpolTmpltPath = "c:\temp\secpol.inf" #path to configuration file to work with
$resultLog = ""
$hostname = invoke-expression -command "hostname"
$isDC = (Get-WindowsFeature | Where {$_.Name -eq "AD-Domain-Services"}).installed #check if server is domain controller, need for later to check wether to rename newAdministratorName admin or not
$isSQL = Get-Service | Where {$_.name -match "SQL"} #check if SQL is installed
$isIIS = Get-Service | Where {$_.name -match "w3svc"} #check if IIS is installed
$skipImport = $false #see issue #1

$systemInfoOS = gwmi Win32_OperatingSystem
$OSBuildVersion = $systemInfoOS.Version

#For 2012
#secpol.inf -> MACHINE\Software\Microsoft\Windows\CurrentVersion\Policies\System\InactivityTimeoutSecs=4,1800
#registry -> HKLM\Software\Microsoft\Windows\CurrentVersion\Policies\System\InactivityTimeoutSecs reg_dword 1800d/708h


if ($OSBuildVersion -match "6\.0") { #chcek if server is 2008R1
    if ($isSQL -or $isIIS) { #check if has SQL or IIS installed
        $skipImport = $true #skip import set to true, because server is 2008R1 and has IIS or MSSQL installed which is causing privileges discrepancy, see issue #1
    }
}

$output = invoke-expression -command "secedit /export /cfg $secpolBkpPath" #exporting backup configuration, it's in variable so it's not written to console, same for later
$output = invoke-expression -command "secedit /export /cfg $secpolTmpltPath" #exporting configuration to work with

#array of policies to check with required values
$arraysOfPolicies = @(
    ("NewAdministratorName","admin1|admin2"),
    ("EnableGuestAccount","0","eq"),
    ("NewGuestName",'"localguest"',"eq"),
    ("MinimumPasswordAge","1","eq"),
    ("MaximumPasswordAge","90","gt"), #if value is higher than 90, don't choose for replace (softer setting)
    ("MinimumPasswordLength","8","lt"), #if value is lower than 8, don't choose for replace (softer setting)
    ("PasswordComplexity","1","eq"),
    ("PasswordHistorySize","6","lt"),
    ("LockoutBadCount","6","gt"), #this should be from 1-6
    ("ResetLockoutCount","60","lt"),
    ("LockoutDuration","60","lt")
)
$policiesToReplace = @()

#if ($OSBuildVersion -match "6\.3") {
#    $arraysOfPolicies += ,("InactivityTimeoutSecs","4,1800") #addiotion for windows 2012 to timeout inactive session after 1hour
#}

#Function to check wether policy should be replaced or not
function checkToReplace {
    param ($array)
    for ($i = 0; $i -lt $array.Length; $i++) {
        if ($array[$i][0] -eq "NewAdministratorName") {
            if (-not $script:isDC) {
                #check here current administrator name and add to policiesToReplace if any of these are set
                $script:policiesToReplace += ,("NewAdministratorName",'"_admin1_|_admin2_"')
            }
            continue
        }
#        if ($array[$i][0] -eq "InactivityTimeoutSecs") {
#            Get-Content $script:secpolTmpltPath | Where {$_ -match $policy + ' =.+'}
#        }
        if ($array[$i][2] -eq "eq") {
            $script:policiesToReplace += ,($array[$i][0],$array[$i][1])
        }
        elseif ($array[$i][2] -match "lt|gt") {
            [int]$substr = createSubstring $array[$i][0] #to return value behind "="
            if ($array[$i][2] -eq "lt") {
                if ($substr -lt $array[$i][1]) { #if the actual value is lower choose for replace
                    $script:policiesToReplace += ,($array[$i][0],$array[$i][1])
                }
            }
            elseif ($array[$i][2] -eq "gt") {
                if ($substr -gt $array[$i][1]) { #if the actual value is higher choose for replace
                    $script:policiesToReplace += ,($array[$i][0],$array[$i][1])
                }
            }
            if ($array[$i][0] -eq "LockoutBadCount") { #policy should be between 1-6, 0 is disable, 7 is not desired
                if ($substr -lt 7 -and $substr -gt 0) {
                    continue
                }
                else {
                    $script:policiesToReplace += ,($array[$i][0],$array[$i][1])
                }
            }
        }
    }
}

#to create substring behind "=" to check wether policy is softer or not
function createSubstring {
    param ($policy)
    $policyLine = Get-Content $script:secpolTmpltPath | Where {$_ -match $policy + ' =.+'}
    $actualPolicyValue = $policyLine.substring($policyLine.Length - ($policyLine.Length - $policy.Length - 3), ($policyLine.Length - $policy.Length - 3)) #-3 is because of string " = " in line after policy name
    return $actualPolicyValue
}


#to replace policy value with second value from array
function replace {
    param ($array)
    for ($i = 0; $i -lt $array.length; $i++) {
        $part1 = $array[$i][0]
        $part2 = $array[$i][1]
        (Get-Content $script:secpolTmpltPath) | Foreach-Object {[regex]::replace($_, $array[$i][0] + ' =.+', "$part1 = $part2")} | Set-Content $script:secpolTmpltPath
    }
}

#to check replaced policies after GPOs are applied
function checkAfterGPO {
    param ($array)
    if ($script:skipImport) {
        $script:resultLog += $script:hostname + ";" + "2008R1 with SQL or IIS, check policies manually" + "`n" #added alert message before policies are written to log, see issue #1
    }
    for ($i = 0; $i -lt $array.Length; $i++) {
        if ($array[$i][0] -eq "NewAdministratorName") {
            if (-not $script:isDC) {
                if (-not (Get-Content $script:secpolTmpltPath | Where {$_ -match $array[$i][0] + " = " + $array[$i][1]})) {
                    $script:resultLog += $script:hostname + ";" + $array[$i][0] + "`n"
                }
            }
            else {
                continue
            }
        }
        else {
            if (-not (Get-Content $script:secpolTmpltPath | Where {$_ -match $array[$i][0] + " = " + $array[$i][1]})) {
                $script:resultLog += $script:hostname + ";" + $array[$i][0] + "`n"
            }
        }
    }
}

checkToReplace $arraysOfPolicies
replace $policiesToReplace

if ($skipImport) {
    #skip import of policies see issue #1
}
else {
    $output = invoke-expression -command "secedit /configure /db $secpolDbPath /cfg $secpolTmpltPath" #applying new local policy
    #check here, if output has any errors
}

$output = gpupdate /Force #applying GPOs to check for replaced policies
$output = invoke-expression -command "secedit /export /cfg $secpolTmpltPath" #exporting config to check policies

checkAfterGPO $policiesToReplace
write-host $resultLog

Remove-Item -force $secpolTmpltPath -confirm:$false #removing policy file
Remove-Item -force $secpolDbPath -confirm:$false #removing policy database