judgelg
Goto Top

Zertifikate in die GAL per Powershell

Hallo,
gibt es auch die Möglichkeit den UPN raus zu suchen, anstatt den CN? Er findet teilweise den CN (weil dort teilweise Prof.Name und Dr. Name steht) nicht und müsste besser mit der E-Mail Adresse arbeiten.

foreach($file in Get-ChildItem "D:\certs" -File -Filter *.pem){      
    $cert = [System.Security.Cryptography.X509Certificates.x509certificate2]::new($file.Fullname)
    $cn = $cert.Subject -replace '.*CN=([^,]+).*','$1' -replace 'oe','ö' -replace 'ae','ä' -replace 'ue','ü'    
    Set-Mailbox -Identity $cn -UserCertificate (,$cert.GetRawCertData())
}


Mfg

Content-ID: 670230

Url: https://administrator.de/forum/zertifikate-in-die-gal-per-powershell-670230.html

Ausgedruckt am: 21.01.2025 um 14:01 Uhr

prinzjulius
prinzjulius 17.12.2024 aktualisiert um 10:12:03 Uhr
Goto Top
Guten Morgen,

Ich denke, was du suchst ist der „Subject Alternative Name“ anstelle des „Common Name“, der die Mail-Adresse enthält.

AKTUALISIERT:

foreach ($file in Get-ChildItem "D:\certs" -File -Filter *.pem) {        
    # Zertifikat laden
    $cert = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new($file.Fullname)

    # SAN-Erweiterung extrahieren
    $sanExtension = $cert.Extensions | Where-Object { $_.Oid.value -eq '2.5.29.17' }  
    if ($sanExtension) {
        $sanContent = $sanExtension.Format(0)

        # Suche nach Mail-Adresse oder RFC822-Name
        $sanMail = ($sanContent -split '\r?\n' | Where-Object { $_ -match "email:" -or $_ -match "RFC822-Name" }) `  
            -replace '.*(?:email:|RFC822-Name=)([^,]+).*', '$1'  

        if ($sanMail) {
            Write-Output "Verwende E-Mail/RFC822-Name aus SAN: $sanMail"  

            # Set-Mailbox-Befehl
            Set-Mailbox -Identity $sanMail -UserCertificate (, $cert.GetRawCertData())
        }
        else {
            Write-Warning "Keine E-Mail-Adresse oder RFC822-Name im SAN gefunden für Zertifikat: $($file.FullName)"  
        }
    }
    else {
        Write-Warning "Keine SAN-Erweiterung gefunden für Zertifikat: $($file.FullName)"  
    }
}
Judgelg
Judgelg 17.12.2024 um 09:27:41 Uhr
Goto Top
Hallo,

danke für deine Antwort. Ich werde es in den nächsten Tagen testen und gebe eine rückmeldung.

Mfg
prinzjulius
prinzjulius 17.12.2024 um 10:15:53 Uhr
Goto Top
Ich konnte jetzt kurz testen und es hat nicht ganz funktioniert. Den Code oben habe ich entsprechend angepasst.

Es werden jetzt die SAN mail: bzw. RFC822-Name: aus den Zertifikaten ausgelesen und als Identity für das Set-Mailbox verwendet.
prinzjulius
prinzjulius 17.12.2024 aktualisiert um 15:52:49 Uhr
Goto Top
Und hier das ganze in schön:

Aktualisiert
Set-MailboxCert.ps1
<#

.SYNOPSIS
    Lädt Zertifikate aus Zertifikat-Dateien, extrahiert die E-Mail-Adresse oder den RFC822-Namen aus dem SAN-Feld und aktualisiert die Benutzerzertifikate im Exchange Server.

.DESCRIPTION
    Dieses Skript durchsucht alle Zertifikat-Dateien in einem angegebenen Ordner, lädt die Zertifikate, prüft auf eine SAN-Erweiterung (Subject Alternative Name) und extrahiert die E-Mail-Adresse oder den RFC822-Namen. Anschließend wird das Zertifikat der entsprechenden Mailbox im Exchange Server zugewiesen.

.NOTES
    Version:    2024-06-17
    Autor:      Julius Prinz

.PARAMETER CertPath
    Der Pfad zum Ordner, der die PEM-Zertifikatsdateien enthält.

.PARAMETER Extension
    Die Datei-Erweiterung für die Zertifikatsdateien.

#>


<# Parameter #>
param(
    [Parameter(Mandatory = $true, HelpMessage = "Geben Sie den Pfad zu den Zertifikatsdateien an.")]  
    [string]$CertPath,

    [Parameter(Mandatory = $false, HelpMessage = "Geben Sie die Datei-Erweiterung für die Zertifikatsdateien an (z.B. *.pem).")]  
    [string]$Extension = "pem"  
)


<# Variablen #>
$ErrorActionPreference = 'Stop'  


<# Programm #>
$Extension = "*.$Extension"  
foreach ($file in Get-ChildItem -Path $CertPath -File -Filter $Extension -Recurse) {
    # Zertifikat aus Datei laden
    try {
        $cert = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new($file.FullName)
    }
    catch {
        Write-Warning "Fehler beim Laden des Zertifikats: $($file.FullName). $_"  
        continue
    }

    # SAN-Erweiterung extrahieren
    $sanExtension = $cert.Extensions | Where-Object { $_.Oid.Value -eq '2.5.29.17' }  
    if ($sanExtension) {
        # Inhalt der SAN-Erweiterung formatieren
        $sanContent = $sanExtension.Format(0)

        # Suche nach Mail-Adresse oder RFC822-Name
        $sanMail = ($sanContent -split '\r?\n' | Where-Object { $_ -match "email:" -or $_ -match "RFC822-Name" }) `  
            -replace '.*(?:email:|RFC822-Name=)([^,]+).*', '$1'  

        if ($sanMail) {
            Write-Output "Verwende E-Mail/RFC822-Name aus SAN: $sanMail"  

            # Set-Mailbox-Befehl ausführen
            try {
                Set-Mailbox -Identity $sanMail -UserCertificate (, $cert.GetRawCertData())
                Write-Output "Zertifikat erfolgreich zugewiesen für: $sanMail"  
            }
            catch {
                Write-Warning "Fehler beim Zuweisen des Zertifikats für Mailbox $($sanMail); $_"  
            }
        }
        else {
            Write-Warning "Keine E-Mail-Adresse oder RFC822-Name im SAN gefunden für Zertifikat: $($file.FullName)"  
        }
    }
    else {
        Write-Warning "Keine SAN-Erweiterung gefunden für Zertifikat: $($file.FullName)"  
    }
}


<# Signatur #>
gastric
gastric 17.12.2024 aktualisiert um 11:38:38 Uhr
Goto Top
Hi
# Set-Mailbox-Befehl ausführen
try {
Set-Mailbox -Identity $sanMail -UserCertificate (, $cert.GetRawCertData())
Write-Output "Zertifikat erfolgreich zugewiesen für: $sanMail"
}
catch {
Write-Warning "Fehler beim Zuweisen des Zertifikats für Mailbox $($sanMail); $_"
}

Nur zur Info und Korrektur.
Cmdlets werfen per Default keine richtige Exception innerhalb von try catch Blöcken wenn sie fehl schlagen. Der Catch Block oben wird also auch bei einem Fehler niemals ausgeführt .
Das tun sie nur wenn man entweder im CMDLet selbst explizit den Common-Parameter -ErrorAction auf Stop setzt oder auf Skriptebene generell bei allen Fehlern eine Exception geworfen werden soll, mittels Setzen der globalen Variable
$ErrorActionPreference = 'Stop'  

Gruß gastric
prinzjulius
prinzjulius 17.12.2024 um 11:50:42 Uhr
Goto Top
$ErrorActionPreference = 'Stop'  

Vielen Dank für den Hinweis. Dessen war ich mir nicht bewusst.

VG
Julius
Judgelg
Judgelg 17.12.2024 um 15:01:07 Uhr
Goto Top
Zitat von @prinzjulius:

$ErrorActionPreference = 'Stop'  

Vielen Dank für den Hinweis. Dessen war ich mir nicht bewusst.

VG
Julius

wo füge ich den Part noch hinzuß

Mfg
gastric
gastric 17.12.2024 aktualisiert um 15:21:44 Uhr
Goto Top
Zitat von @Judgelg:

Zitat von @prinzjulius:

$ErrorActionPreference = 'Stop'  

Vielen Dank für den Hinweis. Dessen war ich mir nicht bewusst.

VG
Julius

wo füge ich den Part noch hinzuß

Mfg

Beim letzten Code von @prinzjulius z.B. in Zeile 31.
Da dies das Verhalten der folgenden Befehle in der ganzen Session steuert also irgendwo vor den entsprechenden Befehlen die in den TryCatches stehen.

Lesen hilft übrigens. 😋
$ErrorActionPreference
prinzjulius
prinzjulius 17.12.2024 um 15:54:56 Uhr
Goto Top
... ist oben aktualisiert face-wink
Judgelg
Judgelg 18.12.2024 um 06:55:52 Uhr
Goto Top
Zitat von @prinzjulius:

... ist oben aktualisiert face-wink

Ich danke dir. wie gesagt, ich werde das ganze demnächst Testen.

Mfg