@echo off REM ============================================================================ REM WinRM Setup Script for Shopfloor PCs REM ============================================================================ REM REM PURPOSE: Configures WinRM on a Windows PC and restricts access to members REM of a specific Active Directory security group. Logs setup to CSV. REM REM USAGE: Run as Administrator on each shopfloor PC REM Setup-WinRM.bat [SecurityGroupName] [LogPath] REM REM EXAMPLE: Setup-WinRM.bat "logon\groupid" "\\server\share\winrm-inventory" REM REM REQUIREMENTS: REM - Must be run as Administrator REM - PC must be domain-joined REM - Security group must exist in Active Directory REM REM ============================================================================ setlocal EnableDelayedExpansion REM Check for admin privileges net session >nul 2>&1 if %ERRORLEVEL% neq 0 ( echo. echo ERROR: This script must be run as Administrator. echo Right-click and select "Run as administrator" echo. pause exit /b 1 ) REM ============================================================================ REM Configuration - EDIT THESE VALUES FOR YOUR ENVIRONMENT REM ============================================================================ REM Default security group (can be overridden by parameter) set "DEFAULT_SECURITY_GROUP=logon\groupid" REM Default log path for CSV inventory (can be overridden by parameter) REM Use a network share that all PCs can write to set "DEFAULT_LOG_PATH=\\server\share\winrm-inventory" REM Domain suffix for TrustedHosts (e.g., *.logon.ds.ge.com) set "TRUSTED_DOMAIN=*.logon.ds.ge.com" REM Optional: Trusted subnets - comma-separated (leave empty to skip) REM For /24 subnet: "10.48.130.*" REM For /23 subnet: "10.48.130.*,10.48.131.*" REM For /22 subnet: "10.48.128.*,10.48.129.*,10.48.130.*,10.48.131.*" REM set "TRUSTED_SUBNET=10.48.130.*,10.48.131.*" set "TRUSTED_SUBNET=" REM ============================================================================ REM Get parameters or use defaults set "SECURITY_GROUP=%~1" set "LOG_PATH=%~2" if "%SECURITY_GROUP%"=="" set "SECURITY_GROUP=%DEFAULT_SECURITY_GROUP%" if "%LOG_PATH%"=="" set "LOG_PATH=%DEFAULT_LOG_PATH%" echo. echo ============================================================================ echo WinRM Setup Script echo ============================================================================ echo. echo Computer: %COMPUTERNAME% echo Security Group: %SECURITY_GROUP% echo Log Path: %LOG_PATH% echo Trusted Domain: %TRUSTED_DOMAIN% if not "%TRUSTED_SUBNET%"=="" echo Trusted Subnet: %TRUSTED_SUBNET% echo. echo ============================================================================ echo. REM Step 1: Enable WinRM service echo [1/7] Enabling WinRM service... sc config WinRM start= auto >nul 2>&1 net start WinRM >nul 2>&1 if %ERRORLEVEL% equ 0 ( echo WinRM service started ) else ( echo WinRM service already running ) REM Step 2: Run quick config (creates listener, firewall rules) echo [2/7] Running WinRM quick configuration... winrm quickconfig -quiet >nul 2>&1 echo Quick config completed REM Step 3: Configure WinRM settings echo [3/7] Configuring WinRM settings... REM Disable unencrypted traffic (security best practice) winrm set winrm/config/service @{AllowUnencrypted="false"} >nul 2>&1 REM Enable Negotiate authentication (Kerberos/NTLM) winrm set winrm/config/service/auth @{Negotiate="true"} >nul 2>&1 REM Enable CredSSP for double-hop scenarios (optional) winrm set winrm/config/service/auth @{CredSSP="true"} >nul 2>&1 REM Set max concurrent operations winrm set winrm/config/service @{MaxConcurrentOperationsPerUser="50"} >nul 2>&1 REM Set max memory per shell (512MB) winrm set winrm/config/winrs @{MaxMemoryPerShellMB="512"} >nul 2>&1 echo WinRM settings configured REM Step 4: Configure TrustedHosts on CLIENT side (for the admin workstation) REM This step configures this PC to trust connections TO other PCs echo [4/7] Configuring TrustedHosts... REM Build TrustedHosts value set "TRUSTED_HOSTS=%TRUSTED_DOMAIN%" if not "%TRUSTED_SUBNET%"=="" ( set "TRUSTED_HOSTS=%TRUSTED_HOSTS%,%TRUSTED_SUBNET%" ) REM Get current TrustedHosts and append if needed powershell -ExecutionPolicy Bypass -Command ^ "$currentTrusted = (Get-Item WSMan:\localhost\Client\TrustedHosts -ErrorAction SilentlyContinue).Value; " ^ "$newHosts = '%TRUSTED_HOSTS%'; " ^ "if ([string]::IsNullOrEmpty($currentTrusted)) { " ^ " Set-Item WSMan:\localhost\Client\TrustedHosts -Value $newHosts -Force; " ^ " Write-Host ' Set TrustedHosts: ' $newHosts; " ^ "} elseif ($currentTrusted -notlike '*%TRUSTED_DOMAIN%*') { " ^ " $combined = $currentTrusted + ',' + $newHosts; " ^ " Set-Item WSMan:\localhost\Client\TrustedHosts -Value $combined -Force; " ^ " Write-Host ' Added to TrustedHosts: ' $newHosts; " ^ "} else { " ^ " Write-Host ' TrustedHosts already configured'; " ^ "}" REM Step 5: Configure firewall rules echo [5/7] Configuring firewall rules... REM Enable WinRM firewall rule for domain profile netsh advfirewall firewall set rule name="Windows Remote Management (HTTP-In)" new enable=yes profile=domain >nul 2>&1 if %ERRORLEVEL% neq 0 ( netsh advfirewall firewall add rule name="Windows Remote Management (HTTP-In)" dir=in action=allow protocol=tcp localport=5985 profile=domain >nul 2>&1 ) echo Firewall rule enabled for domain profile REM Step 6: Set WinRM permissions for security group echo [6/7] Configuring WinRM permissions for security group... powershell -ExecutionPolicy Bypass -Command ^ "$group = '%SECURITY_GROUP%'; " ^ "try { " ^ " $ntAccount = New-Object System.Security.Principal.NTAccount($group); " ^ " $sid = $ntAccount.Translate([System.Security.Principal.SecurityIdentifier]); " ^ " $sidString = $sid.Value; " ^ " Write-Host ' Group SID: ' $sidString; " ^ " $currentSDDL = (Get-Item WSMan:\localhost\Service\RootSDDL).Value; " ^ " $newACE = '(A;;GXGR;;;' + $sidString + ')'; " ^ " if ($currentSDDL -notmatch [regex]::Escape($sidString)) { " ^ " $newSDDL = $currentSDDL -replace 'D:', ('D:' + $newACE); " ^ " Set-Item WSMan:\localhost\Service\RootSDDL -Value $newSDDL -Force; " ^ " Write-Host ' Added security group to WinRM permissions'; " ^ " } else { " ^ " Write-Host ' Security group already has WinRM permissions'; " ^ " } " ^ "} catch { " ^ " Write-Host ' ERROR: Could not resolve security group - ' $_.Exception.Message; " ^ " exit 1; " ^ "}" if %ERRORLEVEL% neq 0 ( echo. echo ERROR: Failed to configure security group permissions. echo Verify the security group exists in Active Directory. echo. pause exit /b 1 ) REM Step 7: Log to CSV inventory file echo [7/7] Logging to inventory CSV... REM Get IP address for /f "tokens=2 delims=:" %%a in ('ipconfig ^| findstr /i "IPv4"') do ( set "IP_ADDRESS=%%a" goto :gotip ) :gotip set "IP_ADDRESS=%IP_ADDRESS: =%" REM Get current date/time for /f "tokens=2 delims==" %%a in ('wmic os get localdatetime /value') do set "DT=%%a" set "SETUP_DATE=%DT:~0,4%-%DT:~4,2%-%DT:~6,2% %DT:~8,2%:%DT:~10,2%:%DT:~12,2%" REM Get OS version for /f "tokens=4-5 delims=. " %%a in ('ver') do set "OS_VERSION=%%a.%%b" REM Create CSV directory if it doesn't exist if not exist "%LOG_PATH%" ( mkdir "%LOG_PATH%" 2>nul if %ERRORLEVEL% neq 0 ( echo WARNING: Could not create log directory. Logging skipped. goto :skiplog ) ) REM Define CSV file set "CSV_FILE=%LOG_PATH%\winrm-inventory.csv" REM Create CSV header if file doesn't exist if not exist "%CSV_FILE%" ( echo Hostname,IPAddress,SetupDate,OSVersion,SecurityGroup > "%CSV_FILE%" if %ERRORLEVEL% neq 0 ( echo WARNING: Could not create CSV file. Logging skipped. goto :skiplog ) ) REM Check if this hostname already exists in CSV and update or append powershell -ExecutionPolicy Bypass -Command ^ "$csvFile = '%CSV_FILE%'; " ^ "$hostname = '%COMPUTERNAME%'; " ^ "$newLine = '%COMPUTERNAME%,%IP_ADDRESS%,%SETUP_DATE%,%OS_VERSION%,%SECURITY_GROUP%'; " ^ "try { " ^ " $content = Get-Content $csvFile -ErrorAction SilentlyContinue; " ^ " $found = $false; " ^ " $newContent = @(); " ^ " foreach ($line in $content) { " ^ " if ($line -like \"$hostname,*\") { " ^ " $newContent += $newLine; " ^ " $found = $true; " ^ " } else { " ^ " $newContent += $line; " ^ " } " ^ " } " ^ " if (-not $found) { $newContent += $newLine; } " ^ " $newContent | Set-Content $csvFile -Force; " ^ " Write-Host ' Logged: %COMPUTERNAME% (%IP_ADDRESS%)'; " ^ "} catch { " ^ " Write-Host ' WARNING: Could not write to CSV - ' $_.Exception.Message; " ^ "}" :skiplog REM Verify configuration echo. echo ============================================================================ echo WinRM Setup Complete! echo ============================================================================ echo. echo Computer: %COMPUTERNAME% echo IP Address: %IP_ADDRESS% echo Security Group: %SECURITY_GROUP% echo WinRM Port: 5985 (HTTP) echo Trusted Hosts: %TRUSTED_HOSTS% echo. echo Inventory logged to: %CSV_FILE% echo. echo Members of '%SECURITY_GROUP%' can now connect using: echo Enter-PSSession -ComputerName %COMPUTERNAME% -Credential (Get-Credential) echo. echo To test from a remote PC (as a member of the security group): echo Test-WSMan -ComputerName %COMPUTERNAME% echo. echo ============================================================================ pause exit /b 0