Stai richiedendo un certificato TLS a una CA Microsoft e con certreq -submit -attrib ottieni solo il primo Subject Alternative Name? In questa guida trovi cause, soluzioni e procedure operative affidabili per avere tutti i SAN desiderati, con esempi pronti all’uso in INF e PowerShell.
Contesto: perché i SAN “spariscono” con certreq -attrib
Quando si inviano attributi a una Certification Authority (CA) Microsoft tramite certreq -submit -attrib, i parametri sono interpretati come coppie chiave:valore separate da ritorni a capo. Se si tenta di comprimere tutto in una singola stringa (per esempio SAN:DNS=a&DNS=b&DNS=c subito dopo CertificateTemplate:), alcune CA considerano solo la prima voce oppure ignorano completamente i SAN. Il comportamento varia tra versioni e configurazioni, ma l’effetto percepito è identico: nel certificato finito compare soltanto il primo SAN.
Le cause più frequenti sono tre:
- Template non allineato: il modello non è configurato su “Supply in the request”, quindi la CA scarta qualunque estensione SAN portata nella CSR/attributi.
- Formattazione dell’attributo:
certreqsi aspetta attributi multipli separati da veri ritorni a capo; usare l’escape testuale\nin CMD non produce un newline reale. - Escaping dei caratteri speciali: il carattere
&(usato per concatenare piùDNS=) è un operatore sia in CMD che in PowerShell se non correttamente quotato/escapato.
Roadmap rapida: la soluzione più affidabile
La via maestra è generare la CSR partendo da un file INF che contenga tutte le SAN. È ripetibile, leggibile e funziona in modo consistente con le CA Microsoft moderne.
- Verifica e prepara il template: il template deve essere impostato su Supply in the request e pubblicato sulla CA.
- Crea un INF con
2.5.29.17(Subject Alternative Name) già popolato didns=. - Genera la CSR con
certreq -newe inviala concertreq -submit. - Accetta il certificato nel computer che possiede la chiave con
certreq -accept.
Se devi per forza usare -attrib, funziona bene aggiungere un vero newline tra CertificateTemplate: e SAN: (PowerShell è ideale, perché `n diventa newline reale). Maggiori dettagli più avanti.
Checklist del template CA (fondamentale)
Prima di toccare i comandi, conferma questi punti nella Console dei Template dei Certificati:
- Scheda “Subject Name”: seleziona Supply in the request. In caso contrario, la CA non copierà i SAN dalla richiesta.
- Permessi: l’entità che richiede (computer/utente/servizio) deve avere almeno Enroll (e se serve Autoenroll).
- Pubblicazione del template: la CA deve “conoscere” quel template (aggiunto alla CA) e non applicare restrizioni che rimuovono l’estensione SAN.
Soluzioni a confronto (con pro e contro)
| Passo / Soluzione | Dettagli operativi | Punti di attenzione |
|---|---|---|
| Controllo del template | Imposta il template su Supply in the request e pubblicalo sulla CA. | Senza questa opzione la CA ignora o sovrascrive i SAN presenti nella richiesta. |
| Attributi con “a capo” reale | Usa un newline reale tra gli attributi, per esempio in PowerShell: "CertificateTemplate:Appliance`nSAN:DNS=a&DNS=b&DNS=c". | \n in CMD resta letterale; in PowerShell `n genera il vero newline. Quota/escapa bene il carattere &. |
| CSR da file INF (consigliata) | Definisci l’OID 2.5.29.17 con tutte le SAN nel file INF, poi certreq -new e -submit. | È la strada più stabile: la CA copia i SAN già nella CSR, evitando edge case di -attrib. |
| Post‑processing per appliance | Se il dispositivo accetta solo PEM: esporta PFX, converti in PEM con OpenSSL e separa KEY / CERT / CHAIN. | Richiede passi extra ma garantisce compatibilità con dispositivi che non supportano PFX. |
Procedura passo‑passo con file INF (best practice)
INF per chiave RSA (server web tipico)
; san-rsa.inf
[Version]
Signature="$Windows NT$"
[NewRequest]
Subject = "CN=appliance.example.com"
KeySpec = 1
KeyLength = 2048
Exportable = TRUE ; metti FALSE in ambienti altamente protetti
MachineKeySet = TRUE ; TRUE per certificati macchina
ProviderName = "Microsoft RSA SChannel Cryptographic Provider"
ProviderType = 12
RequestType = PKCS10
SMIME = FALSE
HashAlgorithm = sha256
KeyUsage = 0xa0
[Extensions]
; 2.5.29.17 = Subject Alternative Name
2.5.29.17 = "{text}"
continue = "dns=appliance.example.com&dns=api.example.com&dns=internal.example.local"
; eventuale SAN IP:
; continue = "ipaddress=192.0.2.10"
[RequestAttributes]
CertificateTemplate = Appliance ; o il tuo template (es. WebServer)
INF per chiave ECDSA (P‑256)
; san-ecdsa.inf
[Version]
Signature="$Windows NT$"
[NewRequest]
Subject = "CN=appliance.example.com"
KeySpec = 1
Exportable = TRUE
MachineKeySet = TRUE
KeyAlgorithm = ECDSA_P256
ProviderName = "Microsoft Software Key Storage Provider"
RequestType = PKCS10
HashAlgorithm = sha256
[Extensions]
2.5.29.17 = "{text}"
continue = "dns=appliance.example.com&dns=api.example.com"
[RequestAttributes]
CertificateTemplate = Appliance
Generazione e invio
# Genera CSR e chiave privata
certreq -new .\san-rsa.inf .\san.req
Invia alla CA (specifica il nome esatto della tua CA)
certreq -submit -config "CAHOST\NOME-CA" .\san.req .\san.cer
Installa il certificato nel computer che possiede la chiave
certreq -accept .\san.cer
Note importanti:
- Macchina di destinazione: esegui
certreq -newnel sistema dove deve risiedere la chiave privata (o usaUseExistingKeySet=TRUEse devi rigenerare solo la CSR). - Exportable: imposta
Exportable=TRUEsolo se devi esportare la chiave in PFX per un’appliance. In ambienti ad alta sicurezza, valutaFALSEe l’uso di HSM/KSP dedicati. - CA interattiva: senza
-config,certreqapre una finestra per scegliere la CA pubblicata in AD. Indicando-configeviti l’interazione.
Metodo alternativo: -attrib con newline reale
Se devi usare -attrib, il trucco è separare gli attributi con un vero a‑capo. In PowerShell è immediato perché `n (backtick + n) viene espanso in newline.
Esempio PowerShell “tutto in uno”
$attrib = @"
CertificateTemplate:Appliance
SAN:DNS=appliance.example.com&DNS=api.example.com&DNS=internal.example.local
"@
certreq -submit -config "CAHOST\NOME-CA" -attrib $attrib .\san.req .\san.cer
In alternativa, con stringa singola:
certreq -submit -config "CAHOST\NOME-CA" `
-attrib "CertificateTemplate:Appliance`nSAN:DNS=appliance.example.com&DNS=api.example.com&DNS=internal.example.local" `
.\san.req .\san.cer
Attenzione all’escaping:
- In PowerShell l’operatore di chiamata è
&. Dentro stringhe quotate rimane letterale; se componi l’attributo per concatenazione non quotata, escapa con backtick`&o racchiudi sempre il valore completo tra doppi apici. - In CMD,
&è un operatore di concatenazione comandi: racchiudi sempre l’intero valore di-attribtra virgolette oppure preferisci PowerShell. - La sequenza
\nnon crea un newline in CMD: verrà passata come testo letterale.
Verifica: come controllare che i SAN ci siano davvero
Subito dopo l’emissione/accettazione:
REM Dump rapido con certutil
certutil -dump .\san.cer | findstr /I "Alternative DNS IP"
REM Oppure con OpenSSL
openssl x509 -in .\san.cer -noout -text | findstr /I "Subject Alternative Name"
Se vedi solo un SAN nel blocco Subject Alternative Name, riparti dalla verifica del template e del formato dell’attributo/INF.
Esportazione e conversione per appliance (PEM)
Molti dispositivi richiedono tre file separati in formato PEM: key, cert e chain. Procedura tipica:
Esporta in PFX (con chiave)
# Trova il certificato per thumbprint
$thumb = "INSERISCI-THUMBPRINT-SHA1"
$cert = Get-ChildItem Cert:\LocalMachine\My\$thumb
Esporta in PFX con password
$pwd = ConvertTo-SecureString 'S3greta!' -AsPlainText -Force
Export-PfxCertificate -Cert $cert -FilePath .\appliance.pfx -Password $pwd
Converti in PEM e separa i pezzi
# Estrai tutto in un unico PEM (senza cifrare la key: -nodes)
openssl pkcs12 -in appliance.pfx -out bundle.pem -nodes
Separa key e cert "foglia"
openssl pkey -in bundle.pem -out key.pem
openssl x509 -in bundle.pem -out cert.pem
Estrai la chain (CA intermedie + radice, se presente)
openssl crl2pkcs7 -nocrl -certfile bundle.pem -out chain.p7b
openssl pkcs7 -print_certs -in chain.p7b -out chain.pem
Carica key.pem, cert.pem e chain.pem sull’appliance nell’ordine richiesto. Se il dispositivo pretende un bundle singolo, concatena cert.pem + chain.pem in un file unico.
Automazione: generare INF e CSR da una lista di FQDN
Se crei spesso certificati con molti SAN, automatizza la generazione dell’INF e dei comandi:
$DnsNames = @(
"appliance.example.com",
"api.example.com",
"internal.example.local"
)
$sanText = ($DnsNames | ForEach-Object { "dns=$_" }) -join "&"
$inf = @"
[Version]
Signature="$Windows NT$"
[NewRequest]
Subject = "CN=$($DnsNames[0])"
KeySpec = 1
KeyLength = 2048
Exportable = TRUE
MachineKeySet = TRUE
ProviderName = "Microsoft RSA SChannel Cryptographic Provider"
ProviderType = 12
RequestType = PKCS10
HashAlgorithm = sha256
[Extensions]
2.5.29.17 = "{text}"
continue = "$sanText"
[RequestAttributes]
CertificateTemplate = Appliance
"@
$infPath = ".\san-auto.inf"
$reqPath = ".\san-auto.req"
$cerPath = ".\san-auto.cer"
$inf | Set-Content -Encoding ASCII $infPath
certreq -new $infPath $reqPath
certreq -submit -config "CAHOST\NOME-CA" $reqPath $cerPath
certreq -accept $cerPath
Vantaggi:
- La logica di composizione dei SAN è centralizzata e leggibile.
- Il template è fissato in
[RequestAttributes], evitando l’uso di-attrib. - Riduci gli errori umani su escape/quoting.
Diagnostica: come capire dove si rompe il flusso
- Solo il primo SAN appare: quasi sempre separatore di attributi mancante (nessun newline reale) o template non “Supply in the request”.
- Nessun SAN appare: la CA ha ignorato l’estensione (template errato) o la CSR non conteneva
2.5.29.17. - Errore al submit: controlla Application e System nel Visualizzatore Eventi sul server CA; verifica anche permessi di enroll.
- CSR rigettata: alcune policy CA impediscono caratteri non ammessi nei SAN (spazi, caratteri non DNS). Mantieni i DNS Name conformi a RFC (niente underscore a meno di accettazione esplicita).
CMD vs PowerShell: differenze pratiche su quoting ed escape
| Shell | Quoting consigliato | Newline reale | Carattere & | Nota operativa |
|---|---|---|---|---|
| CMD | Virgolette doppie attorno all’intero -attrib | Non supportato con \n; difficile da inserire inline | Operatore; necessario quotare tutto o evitare CMD | Per -attrib con più linee, preferisci PowerShell o INF |
| PowerShell | Stringhe tra doppi apici o here‑string @"..."@ | `n si espande in newline reale | Operatore di chiamata, ma letterale dentro le stringhe | È il modo più semplice per usare -attrib con SAN multipli |
Domande frequenti
Posso usare DNS= maiuscolo o dns= minuscolo?
Sì, la dicitura non è case‑sensitive nell’estensione testuale dell’INF. Mantieni coerenza per leggibilità.
Posso aggiungere SAN IP o URI?
Sì. Nelle righe continue usa ipaddress=198.51.100.10 oppure url=https://esempio.tld secondo necessità. Verifica che il template non imponga restrizioni al tipo di SAN.
È obbligatorio impostare MachineKeySet?
Per certificati macchina sì, perché la chiave deve finire nello store LocalMachine. Per certificati utente usa lo store CurrentUser (MachineKeySet=FALSE o ometti).
Le CA più vecchie hanno limiti sul numero di SAN?
Alcune implementazioni datate o policy personalizzate possono imporre limiti (dimensione della richiesta o numero di voci). Se sospetti un limite, prova prima con INF e pochi SAN, poi aumenta progressivamente.
Quando usare Exportable=FALSE?
Quando la chiave non deve lasciare il sistema (policy di sicurezza). Se devi fornire file PEM a un dispositivo esterno, imposta Exportable=TRUE solo per la generazione e conserva il PFX in modo sicuro.
Procedura completa “dal zero al certificato” (copiabile)
- Template: crea/clona il template (es. WebServer → Appliance), abilita Supply in the request, pubblicalo sulla CA e assegna i permessi di enroll.
- INF: prepara
san.infincludendo tutti i SAN in2.5.29.17e ilCertificateTemplatein[RequestAttributes]. - CSR:
certreq -new .\san.inf .\san.reqnel computer target. - Invio:
certreq -submit -config "CAHOST\NOME-CA" .\san.req .\san.cer. - Installazione:
certreq -accept .\san.cer. - Verifica:
certutil -dump .\san.cere controlla Subject Alternative Name. - Export/PEM (se serve): Export-PfxCertificate + OpenSSL come da esempi.
Raccomandazioni pratiche
- Prima scelta: genera sempre la CSR con tutte le SAN in un file INF. È deterministico e compatibile con le CA Microsoft recenti.
- Seconda scelta: se devi usare
-attrib, separa gli attributi con un vero newline (in PowerShell con`no here‑string). - Template: assicurati che il modello sia su Supply in the request e che la CA non applichi policy che rimuovono i SAN.
- Quoting: tratta
&con cura (quoting/escaping); evita composizioni non quotate in CMD/PowerShell. - Automazione: usa script per generare INF/CSR da liste di FQDN, riducendo errori manuali.
Appendice: esempi di comandi utili
Selezionare quando la CA chiede la scelta del template
Se la tua CA ignora [RequestAttributes] o devi forzare il template via attributo, usa PowerShell con newline reale:
$attrib = @"
CertificateTemplate:WebServer
SAN:DNS=www.example.com&DNS=api.example.com
"@
certreq -submit -config "CAHOST\NOME-CA" -attrib $attrib .\web.req .\web.cer
Rigenerare una CSR da chiave esistente
; renew.inf
[Version]
Signature="$Windows NT$"
[NewRequest]
Subject = "CN=appliance.example.com"
UseExistingKeySet = TRUE
RequestType = PKCS10
[Extensions]
2.5.29.17 = "{text}"
continue = "dns=appliance.example.com&dns=api.example.com"
[RequestAttributes]
CertificateTemplate = Appliance
certreq -new .\renew.inf .\renew.req
certreq -submit -config "CAHOST\NOME-CA" .\renew.req .\renew.cer
certreq -accept .\renew.cer
Verifica catena di fiducia lato server
# Simula la presentazione lato server
openssl s_client -connect appliance.example.com:443 -servername appliance.example.com -showcerts < /dev/null
Conclusione
Il problema dei “SAN monchi” con certreq -attrib non è un mistero: nasce dalla combinazione di formattazione degli attributi, escaping e impostazioni del template. Impostando il template su Supply in the request e generando la CSR da INF (includendo l’estensione 2.5.29.17), ottieni risultati coerenti e ripetibili. Quando serve usare -attrib, passa per PowerShell e inserisci un ritorno a capo reale tra CertificateTemplate: e SAN:. Con queste accortezze, la CA emetterà certificati con tutti i SAN richiesti, senza workaround faticosi.
