how to enable WinRM securely in PowerShell?
Article 2: Enabling WinRM over HTTPS Using PowerShell
This article will provide you with a PowerShell script to automate the process of enabling WinRM over HTTPS on multiple servers, configuring certificate auto-enrollment, creating a specific certificate template, and setting up the HTTPS listener.
PowerShell Script for Enabling WinRM over HTTPS
Save the following script as Configure-WinRM-HTTPS.ps1
and run it with administrative privileges on the server.
# Define variables $domain = (Get-WmiObject Win32_ComputerSystem).Domain $gpoName = "Enable WinRM with HTTPS and Auto-Enrollment" $certificateTemplateName = "WinRM HTTPS" $certRenewalPeriodHours = 1 # Certificate renewal period in hours $additionalOU = "Servers" # Additional OU or attribute to be included in the certificate subject # Function to create a new GPO and edit settings function Configure-GPO { # Import the GroupPolicy module Import-Module GroupPolicy # Create a new GPO Write-Output "Creating GPO: $gpoName" New-GPO -Name $gpoName # Link GPO to the domain root Write-Output "Linking GPO to domain root" New-GPLink -Name $gpoName -Target "DC=$($domain -replace '\.', ',DC=')" # Configure Auto-Enrollment for Certificates Write-Output "Configuring Auto-Enrollment for Certificates" Set-GPRegistryValue -Name $gpoName -Key "HKLM\Software\Policies\Microsoft\Cryptography\AutoEnrollment" -ValueName "AEPolicy" -Type DWORD -Value 1 # Configure Allow Remote Management through WinRM Write-Output "Configuring WinRM Settings" Set-GPRegistryValue -Name $gpoName -Key "HKLM\SOFTWARE\Policies\Microsoft\Windows\WinRM\Service" -ValueName "AllowAutoConfig" -Type DWORD -Value 1 Set-GPRegistryValue -Name $gpoName -Key "HKLM\SOFTWARE\Policies\Microsoft\Windows\WinRM\Service" -ValueName "IPv4Filter" -Type String -Value "*" # Enable WinRM Service Write-Output "Configuring WinRM Service to start automatically" Set-GPRegistryValue -Name $gpoName -Key "HKLM\SYSTEM\CurrentControlSet\Services\WinRM" -ValueName "Start" -Type DWORD -Value 2 # Configure firewall rules for WinRM Write-Output "Configuring Firewall Rules for WinRM" Invoke-Expression "netsh advfirewall firewall add rule name='WinRM HTTPS' dir=in action=allow protocol=TCP localport=5986" Invoke-Expression "netsh advfirewall firewall add rule name='WinRM HTTP' dir=in action=allow protocol=TCP localport=5985" } # Function to create and publish a certificate template function Configure-CertificateTemplate { # Import Certificate Authority module Import-Module PKI # Duplicate the Web Server template Write-Output "Creating new Certificate Template for WinRM" $webServerTemplate = Get-CATemplate | Where-Object {$_.DisplayName -eq 'Web Server'} $newTemplate = $webServerTemplate.Duplicate() $newTemplate.DisplayName = $certificateTemplateName # Configure the template for dynamic subject with hostname and additional criteria $newTemplate.SubjectNameFlags = 'Machine Name' $newTemplate.ValidityPeriod = 'Hours' $newTemplate.ValidityPeriodUnits = $certRenewalPeriodHours $newTemplate.Purpose = @('Server Authentication') # Set template for automatic enrollment Write-Output "Publishing Certificate Template for Auto-Enrollment" $newTemplate.EnrollmentFlags = 'IncludeSymmetricAlgorithms' Add-CATemplate -Template $newTemplate } # Function to create WinRM HTTPS listener using a specific certificate function Configure-WinRMHTTPSListener { Write-Output "Creating Scheduled Task to configure WinRM HTTPS Listener" # Retrieve the certificate thumbprint for the specific template name $certThumbprint = (Get-ChildItem Cert:\LocalMachine\My | Where-Object { $_.NotAfter -gt (Get-Date) } | ForEach-Object { $templateName = ($_.Extensions | Where-Object { $_.Oid.Value -eq "1.3.6.1.4.1.311.21.7" }).Format($false); if ($templateName -like "*WinRM*") { [PSCustomObject]@{ Subject = $_.Subject; TemplateName = $templateName } } }).Thumbprint if (-not $certThumbprint) { Write-Output "No valid certificate found for template: $certificateTemplateName" return } # Create a scheduled task to configure the WinRM HTTPS listener $action = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument "-Command `"New-Item -Path WSMan:\Localhost\Listener -Transport HTTPS -Address * -CertificateThumbprint $certThumbprint`"" $trigger = New-ScheduledTaskTrigger -AtStartup Register-ScheduledTask -Action $action -Trigger $trigger -TaskName 'Configure WinRM HTTPS Listener' -Description 'Configure WinRM HTTPS Listener for secure remote management' -RunLevel Highest -User 'SYSTEM' } # Function to set up scheduled task for certificate renewal function Configure-CertRenewalTask { Write-Output "Creating Scheduled Task for frequent certificate renewal check" # Create a scheduled task action to trigger certificate renewal $renewalAction = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument '-Command "gpupdate /force"' # Set a trigger to run the task every hour $renewalTrigger = New-ScheduledTaskTrigger -Once -At (Get-Date).AddMinutes(1) -RepetitionInterval (New-TimeSpan -Hours $certRenewalPeriodHours) -RepetitionDuration ([TimeSpan]::MaxValue) Register-ScheduledTask -Action $renewalAction -Trigger $renewalTrigger -TaskName 'CertRenewal' -Description 'Certificate auto-renewal every hour' -RunLevel Highest -User 'SYSTEM' } # Main script execution Write-Output "Starting the configuration process..." Configure-GPO Configure-CertificateTemplate Configure-WinRMHTTPSListener Configure-CertRenewalTask Write-Output "Configuration completed successfully!"
How to Use the PowerShell Script
- Run PowerShell as Administrator: Open PowerShell with elevated privileges.
-
Save the Script: Save the script as
Configure-WinRM-HTTPS.ps1
. - Execute the Script:
powershell
.\Configure-WinRM-HTTPS.ps1