SAN-Erweiterung in CSR nachträglich setzen (bei Windows CA)

Zeigefinger hoch

In diesem Artikel stellen wir Ihnen ein PowerShell-Skript vor, mit dem Sie mit einer Windows CA, trotz der fehlerhaften bzw. fehlenden Anforderung, ein Zertifikat mit SAN-Erweiterung ausstellen können.

Ab wann ist eine SAN-Erweiterung erforderlich?

Die SAN-Erweiterung ist insbesondere dann erforderlich, wenn Sie Chrome ab Version 58 oder Firefox ab Version 48 einsetzen. Seit diesen Versionen wird die Prüfung des CommonName-Attributs von den Browsern nicht mehr unterstützt.

Laut RFC-2818 galt diese Prüfung bereits seit dem Jahr 2000 als „überholt“. Der Internet Explorer toleriert das Fehlen der SAN-Erweiterung (noch). Der bei Chrome-Benutzern beliebte Workaround mit der Option EnableCommonNameFallbackForLocalAnchors wird auch nur noch bis zur Version 65 funktionieren. Danach steht diese Option nicht mehr zur Verfügung.

Kopieren Sie das Skript (welches Sie am Ende des Artikels finden) in eine Text-Datei und benennen Sie diese in „Set-SANCertificateExtension.ps1“ um!

Verwenden Sie das Skript wie folgt:

1. Als erstes ändern Sie im Richtlinienmodul der CA die Anforderungsverarbeitung, damit bei Einreichung eines CSR nicht sofort und automatisch das Zertifikat ausgestellt wird. Klicken Sie dazu im Dialogfenster „Eigenschaften“ Ihrer CA auf der Registerkarte „Richtlinienmodul“ auf „Eigenschaften…“

2. Wählen Sie die Option Den Status der Zertifikatsanforderung auf ‚Ausstehend‘ setzen. Der Administrator muss der Zertifikat explizit ausstellen“ und schließen Sie beide Fenster mit „OK“

3. Starten Sie jetzt die „Active Directory-Zertifikatdienste“  neu.
ACHTUNG: Lassen Sie diesen Schritt aus, ist die eben vorgenommene Änderung der Anforderungsverarbeitung nicht wirksam und das Skript funktioniert nicht!

Reichen Sie jetzt den CSR ein:

certreq -attrib "CertificateTemplate: WebServer" -submit

Die Anforderung erscheint nun in der Zertifizierungsstelle unter „Ausstehende Anforderungen“ mit einer eindeutigen Anforderungs-ID. Mit dieser ID rufen Sie das Script auf:

(Achten Sie darauf, IHRE Anforderungs-ID, IHREN CA-Namen und IHREN Domain-Namen einzusetzen!)

Set-SANCertificateExtension.ps1 -CA "SVRCERT\example.com CA" -RequestID 42 -AlternativeNames "www.example.com"

Achten Sie bei der Verwendung des Scripts außerdem darauf, dass evtl. vorhandenen Anforderungen für eine SAN-Erweiterung überschrieben werden! Weitere Hinweise zu den Verwendungsmöglichkeiten des Skripts finden Sie am Ende des Artikels!

Danach kann mit einem Rechtsklick das Zertifikat ausgestellt werden:


Zum Schluss setzen Sie die Anforderungsverarbeitung wieder zurück auf „Den Einstellungen der Zertifikatvorlage folgen, falls zutreffend. Zertifikat ansonsten automatisch ausstellen“ und starten den Dienst neu.
 
(ACHTUNG: Lassen Sie diesen Schritt aus, funktioniert ggf. das automatische Erneuern Ihrer sonstigen Zertifikate nicht mehr! Das betrifft vor allem die internen Zertifikate Ihrer Active Directory-Domain Controller.)  

Jetzt können Sie das Zertifikat auf Ihrem Server verwenden.

Weitere Beispiele zur Verwendung des Scripts:

Statt eines Hostnamens ein Zertifikat für eine IP-Adresse ausstellen (bei internen CA ist das nach wie vor möglich):

Set-SANCertificateExtension.ps1 -CA "SVRCERT\example.com CA" -RequestID 49 -AlternativeIPs "192.0.2.3"


Mehrere Hostnamen können durch Komma getrennt angegeben werden („klassisches“ SAN-Zertifikat):

Set-SANCertificateExtension.ps1 -CA "SVRCERT\example.com CA" -RequestID 50 "www.example.com","example.com"


Es lassen sich auch IP-Adressen und Hostnamen in einem Zertifikat kombinieren:

Set-SANCertificateExtension.ps1 -CA "SVRCERT\example.com CA" -RequestID 51 -AlternativeNames "www.example.com","example.com" -AlternativeIPs "192.0.2.3"

Achten Sie unbedingt darauf, dass evtl. vorhandenen Anforderungen für eine SAN-Erweiterung überschrieben werden! Sie müssen diese bereits vorhandenen Namen beim Aufruf des Skripts mit angeben.

Die Parameter des Skripts im Überblick:

Die Parameter des Skripts im Überblick

Anstelle der Änderung der Anforderungsverarbeitung des Richtlinienmodul können Sie übrigens auch eine Vorlage verwenden, die eine Genehmigung erfordert. Damit umgehen Sie die Änderung der Einstellung und den damit verbundenen Neustart des Dienstes.

Der Quelltext des Skripts

[CmdletBinding()]
Param(
	[Parameter(Mandatory = $true)]
	[string]$CA,

	[Parameter(Mandatory = $true)]
	[int]$RequestID,

	[Parameter(Mandatory = $false)]
	[String[]]$AlternativeNames,

	[Parameter(Mandatory = $false)]
	[String[]]$AlternativeIPs
)

function ConvertTo-DERstring ([byte[]]$bytes)
{
	if ($bytes.Length % 2 -eq 1) { $bytes += 0 }
	$SB = New-Object System.Text.StringBuilder
	for ($n = 0; $n -lt $bytes.count; $n += 2)
	{
		[void]$SB.Append([char]([int]$bytes[$n+1] -shl 8 -bor $bytes[$n]))
	}
	$SB.ToString()
}

$SAN = New-Object -ComObject X509Enrollment.CX509ExtensionAlternativeNames
$IANs = New-Object -ComObject X509Enrollment.CAlternativeNames

foreach ($SANstr in $AlternativeNames)
{
	$IAN = New-Object -ComObject X509Enrollment.CAlternativeName
	$IAN.InitializeFromString(0x3,$SANstr)
	$IANs.Add($IAN)
}
foreach ($SANstr in $AlternativeIPs)
{
	$IAN = New-Object -ComObject X509Enrollment.CAlternativeName
	$IAN.InitializeFromString(0x3,$SANstr)
	$IANs.Add($IAN)
	
	$IAI = New-Object -ComObject X509Enrollment.CAlternativeName
	$IAI.InitializeFromRawData(8, 0x1, [Convert]::ToBase64String(([System.Net.IpAddress] $SANstr).GetAddressBytes()))
	$IANs.Add($IAI)
}

$SAN.InitializeEncode($IANs)
$bytes = [Convert]::FromBase64String($SAN.RawData(1))
$pvarvalue = ConvertTo-DERstring $bytes
$CertAdmin = New-Object -ComObject CertificateAuthority.Admin
$CertAdmin.SetCertificateExtension($CA,$RequestID,"2.5.29.17",0x3,0x0,$pvarvalue)
To top