Advertisement
Yevrag35

Create WinRM SSL listener

Jun 13th, 2019
843
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. <#
  2.     .SYNOPSIS
  3.         Automatically create an HTTPS WinRM Listener on a local computer.
  4.  
  5.     .DESCRIPTION
  6.         Created:    5/21/2017
  7.         Author:     Mike Garvey
  8.  
  9.         This script is best viewed with an advanced text editor (e.g. - Notepad++, Visual Studio Code, etc.)
  10.  
  11.         ----------------------------------------------------------------
  12.  
  13.         Recommended that you have .NET Framework 3.5.1 w/ SP1 installed.  Minimum PowerShell version 2.0
  14.  
  15.         ----------------------------------------------------------------
  16.  
  17.         You must have already created the necessary certificate in order to use this script.  Running this along with specifying a SHA1 Thumbprint
  18.         will create the HTTPS listener for the WinRM service, as well as creating the necessary firewall rule.
  19.  
  20.         This script can called easily by right-clicking and selecting "Run with PowerShell".  The script will re-launch as an elevated process if necessary.
  21.  
  22.     .INPUTS
  23.         <None>
  24.     .OUTPUTS
  25.         <None>
  26.  
  27.     .EXAMPLE
  28.         .\CreateWinRMListener-SSL.ps1 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  29.     .EXAMPLE
  30.         .\CreateWinRMListener-SSL.ps1 -SHA1Thumbprint XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  31.     .EXAMPLE
  32.         .\CreateWinRMListener-SSL.ps1 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -NonInteractive
  33. #>
  34. [CmdletBinding(PositionalBinding=$false)]
  35. param
  36. (
  37.     [switch]$NonInteractive
  38.     ,
  39.     [switch]$DontCreateFirewallRule
  40.     ,
  41.     [switch]$DontChangePrivateKeyPermissions
  42. )
  43. DynamicParam
  44. {
  45.     $n = "SHA1Thumbprint"
  46.     if ($null -eq $global:certs -or $null -eq $global:rtDict)
  47.     {
  48.         [string[]]$global:certs = (Get-ChildItem -Path Cert:\LocalMachine\My).Thumbprint;
  49.         $attCol = New-Object System.Collections.ObjectModel.Collection[System.Attribute];
  50.         $pAtt = New-Object System.Management.Automation.ParameterAttribute -Property @{
  51.             Mandatory = $true
  52.             Position = 0
  53.         }
  54.         $attCol.Add($pAtt);
  55.         $valSet = New-Object System.Management.Automation.ValidateSetAttribute($global:certs);
  56.         $attCol.Add($valSet);
  57.         $alias = New-Object System.Management.Automation.AliasAttribute("sha1", "cert");
  58.         $attCol.Add($alias);
  59.         $rtParam = New-Object System.Management.Automation.RuntimeDefinedParameter($n, [string], $attCol);
  60.         $global:rtDict = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
  61.         $global:rtDict.Add($n, $rtParam);
  62.     }
  63.     return $global:rtDict;
  64. }
  65. Begin
  66. {
  67.     $SHA1Thumbprint = $PSBoundParameters["SHA1Thumbprint"]
  68.     $srv = Get-Service winrm
  69.     if ($srv.Status -eq "Stopped")
  70.     {
  71.         if ($srv.StartType -eq "Disabled")
  72.         {
  73.             $srv | Set-Service -StartupType Automatic
  74.         }
  75.         $srv | Start-Service
  76.     }
  77. }
  78. Process
  79. {
  80.     Function Get-PrivateKeyContainerPath
  81.     {
  82.         [CmdletBinding(PositionalBinding=$false)]
  83.         Param(
  84.             [Parameter(Mandatory=$True)][string][ValidateNotNullOrEmpty()] $Name,
  85.             [Parameter(Mandatory=$True)][boolean] $IsCNG
  86.         )
  87.         If ($IsCNG)
  88.         {
  89.             $searchDirectories = @("Microsoft\Crypto\Keys","Microsoft\Crypto\SystemKeys")
  90.         }
  91.         else
  92.         {
  93.             $searchDirectories = @("Microsoft\Crypto\RSA\MachineKeys","Microsoft\Crypto\RSA\S-1-5-18","Microsoft\Crypto\RSA\S-1-5-19","Crypto\DSS\S-1-5-20")
  94.         }
  95.         foreach ($searchDirectory in $searchDirectories)
  96.         {
  97.             $machineKeyDirectory = Join-Path -Path $([Environment]::GetFolderPath("CommonApplicationData")) -ChildPath $searchDirectory
  98.             $privateKeyFile = Get-ChildItem -Path $machineKeyDirectory -Filter $Name -Recurse
  99.             if ($null -ne $privateKeyFile)
  100.             {
  101.                return $privateKeyFile.FullName
  102.             }
  103.         }
  104.         Throw "Cannot find private key file path for key container ""$Name"""
  105.     }
  106.  
  107.     # Make sure script execution is elevated, if not re-launch with elevation.
  108.     $curDir= Split-Path -Parent $MyInvocation.MyCommand.Definition
  109.     $myWinID = [System.Security.Principal.WindowsIdentity]::GetCurrent()
  110.     $myPrinID = New-Object System.Security.Principal.WindowsPrincipal($myWinID)
  111.     $adm = [System.Security.Principal.WindowsBuiltInRole]::Administrator
  112.     if (!($myPrinID.IsInRole($adm)))
  113.     {
  114.         $curScr= Split-Path $MyInvocation.MyCommand.Definition -Leaf
  115.         $psArgs=@('-ExecutionPolicy','Bypass','-File')
  116.         $psArgs += '"'+$curDir+'\'+$curScr+'"'
  117.         if ($SHA1Thumbprint)
  118.         {
  119.             $psArgs += $SHA1Thumbprint
  120.         }
  121.         Start-Process powershell -ArgumentList $psArgs -Verb RunAs
  122.         exit 5
  123.     }
  124.  
  125.     if ((!$SHA1Thumbprint) -and (!$NonInteractive))
  126.     {
  127.         $cert = gci Cert:\LocalMachine\My | Select Thumbprint, FriendlyName, `
  128.             @{N="Template";E={($_.Extensions | ?{$_.oid.FriendlyName -match 'Certificate Template Information'}).Format(0) -replace '^.*[=](.*)[(].*$', '$1'}}, `
  129.             @{N="Subject";E={$_.SubjectName.Name}} | Out-GridView -Title "Choose a certificate for the binding:" -PassThru
  130.         if (!$cert)
  131.         {
  132.             exit 2
  133.         }
  134.         else
  135.         {
  136.             $SHA1Thumbprint=$cert.Thumbprint
  137.         }
  138.     }
  139.     elseif ((!$SHA1Thumbprint) -and ($NonInteractive))
  140.     {
  141.         Add-Content $curDir -Value "You didn't specify a SHA1 Thumbprint in order for the script to run non-interactively!" -Force
  142.         throw "You didn't specify a SHA1 Thumbprint in order for the script to run non-interactively!"
  143.     }
  144.  
  145.     $hn = (gci Cert:\LocalMachine\My | ? Thumbprint -eq $SHA1Thumbprint).Subject.Replace('CN=','')
  146.     $create=@('create')
  147.     $create += 'winrm/config/Listener?Address=*+Transport=HTTPS'
  148.     $create += '@{Hostname="'+$hn+'";CertificateThumbprint="'+$SHA1Thumbprint+'"}'
  149.     $cProc = Start-Process winrm -ArgumentList $create -NoNewWindow -Wait -PassThru
  150.     if ($cProc.ExitCode -ne 0)
  151.     {
  152.         if (!$NonInteractive)
  153.         {
  154.             Write ""
  155.             Write-Host "An error occurred creating the SSL Listener on port 5986! " -F Red
  156.             Write ""
  157.             Read-Host
  158.         }
  159.         exit 1
  160.     }
  161.     else
  162.     {
  163.         $set=@('set')
  164.         $set += 'winrm/config/service'
  165.         $set += '@{CertificateThumbprint="'+$SHA1Thumbprint+'"}'
  166.         $sProc = Start-Process winrm -ArgumentList $set -NoNewWindow -Wait -PassThru
  167.         if ($sProc.ExitCode -ne 0)
  168.         {
  169.             Write-Host "An error occurred while trying the WinRM service's thumbprint!" -F Red
  170.             Write-Host "Reverting changes that were made... " -F Yellow -NoNewline
  171.             $delete=@('delete')
  172.             $delete += 'winrm/config/Listener?Address=*+Transport=HTTPS'
  173.             $dProc = Start-Process winrm -ArgumentList $delete -Wait -PassThru
  174.             if ($dProc.ExitCode -ne 0)
  175.             {
  176.                 if (!$NonInteractive)
  177.                 {
  178.                     Write-Host "ERROR!" -F Red -NoNewline
  179.                     Write ""
  180.                     Write-Host "Press enter to exit " -F Cyan -NoNewline
  181.                     Read-Host
  182.                 }
  183.                 exit 1
  184.             }
  185.             else
  186.             {
  187.                 if (!$NonInteractive)
  188.                 {
  189.                     Write-Host "Success." -F Green -NoNewline
  190.                     Write ""
  191.                     Write-Host "Press enter to exit " -F Cyan -NoNewline
  192.                     Read-Host
  193.                 }
  194.                 exit 0
  195.             }
  196.         }
  197.         else
  198.         {
  199.             if (!$DontChangePrivateKeyPermissions)
  200.             {
  201.                 $dllPath = "$curDir\Security.Cryptography.dll"
  202.                 if (Test-Path $dllPath)
  203.                 {
  204.                     # Load the Assembly
  205.                     [System.Reflection.Assembly]::LoadFile($dllPath)
  206.                     $Certificate = Get-ChildItem "Cert:\LocalMachine\My\$SHA1Thumbprint"
  207.                     if ([Security.Cryptography.X509Certificates.X509CertificateExtensionMethods]::HasCngKey($Certificate))
  208.                     {
  209.                         Write-Verbose "Private Key is CNG"
  210.                         $privateKey = [Security.Cryptography.X509Certificates.X509Certificate2ExtensionMethods]::GetCngPrivateKey($Certificate)
  211.                         $keyContainerName = $privateKey.UniqueName
  212.                         $privateKeyPath = Get-PrivateKeyContainerPath -Name $keyContainerName -IsCNG $true
  213.                     }
  214.                     elseif ($null -ne $Certificate.PrivateKey)
  215.                     {
  216.                         Write-Verbose "Private Key CSP is Legacy"
  217.                         $privateKey = $Certificate.PrivateKey
  218.                         $keyContainerName = $privateKey.CspKeyContainerInfo.UniqueKeyContainerName
  219.                         $privateKeyPath = Get-PrivateKeyContainerPath -Name $keyContainerName -IsCNG $false
  220.                     }
  221.                     else
  222.                     {
  223.                         throw "Certificate `"$($Certificate.GetNameInfo("SimpleName",$false))`" does not have a private key, or that key is inaccessible, therefore permission not granted"
  224.                     }
  225.  
  226.                     # Grant the "Network Service" read access to the private key
  227.                     $Acl = Get-Acl -Path $privateKeyPath
  228.                     $permission = "NT AUTHORITY\NETWORK SERVICE", "Read", "Allow"
  229.                     $rule = New-Object System.Security.AccessControl.FileSystemAccessRule $permission
  230.                     $Acl.AddAccessRule($rule)
  231.                     Set-Acl $privateKeyPath $Acl -Verbose
  232.                 }
  233.  
  234.             }
  235.             # Commit the changes by restarting the Remote Management service.
  236.             Restart-Service winrm
  237.  
  238.             if (!$DontCreateFirewallRule)
  239.             {
  240.                 $shArgs=@('advfirewall','firewall','add','rule')
  241.                 $shArgs += 'name="WinRM SSL"'
  242.                 $shArgs += @('dir=in','action=allow','enable=yes','profile=any','localport=5986','protocol=TCP','interfacetype=any')
  243.                 &netsh.exe $shArgs
  244.             }
  245.             if (!$NonInteractive)
  246.             {
  247.                 Write-Host "The WinRM-HTTPS listener has been successfully created. " -F Green
  248.                 Write ""
  249.                 Write-Host "Press enter to exit " -F Cyan -NoNewline
  250.                 Read-Host
  251.             }
  252.             exit 0
  253.         }
  254.     }
  255. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement