SSL in .NET-Dev-Umgebung einrichten
Savety first! So sollte es jedenfalls sein. Das heißt aber auch, dass ich eigene Webanwendungen in Visual Studio immer mit SSL als Default entwickle.
Visual Studio ist dabei so nett ein eigenes Dev-Zertifikat für localhost
zu generieren und einzurichten. Man braucht also eigentlich nicht viel tun um SSL nutzen zu können.
Ein Problem kann es aber sein, wenn Kommunikation zwischen mehreren Geräten stattfindet. Das kann z.B. in einem Integrationstestszenario so sein. In diesen Fällen eignet sich das automatisch generierte Zertifikat nicht. Es muss ein eigenes her.
In folgendem Artikel werde ich erklären wie man sich ein eigenes Zertifikat für Entwicklungs- und Testzwecke mit der PowerShell generieren kann.
Dieses werde ich dann in unterschiedlichen Konfigurationen einrichten.
- Dem IIS Express für die lokale Entwicklung.
- Kestrel, als Alternative für .NET Core- bzw. .NET 5-Entwicklung
- IIS, für Integrationstestszenarion.
Zertifikat erstellen und installieren
Mit der PowerShell ist es ein Klacks sich selbst ein Zertifikat auszustellen. Stamm- oder Wildecard-Zertifikate sind kein Problem.
# The certificate authenticator's name.
$Ca = "Marcel Melzig"
# The DNS name for the identity certificate.
$DnsName = "*.net.work"
# Password used for the exported PFX file.
$Password = "T3st"
# Paths to store the certs.
$PathToStoreRootCertPFXFile = "C:\root.pfx"
$PathToStoreRootCertCERFile = "C:\root.cer"
$PathToStoreIdentityCertPFXFile = "C:\identity.pfx"
$PathToStoreIdentityCertCERFile = "C:\identity.cer"
# Creates a root certificate with the CA and stores it into a variable to used it to sign an identity certificate.
$RootCert = New-SelfSignedCertificate -Subject "CN=$Ca,O=$Ca,OU=$Ca" -KeyExportPolicy Exportable -KeyUsage CertSign,CRLSign,DigitalSignature -KeyLength 2048 -KeyUsageProperty All -KeyAlgorithm 'RSA' -HashAlgorithm 'SHA256' -Provider 'Microsoft Enhanced RSA and AES Cryptographic Provider'
# Creates an identity certificate with the primarily created root certificate. It also stores the object into a variable to use it's thumbprint later on.
$IdentityCert = New-SelfSignedCertificate -CertStoreLocation cert:\LocalMachine\My -DnsName $DnsName -Signer $RootCert -KeyUsage KeyEncipherment,DigitalSignature,DataEncypherment,KeyAgreement -KeyAlgorithm 'RSA' -HashAlgorithm 'SHA256' -Provider 'Microsoft Enhanced RSA and AES Cryptographic Provider'
# Exports the certificates into files.
$CertPassword = ConvertTo-SecureString $Password -AsPlainText -Force
$CertFile = Export-PfxCertificate -Cert "cert:\LocalMachine\My\$($RootCert.Thumbprint)" -FilePath $PathToStoreRootCertPFXFile -Password $CertPassword
Export-Certificate -Cert "cert:\LocalMachine\My\$($RootCert.Thumbprint)" -FilePath $PathToStoreRootCertCERFile
Export-PfxCertificate -Cert "cert:\LocalMachine\My\$($IdentityCert.Thumbprint)" -FilePath $PathToStoreIdentityCertPFXFile -Password $CertPassword
Export-Certificate -Cert "cert:\LocalMachine\My\$($IdentityCert.Thumbprint)" -FilePath $PathToStoreIdentityCertCERFile
# Imports the generated root cert into the Trusted Root Certificate store.
Import-PfxCertificate -CertStoreLocation Cert:\LocalMachine\AuthRoot -FilePath $CertFile.FullName -Password $CertPassword
$Ca = "Marcel Melzig"
ist die Signierungsstelle des Root-Zertifikats. In diesem Fall ich.
$DnsName = "*.net.work"
ist der DNS für den das Identitätszertifikat ausgestellt werden soll. Das Schema ist <hostname>.<domain>
. In diesem Fall nutze ich *
um ein Wildecardzertifikat zu erstellen. Es gilt für alle Hosts.
$Password = "T3st"
definiert ein Passwort für die PFX-Dateien. Es handelt sich um ein Format mit dem Zertifikate ausgetauscht werden können. Diese werden durch ein Passwort geschützt.
$Path…
definiert Pfade unter denen das Root-Zertifikat und die Identitätszertifikate in Dateien exportiert werden. Mit diesen Dateien können die Zertifikate später installiert bzw. genutzt werden.
Als nächstes erstellt das Skript ein Stammzertifikat und nutzt dieses um das Wildcardzertifikat zu erstellen.
Die Zertifikate sind direkt im eigenen Zertifikatstore der Maschine installiert. Aus diesem werden sie im nächsten Schritt in Dateien exportiert.
Als letzter Schritt importiert das Skript das Stammzertifikat in den Trusted Store. Erst jetzt vertraut das System Zertifikaten, die mit dem Stammzertifikat signiert wurden.
Damit kann das Identitätszertifikat von Anwendungen auf diesem System genutzt werden.
IIS Express konfigurieren
Eine dieser Anwendungen ist IIS Express. Die leichtgewichtige Version des IIS eignet sich gut zum Entwickeln von Anwendungen, die mal im IIS gehostet werden sollen. Die Entwicklungs- und Debugumgebung unterscheidet sich somit möglichst wenig von der Produktivumgebung.
Debugkonfiguration in Visual Studio anlegen
Um eine Anwendung im IIS Express zu starten muss man im Projekt eine Debugkonfiguration anlegen.
In den Properties des Projekts kann man unter Debug eine Debugkonfiguration anlegen. Unter Launch gibt man IIS Express an, damit die Anwendung im IIS Express gehostet wird.
Unter Launch browser kann man eine URL angeben, die beim Debuggen in einem Browser geöffnet wird. In Beispiel mein Hostname mit https
und dem SSL-Port 44300. Dieser Link wird generiert, wenn man Enable SLL aktiviert. Er kann mit Copy in die Zwischenablage kopiert und oben eingefügt werden.
Die Konfiguration wird übrigens unter Properties\launchSettings.json gespeichert.
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://dev-mm.fritz.box:57066/",
"sslPort": 44300
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "https://dev-mm.fritz.box:44300/testing/deployment",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"sqlDebugging": false,
"nativeDebugging": false
}
}
}
Diese Datei sollte von Git ignoriert werden und gehört in .gitignore, da es sich um eine Konfiguration handelt, die nur für einen Entwicklerrechner sinnvoll ist.
Zertifikat konfigurieren
Visual Studio konfiguriert die Ports 44300 bis 44399 automatisch für die Nutzung mit dem IIS Express.
Man kann sich die Konfigurationen der Bindungen mit netsh http show sslcert > certs.txt
in die Datei certs.txt exportieren. Hier lässt sich die Anwendungs-ID des IISExpress und der Fingerabdruck des Zertifikats einsehen.
Zertifikathash : a31c119eed03116a90c757452cfc447f09c2466c
Anwendungs-ID : {214124cd-d05b-4309-9af9-9caa44b2b74a}
Im certmgr kann das selbst erstellte Zertifikat geöffnet werden.
Unter Details kann man sich den Fingerabdruck kopieren.
IIS und IIS Express hosten Webseiten beide über die selbe Windows-Komponente, http.sys.
Diesen kann man über die PowerShell konfigurieren.
Zuerst muss man das bestehende Binding für den genutzten SSL-Port löschen.
netsh http delete sslcert ipport=0.0.0.0:44300
Nun kann man mit dem Fingerprint das eigene Zertifikat für den Port konfigurieren.
netsh http add sslcert ipport=0.0.0.0:44300 certhash=aa586c27a2f73b317a60171c14c3fadba2d5f691 appid="{214124cd-d05b-4309-9af9-9caa44b2b74a}"
Die appid
ist fix. Es handelt sich um die AppId des IIS Express.
certhash
ist der Fingerprint des Zertifikats.
Nach einem Neustart des IIS Express, oder besser des Systems, wird das eigene Zertifikat verwendet.
Die Konfiguration der Bindings ist übrigens in der Datei “Projektverzeichnis.vs\Projektname\config\applicationhost.config gespeichert. Hier kann man sehen ob die Bindings auch korrekt konfiguriert wurden.
<site name="Projektname" id="1">
<application path="/" applicationPool="Clr4IntegratedAppPool">
<virtualDirectory path="/" physicalPath="Projektpfad" />
</application>
<bindings>
<binding protocol="http" bindingInformation="*:57066:dev-mm.fritz.box" />
<binding protocol="https" bindingInformation="*:44300:dev-mm.fritz.box" />
</bindings>
</site>
Kestrel konfigurieren
.NET Core oder .NET 5-Anwendungen können zwar auch in einem IIS gehostet werden, aber es erscheint mir so als seien sie vor allem für Container gedacht. Deshalb liefert Microsoft direkt einen eigenen leichtgewichtigen, auf Performance optimierten Server mit. Kestrel. Ich mag es Anwendungen direkt in Kestrel zu debuggen. Plant man die Anwendung in der Cloud zu hosten, dann kommt dies auch der Produktivumgebung näher.
Ein praktischer Nebeneffekt ist, dass man ein Live-Log in der Konsole hat und so direkt einige Informationen ablesen kann.
Debugkonfiguration in Visual Studio anlegen
Die Konfiguration wird ebenfalls in Visual Studio Properties –> Debug angelegt.
Als Launch-Typ wähl man Project und aktiviert Launch browser. Als URL kopiert man dann die HTTPS-URL von Kestrel in das Feld.
Es wird das Startprojekt der Solution im Browser mit SSL gestartet.
Die GUI speichert die Einstellungen in der Datei Properties\launchSettings.json.
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://dev-mm.fritz.box:57066/",
"sslPort": 44300
}
},
"profiles": {
"Kestrel": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "https://dev-mm.fritz.box:5001",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "https://dev-mm.fritz.box:5001;http://dev-mm.fritz.box:5000"
}
}
}
Zertifikat konfigurieren
In Kestrel kann man das Zertifikat über den integrierten Konfigurationsmechanismus im WebHostBuilder
konfigurieren.
return WebHost.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.AddJsonFile("kestrel.json", true);
})
.UseKestrel()
Ich habe die Konfiguration von Kestrel in einer eigenen Datei, kestrel.json, gespeichert. In diesem Beispiel liegt sie im Startverzeichnis der Anwendung.
{
"Kestrel": {
"AllowInvalid": true,
"Certificates": {
"Default": {
"Path": "C:\\identity.pfx",
"Password": "P4ssW0rd"
}
}
}
}
AllowInvalid
erlaubt selbst signierte Zertifikate. Das Default Zertifikat wird mit Pfad zur Datei und Passwort konfiguriert.
IIS konfigurieren
In z.B. Integrationstestszenarien wird es nicht reichen die Anwendung aus Visual Studio heraus zu starten. Das Zertifikat lässt sich natürlich auch in einer VM installieren und in IIS konfigurieren.
Mit den Zertifikatdateien können die Zertifikate auf dem System installiert werden. Ein Doppelklick auf die Datei öffnet dazu einen Wizard. Das Stammzertifikat wird in den Trusted Root Certificate Store installiert. Das Wildcardzertifikat kann unter eigene Zertifikate installiert werden.
Im Internetinformationsdiesnte (IIS)-Manager legt man eine neue Seite unter Sites → Webseite hinzufügen an, sofern sie noch nicht vorhanden ist.
Im Kontextmenü der Seite kann man mit Bindung bearbeiten… eine https
Bindung für die Webseite anlegen.
Als Typ wird https
gewählt. Der Hostname muss zu der Domäne gehören, für die das Wildcardzertifikat gültig ist. Als SSL-Zertifikat wird das Wildcardzertifikat gesetzt.
Die Webseite wird jetzt mit diesem verschlüsselt.
Fazit
Glückwunsch. Es ist geschafft. In der kompletten Dev- und Testumgebung wird nun das gleiche Zertifikat verwendet.