Selfsigned Certificate - Selbsterstellte PKI - Powershell v5

08.12.2019 | Autor: Mark Heitbrink

Eine PKI im Eigenbau

PKI - Public Key Infrastructure. Das muss man intern professionell lösen.

Ich arbeite seit 20 Jahren mit Michael Buth zusammen, in den letzten Jahren hat er sich auf PKI spezialisiert. Er ist derjenige, den ich zu euch schicken würde, wenn ihr mich auf das Thema ansprecht. Oder bestellt ihm schöne Grüsse ... Zertwerk - Michael Buth  - mbuth.de

Ich weiss, ich werde jetzt geprügelt und geschlagen, weil man eine PKI nicht "mal eben" installiert und aus dem Boden stampft. Das ist ein organisatorisches Konzept, das wohl überlegt und geplant sein will. Es betrifft alle Geschäftsbereiche, alle müssen(!) mitreden, denn es ist ein Infrastruktur Impakt, der von der Rechtsabteilung (Certification Practise Statement) bis zur IT Infrastruktur alle betrifft. Das Zertifikat ist das kleinste Problem, wir reden über Workflows, Arbeitsprozesse und Design. Über Ansprüche und was will man überhaupt?

Aber was soll ich sagen? Die Realität ist ... Klick-Klick ... weiter .. weiter ..OK.

Ich habe auf dieser Seite schon Anleitungen für ein SelfSigned SSL Zertifikate hinterlegt:

  • Selfsigned Certificate - Selbsterstelltes Zertifikat - MakeCert.exe
  • Selfsigned Certificate - Selbsterstelltes Zertifikat - SelfSSL.exe

Die Verteilung der Selbsterstellten Zertifikate geht prima per Gruppenrichtlinie. Dort sind alle Speicherorte hinterlegt, die man aus der MMC kennt.

Anleitung für das Verteilen: Zertifikate verteilen

Diese obigen Anleitungen erstellten ein SSL (SAN) Zertifikat für einen Server, das ein einzelnes Zertifikat darstellt. Es ist ist die Ausstellende Zertifizierungsstelle und der Reisepass in einem. Jedes erstellte Zertifikat muss nun an die Clients verteilt werden, damit sie diesem Vertrauen und es keine Fehler beim Aufruf der Verbindungen gibt. Das ist aufwendig, aber für wenige Zertifikate vom Aufwand vertretbar. Sobald es mehr Zertifikate werden, wäre eine Zertifizierungsstelle wesentlich angenehmer. Dann wird der Zertifizierungsstelle vertraut und alle daraus folgenden Zertifikate sind automatisch glaubwürdig. Wir haben dann nur einen Verteilprozess.

Mit dem Anspruch einer PKI wird es nun aufwendig, siehe oben. Wer die Zertifikate nur intern verwenden möchte, auf eine CRL (Certificate Revocation List) verzichten kann und keine automatisierten Deployment Mechanismus über das AD mit Zertifikat Vorlagen über Sicherheitsgruppen mit Autoenrollment etc benötigt, der kann auf die Powershell zurückgreifen.

In diesem Artikel bauen wir eine RootCA (Vertrauenswürdige Stammzertifizierungsstelle). Von dieser wird eine weitere CA als Zwischenzertifizierungsstelle (Intermediate CA) erstellt. Diese erzeugt gleichzeitig die Zertifikate für die Clients, Server oder Benutzer. Sie ist die Ausstellende CA (Issuing CA). Eine RootCA sollte keine Zertifikate für die Entpunkte direkt erzeugen, deswegen der Zwischenschritt.

Mein Dank geht an infiniteloop.io. Dort habe ich mir einiges 1zu1 mitgenommen und dann für dieses HowTo erweitert.
Powershell – Self-signed Certificate via Self-signed Root CA

Root CA - Vertrauenswürdige Stammzertifizierungsstelle
(Bitte Pfade und Passwort anpassen ... und das Script nicht für jeden lesbar ablegen, wegen des Passworts, ihr wisst schon ...)

 

# Tribute to:
# infiniteloop.io/powershell-self-signed-certificate-via-self-signed-root-ca/
# Extended the Scripts with an Intermediate Issuing CA and some automation
# for Export and Import Certificates
$Path="C:\PoSH-PKI"

# Create Root CA
$params = @{  
DnsName = "gruppenrichtlinien.de - RootCA"  
KeyLength = 4096  
KeyAlgorithm = 'RSA'  
HashAlgorithm = 'SHA512'  
KeyExportPolicy = 'Exportable'  
NotAfter = '31.12.2030'  
CertStoreLocation = 'Cert:\LocalMachine\My'  
KeyUsage = 'CertSign','CRLSign' #fixes invalid cert error  
Textextension = '2.5.29.37={text}1.3.6.1.5.5.7.3.2,1.3.6.1.5.5.7.3.1,1.3.6.1.5.5.7.3.4,1.3.6.1.5.5.7.3.3,1.3.6.1.5.5.7.3.8,1.3.6.1.5.5.7.3.1','2.5.29.19={critical}{text}ca=TRUE'}
$rootCA = New-SelfSignedCertificate @params

# Export Private and Public Certificate, Import Public as Trusted Root
# Extra step needed since self-signed cannot be directly shipped to trusted root CA store
$Name=($RootCA| Select-Object -ExpandProperty Subject).Replace("CN=","")
Export-Certificate -Cert $rootCA -FilePath "$Path\$Name.crt"
Export-PfxCertificate -Cert $rootCA -FilePath "$Path\$Name.pfx" -Password (ConvertTo-SecureString -AsPlainText 'MEINGEHEIMNIS' -Force)
Import-Certificate -CertStoreLocation "Cert:\LocalMachine\Root" -FilePath "$Path\$Name.crt"

 

Intermediate / Issuing CA - Zwischenzertifizierungsstelle

 

# Create Intermediate Issuing CA, from Root
# Parameter $RootCA would function from above Code, if Script runs completly in one call.
# Doing it step by step, the RootCA must be selected
$Path="C:\PoSH-PKI"
$RootCA=Get-ChildItem -Path cert:\LocalMachine\My | where {$_.Subject -like 'cn=gruppenrichtlinien.de - RootCA'}

$params = @{  
DnsName = "gruppenrichtlinien.de - IssuingCA"  
Signer = $RootCA  
KeyLength = 4096  
KeyAlgorithm = 'RSA'  
HashAlgorithm = 'SHA512'  
KeyExportPolicy = 'Exportable'  
NotAfter = '30.12.2030'  
Textextension = '2.5.29.37{text}1.3.6.1.5.5.7.3.2,1.3.6.1.5.5.7.3.1,1.3.6.1.5.5.7.3.4,1.3.6.1.5.5.7.3.3,1.3.6.1.5.5.7.3.8,1.3.6.1.5.5.7.3.1','2.5.29.19={critical}{text}ca=TRUE'  
CertStoreLocation = 'Cert:\LocalMachine\My'  
Subject = 'CN=gruppenrichtlinien.de - IssuingCA,E=info@gruppenrichtlinien.de,O=gruppenrichtlinien.de,OU=1.3.6.1.4.1.40369 - IANA.org - Private Enterprise Number,C=DE'  
KeyUsage = 'CertSign','CRLSign' #fixes invalid cert error}
$IssuingCA = New-SelfSignedCertificate @params

# Export Private and Public Certificate, Import Public as Trusted Root and Intermediate CA
# Extra step needed since self-signed cannot be directly shipped to trusted root CA store
$Name=($IssuingCA| Select-Object -ExpandProperty Subject).Replace("CN=","")
Export-Certificate -Cert $IssuingCA -FilePath "$Path\$Name.crt"
Export-PfxCertificate -Cert $IssuingCA -FilePath "$Path\$Name.pfx" -Password (ConvertTo-SecureString -AsPlainText 'MEINGEHEIMNIS' -Force)
Import-Certificate -CertStoreLocation "Cert:\LocalMachine\CA" -FilePath "$Path\$Name.crt"
Import-Certificate -CertStoreLocation "Cert:\LocalMachine\Root" -FilePath "$Path\$Name.crt"

 

SSL SAN Zertifkate von der Intermediate / Issuing CA beziehen/ausstellen

 

# Create the Computer SSL cert signed by the new Issuing Intermediate CA
# Parameter $IssuingCA would function from Code above, if Script runs completly in one call.
# Creating SSL certificates will be an ongoing process, so the IssuingCA must be selected
$Path="C:\PoSH-PKI"
$IssuingCA=Get-ChildItem -Path cert:\LocalMachine\My\ | where {$_.Subject -match 'CN=gruppenrichtlinien.de - IssuingCA'}

# Create the User cert signed by the new Issuing Internediate CA
$params = @{ 
Signer = $IssuingCA 
KeyLength = 2048 
KeyAlgorithm = 'RSA' 
HashAlgorithm = 'SHA256' 
KeyExportPolicy = 'Exportable' 
NotAfter = (Get-date).AddYears(5) 
CertStoreLocation = 'Cert:\LocalMachine\My'}
$ComputerCert = New-SelfSignedCertificate @params -DnsName Majestix,Majestix.gallier.ads,gallier.ads,workfolders,workfolders.gallier.ads,workfolders.gruppenrichtlinien.de 

# Export ComputerCert
$Name=($ComputerCert | Select-Object -ExpandProperty Subject).Replace("CN=","")
Export-PfxCertificate -Cert $ComputerCert -FilePath "$Path\$Name.pfx" -Password (ConvertTo-SecureString -AsPlainText 'MEINGEHEIMNIS' -Force)
Export-Certificate -Cert $ComputerCert -FilePath "$Path\$Name.cer"

Benutzerzertifkat von der Intermediate / Issuing CA beziehen/ausstellen

$Path="C:\PoSH-PKI"
$Thumbprint=Get-ChildItem -Path cert:\LocalMachine\My | where {$_.Subject -match 'CN=gruppenrichtlinien.de - IssuingCA'} | Select-Object -ExpandProperty Thumbprint
$IssuingCA=Get-ChildItem -Path cert:\LocalMachine\My\$Thumbprint 

# Create the User cert signed by the new Issuing Internediate CA
$params = @{
Signer = $IssuingCA
KeyLength = '4096'
KeyAlgorithm = 'RSA'
HashAlgorithm = 'SHA512'
KeyExportPolicy = 'Exportable'
NotAfter = '27.07.2030'
FriendlyName = 'Mark Heitbrink'
CertStoreLocation = 'Cert:\CurrentUser\My'
Subject = 'E=gpo@gruppenrichtlinien.de,CN=Mark Heitbrink,O=gruppenrichtlinien.de,OU=1.3.6.1.4.1.40369 - IANA.org - Private Enterprise Number,C=DE'
# Purpose, Usage
TextExtension = '2.5.29.37={text}1.3.6.1.5.5.7.3.3,1.3.6.1.5.5.7.3.4,1.3.6.1.5.5.7.3.2,1.3.6.1.4.1.311.10.3.4'
# 1.3.6.1.5.5.7.3.3, Code Signing
# 1.3.6.1.5.5.7.3.4, Secure Email
# 1.3.6.1.5.5.7.3.2, Client Authentication
# 1.3.6.1.4.1.311.10.3.4, Encrypting File System}
$userCert = New-SelfSignedCertificate @params -type Custom -SmimeCapabilities -KeyUsage DataEncipherment,KeyEncipherment,NonRepudiation,DigitalSignature
# Export UserCert
$Name=($UserCert | Select-Object -ExpandProperty Subject).Replace("CN=","")
Export-PfxCertificate -Cert $UserCert -FilePath "$Path\$Name.pfx" -Password (ConvertTo-SecureString -AsPlainText 'MEINGEHEIMNIS' -Force)
Export-Certificate -Cert $UserCert -FilePath "$Path\$Name.cer"

Über die Schlüssellängen und den Hash Algorythmus könnt ihr euch noch Gedanken machen, ebenfalls steht die Laufzeit der Zertifikate sicherlich zur Diskussion. Aber sobald ihr darüber nachdenkt, dann macht es doch gleich "richtig". Baut eine ordentliche PKI, 3-stufig, mit IANA PEN Number, mit Struktur, mit einem Certificate Practise Statement, einem planbaren Ausrollen mit Prozessen und allem was dazugehört.