Last active
October 11, 2019 21:01
-
-
Save jeremygaither/0979e4c2e6e3a4a69467dcc85d8a1eed to your computer and use it in GitHub Desktop.
This file contains 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
# Invoke with: | |
# [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]'Tls11,Tls12'; Set-ExecutionPolicy Bypass -Scope Process -Force; Invoke-WebRequest -UseBasicParsing -Uri "https://gist.github.com/jeremygaither/0979e4c2e6e3a4a69467dcc85d8a1eed/raw/Enable-WinRMRemoting.ps1" | Invoke-Expression | |
Set-StrictMode -Version Latest | |
$ErrorActionPreference = "Stop" | |
If (-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) | |
{ | |
Write-Warning "You do not have Administrator rights to run this script!" | |
exit 1 | |
} | |
Write-Output "$(Get-Date -Format u) ==> Set Power Plan: High Performance" | |
$powerPlan = Get-CimInstance -Name root\cimv2\power -Class win32_PowerPlan -Filter "ElementName = 'High Performance'" | |
Invoke-CimMethod -InputObject $powerPlan -MethodName Activate | |
Write-Output "$(Get-Date -Format u) ==> Enabling Windows Remote Management and PowerShell Remoting..." | |
Write-Output "$(Get-Date -Format u) --> Configure Networking Profile" | |
# disable annoying popup | |
$registryNewNetworkWindowOff = "HKLM:\System\CurrentControlSet\Control\Network\NewNetworkWindowOff" | |
if (!(Test-Path $registryNewNetworkWindowOff)) { | |
New-Item -Path $registryNewNetworkWindowOff -Force | |
} | |
# winrm and psremoting wants adapters in Private networks | |
$netAdapters = Get-NetAdapter -Name "*" | |
foreach ($adapter in $netAdapters) { | |
Write-Output ("Seting connection profile on " + $adapter.Name) | |
Set-NetConnectionProfile -InterfaceAlias $adapter.Name -NetworkCategory Private | |
} | |
Write-Output "$(Get-Date -Format u) --> Configure WinRM" | |
Write-Output "$(Get-Date -Format u) ----> Ensure firewall rules exist" | |
# Configure-SMRemoting fails if expected firewall rules are not present | |
try { | |
$httpWinrmRule = Get-NetFirewallRule -DisplayName "Windows Remote Management (HTTP-In)" | |
Disable-NetFirewallRule -InputObject $httpWinrmRule | |
Write-Output "HTTP firewall rule disabled" | |
} | |
catch { | |
Write-Output "No original HTTP firewall rule found, creating..." | |
$httpWinrmRule = New-NetFirewallRule -DisplayName "Windows Remote Management (HTTP-In)" -Name "Windows Remote Management (HTTP-In)" -Profile Any -LocalPort 5985 -Protocol TCP -RemoteAddress Any | |
Disable-NetFirewallRule -InputObject $httpWinrmRule | |
Write-Output "new HTTP firewall rule disabled" | |
} | |
Write-Output "$(Get-Date -Format u) ----> Disable default SMRemoting to clean up settings" | |
& "$env:SYSTEMROOT\System32\Configure-SMRemoting.exe" -disable | Out-String | |
Write-Output "$(Get-Date -Format u) ----> Enable SMRemoting" | |
& "$env:SYSTEMROOT\System32\Configure-SMRemoting.exe" -enable | Out-String | |
Write-Output "$(Get-Date -Format u) ----> Enable PSRemoting" | |
Enable-PSRemoting -Force | |
Write-Output "$(Get-Date -Format u) ----> Override UAC and allow all remote admin actions" | |
$regLocalPolicies="HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" | |
if (!(Test-Path $regLocalPolicies)) { | |
New-Item -Path $regLocalPolicies -Force | |
} | |
Remove-ItemProperty -Path $regLocalPolicies -Name "LocalAccountTokenFilterPolicy" -Force -ErrorAction Ignore | |
New-ItemProperty -Path $regLocalPolicies -Name "LocalAccountTokenFilterPolicy" -PropertyType "DWord" -Value 1 -Force | |
Write-Output "$(Get-Date -Format u) ----> Disable default WinRM firewall rules during listener config" | |
# Get-NetFirewallPortFilter not always working on Win2012 | |
try { | |
$httpWinrmRule = Get-NetFirewallRule -DisplayName "Windows Remote Management (HTTP-In)" | |
Disable-NetFirewallRule -InputObject $httpWinrmRule | |
Write-Output "HTTP firewall rule disabled" | |
} | |
catch { | |
Write-Output "No HTTP firewall rule found" | |
} | |
try { | |
$httpsWinrmRule = Get-NetFirewallRule -DisplayName "Windows Remote Management (HTTPS-In)" | |
Disable-NetFirewallRule -InputObject $httpsWinrmRule | |
Write-Output "WinRM HTTPS firewall rule disabled" | |
} | |
catch { | |
Write-Output "No WinRM HTTPS firewall rule found" | |
} | |
Write-Output "$(Get-Date -Format u) ----> Reconfigure WinRM Listeners" | |
Remove-Item -Path WSMan:\Localhost\listener\listener* -Recurse | |
Write-Output "old certificates:" | |
$certSubjectName = "CN=" + $env:COMPUTERNAME | |
Get-ChildItem -Path cert:\localmachine\My -Recurse | ` | |
Where-Object { $_.Subject -eq ($certSubjectName)} | ` | |
Format-Table subject, thumbprint, notbefore, notafter -AutoSize | |
Write-Output "Removing old certificates..." | |
Get-ChildItem -Path cert:\localmachine\My -Recurse | ` | |
Where-Object { $_.Subject -eq ($certSubjectName)} | ` | |
Remove-Item -Force | |
Write-Output "Creating new certificate..." | |
$SubjectName = $env:COMPUTERNAME | |
$ValidDays = 3650 | |
$hostnonFQDN = $SubjectName | |
$SignatureAlgorithm = "SHA256" | |
$name = New-Object -COM "X509Enrollment.CX500DistinguishedName.1" | |
$name.Encode("CN=$SubjectName", 0) | |
$key = New-Object -COM "X509Enrollment.CX509PrivateKey.1" | |
$key.ProviderName = "Microsoft Enhanced RSA and AES Cryptographic Provider" | |
$key.KeySpec = 1 | |
$key.Length = 4096 | |
$key.SecurityDescriptor = "D:PAI(A;;0xd01f01ff;;;SY)(A;;0xd01f01ff;;;BA)(A;;0x80120089;;;NS)" | |
$key.MachineContext = 1 | |
$key.Create() | |
$serverauthoid = New-Object -COM "X509Enrollment.CObjectId.1" | |
$serverauthoid.InitializeFromValue("1.3.6.1.5.5.7.3.1") | |
$ekuoids = New-Object -COM "X509Enrollment.CObjectIds.1" | |
$ekuoids.Add($serverauthoid) | |
$ekuext = New-Object -COM "X509Enrollment.CX509ExtensionEnhancedKeyUsage.1" | |
$ekuext.InitializeEncode($ekuoids) | |
$cert = New-Object -COM "X509Enrollment.CX509CertificateRequestCertificate.1" | |
$cert.InitializeFromPrivateKey(2, $key, "") | |
$cert.Subject = $name | |
$cert.Issuer = $cert.Subject | |
$cert.NotBefore = (Get-Date).AddDays(-1) | |
$cert.NotAfter = $cert.NotBefore.AddDays($ValidDays) | |
$SigOID = New-Object -ComObject X509Enrollment.CObjectId | |
$SigOID.InitializeFromValue(([Security.Cryptography.Oid]$SignatureAlgorithm).Value) | |
$AlternativeName = @() | |
$AlternativeName += $hostnonFQDN | |
$AlternativeName += [System.Net.Dns]::GetHostName() | |
$ec2Hosatname = $null | |
try { | |
$ec2Hostname = (Invoke-WebRequest -UseBasicParsing -Uri "http://169.254.169.254/latest/meta-data/local-hostname" -ErrorAction "Stop").Content | |
if ([String].IsNullOrWhiteSpace($ec2Hostname)) { | |
Write-Output "dns resolution for computername was empty" | |
} | |
else { | |
$AlternativeName += $ec2Hostname | |
} | |
} | |
catch { | |
Write-Output "unable to add ec2 local-hostname to certificate" | |
} | |
$resolvedHostname = $null | |
try { | |
$resolvedHostname = [System.Net.Dns]::GetHostByName(($env:COMPUTERNAME)).Hostname | |
if ([String].IsNullOrWhiteSpace($resolvedHostname)) { | |
Write-Output "dns resolution for computername was empty" | |
} | |
else { | |
$AlternativeName += $resolvedHostname | |
} | |
} | |
catch { | |
Write-Output "unable to add DNS resolved hostname to certificate" | |
} | |
$IAlternativeNames = New-Object -ComObject X509Enrollment.CAlternativeNames | |
foreach ($AN in $AlternativeName) | |
{ | |
$AltName = New-Object -ComObject X509Enrollment.CAlternativeName | |
$AltName.InitializeFromString(0x3,$AN) | |
$IAlternativeNames.Add($AltName) | |
} | |
$SubjectAlternativeName = New-Object -ComObject X509Enrollment.CX509ExtensionAlternativeNames | |
$SubjectAlternativeName.InitializeEncode($IAlternativeNames) | |
[String[]]$KeyUsage = ("DigitalSignature", "KeyEncipherment") | |
$KeyUsageObj = New-Object -ComObject X509Enrollment.CX509ExtensionKeyUsage | |
$KeyUsageObj.InitializeEncode([int][Security.Cryptography.X509Certificates.X509KeyUsageFlags]($KeyUsage)) | |
$KeyUsageObj.Critical = $true | |
$cert.X509Extensions.Add($KeyUsageObj) | |
$cert.X509Extensions.Add($ekuext) | |
$cert.SignatureInformation.HashAlgorithm = $SigOID | |
$CERT.X509Extensions.Add($SubjectAlternativeName) | |
$cert.Encode() | |
$enrollment = New-Object -COM "X509Enrollment.CX509Enrollment.1" | |
$enrollment.InitializeFromRequest($cert) | |
$certdata = $enrollment.CreateRequest(0) | |
$enrollment.InstallResponse(2, $certdata, 0, "") | |
Write-Output "New certificate:" | |
$certificateThumbprint = $null | |
Get-ChildItem -Path cert:\localmachine\My -Recurse | ` | |
Where-Object { $_.Subject -eq ($certSubjectName)} | ` | |
Format-Table subject, thumbprint, notbefore, notafter -AutoSize | |
$certs = Get-ChildItem -Path cert:\localmachine\My -Recurse | ` | |
Where-Object { $_.Subject -eq ($certSubjectName) } | |
foreach ($cert in $certs) { | |
Write-Output ("Cert: " + $cert.Subject + " = " + $cert.Thumbprint) | |
$certificateThumbprint = $cert.Thumbprint | |
} | |
Write-Output "new thumbprint: " $certificateThumbprint | |
New-Item -Path WSMan:\Localhost\Listener ` | |
-Transport HTTPS ` | |
-Address * ` | |
-CertificateThumbPrint $certificateThumbprint ` | |
-Force | |
# allow non-domain and non-ntlm authentication (over https) | |
Set-Item -Path WSMan:\Localhost\Service\Auth\Basic true -Force | |
# prevent out of memory crashes | |
Set-Item -Path WSMan:\localhost\Shell\MaxMemoryPerShellMB -Value 4096 -Force | |
Set-Item -Path WSMan:\localhost\Plugin\Microsoft.PowerShell\Quotas\MaxMemoryPerShellMB -Value 4096 -Force | |
Write-Output "$(Get-Date -Format u) ----> Restrict WinRM to internal subnets" | |
try { | |
$httpsWinrmRule = Get-NetFirewallRule -DisplayName "Windows Remote Management (HTTPS-In)" | |
Remove-NetFirewallRule -InputObject $httpsWinrmRule | |
Write-Output "Old HTTPS firewall rule disabled" | |
} | |
catch { | |
Write-Output "No old HTTPS firewall rule found" | |
} | |
New-NetFirewallRule -DisplayName "Windows Remote Management (HTTPS-In)" -Name "Windows Remote Management (HTTPS-In)" -Profile Any -LocalPort 5986 -Protocol TCP -RemoteAddress '10.0.0.0/8' | |
Write-Output "New HTTPS firewall rule created" | |
Write-Output "$(Get-Date -Format u) ----> Ensure WinRM over HTTP is still blocked" | |
try { | |
$httpWinrmRule = Get-NetFirewallRule -DisplayName "Windows Remote Management (HTTP-In)" | |
Disable-NetFirewallRule -InputObject $httpWinrmRule | |
Write-Output "HTTP firewall rule disabled" | |
} | |
catch { | |
Write-Output "No HTTP firewall rule found" | |
} | |
Write-Output "$(Get-Date -Format u) ----> Restarting WinRM to enable changes" | |
Restart-Service -Force winrm | |
Write-Output "$(Get-Date -Format u) --> Enable other useful networking features" | |
Enable-NetFirewallRule -DisplayGroup "Remote Desktop" | |
Enable-NetFirewallRule -DisplayGroup "File and Printer Sharing" | |
Enable-NetFirewallRule -DisplayGroup "Network Discovery" | |
Write-Output "$(Get-Date -Format u) --> COMPLETE: Windows Remote Management and PowerShell Remoting enabled!" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment