source/Scripts/Configuration/Apply-STIGAutoLogonExceptions.ps1 (291 lines of code) (raw):
[CmdletBinding(SupportsShouldProcess = $true)]
param (
[Parameter(Mandatory = $false)]
[Hashtable] $DynParameters
)
[uri]$LGPOWebUrl = "https://www.microsoft.com/en-us/download/confirmation.aspx?id=55319"
[string]$LogDir = "$env:SystemRoot\Logs\Configuration"
[string]$ScriptName = "Apply-STIG-Exceptions"
[string]$Log = Join-Path -Path $LogDir -ChildPath "$ScriptName.log"
[string]$tempDir = Join-Path -Path $env:Temp -ChildPath $ScriptName
#region Functions
Function Get-InternetUrl {
[CmdletBinding()]
Param (
[Parameter(Mandatory = $true, Position = 0)]
[uri]$Url,
[Parameter(Mandatory = $true, Position = 1)]
[string]$searchstring
)
Begin {
[string]${CmdletName} = $PSCmdlet.MyInvocation.MyCommand.Name
}
Process {
Try {
Write-Verbose "${CmdletName}: Now extracting download URL from '$Url'."
$HTML = Invoke-WebRequest -Uri $Url -UseBasicParsing
$Links = $HTML.Links
$ahref = $null
$ahref=@()
$ahref = ($Links | Where-Object {$_.href -like "*$searchstring*"}).href
If ($ahref.count -eq 0 -or $null -eq $ahref) {
$ahref = ($Links | Where-Object {$_.OuterHTML -like "*$searchstring*"}).href
}
If ($ahref.Count -eq 1) {
Write-Verbose "${CmdletName}: Download URL = '$ahref'"
$ahref
}
Elseif ($ahref.Count -gt 1) {
Write-Verbose "${CmdletName}: Download URL = '$($ahref[0])'"
$ahref[0]
}
}
Catch {
Write-Error "${CmdletName}: Error Downloading HTML and determining link for download."
Exit 1
}
}
End {
}
}
Function Get-InternetFile {
[CmdletBinding()]
Param (
[Parameter(Mandatory = $true, Position = 0)]
[uri]$Url,
[Parameter(Mandatory = $true, Position = 1)]
[string]$OutputDirectory,
[Parameter(Mandatory = $false, Position = 2)]
[string]$OutputFileName
)
Begin {
[string]${CmdletName} = $PSCmdlet.MyInvocation.MyCommand.Name
$ProgressPreference = 'SilentlyContinue'
}
Process {
$start_time = Get-Date
If (!$OutputFileName) {
Write-Verbose "${CmdletName}: No OutputFileName specified. Trying to get file name from URL."
If ((split-path -path $Url -leaf).Contains('.')) {
$OutputFileName = split-path -path $url -leaf
Write-Verbose "${CmdletName}: Url contains file name - '$OutputFileName'."
}
Else {
Write-Verbose "${CmdletName}: Url does not contain file name. Trying 'Location' Response Header."
$request = [System.Net.WebRequest]::Create($url)
$request.AllowAutoRedirect=$false
$response=$request.GetResponse()
$Location = $response.GetResponseHeader("Location")
If ($Location) {
$OutputFileName = [System.IO.Path]::GetFileName($Location)
Write-Verbose "${CmdletName}: File Name from 'Location' Response Header is '$OutputFileName'."
}
Else {
Write-Verbose "${CmdletName}: No 'Location' Response Header returned. Trying 'Content-Disposition' Response Header."
$result = Invoke-WebRequest -Method GET -Uri $Url -UseBasicParsing
$contentDisposition = $result.Headers.'Content-Disposition'
If ($contentDisposition) {
$OutputFileName = $contentDisposition.Split("=")[1].Replace("`"","")
Write-Verbose "${CmdletName}: File Name from 'Content-Disposition' Response Header is '$OutputFileName'."
}
}
}
}
If ($OutputFileName) {
$wc = New-Object System.Net.WebClient
$OutputFile = Join-Path $OutputDirectory $OutputFileName
Write-Verbose "${CmdletName}: Downloading file at '$url' to '$OutputFile'."
Try {
$wc.DownloadFile($url, $OutputFile)
$time = (Get-Date).Subtract($start_time).Seconds
Write-Verbose "Time taken: '$time' seconds."
if (Test-Path -Path $outputfile) {
$totalSize = (Get-Item $outputfile).Length / 1MB
Write-Verbose "${CmdletName}: Download was successful. Final file size: '$totalsize' mb"
$OutputFile
}
}
Catch {
Write-Error "${CmdletName}: Error downloading file. Please check url."
Exit 2
}
}
Else {
Write-Error "${CmdletName}: No OutputFileName specified. Unable to download file."
Exit 2
}
}
End {
}
}
Function Update-LocalGPOTextFile {
[CmdletBinding(DefaultParameterSetName = 'Set')]
Param (
[Parameter(Mandatory = $true, ParameterSetName = 'Set')]
[Parameter(Mandatory = $true, ParameterSetName = 'Delete')]
[Parameter(Mandatory = $true, ParameterSetName = 'DeleteAllValues')]
[ValidateSet('Computer', 'User')]
[string]$scope,
[Parameter(Mandatory = $true, ParameterSetName = 'Set')]
[Parameter(Mandatory = $true, ParameterSetName = 'Delete')]
[Parameter(Mandatory = $true, ParameterSetName = 'DeleteAllValues')]
[string]$RegistryKeyPath,
[Parameter(Mandatory = $true, ParameterSetName = 'Set')]
[Parameter(Mandatory = $true, ParameterSetName = 'Delete')]
[Parameter(Mandatory = $true, ParameterSetName = 'DeleteAllValues')]
[string]$RegistryValue,
[Parameter(Mandatory = $true, ParameterSetName = 'Set')]
[AllowEmptyString()]
[string]$RegistryData,
[Parameter(Mandatory = $true, ParameterSetName = 'Set')]
[ValidateSet('DWORD', 'String')]
[string]$RegistryType,
[Parameter(Mandatory = $false, ParameterSetName = 'Delete')]
[switch]$Delete,
[Parameter(Mandatory = $false, ParameterSetName = 'DeleteAllValues')]
[switch]$DeleteAllValues,
[string]$outputDir = "$TempDir",
[string]$outfileprefix = $appName
)
Begin {
[string]${CmdletName} = $PSCmdlet.MyInvocation.MyCommand.Name
}
Process {
# Convert $RegistryType to UpperCase to prevent LGPO errors.
$ValueType = $RegistryType.ToUpper()
# Change String type to SZ for text file
If ($ValueType -eq 'STRING') { $ValueType = 'SZ' }
# Replace any incorrect registry entries for the format needed by text file.
$modified = $false
$SearchStrings = 'HKLM:\', 'HKCU:\', 'HKEY_CURRENT_USER:\', 'HKEY_LOCAL_MACHINE:\'
ForEach ($String in $SearchStrings) {
If ($RegistryKeyPath.StartsWith("$String") -and $modified -ne $true) {
$index = $String.Length
$RegistryKeyPath = $RegistryKeyPath.Substring($index, $RegistryKeyPath.Length - $index)
$modified = $true
}
}
#Create the output file if needed.
$Outfile = "$OutputDir\$Outfileprefix-$Scope.txt"
If (-not (Test-Path -LiteralPath $Outfile)) {
If (-not (Test-Path -LiteralPath $OutputDir -PathType 'Container')) {
Try {
$null = New-Item -Path $OutputDir -Type 'Directory' -Force -ErrorAction 'Stop'
}
Catch {}
}
$null = New-Item -Path $outputdir -Name "$OutFilePrefix-$Scope.txt" -ItemType File -ErrorAction Stop
}
Write-Verbose "${CmdletName}: Adding registry information to '$outfile' for LGPO.exe"
# Update file with information
Add-Content -Path $Outfile -Value $Scope
Add-Content -Path $Outfile -Value $RegistryKeyPath
Add-Content -Path $Outfile -Value $RegistryValue
If ($Delete) {
Add-Content -Path $Outfile -Value 'DELETE'
}
ElseIf ($DeleteAllValues) {
Add-Content -Path $Outfile -Value 'DELETEALLVALUES'
}
Else {
Add-Content -Path $Outfile -Value "$($ValueType):$RegistryData"
}
Add-Content -Path $Outfile -Value ""
}
End {
}
}
Function Invoke-LGPO {
[CmdletBinding()]
Param (
[string]$InputDir = "$TempDir",
[string]$SearchTerm
)
Begin {
[string]${CmdletName} = $PSCmdlet.MyInvocation.MyCommand.Name
}
Process {
Write-Verbose "${CmdletName}: Gathering Registry text files for LGPO from '$InputDir'"
If ($SearchTerm) {
$InputFiles = Get-ChildItem -Path $InputDir -Filter "$SearchTerm*.txt"
}
Else {
$InputFiles = Get-ChildItem -Path $InputDir -Filter '*.txt'
}
ForEach ($RegistryFile in $inputFiles) {
$TxtFilePath = $RegistryFile.FullName
Write-Verbose "${CmdletName}: Now applying settings from '$txtFilePath' to Local Group Policy via LGPO.exe."
$lgporesult = Start-Process -FilePath 'lgpo.exe' -ArgumentList "/t `"$TxtFilePath`"" -Wait -PassThru
Write-Verbose "${CmdletName}: LGPO exitcode: '$($lgporesult.exitcode)'"
}
Write-Verbose "${CmdletName}: Gathering Security Templates files for LGPO from '$InputDir'"
$ConfigFile = Get-ChildItem -Path $InputDir -Filter '*.inf'
If ($ConfigFile) {
$ConfigFile = $ConfigFile.FullName
Write-Verbose "${CmdletName}: Now applying security settings from '$ConfigFile' to Local Security Policy via LGPO.exe."
$lgporesult = Start-Process -FilePath 'lgpo.exe' -ArgumentList "/s `"$ConfigFile`"" -Wait -PassThru
Write-Verbose "${CmdletName}: LGPO exitcode: '$($lgporesult.exitcode)'"
}
}
End {
}
}
#endregion Functions
# these are settings that are known to be required to provide the best autologon experience.
$SecFileContent = @'
[Unicode]
Unicode=yes
[Version]
signature="$CHICAGO$"
Revision=1
[Registry Values]
MACHINE\Software\Microsoft\Windows\CurrentVersion\Policies\System\LegalNoticeCaption=1,
MACHINE\Software\Microsoft\Windows\CurrentVersion\Policies\System\LegalNoticeText=7,
MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\Pku2u\AllowOnlineID=4,1
MACHINE\Software\Microsoft\Windows\CurrentVersion\Policies\System\InactivityTimeoutSecs=4,0
'@
If (-not (Test-Path $env:SystemRoot\Logs)) {
New-Item -Path $env:SystemRoot -Name 'Logs' -ItemType Directory -Force
}
If (-not (Test-Path $LogDir)) {
New-Item -Path "$env:SystemRoot\Logs" -Name 'Configuration' -ItemType Directory -Force
}
If (-not (Test-Path $TempDir)) {
New-Item -Path "$env:Temp" -Name $ScriptName -ItemType Directory -Force
}
Start-Transcript -Path $Log -Force -IncludeInvocationHeader
Write-Output "Checking for lgpo.exe in '$env:SystemRoot\system32'."
If (-not(Test-Path -Path "$env:SystemRoot\System32\Lgpo.exe")) {
Write-Output "Not found. Downloading Local GPO tool (lgpo.exe) from Internet."
$LGPOUrl = Get-InternetUrl -Url $LGPOWebUrl -Searchstring "LGPO" -Verbose
If ($LGPOUrl) {
$LGPOZip = Get-InternetFile -url $LGPOUrl -OutputDir $TempDir -Verbose
If ($LGPOZip) {
Write-Output "Expanding '$LGPOZip' to '$TempDir'."
Expand-Archive -path "$LGPOZip" -DestinationPath "$TempDir" -force
$algpoexe = Get-ChildItem -Path $TempDir -filter 'lgpo.exe' -recurse
If ($algpoexe.count -gt 0) {
$lgpoexe=$algpoexe[0].FullName
Write-Output "Copying '$lgpoexe' to '$env:SystemRoot\system32'."
Copy-Item -Path $lgpoexe -Destination "$env:SystemRoot\System32" -force
}
Else {
Write-Error "'lgpo.exe' not found in downloaded zip."
Exit 2
}
}
}
}
If (Test-Path -Path "$env:SystemRoot\System32\Lgpo.exe") {
$SecFileContent | Out-File -FilePath "$tempDir\STIGExceptions.inf" -Encoding unicode
$appName = 'STIG_Exceptions'
Update-LocalGPOTextFile -Scope 'Computer' -RegistryKeyPath 'SOFTWARE\Policies\Microsoft\Edge' -RegistryValue 'ProxySettings' -Delete -outfileprefix $appName -Verbose
Invoke-LGPO -Verbose
}
Else {
Write-Error "Unable to configure local policy with lgpo tool because it was not found and could not be downloaded."
Stop-Transcript
Exit 2
}
Remove-Item -Path $TempDir -Recurse -Force -ErrorAction SilentlyContinue
Stop-Transcript