Turns out that it's possible to deliver this using a certificate with SAN (Subject Alternative Name) entries. For anyone who's interested, here's the PowerShell to do it:
<#
.Synopsis
Creates a new Certificate for an RD Gateway Server
.DESCRIPTION
Creates a self-signed Certificate and associates it with the local RD Gateway Server
.EXAMPLE
New-RDGCertificate -SubjectName
'CN=MyServer.PrimaryLocation.Provider.com'
Creates a new self-signed certificate which can be used to to authenticate incoming RD Gateway traffic
to the DNS name MyServer.PrimaryLocation.Provider.com
.EXAMPLE
[string[]] $SAN = "MyServer.SecondaryLocation.Provider.com"
$SAN += "MyServer.TertiaryLocation.Provider.com"
$SAN += "MyServer.local"
New-RDGCertificate -SubjectName
'CN=MyServer.PrimaryLocation.Provider.com' -SAN $SAN
Creates a new self-signed certificate which can be used to to authenticate incoming RD Gateway traffic
to the following DNS names:
1) MyServer.PrimaryLocation.Provider.com
2) MyServer.SecondaryLocation.Provider.com
3) MyServer.TertiaryLocation.Provider.com
4) MyServer.local
#>
function New-RDGCertificate
{
[CmdletBinding()]
Param
(
# Name of the certificate to create
[Parameter(Mandatory=$true)]
[string]$SubjectName,
# Subject-alternative name(s) to add to the certificate
[Parameter(Mandatory=$false)]
[ValidateNotNullOrEmpty()]
[string[]]$SAN
)
Write-Verbose "Creating Certificate: $SubjectName"
$Name = New-Object -Com 'X509Enrollment.CX500DistinguishedName.1'
$Name.Encode($SubjectName, 0)
$Key = New-Object -Com 'X509Enrollment.CX509PrivateKey.1'
$Key.ProviderName = 'Microsoft RSA SChannel Cryptographic Provider'
$Key.KeySpec = 1
$Key.Length = 1024
$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).AddHours(-2)
$Cert.NotAfter = $Cert.NotBefore.AddDays(2998)
#SAN
if ($SAN) {
$IAlternativeNames = New-Object -ComObject X509Enrollment.CAlternativeNames
foreach ($AN in $SAN) {
# Instantiate a IAlternativeName object
$AltName = New-Object -ComObject X509Enrollment.CAlternativeName
# Initialize the object by using current element
$AltName.InitializeFromString(0x3,$AN)
# Add created object to an object of collection of IAlternativeNames
$IAlternativeNames.Add($AltName)
}
$SubjectAlternativeName = New-Object -ComObject X509Enrollment.CX509ExtensionAlternativeNames
$SubjectAlternativeName.InitializeEncode($IAlternativeNames)
$Cert.X509Extensions.Add($SubjectAlternativeName)
}
$Cert.X509Extensions.Add($ekuext)
$Cert.Encode()
$Enrollment = New-Object -Com 'X509Enrollment.CX509Enrollment.1'
$Enrollment.InitializeFromRequest($Cert)
$CertData = $Enrollment.CreateRequest(0)
$Enrollment.InstallResponse(2, $CertData, 0, '')
}
<#
.Synopsis
Searches certificate store for a given Subject Name, returning the Certificate
.DESCRIPTION
Searches through the LocalMachine or CurrentUser store location for a certificate whose Subject Name matches the given value
.EXAMPLE
Find-RDSCertificate -SubjectName "CN=MyDNS.com"
This will search the LocalMachine\My store for a certificate whose Subject Name matches MyDNS.com.
It returns the certificate or $Null, based on whether or not a matching certificate is found.
.EXAMPLE
Find-RDSCertificate -SubjectName "CN=MyOtherDNS.com" -Store "TrustedPublisher" -Location "CurrentUser"
This will search the CurrentUser\TrustedPublisher store for a certificate whose Subject Name matches MyDNSOther.com.
It returns the certificate or $Null, based on whether or not a matching certificate is found.
#>
function Find-RDSCertificate
{
[CmdletBinding()]
Param
(
# Name of the certificate to search for
[Parameter(Mandatory=$true)]
$SubjectName,
# Certificate store to search in
[Parameter(Mandatory=$false)]
[ValidateSet("AddressBook", "AuthRoot", "CertificateAuthority", "Disallowed", "My", "Root", "TrustedPeople", "TrustedPublisher")]
$Store = "My",
# Location to search in
[Parameter(Mandatory=$false)]
[ValidateSet("LocalMachine", "CurrentUser")]
$Location = "LocalMachine"
)
$CertStore = New-Object System.Security.Cryptography.X509Certificates.X509Store($Store,$Location)
$CertStore.Open('ReadOnly')
$CertStore.Certificates | where {$_.Subject -Eq $SubjectName}
}
Import-Module RemoteDesktopServices
$RDGCertificateSubject = 'CN=MyServer.PrimaryLocation.Provider.com'
[string[]] $SAN = 'MyServer.SecondaryLocation.Provider.com'
$SAN += 'MyServer.TertiaryLocation.Provider.com'
$SAN += 'MyServer.local'
New-RDGCertificate -SubjectName $RDGCertificateSubject -SAN $SAN
$Cert = Find-RDSCertificate -SubjectName $RDGCertificateSubject
#Apply cert
Set-Item -Path "RDS:\GatewayServer\SSLCertificate\Thumbprint" -Value $Cert.Thumbprint