Ein Exit Modul für die Zertifizierungsstelle in C# erstellen

Microsoft Active Directory Certificate Services bietet die Möglichkeit, eigene Policy- und Exitmodule zu entwickeln, um die Funktionalität der Zertifizierungsstelle zu erweitern.

Nachfolgend die notwendigen Schritte, um ein Exit Modul in C# mit Visual Studio 2019 zu erstellen. Das Exit Modul wird ausgestellte Zertifikate in ein konfigurierbares Verzeichnis im Dateisystem schreiben.

Dankenswerterweise hat ein nicht namentlich genannter Verfasser die meiste Vorarbeit bereits erledigt. Mein Dank geht an dieser Stelle an diese Person! Ich habe seinen Beispielcode als Ausgangsbasis genommen.

Visual Studio beschaffen

Visual Studio 2019 kann in der Community Edition kostenlos von Microsoft bezogen werden. Bitte die Lizenzbedingungen beachten und berücksichtigen.

Bei der Installation muss die Option "Desktop Development with C#" ausgewählt werden.

Interop Assemblies erzeugen

Kennen Sie TameMyCerts? TameMyCerts ist ein Add-On für die Microsoft Zertifizierungsstelle (Active Directory Certificate Services). Es erweitert die Funktion der Zertifizierungsstelle und ermöglicht die Anwendung von Regelwerken, um die sichere Automatisierung von Zertifikat-Ausstellungen zu realisieren. TameMyCerts ist einzigartig im Microsoft-Ökosystem und steht unter einer freien Lizenz. Es kann über GitHub heruntergeladen und kostenlos verwendet werden.

Die Entwicklung muss nicht auf einem System erfolgen, auf dem die Zertifizierungsstelle installiert ist. Ein üblicher Windows 10 PC ist ausreichend. Wir benötigen jedoch zwei DLL-Dateien von der Zertifizierungsstelle, welche von einem Windows Server System kopiert werden müssen:

  • certxds.dll
  • certcli.dll

Die beiden DLL-Dateien befinden sich auf dem Zertifizierungsstellen-Server unter C:\Windows\System32.

Für diese beiden DLL-Dateien müssen Interop-Dateien erzeugt werden. Dies kann mit dem Programm tlbimport erfolgen, welches mit Visual Studio ausgeliefert wird.

Hierzu wird die Developer Command Prompt gestartet. Anschließend werden folgende Befehle eingegeben:

tlbimp certxds.dll
tlbimp certcli.dll

Der Befehl wird die beiden folgenden Interop Assemblies als DLL-Dateien erzeugen:

  • CERTEXITLib.dll
  • CERTCLILib.dll

Anpassen der CERTCLILIB.dll

Bei der Übersetzung vom zugrundeliegenden C++ Code auf C# ist die Konvertierung der Datentypen nicht in jedem Fall korrekt (siehe hier für weitere Informationen). Daher muss die eben erzeugte CERTCLILIB zunächst disassembliert werden:

"C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools\ildasm.exe" ^
CERTCLILib.dll ^
/out:CERTCLILIB.il

Die originale CERTCLILIB.dll muss nun gelöscht werden.

Innerhalb der CERTCLILIB.in werden alle Vorkommnisse von GetCertificateProperty ausgetauscht von…

GetCertificateProperty([in] string  marshal( bstr) strPropertyName,
                       [in] int32 PropertyType) runtime managed internalcall

Zu…

GetCertificateProperty([in] string  marshal( bstr) strPropertyName,
                       [in] int32 PropertyType,
                       [out] native int pvarPropertyValue) runtime managed internalcall

Möchte man GetRequestProperty verwenden um z.B. das "RawRequest" Attribut auszulesen, muss für GetRequestProperty nach dem gleichen Schema vorgegangen werden.

Anschließend kann die DLL wieder assembliert werden.

"C:\Windows\Microsoft.NET\Framework\v4.0.30319\ilasm.exe" ^
/DLL CERTCLILIB.il ^
/res:CERTCLILIB.res ^
/out=CERTCLILIB.dll

Projekt erzeugen

Nach dem Start von Visual Studio wird ein neues Projekt erzeugt.

Wir benötigen eine Class Library mit dem .NET Framework.

Das Projekt erhält im nächsten Schritt einen Namen und einen Speicheort, dann kann es losgehen.

Referenzieren der Interop-DLL-Dateien

Die zuvor erzeugen Interop-DLL-Dateien CERTEXITLib.dll und CERTCLILib.dll werden ins Projektverzeichnis kopiert.

Anschließend werden die beiden DLL-Dateien referenziert.

Erzeugen der Klassen-Dateien

Es müssen zwei Klassen erzeugt werden. Beispiele für die beiden Klassendateien finden sich in meinem Beispiel-Projekt auf GitHub:

Neue GUID vergeben

Wenn die Beispiel-Datei verwendet werden soll, sollte jeweils eine neue GUID in beiden Dateien eingetragen werden.

Die GUID darf in beiden Dateien nicht identisch sein.

Eine neue GUID kann beispielsweise mit dem PowerShell-Befehl "New-Guid" erzeugt werden.

New-GUID

Modul-Parameter definieren

Die Parameter für das Modul wie Name, Beschreibung, Version und Copyrighthinweis können in der GetProperty Methode in der ExitManageClass.cs definiert werden.

Übersetzen des Quellcodes

Nun kann das Exit Modul kompiliert werden.

Registrieren des Exit-Moduls auf der Zertifizierungsstelle

Die erzeugte DLL-Datei kann nun auf den Ziel-Server kopiert werden. Sie muss in zwei Verzeichnisse gespeichert werden:

  • C:\Windows\System32
  • C:\Windows\SysWOW64

Anschließend muss die DLL-Datei mit folgendem Befehl registriert werden:

C:\Windows\Microsoft.NET\Framework64\v4.0.30319\regasm.exe ^
C:\Windows\System32\MyFirstExitModule.dll

Es handelt sich bei der regasm.exe um das .NET Äquivalent zur regsvr32.exe.

Der certsvr Prozess ist ein 64-Bit Prozess, daher muss die DLL auch als 64-Bit registriert werden (regasm.exe aus dem Framework64 Verzeichnis). Aktuelle Windows-Versionen werden nur noch in 64-Bit ausgeliefert, historisch gab es jedoch auch 32-Bit Versionen des Dienstes.

In meinem Beispielprojekt auf GitHub liegt auch ein Installations/Deinstallations Script.

Exit Modul konfigurieren

Im Beispielprojekt schreibt das Exit Modul ausgestellte Zertifikate in einen Ordner im Dateisystem. Der Pfad muss als REG_SZ (String Value) namens "OutputDirectory" unterhalb des folgenden Registry Schlüssels konfiguriert werden.

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\CertSvc\Configuration\{Common-Name-der-Zertifizierungsstelle}\ExitModules\MyFirstExitModule

Zertifizierungsstellen-Dienst neu starten

Anschließend muss der Zertifizierungsstellen-Dienst neu gestartet werden.

net stop certsvc
net start certsvc

Sollte das Exit-Modul nicht geladen werden können, oder einen Fehler verursachen, wird die Zertifizierungsstelle das Ereignis Nr. 46 protokollieren.

Öffnet man nun die Verwaltungskonsole für die Zertifizierungsstelle (certsrv.msc), sollte in der Karteikarte "Exit Modules" unter "Add" das neu erzeugte Exit-Modul zur Auswahl stehen.

Stellt die Zertifizierungsstelle ein Zertifikat aus, sollte dieses nun in das konfigurierte Verzeichnis exportiert werden.

Ab dieser Stelle ist das Projekt bereit für Eigenentwicklungen. Hier einige Ideen:

  • Speichern ausgestellter Zertifikate in einer Datenbank
  • Direktes melden einer Veränderung des Sperrstatus (Sperrent/Entsperren) eines Zertifikats an eine Datenbank
  • Direktes Exportieren der Zertifikat-Seriennummern ins Dateisystem für das deterministische Good des Onlineresponders (OCSP)
  • Aufruf einer Web-API zur Übermittlung der Zertifikatinformationen zur weiteren Bearbeitung (ausgestellte Zertifikate, Sperrungen, Entsperrungen)
  • Entwicklung eines Exitmoduls, welches per SMTP Nachrichten versenden kann und im Gegensatz zum Standard Microsoft Exit Modul auch auf Server Core lauffähig ist

Weiterführende Links:

Externe Quellen

de_DEDeutsch