Inhaltsverzeichnis
Inventario certificati
Complessità: Bassa
Durata: 1-4 ore (a seconda della dimensione)
Prerequisito: Accesso a tutti i sistemi
Rilevamento completo di tutti i certificati come base per la migrazione.
Perché l'inventario?
| Motivo | Descrizione |
| ——– | ————- |
| Scope | Quanti certificati devono essere migrati? |
| Algoritmi | Quali algoritmi sono in uso? |
| Scadenze | Quando possono essere migrati al rinnovo? |
| Dipendenze | Quali sistemi sono collegati? |
| Rischi | Dove sono i certificati critici? |
Fonti inventario
flowchart TB
subgraph LOCAL["💻 LOCALE"]
L1[Filesystem]
L2[Archivi certificati]
L3[File configurazione]
end
subgraph NETWORK["🌐 RETE"]
N1[Endpoint TLS]
N2[LDAP/AD]
N3[HSM]
end
subgraph MGMT["📊 MANAGEMENT"]
M1[Database CA]
M2[CMDB]
M3[Monitoraggio]
end
subgraph OUTPUT["📋 OUTPUT"]
O[Inventario-CSV]
end
L1 & L2 & L3 --> O
N1 & N2 & N3 --> O
M1 & M2 & M3 --> O
Linux: Scansione filesystem
#!/bin/bash # cert-inventory-linux.sh OUTPUT="inventory-linux-$(hostname)-$(date +%Y%m%d).csv" echo "Percorso,Subject,Issuer,Algoritmo,LunghezzaChiave,ValidoDa,ValidoFino,GiorniRimanenti,Serial,SAN" > "$OUTPUT" # Directory standard CERT_DIRS=( "/etc/ssl/certs" "/etc/pki/tls/certs" "/etc/nginx/ssl" "/etc/apache2/ssl" "/opt/*/ssl" ) for dir in "${CERT_DIRS[@]}"; do for cert in $(find $dir -name "*.pem" -o -name "*.crt" -o -name "*.cer" 2>/dev/null); do # Solo certificati (no chiavi/CSR) openssl x509 -in "$cert" -noout 2>/dev/null || continue subject=$(openssl x509 -in "$cert" -subject -noout | sed 's/subject=//' | tr ',' ';') issuer=$(openssl x509 -in "$cert" -issuer -noout | sed 's/issuer=//' | tr ',' ';') algo=$(openssl x509 -in "$cert" -text -noout | grep "Signature Algorithm" | head -1 | awk '{print $3}') keysize=$(openssl x509 -in "$cert" -text -noout | grep "Public-Key:" | grep -oP '\d+') not_before=$(openssl x509 -in "$cert" -startdate -noout | cut -d= -f2) not_after=$(openssl x509 -in "$cert" -enddate -noout | cut -d= -f2) days_left=$(( ($(date -d "$not_after" +%s) - $(date +%s)) / 86400 )) serial=$(openssl x509 -in "$cert" -serial -noout | cut -d= -f2) sans=$(openssl x509 -in "$cert" -text -noout | grep -A1 "Subject Alternative Name" | tail -1 | tr ',' ';') echo "\"$cert\",\"$subject\",\"$issuer\",\"$algo\",\"$keysize\",\"$not_before\",\"$not_after\",\"$days_left\",\"$serial\",\"$sans\"" >> "$OUTPUT" done done echo "Inventario completato: $OUTPUT" echo "Certificati trovati: $(tail -n +2 "$OUTPUT" | wc -l)"
Windows: Scansione archivio certificati
# Cert-Inventory-Windows.ps1 param( [string]$OutputPath = "inventory-windows-$env:COMPUTERNAME-$(Get-Date -Format 'yyyyMMdd').csv" ) $results = @() # Scansione tutti gli archivi certificati $stores = @( @{ Location = "LocalMachine"; Name = "My" }, @{ Location = "LocalMachine"; Name = "Root" }, @{ Location = "LocalMachine"; Name = "CA" }, @{ Location = "LocalMachine"; Name = "WebHosting" }, @{ Location = "CurrentUser"; Name = "My" } ) foreach ($store in $stores) { $storePath = "Cert:\$($store.Location)\$($store.Name)" Get-ChildItem $storePath -ErrorAction SilentlyContinue | ForEach-Object { $cert = $_ $daysLeft = ($cert.NotAfter - (Get-Date)).Days # Estrazione SAN $sanExt = $cert.Extensions | Where-Object { $_.Oid.Value -eq "2.5.29.17" } $sans = if ($sanExt) { $sanExt.Format($false) } else { "" } $results += [PSCustomObject]@{ Store = "$($store.Location)\$($store.Name)" Subject = $cert.Subject Issuer = $cert.Issuer Algorithm = $cert.SignatureAlgorithm.FriendlyName KeySize = $cert.PublicKey.Key.KeySize NotBefore = $cert.NotBefore NotAfter = $cert.NotAfter DaysLeft = $daysLeft Serial = $cert.SerialNumber Thumbprint = $cert.Thumbprint SANs = $sans HasPrivateKey = $cert.HasPrivateKey } } } $results | Export-Csv -Path $OutputPath -NoTypeInformation -Encoding UTF8 Write-Host "Inventario completato: $OutputPath" Write-Host "Certificati trovati: $($results.Count)"
Rete: Scansione endpoint TLS
#!/bin/bash # cert-inventory-network.sh OUTPUT="inventory-network-$(date +%Y%m%d).csv" ENDPOINTS_FILE="endpoints.txt" echo "Endpoint,Subject,Issuer,Algoritmo,LunghezzaChiave,ValidoFino,Giorni,Serial" > "$OUTPUT" # Endpoint da file o CMDB/DNS # Formato: hostname:porta cat "$ENDPOINTS_FILE" | while read endpoint; do host=${endpoint%:*} port=${endpoint#*:} [ -z "$port" ] && port=443 echo "Scansione $host:$port..." cert_info=$(echo | openssl s_client -connect "$host:$port" -servername "$host" 2>/dev/null | openssl x509 -text -noout 2>/dev/null) if [ -n "$cert_info" ]; then subject=$(echo "$cert_info" | grep "Subject:" | head -1 | sed 's/.*Subject: //' | tr ',' ';') issuer=$(echo "$cert_info" | grep "Issuer:" | head -1 | sed 's/.*Issuer: //' | tr ',' ';') algo=$(echo "$cert_info" | grep "Signature Algorithm" | head -1 | awk '{print $3}') keysize=$(echo "$cert_info" | grep "Public-Key:" | grep -oP '\d+') not_after=$(echo | openssl s_client -connect "$host:$port" -servername "$host" 2>/dev/null | openssl x509 -enddate -noout | cut -d= -f2) days_left=$(( ($(date -d "$not_after" +%s) - $(date +%s)) / 86400 )) serial=$(echo | openssl s_client -connect "$host:$port" -servername "$host" 2>/dev/null | openssl x509 -serial -noout | cut -d= -f2) echo "\"$endpoint\",\"$subject\",\"$issuer\",\"$algo\",\"$keysize\",\"$not_after\",\"$days_left\",\"$serial\"" >> "$OUTPUT" else echo "\"$endpoint\",\"CONNECTION FAILED\",\"\",\"\",\"\",\"\",\"\",\"\"" >> "$OUTPUT" fi done echo "Inventario rete completato: $OUTPUT"
Inventario database CA
#!/bin/bash # cert-inventory-ca.sh - Da OpenSSL CA-Index CA_INDEX="/etc/pki/CA/index.txt" OUTPUT="inventory-ca-$(date +%Y%m%d).csv" echo "Stato,Serial,Scadenza,Subject,File" > "$OUTPUT" while IFS=$'\t' read -r status expiry revoke serial unknown subject; do # Stato: V=Valido, R=Revocato, E=Scaduto status_text="" case "$status" in V) status_text="Valido" ;; R) status_text="Revocato" ;; E) status_text="Scaduto" ;; esac # Conversione data scadenza (formato YYMMDDHHMMSSZ) expiry_formatted=$(date -d "20${expiry:0:2}-${expiry:2:2}-${expiry:4:2}" +%Y-%m-%d 2>/dev/null) # File certificato cert_file="/etc/pki/CA/newcerts/${serial}.pem" echo "\"$status_text\",\"$serial\",\"$expiry_formatted\",\"$subject\",\"$cert_file\"" >> "$OUTPUT" done < "$CA_INDEX" echo "Inventario CA completato: $OUTPUT" echo "Certificati:" echo " Validi: $(grep -c "^\"Valido\"" "$OUTPUT")" echo " Revocati: $(grep -c "^\"Revocato\"" "$OUTPUT")" echo " Scaduti: $(grep -c "^\"Scaduto\"" "$OUTPUT")"
Analisi e reporting
#!/usr/bin/env python3 # analyze-inventory.py import pandas as pd # Caricamento tutti i file inventario df = pd.concat([ pd.read_csv('inventory-linux*.csv'), pd.read_csv('inventory-windows*.csv'), pd.read_csv('inventory-network*.csv') ]) # Analisi print("=== Riepilogo inventario ===\n") print(f"Totale certificati: {len(df)}") print("\n--- Per algoritmo ---") print(df['Algoritmo'].value_counts()) print("\n--- Per lunghezza chiave ---") print(df['LunghezzaChiave'].value_counts()) print("\n--- Analisi scadenze ---") df['GiorniRimanenti'] = pd.to_numeric(df['GiorniRimanenti'], errors='coerce') print(f"Scaduti: {len(df[df['GiorniRimanenti'] < 0])}") print(f"< 30 giorni: {len(df[(df['GiorniRimanenti'] >= 0) & (df['GiorniRimanenti'] < 30)])}") print(f"30-90 giorni: {len(df[(df['GiorniRimanenti'] >= 30) & (df['GiorniRimanenti'] < 90)])}") print(f"90-365 giorni: {len(df[(df['GiorniRimanenti'] >= 90) & (df['GiorniRimanenti'] < 365)])}") print(f"> 1 anno: {len(df[df['GiorniRimanenti'] >= 365])}") print("\n--- Potenziale migrazione ---") rsa = len(df[df['Algoritmo'].str.contains('rsa', case=False, na=False)]) ecdsa = len(df[df['Algoritmo'].str.contains('ecdsa|ec', case=False, na=False)]) hybrid = len(df[df['Algoritmo'].str.contains('ml-dsa|hybrid', case=False, na=False)]) print(f"RSA (da migrare): {rsa}") print(f"ECDSA (da migrare): {ecdsa}") print(f"Hybrid (già): {hybrid}") # Esportazione per pianificazione migrazione df.to_excel('inventory-complete.xlsx', index=False) print("\nInventario completo esportato: inventory-complete.xlsx")
Template dashboard
| Categoria | Quantità | Migrazione |
| ———– | ———- | ———— |
| Algoritmo | ||
| RSA-2048 | 150 | → Hybrid |
| RSA-4096 | 30 | → Hybrid |
| ECDSA P-256 | 80 | → Hybrid |
| ECDSA P-384 | 20 | → Hybrid |
| ML-DSA/Hybrid | 5 | ✓ Completato |
| Scadenza | ||
| < 30 giorni | 12 | Migrare subito |
| 30-90 giorni | 25 | Fase 1 |
| 90-365 giorni | 100 | Fase 2 |
| > 1 anno | 148 | Fase 3 |
| Criticità | ||
| Esterni | 40 | Priorità 1 |
| Interni-critici | 80 | Priorità 2 |
| Development | 165 | Priorità 3 |
Checklist
| # | Punto di verifica | ✓ |
| — | ——————- | — |
| 1 | Tutti i server Linux scansionati | ☐ |
| 2 | Tutti i server Windows scansionati | ☐ |
| 3 | Tutti gli endpoint TLS scansionati | ☐ |
| 4 | Database CA esportato | ☐ |
| 5 | Dati consolidati | ☐ |
| 6 | Analisi eseguita | ☐ |
| 7 | Piano migrazione creato | ☐ |
Documentazione correlata
- Classic → Hybrid – Avviare migrazione
- Monitoraggio scadenze – Sorveglianza continua
- Business – Pianificazione strategica
« ← Strategia di rollback | → Scenari per operatori »
Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional
Zuletzt geändert: il 30/01/2026 alle 01:38