Last active
January 28, 2026 01:47
-
-
Save SweetAsNZ/a891eb771d0622b65c4dc377f2ba2ec5 to your computer and use it in GitHub Desktop.
Sets up the Windows Firewall log file and folder with the correct permissions and creates the log files. Then prompts to reboot.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Function Set-FirewallLogFile { | |
| <# | |
| .SYNOPSIS | |
| Sets up the Windows Firewall log file with the correct permissions. | |
| .DESCRIPTION | |
| This function creates a Windows Firewall log file at the specified location and sets the appropriate permissions for system services and administrators. | |
| Requires Administrator privileges. System reboot is required for changes to take effect. | |
| Added NetSH commands to configure firewall logging as overkill just in case. | |
| Script works for standard and .old log files after reboot | |
| .PARAMETER Filename | |
| The name of the firewall log file to create. Valid values: 'pfirewall.log', 'domainfw.log', 'privatefw.log', 'publicfw.log' | |
| .PARAMETER UseNetSH | |
| Switch to configure firewall logging using netsh commands. | |
| .EXAMPLE | |
| Set-FirewallLogFile -Filename 'domainfw.log' | |
| Creates domain firewall log file with proper permissions. | |
| .EXAMPLE | |
| Set-FirewallLogFile -Filename 'pfirewall.log' | |
| Creates dafault firewall log file with proper permissions. | |
| .EXAMPLE | |
| Set-FirewallLogFile 'domainfw.log' | |
| Set-FirewallLogFile 'domainfw.log.old' | |
| Set-FirewallLogFile 'privatefw.log' | |
| Set-FirewallLogFile 'privatefw.log.old' | |
| Set-FirewallLogFile 'publicfw.log' | |
| Set-FirewallLogFile 'publicfw.log.old' | |
| .NOTES | |
| Author: Tim West | |
| Created: 28/01/2026 | |
| Updated: 28/01/2026 | |
| Status: Production | |
| Version: 1.0.1 | |
| .CHANGELOG | |
| 28/01/2026 - Initial version | |
| 0.2.0 - Updated error handling and verbose output | |
| 0.3.0 - Added netsh configuration for firewall logging as overkill | |
| 0.4.0 - Improved permission setting logic | |
| 0.5.0 - Enhanced reboot prompt logic | |
| 1.0.1 - Finalized for production | |
| #> | |
| [CmdletBinding()] | |
| param ( | |
| [Parameter(Mandatory = $true)] | |
| [ValidateSet('pfirewall.log', 'domainfw.log', 'privatefw.log', 'publicfw.log','domainfw.log.old','privatefw.log.old','publicfw.log.old')] | |
| [string]$Filename, | |
| [switch]$UseNetSH | |
| ) | |
| #region Admin Check | |
| Write-Verbose "Checking for Administrator privileges..." | |
| if (-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)) { | |
| Write-Host "Run As Administrator - " -NoNewline | |
| Write-Host "FAILED" -ForegroundColor Red | |
| return [PSCustomObject]@{ | |
| Success = $false | |
| FilePath = $null | |
| Error = "Administrator privileges required" | |
| } | |
| } | |
| Write-Verbose "Administrator check passed" | |
| #endregion Admin Check | |
| #region Create Log File | |
| $logDirectory = "$ENV:windir\System32\LogFiles\Firewall" | |
| $FilePath = Join-Path $logDirectory $Filename | |
| Write-Verbose "Target file path: $FilePath" | |
| # Function to create a single log file | |
| function New-FirewallLogFile { | |
| param([string]$Path) | |
| try { | |
| if (-not (Test-Path $Path)) { | |
| Write-Verbose "Creating firewall log file: $Path" | |
| New-Item -ItemType File -Path $Path -Force -ErrorAction Stop | Out-Null | |
| Write-Host "Firewall log file created: $(Split-Path $Path -Leaf) - " -NoNewline | |
| Write-Host "SUCCESS" -ForegroundColor Green | |
| return $true | |
| } | |
| else { | |
| Write-Host "Firewall log file already exists: $(Split-Path $Path -Leaf) - " -NoNewline | |
| Write-Host "INFO" -ForegroundColor White | |
| return $true | |
| } | |
| } | |
| catch { | |
| $err = $PSItem.Exception.Message | |
| Write-Host "Failed to create log file: $(Split-Path $Path -Leaf) - " -NoNewline | |
| Write-Host "FAILED" -ForegroundColor Red | |
| Write-Host "Error: $err" -ForegroundColor Red | |
| return $false | |
| } | |
| } | |
| try { | |
| # Ensure directory exists | |
| if (-not (Test-Path $logDirectory)) { | |
| Write-Verbose "Creating log directory: $logDirectory" | |
| New-Item -ItemType Directory -Path $logDirectory -Force -ErrorAction Stop | Out-Null | |
| } | |
| # Create the specified file | |
| $success = New-FirewallLogFile -Path $FilePath | |
| if (-not $success) { | |
| return [PSCustomObject]@{ | |
| Success = $false | |
| FilePath = $FilePath | |
| Error = "Failed to create primary log file" | |
| } | |
| } | |
| # If NOT pfirewall.log, ensure all CIS firewall logs exist | |
| if ($Filename -ne 'pfirewall.log') { | |
| Write-Host "`nChecking CIS firewall logs..." -ForegroundColor Cyan | |
| $cisLogs = @('domainfw.log', 'domainfw.log.old', 'privatefw.log', 'privatefw.log.old', 'publicfw.log', 'publicfw.log.old') | |
| foreach ($cisLog in $cisLogs) { | |
| $cisLogPath = Join-Path $logDirectory $cisLog | |
| New-FirewallLogFile -Path $cisLogPath | Out-Null | |
| } | |
| } | |
| } | |
| catch { | |
| $err = $PSItem.Exception.Message | |
| Write-Host "Failed to create log file - " -NoNewline | |
| Write-Host "FAILED" -ForegroundColor Red | |
| Write-Host "Error: $err" -ForegroundColor Red | |
| return [PSCustomObject]@{ | |
| Success = $false | |
| FilePath = $FilePath | |
| Error = $err | |
| } | |
| } | |
| #endregion Create Log File | |
| #region Set Permissions | |
| # Function to set permissions on a log file | |
| function Set-FirewallLogPermissions { | |
| param([string]$Path) | |
| try { | |
| Write-Verbose "Setting permissions for: $(Split-Path $Path -Leaf)" | |
| $Acl = Get-Acl $Path -ErrorAction Stop | |
| $Acl.SetAccessRuleProtection($true, $false) | |
| $PermittedUsers = @( | |
| 'NT AUTHORITY\SYSTEM', | |
| 'BUILTIN\Administrators', | |
| 'BUILTIN\Network Configuration Operators', | |
| 'NT SERVICE\MpsSvc' | |
| ) | |
| foreach ($PermittedUser in $PermittedUsers) { | |
| $Permission = $PermittedUser, 'FullControl', 'Allow' | |
| $AccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule $Permission | |
| $Acl.AddAccessRule($AccessRule) | |
| } | |
| $Acl.SetOwner((New-Object System.Security.Principal.NTAccount('BUILTIN\Administrators'))) | |
| $Acl | Set-Acl $Path -ErrorAction Stop | |
| Write-Host "Permissions set for $(Split-Path $Path -Leaf) - " -NoNewline | |
| Write-Host "SUCCESS" -ForegroundColor Green | |
| return $true | |
| } | |
| catch { | |
| $err = $PSItem.Exception.Message | |
| Write-Host "Failed to set permissions for $(Split-Path $Path -Leaf) - " -NoNewline | |
| Write-Host "FAILED" -ForegroundColor Red | |
| Write-Host "Error: $err" -ForegroundColor Red | |
| return $false | |
| } | |
| } | |
| # Set permissions for the primary file | |
| $permSuccess = Set-FirewallLogPermissions -Path $FilePath | |
| if (-not $permSuccess) { | |
| return [PSCustomObject]@{ | |
| Success = $false | |
| FilePath = $FilePath | |
| Error = "Failed to set permissions on primary file" | |
| } | |
| } | |
| # If NOT pfirewall.log, set permissions for all CIS firewall logs | |
| if ($Filename -ne 'pfirewall.log') { | |
| Write-Host "`nSetting permissions for CIS firewall logs..." -ForegroundColor Cyan | |
| $cisLogs = @('domainfw.log', 'domainfw.log.old', 'privatefw.log', 'privatefw.log.old', 'publicfw.log', 'publicfw.log.old') | |
| foreach ($cisLog in $cisLogs) { | |
| $cisLogPath = Join-Path $logDirectory $cisLog | |
| if (Test-Path $cisLogPath) { | |
| Set-FirewallLogPermissions -Path $cisLogPath | Out-Null | |
| } | |
| } | |
| } | |
| Get-ChildItem $logDirectory | |
| if($UseNetSH){ | |
| $LogNames = @('domainfw.log', 'domainfw.log.old', 'privatefw.log', 'privatefw.log.old', 'publicfw.log', 'publicfw.log.old') | |
| foreach($LogName in $LogNames) { | |
| if($LogName -contains "Domain"){ | |
| netsh advfirewall set domainprofile logging filename %systemroot%\system32\LogFiles\firewall\$LogName | |
| netsh advfirewall set domainprofile logging maxfilesize 32767 | |
| netsh advfirewall set domainprofile logging droppedconnections enable | |
| netsh advfirewall set domainprofile logging allowedconnections enable | |
| } | |
| elseif($LogName -contains "Private"){ | |
| netsh advfirewall set privateprofile logging filename %systemroot%\system32\LogFiles\firewall\$LogName | |
| netsh advfirewall set privateprofile logging maxfilesize 32767 | |
| netsh advfirewall set privateprofile logging droppedconnections enable | |
| netsh advfirewall set privateprofile logging allowedconnections enable | |
| } | |
| elseif($LogName -contains "Public"){ | |
| netsh advfirewall set publicprofile logging filename %systemroot%\system32\LogFiles\firewall\$LogName | |
| netsh advfirewall set publicprofile logging maxfilesize 32767 | |
| netsh advfirewall set publicprofile logging droppedconnections enable | |
| netsh advfirewall set publicprofile logging allowedconnections enable | |
| } | |
| else{ | |
| netsh advfirewall set allprofiles logging filename %systemroot%\system32\LogFiles\firewall\$LogName | |
| netsh advfirewall set allprofiles logging maxfilesize 32767 | |
| netsh advfirewall set allprofiles logging droppedconnections enable | |
| netsh advfirewall set allprofiles logging allowedconnections enable | |
| } | |
| } | |
| } | |
| #endregion Set Permissions | |
| #region Reboot Prompt | |
| $RequiredLogs = @('domainfw.log', 'domainfw.log.old', 'privatefw.log', 'privatefw.log.old', 'publicfw.log', 'publicfw.log.old') | |
| $GCILogDir = Get-ChildItem $logDirectory | |
| # If pfirewall.log, restart computer immediately | |
| if ($GCILogDir.Name -eq 'pfirewall.log') { | |
| Write-Host "`npfirewall.log created..." -ForegroundColor Green | |
| try { | |
| Write-Verbose "Initiating system restart for pfirewall.log" | |
| $Restart = Read-Host "Restart-Computer now? (Y/N)?" | |
| if($Restart -ieq 'y'){ | |
| Restart-Computer -ErrorAction Stop | |
| } | |
| } | |
| catch { | |
| $err = $PSItem.Exception.Message | |
| Write-Host "Restart failed - " -NoNewline | |
| Write-Host "WARNING" -ForegroundColor Yellow | |
| Write-Host "Error: $err" -ForegroundColor Yellow | |
| $ReadHost = Read-Host "Reboot with -Force (Y/N)?" | |
| if ($ReadHost -ieq 'Y') { | |
| try { | |
| Write-Verbose "Forcing system restart" | |
| Restart-Computer -Force -ErrorAction Stop | |
| } | |
| catch { | |
| $err = $PSItem.Exception.Message | |
| Write-Host "Force restart failed - " -NoNewline | |
| Write-Host "FAILED" -ForegroundColor Red | |
| Write-Host "Error: $err" -ForegroundColor Red | |
| } | |
| } | |
| } | |
| } | |
| elseif($GCILogDir.Name -ne 'pfirewall.log'){ | |
| $ExistingLogs = $GCILogDir | Select-Object -ExpandProperty Name | |
| if ($RequiredLogs | Where-Object { $_ -notin $ExistingLogs }) { | |
| # One or more required files are missing | |
| Write-Warning "`nOne or more required CIS firewall log files are missing - " | |
| $GCILogDir.Name | |
| } | |
| else { | |
| # All required files exist For CIS logs, prompt for reboot | |
| Write-Host "`nReboot Required - " -NoNewline | |
| Write-Host "WARNING" -ForegroundColor Yellow | |
| $ReadHost = Read-Host "Reboot now? (Y/N)" | |
| if ($ReadHost -ieq 'Y') { | |
| try { | |
| Write-Verbose "Initiating system restart" | |
| Restart-Computer -ErrorAction Stop | |
| } | |
| catch { | |
| $err = $PSItem.Exception.Message | |
| Write-Host "Restart failed - " -NoNewline | |
| Write-Host "WARNING" -ForegroundColor Yellow | |
| Write-Host "Error: $err" -ForegroundColor Yellow | |
| $ReadHost = Read-Host "Reboot with -Force (Y/N)?" | |
| if ($ReadHost -ieq 'Y') { | |
| try { | |
| Write-Verbose "Forcing system restart" | |
| Restart-Computer -Force -ErrorAction Stop | |
| } | |
| catch { | |
| $err = $PSItem.Exception.Message | |
| Write-Host "Force restart failed - " -NoNewline | |
| Write-Host "FAILED" -ForegroundColor Red | |
| Write-Host "Error: $err" -ForegroundColor Red | |
| } | |
| } | |
| } | |
| } | |
| else { | |
| Write-Host "Reboot postponed - remember to restart for changes to take effect" -ForegroundColor Yellow | |
| } | |
| } | |
| } | |
| #endregion Reboot Prompt | |
| return [PSCustomObject]@{ | |
| Success = $true | |
| FilePath = $FilePath | |
| Error = $null | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment