Salta al contenuto
Guida

Il client secret scade e le integrazioni si fermano, senza un solo avviso

Un client secret di Entra ID scade e nessuno riceve una notifica: il primo segnale è un form che non invia più. Come isolare la causa in cinque secondi, perché un certificato non risolve, e lo script per le scadenze.

SynSphere Italia Pubblicato il 8 min di lettura
Scadenze dei client secret delle app registration di Microsoft Entra ID

Ci sono guasti che si annunciano e guasti che aspettano. Un disco che si riempie manda un alert, un certificato TLS in scadenza fa scrivere al monitoraggio, un servizio che va giù accende un cruscotto. Il client secret di un’app registration, no: scade e non succede niente. Nessuna mail, nessuna notifica nel portale, nessun avviso all’amministratore. L’unica cosa che cambia è che un’autenticazione che ieri funzionava oggi viene rifiutata.

Il problema non è la scadenza — quella è una misura di sicurezza corretta, ed è giusto che i segreti abbiano una vita finita. Il problema è che fra la scadenza e la scoperta passa il tempo che serve a qualcuno per accorgersi che qualcosa non va. E dipende interamente da cosa quel segreto stava tenendo in piedi.

Il caso peggiore: quando nessuno se ne accorge

Se il segreto serviva a un job notturno, la mattina dopo qualcuno trova il job in errore. Fastidioso, ma visibile.

Se serviva all’invio delle email di un form del sito, la faccenda è diversa. Il visitatore compila, invia, vede un messaggio d’errore generico e se ne va. Nessuno in azienda riceve niente — ed è esattamente il punto: l’assenza di email non genera un allarme, perché è indistinguibile da una giornata senza richieste. Il guasto può durare giorni prima che qualcuno pensi “però, da un po’ non arriva niente dal sito”.

È la categoria di difetto peggiore che esiste in un sito aziendale: non produce errori nei log che qualcuno guarda, non fa cadere pagine, non peggiora le prestazioni. Toglie soltanto i contatti commerciali, uno per uno, in silenzio.

L’errore che vedete, e perché è ambiguo

Con l’invio SMTP l’errore lato server è questo:

535 5.7.3 Authentication unsuccessful.
For more information see https://aka.ms/EXOSmtpErrors.

Due avvertenze su questo messaggio.

La prima: quel link a Exchange Online è fuorviante. Se usate Azure Communication Services per l’invio, il servizio sta dietro l’infrastruttura Exchange e ne eredita i codici di errore. Vedere EXOSmtpErrors non significa che stiate usando Exchange Online, e cercare la soluzione in quella direzione porta fuori strada.

La seconda, più insidiosa: il messaggio che l’utente vede è lo stesso in due situazioni completamente diverse. Un’applicazione che non trova le credenziali nella propria configurazione e un’applicazione le cui credenziali vengono rifiutate producono, quasi sempre, lo stesso errore generico in pagina. Se la vostra applicazione gestisce entrambi i casi nello stesso blocco di gestione errori — e succede spesso — anche il log non vi aiuta a distinguerli.

Isolare la causa in cinque secondi

Il modo per uscire dall’ambiguità è provare l’autenticazione fuori dall’applicazione, leggendo le credenziali direttamente dal file di configurazione. Se il test passa, le credenziali sono valide e il problema è che l’applicazione non le vede. Se il test fallisce, sono le credenziali.

set -a && . ./.env && set +a && python3 -c "
import smtplib, os
s = smtplib.SMTP(os.environ['SMTP_HOST'], int(os.environ['SMTP_PORT']), timeout=15)
s.starttls()
try:
    s.login(os.environ['SMTP_USER'], os.environ['SMTP_PASS'])
    print('>>> AUTH OK')
except Exception as e:
    print('>>> AUTH FALLITA:', e)
s.quit()"

Sono cinque righe e non toccano nulla. Il valore non è tecnico, è diagnostico: separa due ipotesi che l’applicazione confonde, e vi dice da subito se dovete guardare in Azure o nella configurazione del vostro server.

Una nota di metodo che vale oltre questo caso: quando due strumenti si contraddicono, la misura utile è quella che non passa da nessuno dei due. Un test che legge la configurazione dal file e parla direttamente col server di posta è esattamente questo.

Come funziona l’autenticazione, e quale segreto è

Con Azure Communication Services l’invio SMTP autentica così:

  • utente: la concatenazione <nome-risorsa>.<id-applicazione>.<id-tenant>
  • password: il client secret di un’app registration di Entra ID

Da qui una conseguenza pratica poco intuitiva: il “problema di posta” si risolve in Entra ID, non nelle impostazioni di posta. L’id dell’applicazione ve lo dice il campo utente stesso: è il GUID centrale dei tre.

E qui arriva la domanda difficile. Un’app registration può avere più segreti contemporaneamente — è così che si fa una rotazione senza interruzioni: si crea il nuovo, si aggiornano i consumatori, si elimina il vecchio. Ma se l’app ne ha quattro, quale sta usando la vostra integrazione?

Il valore completo di un secret non è recuperabile dopo la creazione: il portale lo mostra una volta sola. Esiste però un campo hint che contiene i primi tre caratteri del valore, ed è visibile per sempre. Confrontare quei tre caratteri con i primi tre del valore configurato nella vostra applicazione è l’unico modo di stabilire la corrispondenza:

grep '^SMTP_PASS=' .env | cut -c11-13

⚠️ Attenzione anche a un errore frequente nel momento della rotazione: nella tabella del portale, accanto al Value c’è il Secret ID, e sono adiacenti. Il Value è la password ed è visibile una volta sola; il Secret ID è un identificativo pubblico e non serve ad autenticare. Distinguerli a occhio è semplice: il Value non contiene trattini, il Secret ID ne ha quattro.

Perché un certificato non risolve il problema

Chi si trova a rifare la rotazione arriva quasi sempre alla stessa idea: invece di un segreto che scade fra un anno, carico un certificato con validità lunghissima e non ci penso più. La tab Certificates è proprio lì, accanto a Client secrets.

Non funziona, e il motivo è nel protocollo. L’autenticazione SMTP avviene con AUTH LOGIN, che trasmette due stringhe: utente e password. Un certificato non è una stringa da inviare — serve a firmare un’asserzione dentro un flusso OAuth di richiesta token, che SMTP non prevede in alcun modo. La tab dei certificati esiste per le applicazioni che chiedono token a Entra ID, non per un relay di posta.

E la scadenza non si aggira nemmeno allungandola: il portale limita i client secret a 24 mesi.

La soluzione che elimina il problema invece di rinviarlo

Se l’applicazione gira su una macchina virtuale Azure, esiste una strada che non ha credenziali da ruotare: abbandonare l’SMTP e usare l’SDK di Communication Services con una managed identity.

L’idea è semplice: l’identità appartiene alla macchina, Azure la gestisce, e all’oggetto che invia le email si assegna il permesso sulla risorsa. Non c’è nessun segreto nel file di configurazione, nessuna data di scadenza, nessuna rotazione da ricordare. Il codice usa @azure/communication-email insieme a @azure/identity e non conosce alcuna password.

Il costo è una modifica applicativa contenuta — si sostituisce il client di posta nei punti che inviano — a fronte dell’eliminazione definitiva di una classe di guasti. Su un’integrazione che regge la raccolta contatti, il conto torna facilmente.

Nel frattempo: sapere cosa scade

Finché ci sono segreti, servono due cose: conoscere le scadenze e accorgersi del guasto senza aspettare che lo segnali un cliente.

Per la prima abbiamo pubblicato uno script PowerShell gratuito che elenca tutti i client secret e i certificati di tutte le app registration del tenant, ordinati per scadenza, con quelle già scadute evidenziate e la colonna hint per capire quale segreto usa quale integrazione:

Scarica lo script: scadenze delle credenziali Entra ID

È in sola lettura, richiede il permesso minimo Application.Read.All e sta in un singolo file. Con -SoloInScadenza mostra solo ciò che va sistemato, con -IncludiServicePrincipal copre anche le credenziali registrate sui service principal — dove alcune integrazioni di terze parti le mettono, e dove nessuno le va a cercare.

Due dettagli di implementazione, per chi vuole scriversene uno:

  • Non usate $select su keyCredentials iterando le applicazioni. Microsoft impone un limite di 150 richieste al minuto per tenant su quella specifica proiezione, quindi su un tenant con molte registrazioni si finisce in throttling. Non serve, perché la risposta di default contiene già le date di scadenza.
  • Il filtro sulle date va fatto in locale. passwordCredentials non supporta $filter in Microsoft Graph, quindi non esiste un modo per farsi restituire dal server solo i segreti in scadenza.

Per la seconda — accorgersi del guasto — la misura più economica è un controllo periodico che invii una email di prova e verifichi che arrivi. Sembra banale ed è l’unico controllo che copre l’intera catena: credenziali, configurazione, rete, permessi e recapito. Un test che verifica solo la raggiungibilità del server non avrebbe intercettato nulla di quanto descritto qui.

Tre abitudini che rendono la cosa gestibile

Una app registration per integrazione. Condividerne una fra più sistemi sembra un risparmio e diventa un problema doppio: chi possiede un segreto può autenticarsi come tutti gli altri, e le scadenze arrivano a rotazione senza che si capisca a chi appartengono. Il costo di separarle è zero.

Una descrizione parlante su ogni segreto. Il campo descrizione è libero e quasi sempre vuoto o generico. Scriverci il nome del sistema che lo usa trasforma la lista dei segreti da indovinello a inventario — e nel giorno del guasto è la differenza fra due minuti e due ore.

Un promemoria a data certa, non “quando capita”. Ventiquattro mesi sono lunghi e la persona che ha creato il segreto probabilmente non sarà quella che ne gestirà la scadenza. Un appuntamento in calendario un mese prima, con scritto cosa va rifatto e dove, vale più di qualsiasi buona intenzione.


Se la posta transazionale del vostro sito, i job di integrazione o gli accessi applicativi sono in questa condizione — funzionanti ma senza nessuno che ne presidi le scadenze — è esattamente il perimetro della nostra cybersecurity gestita e dell’assistenza Microsoft 365. Se invece volete guardarci dentro da soli, lo script qui sopra è il punto di partenza, e il toolkit PowerShell per Entra ID copre il resto della governance delle identità.

Prodotti e servizi SynSphere correlati

Dal catalogo SynSphere, quello che c'entra con questo articolo.