PowerShell for Linux Admins
Transition Bash → PowerShell : penser en objets, pas en texte.
Le Choc Culturel : Objets vs Texte
La Différence Fondamentale
BASH : Le flux de texte
flowchart LR
A[Commande] -->|Stream de<br/>TEXTE| B[Commande] -->|Stream de<br/>TEXTE| C[Commande]
subgraph Exemple
D["ls -l"] -->|Texte brut| E["grep 'Dec'"] -->|Parse texte| F["awk '{print $9}'"]
end
style A fill:#9C27B0,stroke:#333,color:#fff
style B fill:#9C27B0,stroke:#333,color:#fff
style C fill:#9C27B0,stroke:#333,color:#fff
style D fill:#9C27B0,stroke:#495057,color:#fff
style E fill:#9C27B0,stroke:#495057,color:#fff
style F fill:#9C27B0,stroke:#495057,color:#fff
POWERSHELL : Le flux d'objets
flowchart LR
A[Cmdlet] -->|Stream<br/>d'OBJETS .NET| B[Cmdlet] -->|Stream<br/>d'OBJETS .NET| C[Cmdlet]
subgraph Exemple
D[Get-ChildItem] -->|Objets FileInfo| E[Where-Object] -->|Propriétés typées| F[Select-Object]
end
style A fill:#2196F3,stroke:#005a9e,color:#fff
style B fill:#2196F3,stroke:#005a9e,color:#fff
style C fill:#2196F3,stroke:#005a9e,color:#fff
style D fill:#2196F3,stroke:#1a5f9e,color:#fff
style E fill:#2196F3,stroke:#1a5f9e,color:#fff
style F fill:#2196F3,stroke:#1a5f9e,color:#fff
Exemple Frappant
Objectif : Lister les fichiers modifiés en décembre
Pourquoi C'est Puissant
# L'objet FileInfo a des propriétés typées
$file = Get-Item "document.txt"
$file.Name # String: "document.txt"
$file.Length # Int64: 1024
$file.LastWriteTime # DateTime: 2024-01-15 10:30:00
$file.Extension # String: ".txt"
$file.Directory # DirectoryInfo: C:\Users\...
# On peut appeler des méthodes
$file.CopyTo("backup.txt")
$file.Delete()
La Grammaire (Verb-Noun)
Structure Standardisée
Toutes les cmdlets suivent le pattern Verbe-Nom :
| Verbe | Action | Exemples |
|---|---|---|
Get- |
Récupérer | Get-Process, Get-Service, Get-Content |
Set- |
Modifier | Set-Location, Set-Content, Set-Variable |
New- |
Créer | New-Item, New-Object, New-Service |
Remove- |
Supprimer | Remove-Item, Remove-Service |
Start- |
Démarrer | Start-Process, Start-Service |
Stop- |
Arrêter | Stop-Process, Stop-Service |
Restart- |
Redémarrer | Restart-Service, Restart-Computer |
Test- |
Tester | Test-Path, Test-NetConnection |
Invoke- |
Exécuter | Invoke-Command, Invoke-WebRequest |
# Lister tous les verbes approuvés
Get-Verb
# Trouver les cmdlets pour les services
Get-Command -Noun Service
# Get-Service, Set-Service, Start-Service, Stop-Service, Restart-Service...
# Trouver les cmdlets "Get-*"
Get-Command -Verb Get
Les Alias : Le Piège !
Attention : Ces commandes ne sont PAS les binaires Linux
PowerShell définit des alias qui ressemblent aux commandes Unix mais ont un comportement différent.
| Alias PS | Cmdlet réelle | Binaire Linux |
|---|---|---|
ls |
Get-ChildItem |
/bin/ls |
dir |
Get-ChildItem |
- |
cat |
Get-Content |
/bin/cat |
cp |
Copy-Item |
/bin/cp |
mv |
Move-Item |
/bin/mv |
rm |
Remove-Item |
/bin/rm |
pwd |
Get-Location |
/bin/pwd |
cd |
Set-Location |
builtin |
curl |
Invoke-WebRequest |
/usr/bin/curl |
wget |
Invoke-WebRequest |
/usr/bin/wget |
# Voir la vraie commande derrière un alias
Get-Alias ls
# Alias: ls -> Get-ChildItem
Get-Alias curl
# Alias: curl -> Invoke-WebRequest
# Piège : les options Linux ne marchent pas !
ls -la # ERREUR
ls -Force # OK (option PowerShell)
Get-ChildItem -Force # Explicite et clair
Bonne pratique
En scripts, utilisez les noms complets des cmdlets, pas les alias.
- Scripts :
Get-ChildItem,Get-Content - Interactif :
ls,cat,gci(OK pour taper vite)
Le Pipeline & Filtrage
Get-Member : Le "man" Interactif
Get-Member (alias gm) révèle la structure d'un objet : ses propriétés et méthodes.
# Voir les membres d'un objet Process
Get-Process | Get-Member
# Output:
# TypeName: System.Diagnostics.Process
#
# Name MemberType Definition
# ---- ---------- ----------
# Kill Method void Kill()
# Start Method bool Start()
# CPU Property double CPU {get;}
# Id Property int Id {get;}
# ProcessName Property string ProcessName {get;}
# WorkingSet64 Property long WorkingSet64 {get;}
# Voir les propriétés uniquement
Get-Process | gm -MemberType Property
# Voir les méthodes
Get-Process | gm -MemberType Method
Select-Object : Choisir des Colonnes
Équivalent de awk '{print $1, $3}' mais typé.
# Sélectionner des propriétés
Get-Process | Select-Object Name, Id, CPU
# Alias court
Get-Process | select Name, Id, CPU
# Premiers/derniers éléments
Get-Process | Select-Object -First 5
Get-Process | Select-Object -Last 3
# Propriétés calculées
Get-Process | Select-Object Name, @{N='RAM_MB';E={$_.WorkingSet64/1MB}}
Where-Object : Filtrer
Équivalent de grep mais sur les propriétés des objets.
# Filtrer par condition
Get-Process | Where-Object { $_.CPU -gt 100 }
# Alias courts
Get-Process | ? { $_.CPU -gt 100 }
Get-Process | where CPU -gt 100 # Syntaxe simplifiée
# Conditions multiples
Get-Service | Where-Object { $_.Status -eq "Running" -and $_.Name -like "Win*" }
# Opérateurs de comparaison
# -eq : Égal
# -ne : Différent
# -gt : Plus grand
# -lt : Plus petit
# -ge : Plus grand ou égal
# -le : Plus petit ou égal
# -like : Pattern matching (* et ?)
# -match : Regex
Sort-Object : Trier
# Trier par propriété
Get-Process | Sort-Object CPU
# Tri descendant
Get-Process | Sort-Object CPU -Descending
# Tri multiple
Get-ChildItem | Sort-Object Extension, Name
# Alias
Get-Process | sort CPU -Descending
Enchaînement Complet
# Processus utilisant le plus de CPU, top 5
Get-Process |
Sort-Object CPU -Descending |
Select-Object -First 5 Name, Id, CPU
# Services Windows en cours, triés par nom
Get-Service |
Where-Object Status -eq "Running" |
Sort-Object DisplayName |
Select-Object DisplayName, Status
One-Liners de Survie
Fichiers et Dossiers
# Top 5 des plus gros fichiers
Get-ChildItem -Recurse | Sort-Object Length -Descending | Select-Object -First 5
# Alias court
gci -Recurse | sort Length -Desc | select -First 5 Name, @{N='Size_MB';E={$_.Length/1MB}}
# Trouver les fichiers > 100MB
gci -Recurse | ? { $_.Length -gt 100MB }
# Fichiers modifiés ces 7 derniers jours
gci -Recurse | ? { $_.LastWriteTime -gt (Get-Date).AddDays(-7) }
# Supprimer les fichiers .tmp
gci -Recurse -Filter "*.tmp" | Remove-Item -Force
Processus
# Tuer un processus par nom
Stop-Process -Name notepad -Force
# Tuer par PID
Stop-Process -Id 1234 -Force
# Processus consommant > 500MB de RAM
Get-Process | ? { $_.WorkingSet64 -gt 500MB } | select Name, @{N='RAM_MB';E={[int]($_.WorkingSet64/1MB)}}
# Lancer un programme
Start-Process notepad
Start-Process "C:\Program Files\App\app.exe" -ArgumentList "-config", "file.conf"
Réseau
# Test de port (équivalent nc/telnet)
Test-NetConnection -ComputerName google.com -Port 443
# Output:
# ComputerName : google.com
# RemoteAddress : 142.250.179.110
# RemotePort : 443
# TcpTestSucceeded : True
# Alias rapide
tnc google.com -Port 443
# Ping
Test-NetConnection google.com
# Résolution DNS
Resolve-DnsName google.com
# Connexions actives (comme netstat)
Get-NetTCPConnection | ? State -eq "Established"
# Ports en écoute
Get-NetTCPConnection -State Listen | select LocalPort, OwningProcess
Services Windows
# État d'un service
Get-Service -Name wuauserv
# Démarrer/Arrêter
Start-Service -Name wuauserv
Stop-Service -Name wuauserv
Restart-Service -Name wuauserv
# Services en échec
Get-Service | ? Status -eq "Stopped"
Remote / Web
# Télécharger un fichier (le "wget" de PowerShell)
Invoke-WebRequest -Uri "https://example.com/file.zip" -OutFile "file.zip"
# API REST
$response = Invoke-RestMethod -Uri "https://api.github.com/users/octocat"
$response.name
# Exécution distante (WinRM)
Invoke-Command -ComputerName Server01 -ScriptBlock { Get-Process }
Référence Rapide
# === DÉCOUVERTE ===
Get-Command *service* # Chercher une cmdlet
Get-Help Get-Process -Examples # Aide avec exemples
Get-Process | Get-Member # Structure d'un objet
# === PIPELINE ===
| Select-Object Name, Id # Choisir colonnes
| Where-Object { $_.CPU -gt 10 } # Filtrer
| Sort-Object CPU -Descending # Trier
| Select-Object -First 5 # Top N
# === FICHIERS ===
Get-ChildItem -Recurse # ls -R
Get-Content file.txt # cat
Set-Content file.txt "text" # echo > file
Add-Content file.txt "more" # echo >> file
# === PROCESS ===
Get-Process # ps
Stop-Process -Name notepad # kill
# === RÉSEAU ===
Test-NetConnection host -Port 443 # nc -zv
Get-NetTCPConnection # netstat
# === ALIAS COURANTS ===
gci = Get-ChildItem
gc = Get-Content
? = Where-Object
% = ForEach-Object
select = Select-Object
sort = Sort-Object
gm = Get-Member
Scripting PKI & AD
Contexte : Générer un CSR Manuellement
Dans certains environnements (SecNumCloud, réseaux isolés), l'auto-enrollment de certificats (via GPO et Active Directory Certificate Services) n'est pas toujours disponible ou souhaitable.
Cas d'usage typiques :
| Scénario | Raison |
|---|---|
| LDAPS sur 389 Directory Server | Serveur Linux n'ayant pas accès à ADCS |
| Certificat pour serveur DMZ | Isolation réseau stricte (pas de connectivité AD directe) |
| Certificate Authority externe | CSR doit être soumis à une CA publique (Sectigo, DigiCert) |
| Certificat wildcard | Auto-enrollment ne supporte pas les wildcards (*.mycorp.com) |
| Validation manuelle | Politique de sécurité exigeant une revue humaine de chaque CSR |
Solution : Générer un CSR (Certificate Signing Request) manuellement avec certreq et un fichier .inf.
Pépite pour admins Windows
certreq est l'outil natif Windows pour gérer les certificats sans installer OpenSSL.
Il utilise le Cryptographic API (CAPI) de Windows et s'intègre parfaitement avec IIS, LDAP, et autres services.
Script : Generate_LDAPS_CSR.ps1
Objectif : Générer un CSR pour activer LDAPS (LDAP over SSL) sur un contrôleur de domaine.
```powershell <# .SYNOPSIS Génère un CSR (Certificate Signing Request) pour LDAPS avec certreq.
.DESCRIPTION Script pour créer un fichier de requête INF et générer un CSR sans utiliser l'auto-enrollment Active Directory.
.PARAMETER ServerFQDN FQDN du serveur LDAP (ex: srv-dc-01.mycorp.internal)
.PARAMETER OutputPath Répertoire de sortie pour les fichiers .inf et .csr
.EXAMPLE .\Generate_LDAPS_CSR.ps1 -ServerFQDN "srv-dc-01.mycorp.internal" -OutputPath "C:\Temp"
.NOTES Auteur : SysOps Team MyCorp Prérequis : Exécuter en tant qu'Administrateur local Le certificat résultant sera stocké dans LocalMachine\My
>
[CmdletBinding()] param( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$ServerFQDN,
[Parameter(Mandatory = $false)]
[string]$OutputPath = "C:\Temp\PKI"
)
Créer le répertoire de sortie si inexistant
if (-not (Test-Path $OutputPath)) { New-Item -ItemType Directory -Path $OutputPath -Force | Out-Null Write-Host "[+] Répertoire créé : $OutputPath" -ForegroundColor Green }
Extraire le hostname et domaine
$Hostname = $ServerFQDN.Split('.')[0] $Domain = $ServerFQDN.Substring($ServerFQDN.IndexOf('.') + 1)
Chemins des fichiers
$InfFile = Join-Path $OutputPath "$Hostname-LDAPS.inf" $CsrFile = Join-Path $OutputPath "$Hostname-LDAPS.csr"
Write-Host "[*] Génération du fichier INF : $InfFile" -ForegroundColor Cyan
Contenu du fichier .inf
$InfContent = @"
[Version]
Signature="$Windows NT$"
[NewRequest] ; === Informations du Sujet === Subject = "CN=$ServerFQDN,O=MyCorp,L=Paris,C=FR"
; === Paramètres de la Clé Privée === KeySpec = 1 KeyLength = 4096 Exportable = FALSE MachineKeySet = TRUE SMIME = FALSE PrivateKeyArchive = FALSE UserProtected = FALSE UseExistingKeySet = FALSE ProviderName = "Microsoft RSA SChannel Cryptographic Provider" ProviderType = 12 RequestType = PKCS10 KeyUsage = 0xa0
; KeyUsage = 0xa0 signifie : ; CERT_DIGITAL_SIGNATURE_KEY_USAGE = 0x80 ; CERT_KEY_ENCIPHERMENT_KEY_USAGE = 0x20
; === Algorithme de Hachage === HashAlgorithm = SHA256
[EnhancedKeyUsageExtension] OID=1.3.6.1.5.5.7.3.1 ; Server Authentication OID=1.3.6.1.5.5.7.3.2 ; Client Authentication
[Extensions] ; === Subject Alternative Name (SAN) === 2.5.29.17 = "{text}" continue = "dns=$ServerFQDN&" continue = "dns=$Hostname&" continue = "dns=crl.mycorp.com&"
; Ajouter l'adresse IP si nécessaire (décommenter et adapter) ; continue = "ipaddress=10.0.1.10&"
[RequestAttributes] CertificateTemplate = WebServer ; Alternative pour LDAPS : CertificateTemplate = DirectoryEmailReplication "@
# Écrire le fichier .inf
Set-Content -Path $InfFile -Value $InfContent -Encoding ASCII
Write-Host "[+] Fichier INF créé : $InfFile" -ForegroundColor Green
# Générer le CSR avec certreq
Write-Host "[*] Génération du CSR avec certreq..." -ForegroundColor Cyan
$certreqOutput = certreq -new $InfFile $CsrFile 2>&1
if ($LASTEXITCODE -eq 0) {
Write-Host "[+] CSR généré avec succès : $CsrFile" -ForegroundColor Green
# Afficher le contenu du CSR
Write-Host "`n[*] Contenu du CSR (à soumettre à la CA) :" -ForegroundColor Cyan
Get-Content $CsrFile | Write-Host -ForegroundColor Yellow
# Vérifier le CSR
Write-Host "`n[*] Vérification du CSR avec certutil..." -ForegroundColor Cyan
certutil -dump $CsrFile
Write-Host "`n[✓] Prochaines étapes :" -ForegroundColor Green
Write-Host " 1. Soumettre le CSR ($CsrFile) à votre Certificate Authority (CA)"
Write-Host " 2. Télécharger le certificat signé (format .cer ou .crt)"
Write-Host " 3. Installer le certificat avec : certreq -accept <certificat.cer>"
Write-Host " 4. Vérifier l'installation : Get-ChildItem Cert:\LocalMachine\My | Where-Object Subject -like '*$ServerFQDN*'"
} else {
Write-Error "❌ Échec de la génération du CSR"
Write-Host "Sortie de certreq :" -ForegroundColor Red
$certreqOutput | ForEach-Object { Write-Host $_ -ForegroundColor Red }
}
```
[Version]
Signature="$Windows NT$"
# Signature obligatoire pour les fichiers INF Windows
[NewRequest]
# === Informations du Sujet (Distinguished Name) ===
Subject = "CN=srv-dc-01.mycorp.internal,O=MyCorp,L=Paris,C=FR"
# CN = Common Name (FQDN du serveur)
# O = Organization
# L = Locality (ville)
# C = Country (code ISO 2 lettres)
# === Paramètres Cryptographiques ===
KeySpec = 1
# 1 = AT_KEYEXCHANGE (pour SSL/TLS)
# 2 = AT_SIGNATURE (pour signatures numériques)
KeyLength = 4096
# Longueur de la clé RSA (minimum 2048, recommandé 4096 pour ANSSI)
Exportable = FALSE
# TRUE = La clé privée peut être exportée (PFX)
# FALSE = La clé reste dans le TPM/HSM (plus sécurisé)
MachineKeySet = TRUE
# TRUE = Clé stockée au niveau machine (LocalMachine\My)
# FALSE = Clé stockée pour l'utilisateur courant (CurrentUser\My)
ProviderName = "Microsoft RSA SChannel Cryptographic Provider"
ProviderType = 12
# Provider pour SSL/TLS (SChannel)
# Autres options : "Microsoft Enhanced Cryptographic Provider v1.0"
RequestType = PKCS10
# Format standard pour les CSR
KeyUsage = 0xa0
# 0xa0 = 0x80 (Digital Signature) + 0x20 (Key Encipherment)
# Requis pour SSL/TLS server authentication
HashAlgorithm = SHA256
# Minimum SHA256 (ANSSI), éviter SHA1 (déprécié)
# === Extensions ===
[EnhancedKeyUsageExtension]
OID=1.3.6.1.5.5.7.3.1 ; Server Authentication (TLS/SSL Server)
OID=1.3.6.1.5.5.7.3.2 ; Client Authentication (TLS/SSL Client)
[Extensions]
# Subject Alternative Name (SAN) - CRITIQUE pour SSL/TLS moderne
2.5.29.17 = "{text}"
_continue_ = "dns=srv-dc-01.mycorp.internal&"
_continue_ = "dns=srv-dc-01&"
_continue_ = "dns=crl.mycorp.com&"
# Le SAN peut inclure :
# - dns=hostname.domain.com (noms DNS)
# - ipaddress=10.0.1.10 (adresses IP)
# - upn=user@domain.com (User Principal Name)
[RequestAttributes]
CertificateTemplate = WebServer
# Template de certificat (si utilisation d'une CA Microsoft interne)
# Options courantes :
# - WebServer : Pour IIS, LDAPS, services HTTPS
# - DirectoryEmailReplication : Spécifique pour LDAPS sur DC
# - Computer : Certificat machine générique
Utilisation Pratique
1. Exécuter le script
# Générer un CSR pour srv-dc-01.mycorp.internal
.\Generate_LDAPS_CSR.ps1 -ServerFQDN "srv-dc-01.mycorp.internal" -OutputPath "C:\Temp\PKI"
# Sortie :
# [+] Répertoire créé : C:\Temp\PKI
# [*] Génération du fichier INF : C:\Temp\PKI\srv-dc-01-LDAPS.inf
# [+] Fichier INF créé : C:\Temp\PKI\srv-dc-01-LDAPS.inf
# [*] Génération du CSR avec certreq...
# [+] CSR généré avec succès : C:\Temp\PKI\srv-dc-01-LDAPS.csr
2. Soumettre le CSR à la CA
# Méthode 1 : Interface Web
# Aller sur https://srv-ca-01.mycorp.internal/certsrv
# -> Request a certificate
# -> Advanced certificate request
# -> Coller le contenu de srv-dc-01-LDAPS.csr
# -> Sélectionner template "Web Server"
# -> Submit
# Méthode 2 : Ligne de commande (sur le serveur CA)
certreq -submit -config "srv-ca-01.mycorp.internal\MyCorp-CA" C:\Temp\PKI\srv-dc-01-LDAPS.csr
# 1. Copier le CSR
Get-Content C:\Temp\PKI\srv-dc-01-LDAPS.csr | Set-Clipboard
# 2. Soumettre via l'interface web de la CA publique
# Sectigo : https://secure.sectigo.com/products/ssl
# DigiCert : https://www.digicert.com/account/
# Let's Encrypt : Utiliser win-acme ou certbot-win
# 3. Télécharger le certificat signé (format .cer ou .crt)
3. Installer le certificat signé
# Une fois le certificat reçu de la CA (ex: srv-dc-01-LDAPS.cer)
certreq -accept C:\Temp\PKI\srv-dc-01-LDAPS.cer
# Vérifier l'installation
Get-ChildItem Cert:\LocalMachine\My | Where-Object { $_.Subject -like "*srv-dc-01*" }
# Sortie attendue :
# Thumbprint Subject
# ---------- -------
# A1B2C3D4E5F6... CN=srv-dc-01.mycorp.internal, O=MyCorp, L=Paris, C=FR
# Vérifier la chaîne de certification complète
$cert = Get-ChildItem Cert:\LocalMachine\My | Where-Object Subject -like "*srv-dc-01*"
$cert | Select-Object Thumbprint, Subject, NotBefore, NotAfter, Issuer
4. Configurer LDAPS avec le certificat
# Le certificat LDAPS doit répondre à ces critères :
# - Subject CN = FQDN du DC
# - Enhanced Key Usage : Server Authentication (1.3.6.1.5.5.7.3.1)
# - Stocké dans LocalMachine\My
# - Chaîne de certification complète installée (Root + Intermediate CA)
# Vérifier LDAPS
Test-NetConnection -ComputerName srv-dc-01.mycorp.internal -Port 636
# Si OK, tester avec ldp.exe (GUI)
ldp.exe
# Connection > Connect > srv-dc-01.mycorp.internal : 636 (cocher SSL)
# Ou avec PowerShell
$LDAPConnection = New-Object System.DirectoryServices.Protocols.LdapConnection("srv-dc-01.mycorp.internal:636")
$LDAPConnection.SessionOptions.SecureSocketLayer = $true
$LDAPConnection.Bind()
# Si succès : LDAPS fonctionne !
Cas Avancés : CSR pour Wildcard et Multi-SAN
CSR Wildcard (*.mycorp.com)
# Modifier la section Subject du fichier .inf
Subject = "CN=*.mycorp.com,O=MyCorp,L=Paris,C=FR"
# Dans [Extensions], ajouter le wildcard au SAN
[Extensions]
2.5.29.17 = "{text}"
_continue_ = "dns=*.mycorp.com&"
_continue_ = "dns=mycorp.com&"
Limitation Auto-Enrollment
Les certificats wildcard ne peuvent PAS être générés via auto-enrollment GPO. Il faut obligatoirement passer par un CSR manuel ou une API de CA.
CSR Multi-SAN (Load Balancer, Proxy)
# Exemple : certificat pour HAProxy avec plusieurs backends
[Extensions]
2.5.29.17 = "{text}"
_continue_ = "dns=lb.mycorp.com&"
_continue_ = "dns=web01.mycorp.com&"
_continue_ = "dns=web02.mycorp.com&"
_continue_ = "dns=api.mycorp.com&"
_continue_ = "ipaddress=10.0.1.100&"
_continue_ = "ipaddress=10.0.1.101&"
Dépannage
Erreur : "The request contains no certificate template information"
# La CA nécessite un template, modifier [RequestAttributes]
[RequestAttributes]
CertificateTemplate = WebServer
# Ou retirer complètement si CA publique externe
Erreur : "Keyset does not exist" lors de certreq -accept
# Le CSR n'a pas été généré sur cette machine ou a été supprimé
# Solution : Regénérer le CSR sur la machine cible (srv-dc-01)
# Vérifier les requests en attente
certutil -store -v request
# Supprimer une ancienne request orpheline
certutil -delstore request <RequestId>
Le certificat n'apparaît pas dans LocalMachine\My
# Vérifier que le CSR a bien été généré sur cette machine
certutil -store request
# Forcer le refresh du magasin de certificats
certutil -pulse
# Vérifier manuellement
mmc
# File > Add/Remove Snap-in > Certificates > Computer Account > Local Computer
# Navigate to Personal > Certificates
LDAPS ne fonctionne pas après installation du certificat
# 1. Vérifier que le certificat a les bons critères
$cert = Get-ChildItem Cert:\LocalMachine\My | Where-Object Subject -like "*srv-dc-01*"
$cert.EnhancedKeyUsageList
# Doit contenir : Server Authentication (1.3.6.1.5.5.7.3.1)
# 2. Vérifier la chaîne de certification
certutil -verify $cert.Thumbprint
# 3. Redémarrer le service Active Directory Domain Services
Restart-Service NTDS -Force
# 4. Vérifier les logs Event Viewer
# Applications and Services Logs > Directory Service
# Event ID 1220 : LDAPS bind succeeded
# Event ID 1221 : LDAPS bind failed (voir détails de l'erreur)
Checklist Déploiement LDAPS
- [ ] Générer le CSR avec
Generate_LDAPS_CSR.ps1 - [ ] Vérifier le CSR avec
certutil -dump <csr-file> - [ ] Soumettre le CSR à la CA (interne ou publique)
- [ ] Télécharger le certificat signé (.cer)
- [ ] Installer le certificat avec
certreq -accept <cer-file> - [ ] Vérifier la présence dans
Cert:\LocalMachine\My - [ ] Vérifier la chaîne de certification complète (Root + Intermediate)
- [ ] Tester le port 636 avec
Test-NetConnection -Port 636 - [ ] Tester LDAPS avec
ldp.exeou PowerShell - [ ] Configurer les clients LDAP pour utiliser LDAPS (port 636)
- [ ] Documenter la date d'expiration et créer une alerte de renouvellement
Production Ready
Avec cette méthode, vous pouvez générer des CSR pour n'importe quel service Windows :
IIS, LDAPS, RDP, SQL Server, Exchange, etc.
Le fichier .inf est entièrement personnalisable selon vos besoins PKI.