RDPCertificate.psm1
Function Set-RDPCertificate { <# .SYNOPSIS Binds a new or existing certificate to the Remote Desktop service. .DESCRIPTION You either pick an existing, installed certificate on your local computer or generate a new certificate with the native Windows 10 "New-SelfSignedCertificate" cmdlet (the module will try to download the "PowerShell PKI" module from the PSGallery if the OS is less than Windows 10). Using this certificate's thumbprint, the cmdlet binds the thumbprint to the service. Changes are immediate, and no reboots (or service restarts) are required. .PARAMETER SHA1Thumbprint Specifies an already installed certificate thumbprint (in the LocalMachine certificate store). .PARAMETER WithNewSelfSignedCertificate Specifies that the script will create a new self-signed certificate using either the built-in cmdlet or the PSPKI module. .PARAMETER ValidUntil Specifies the "end" date the newly-created certificate will be good to. By default, the date will 2 years from the current date. .PARAMETER HashAlgorithm Specifies the hash algorithm the cmdlets will use to generate the certificate with. By default, it will use SHA-256. Valid values are "SHA256", "SHA384", and "SHA512". .PARAMETER KeyLength Specifies the key length the cmdlets will generate. By default, an RSA 2048-bit key is created. Valid values are "2048", "4096", "8192", and "16384". .EXAMPLE Set-RDPCertificate -SHA1Thumbprint XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX .EXAMPLE *** Using a generated self-signed cert with the default values *** Set-RDPCertificate -WithNewSelfSignedCertificate .EXAMPLE Set-RDPCertificate -WithNewSelfSignedCertificate -ValidUntil $([datetime]::Now.AddYears(10)) -HashAlgorithm SHA356 -KeyLength 8192 .LINK https://github.com/Crypt32/PSPKI #> [CmdletBinding(PositionalBinding=$false, DefaultParameterSetName='ExistingCert')] [alias("setrdcert")] param ( [parameter(Mandatory=$true,ParameterSetName='CreateNewCert')] [switch] $WithNewSelfSignedCertificate , [parameter(Mandatory=$false,ParameterSetName='CreateNewCert')] [datetime] $ValidUntil = [datetime]::Now.AddYears(2) , [parameter(Mandatory=$false,ParameterSetName='CreateNewCert')] [ValidateSet("SHA256", "SHA384", "SHA512")] [string] $HashAlgorithm = "SHA256" , [parameter(Mandatory=$false,ParameterSetName='CreateNewCert')] [ValidateSet(2048, 4096, 8192, 16384)] [int] $KeyLength = 2048 ) DynamicParam { $name = 'SHA1Thumbprint' $dict = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary $attCol = New-Object System.Collections.ObjectModel.Collection[System.Attribute] $props = @{ Mandatory = $true; Position = 0; ValueFromPipelineByPropertyName = $true; ParameterSetName='ExistingCert' } $pAtt = New-Object System.Management.Automation.ParameterAttribute -Property $props $attCol.Add($pAtt) $aAtt = New-Object System.Management.Automation.AliasAttribute("sha1", "thumb", "Thumbprint") $attCol.Add($aAtt) $tprints = (Get-ChildItem Cert:\LocalMachine\My).Thumbprint $valSet = New-Object System.Management.Automation.ValidateSetAttribute($tprints) $attCol.Add($valSet) $rtParam = New-Object System.Management.Automation.RuntimeDefinedParameter( $name, [string], $attCol ) $dict.Add($name, $rtParam) return $dict } Begin { if ($PSBoundParameters["SHA1Thumbprint"]) { $SHA1Thumbprint = $PSBoundParameters["SHA1Thumbprint"] } else { if ($null -ne (Get-Module PSPKI)) { $opts = @{ Subject = "CN=$env:COMPUTERNAME" EnhancedKeyUsage = "Client Authentication", "Server Authentication" FriendlyName = "RDP Certificate" IsCA = $false KeyLength = 2048 KeyUsage = "DigitalSignature", "KeyEncipherment" NotBefore = $([datetime]::Now.AddMinutes(-5)) NotAfter = $([datetime]::Now.AddYears(2)) SignatureAlgorithm = "SHA256" StoreLocation = "LocalMachine" } if (![String]::IsNullOrEmpty($env:USERDNSDOMAIN)) { [string[]]$names = "dns:$($env:COMPUTERNAME)", "dns:$($env:COMPUTERNAME).$($env:USERDNSDOMAIN.ToLower())" } else { [string[]]$names = "dns:$($env:COMPUTERNAME)" } $opts.Add("SubjectAlternativeName", $names) $SHA1Thumbprint = $(New-SelfSignedCertificateEx @opts).Thumbprint } else { $opts = @{ Subject = $env:COMPUTERNAME ; NotAfter = $ValidUntil; HashAlgorithm = $HashAlgorithm; KeyLength = $KeyLength } if (![String]::IsNullOrEmpty($env:USERDNSDOMAIN)) { $opts.Add("DnsName", $env:COMPUTERNAME, "$(("$env:COMPUTERNAME.$env:USERDNSDOMAIN").ToLower())") } $SHA1Thumbprint = $(New-SelfSignedCertificate @opts).Thumbprint } } } Process { Set-CimInstance ` -Namespace 'root\cimv2\TerminalServices' ` -Query 'SELECT * FROM Win32_TSGeneralSetting WHERE TerminalName = "RDP-Tcp"' ` -Property @{ SSLCertificateSHA1Hash = $SHA1Thumbprint } if ($EnableFirewallRules) { # I don't use "Set-NetFirewallRule" here because of backwards compatibilty. & netsh.exe advfirewall firewall set rule 'group="Remote Desktop"' new enable=yes > $null } } } |