<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Antonio Musarra&#039;s Blog</title>
	<atom:link href="https://www.dontesta.it/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.dontesta.it/</link>
	<description>The ideal solution for a problem</description>
	<lastBuildDate>Tue, 09 Sep 2025 12:11:01 +0000</lastBuildDate>
	<language>it-IT</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://www.dontesta.it/wp-content/uploads/2024/06/cropped-foto_profilo-32x32.png</url>
	<title>Antonio Musarra&#039;s Blog</title>
	<link>https://www.dontesta.it/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Guida Avanzata: mTLS con Postman CLI, Ambienti e Certificati Multipli</title>
		<link>https://www.dontesta.it/2025/09/09/guida-avanzata-mtls-con-postman-cli-ambienti-e-certificati-multipli/</link>
					<comments>https://www.dontesta.it/2025/09/09/guida-avanzata-mtls-con-postman-cli-ambienti-e-certificati-multipli/#respond</comments>
		
		<dc:creator><![CDATA[Antonio Musarra]]></dc:creator>
		<pubDate>Tue, 09 Sep 2025 12:08:28 +0000</pubDate>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[SSL/TLS]]></category>
		<category><![CDATA[Tools]]></category>
		<guid isPermaLink="false">https://www.dontesta.it/?p=5947</guid>

					<description><![CDATA[<p>L'obiettivo di questa guida è mostrare come testare endpoint REST protetti da mTLS (Mutual TLS), come quelli del progetto quarkus-mtls-auth, attraverso l'utilizzo della Postman CLI. Vedremo come sfruttare gli ambienti per una configurazione flessibile&#46;&#46;&#46;</p>
<p>L'articolo <a href="https://www.dontesta.it/2025/09/09/guida-avanzata-mtls-con-postman-cli-ambienti-e-certificati-multipli/">Guida Avanzata: mTLS con Postman CLI, Ambienti e Certificati Multipli</a> sembra essere il primo su <a href="https://www.dontesta.it">Antonio Musarra&#039;s Blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>L'obiettivo di questa guida è mostrare come testare endpoint REST protetti da mTLS (<a href="https://en.wikipedia.org/wiki/Mutual_authentication">Mutual TLS</a>), come quelli del progetto <a href="https://github.com/amusarra/quarkus-mtls-auth">quarkus-mtls-auth</a>, attraverso l'utilizzo della <a href="https://learning.postman.com/docs/postman-cli/postman-cli-overview/">Postman CLI</a>.</p>



<p>Vedremo come sfruttare gli ambienti per una configurazione flessibile e come gestire più certificati client in modo centralizzato tramite un file di configurazione, una pratica essenziale quando si lavora con diversi servizi.</p>



<p>La documentazione ufficiale di Postman CLI non fornisce informazioni dettagliate su come configurare mTLS, ne quanto meno esempi pratici. Seguendo questa guida, <strong>ti assicuro che sarà un gioco da ragazzi!</strong></p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><strong>Segui la guida fino in fondo!</strong><br>Alla fine troverai un bonus: il link al repository GitHub che contiene l'intero progetto pronto all'uso, con tutte le configurazioni, gli script e le collection Postman illustrate in questo articolo.</p>
</blockquote>



<h2 class="wp-block-heading" id="prerequisiti">Prerequisiti</h2>



<p>Per seguire questa guida, assicuriamoci di avere:</p>



<ul class="wp-block-list">
<li><a href="https://learning.postman.com/docs/postman-cli/postman-cli-installation/">Postman CLI</a> installato sull'ambiente di esecuzione. Versione minima consigliata: 1.18.0, poiché alcune funzionalità potrebbero non essere disponibili nelle versioni precedenti;</li>



<li>un progetto con endpoint protetti da mTLS, come per esempio <a href="https://github.com/amusarra/quarkus-mtls-auth">quarkus-mtls-auth</a>;</li>



<li>certificati client e CA (<a href="https://en.wikipedia.org/wiki/Certificate_authority">Certificate Authority</a>) necessari per l'autenticazione mTLS.</li>
</ul>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>Il login su Postman non è necessario per eseguire collection locali come in questo esempio, ma è richiesto nel caso in cui si voglia sincronizzare collection, ambienti o cronologia con il cloud di Postman.</p>
</blockquote>



<p>Il progetto <a href="https://github.com/amusarra/quarkus-mtls-auth">quarkus-mtls-auth</a> offre un'implementazione di API REST protette dal meccanismo di sicurezza mTLS, che utilizzeremo per dimostrare la configurazione di Postman CLI. Quanto descritto in questa guida è applicabile a qualsiasi altro progetto e/o scenario simile.</p>



<p>Per quanto riguarda i certificati client e CA, esploreremo in seguito come generarli e configurarli correttamente in Postman CLI. La versione CLI, a differenza della versione Desktop, attualmente supporta solo certificati in formato PEM (<a href="https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail">Privacy Enhanced Mail</a>).</p>



<p>Non ci sono restrizioni particolari riguardo il sistema operativo utilizzato, puoi seguire questa guida su Windows, macOS o Linux senza problemi. Per garantire la massima compatibilità, consiglio di utilizzare un terminale con supporto per i comandi Unix/Linux.</p>



<p>Per seguire in modo fluido questa guida, assicurati di avere familiarità con i concetti di base di mTLS e Postman e avere una certa dimestichezza con la linea di comando e il formato JSON.</p>



<h2 class="wp-block-heading" id="configurazione-della-struttura-del-progetto">Configurazione della struttura del progetto</h2>



<p>Come primo passo, organizziamo un ambiente di lavoro che sia agevole e ben strutturato per Postman CLI. Inizieremo creando una cartella dedicata al nostro progetto e all'interno di essa, andremo a creare tutto il necessario per la configurazione.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# Creiamo la struttura delle cartelle
# La directory di lavoro (o root directory) sarà postman-mtls
mkdir postman-mtls

# Creiamo la cartella per i certificati client
mkdir -p postman-mtls/certificates/client

# Creiamo la cartella per i certificati CA
mkdir -p postman-mtls/certificates/ca

# Creiamo la cartella per la collection postman
mkdir postman-mtls/collections

# Creiamo la cartella per i file di configurazione (environments)
mkdir -p postman-mtls/config/environments

# Creiamo la cartella per i file di configurazione (certificates)
mkdir -p postman-mtls/config/certificates
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88"># Creiamo la struttura delle cartelle</span></span>
<span class="line"><span style="color: #616E88"># La directory di lavoro (o root directory) sarà postman-mtls</span></span>
<span class="line"><span style="color: #88C0D0">mkdir</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">postman-mtls</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Creiamo la cartella per i certificati client</span></span>
<span class="line"><span style="color: #88C0D0">mkdir</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-p</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">postman-mtls/certificates/client</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Creiamo la cartella per i certificati CA</span></span>
<span class="line"><span style="color: #88C0D0">mkdir</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-p</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">postman-mtls/certificates/ca</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Creiamo la cartella per la collection postman</span></span>
<span class="line"><span style="color: #88C0D0">mkdir</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">postman-mtls/collections</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Creiamo la cartella per i file di configurazione (environments)</span></span>
<span class="line"><span style="color: #88C0D0">mkdir</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-p</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">postman-mtls/config/environments</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Creiamo la cartella per i file di configurazione (certificates)</span></span>
<span class="line"><span style="color: #88C0D0">mkdir</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-p</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">postman-mtls/config/certificates</span></span>
<span class="line"></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Console 1 - Creazione della struttura delle cartelle per il progetto Postman mTLS</span></div>



<p></p>



<p>Una volta eseguiti i comandi precedenti, la struttura delle cartelle dovrebbe apparire come segue.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="postman-mtls/
├── certificates/
│   ├── client/
│   └── ca/
├── collections/
└── config/
    ├── environments/
    └── certificates/
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">postman-mtls/</span></span>
<span class="line"><span style="color: #88C0D0">├──</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">certificates/</span></span>
<span class="line"><span style="color: #88C0D0">│</span><span style="color: #D8DEE9FF">   </span><span style="color: #A3BE8C">├──</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">client/</span></span>
<span class="line"><span style="color: #88C0D0">│</span><span style="color: #D8DEE9FF">   </span><span style="color: #A3BE8C">└──</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ca/</span></span>
<span class="line"><span style="color: #88C0D0">├──</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">collections/</span></span>
<span class="line"><span style="color: #88C0D0">└──</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">config/</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">├──</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">environments/</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">└──</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">certificates/</span></span>
<span class="line"></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Console 2 - Verifica della struttura delle cartelle (uso del comando tree)</span></div>



<p></p>



<h2 class="wp-block-heading" id="configurazione-delle-variabili-dambiente-di-postman">Configurazione delle variabili d'ambiente di Postman</h2>



<p>Usare le <a href="https://learning.postman.com/docs/sending-requests/variables/managing-environments/">variabili d'ambiente in Postman</a> è fondamentale per gestire configurazioni diverse senza modificare manualmente le richieste. Le variabili possono essere utilizzate per memorizzare valori come URL, token di accesso e certificati.</p>



<p>Per il nostro esempio, creeremo due ambienti: uno per lo sviluppo locale e un altro per l'ambiente di test. Vediamo quali sono le variabili che andremo a definire:</p>



<ul class="wp-block-list">
<li><code>base_url</code>: l'URL di base del servizio. Questa variabile avrà un valore differente per ogni ambiente;</li>



<li><code>api_connection_info_path</code>: il path dell'API per le informazioni di connessione;</li>



<li><code>api_connection_user_identity</code>: il path dell'API per l'identità dell'utente;</li>



<li><code>env_name</code>: il nome dell'ambiente. È utile per identificare l'ambiente attivo durante l'esecuzione delle richieste e dei test.</li>
</ul>



<p>La tabella a seguire riassume le variabili per ciascun ambiente.</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Variabile</th><th>Ambiente local</th><th>Ambiente test</th><th>Descrizione</th></tr></thead><tbody><tr><td><code>env_name</code></td><td>local</td><td>test</td><td>Nome identificativo dell'ambiente</td></tr><tr><td><code>base_url</code></td><td></td><td></td><td>URL di base del servizio</td></tr><tr><td><code>api_connection_info_path</code></td><td>/api/v1/connection-info/info</td><td>/api/v1/connection-info/info</td><td>Path API per informazioni di connessione</td></tr><tr><td><code>api_connection_user_identity</code></td><td>/api/v1/connection-info/user-identity</td><td>/api/v1/connection-info/user-identity</td><td>Path API per identità utente</td></tr></tbody></table></figure>



<p>Tabella 1 - Variabili per gli ambienti</p>



<p>Queste variabili possono essere definite e create dall'interfaccia di Postman o tramite file di configurazione JSON. Noi faremo a meno dell'interfaccia grafica e utilizzeremo file di configurazione JSON per definire i nostri ambienti.</p>



<p>Andremo a creare due file JSON, uno per l'ambiente di sviluppo locale e uno per l'ambiente di test. Questi file conterranno le variabili necessarie per ciascun ambiente. Chiameremo i file <code>local.json</code> e <code>test.json</code> che andranno posizionati nella cartella <code>postman-mtls/config/environments</code>.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# Creiamo i file di configurazione per gli ambienti
touch postman-mtls/config/environments/local.json
touch postman-mtls/config/environments/test.json
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88"># Creiamo i file di configurazione per gli ambienti</span></span>
<span class="line"><span style="color: #88C0D0">touch</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">postman-mtls/config/environments/local.json</span></span>
<span class="line"><span style="color: #88C0D0">touch</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">postman-mtls/config/environments/test.json</span></span>
<span class="line"></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Console 3 - Creazione dei file di configurazione per gli ambienti.</span></div>



<p></p>



<p>Il contenuto del file <code>local.json</code> sarà il seguente.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="{
    &quot;id&quot;: &quot;quarkus-mtls-local-environment&quot;,
    &quot;name&quot;: &quot;Quarkus mTLS local environment&quot;,
    &quot;values&quot;: [
        {
            &quot;key&quot;: &quot;env_name&quot;,
            &quot;value&quot;: &quot;local&quot;,
            &quot;description&quot;: &quot;Name of the environment&quot;,
            &quot;type&quot;: &quot;default&quot;,
            &quot;enabled&quot;: true
        },
        {
            &quot;key&quot;: &quot;base_url&quot;,
            &quot;value&quot;: &quot;https://localhost:8443&quot;,
            &quot;description&quot;: &quot;Base URL for the local environment&quot;,
            &quot;type&quot;: &quot;default&quot;,
            &quot;enabled&quot;: true
        },
        {
            &quot;key&quot;: &quot;api_connection_info_path&quot;,
            &quot;value&quot;: &quot;/api/v1/connection-info/info&quot;,
            &quot;description&quot;: &quot;Path for API connection info&quot;,
            &quot;type&quot;: &quot;default&quot;,
            &quot;enabled&quot;: true
        },
        {
            &quot;key&quot;: &quot;api_connection_user_identity&quot;,
            &quot;value&quot;: &quot;/api/v1/connection-info/user-identity&quot;,
            &quot;description&quot;: &quot;Path for API user identity&quot;,
            &quot;type&quot;: &quot;default&quot;,
            &quot;enabled&quot;: true
        }
    ]
}
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">id</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">quarkus-mtls-local-environment</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">name</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Quarkus mTLS local environment</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">values</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">[</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">key</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">env_name</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">value</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">local</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Name of the environment</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">default</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">enabled</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">true</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">key</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">base_url</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">value</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">https://localhost:8443</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Base URL for the local environment</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">default</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">enabled</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">true</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">key</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">api_connection_info_path</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">value</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">/api/v1/connection-info/info</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Path for API connection info</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">default</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">enabled</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">true</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">key</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">api_connection_user_identity</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">value</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">/api/v1/connection-info/user-identity</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Path for API user identity</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">default</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">enabled</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">true</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">]</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Config. 1 - Configurazione variabili per l'ambiente locale.</span></div>



<p></p>



<p>Per l'ambiente di test il contenuto del file <code>test.json</code> sarà il seguente.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="{
    &quot;id&quot;: &quot;quarkus-mtls-test-environment&quot;,
    &quot;name&quot;: &quot;Quarkus mTLS test environment&quot;,
    &quot;values&quot;: [
        {
            &quot;key&quot;: &quot;env_name&quot;,
            &quot;value&quot;: &quot;test&quot;,
            &quot;description&quot;: &quot;Name of the environment&quot;,
            &quot;type&quot;: &quot;default&quot;,
            &quot;enabled&quot;: true
        },
        {
            &quot;key&quot;: &quot;base_url&quot;,
            &quot;value&quot;: &quot;https://blog.quarkus.dontesta.it:8443&quot;,
            &quot;description&quot;: &quot;Base URL for the test environment&quot;,
            &quot;type&quot;: &quot;default&quot;,
            &quot;enabled&quot;: true
        },
        {
            &quot;key&quot;: &quot;api_connection_info_path&quot;,
            &quot;value&quot;: &quot;/api/v1/connection-info/info&quot;,
            &quot;description&quot;: &quot;Path for API connection info&quot;,
            &quot;type&quot;: &quot;default&quot;,
            &quot;enabled&quot;: true
        },
        {
            &quot;key&quot;: &quot;api_connection_user_identity&quot;,
            &quot;value&quot;: &quot;/api/v1/connection-info/user-identity&quot;,
            &quot;description&quot;: &quot;Path for API user identity&quot;,
            &quot;type&quot;: &quot;default&quot;,
            &quot;enabled&quot;: true
        }
    ]
}
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">id</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">quarkus-mtls-test-environment</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">name</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Quarkus mTLS test environment</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">values</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">[</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">key</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">env_name</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">value</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">test</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Name of the environment</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">default</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">enabled</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">true</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">key</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">base_url</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">value</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">https://blog.quarkus.dontesta.it:8443</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Base URL for the test environment</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">default</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">enabled</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">true</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">key</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">api_connection_info_path</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">value</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">/api/v1/connection-info/info</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Path for API connection info</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">default</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">enabled</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">true</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">key</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">api_connection_user_identity</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">value</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">/api/v1/connection-info/user-identity</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Path for API user identity</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">default</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">enabled</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">true</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">]</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Config. 2 - Configurazione variabili per l'ambiente di test.</span></div>



<p></p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><strong>Importante</strong>: come <code>base_url</code> per l'ambiente di test abbiamo indicato l'FQDN <code>blog.quarkus.dontesta.it</code>, dobbiamo quindi assicurarci che questo sia risolvibile. In questo caso è più che sufficiente aggiungere una voce nel file <code>/etc/hosts</code> del nostro ambiente di sviluppo.</p>
</blockquote>



<p>Una volta creati i file di configurazione per gli ambienti, possiamo procedere con la configurazione dei certificati client che saranno usati dalla CLI di Postman per eseguire le richieste HTTPS verso i servizi.</p>



<h2 class="wp-block-heading" id="configurazione-dei-certificati-client-in-postman-cli">Configurazione dei certificati client in Postman CLI</h2>



<p>La configurazione dei certificati client in Postman CLI è un passaggio cruciale per l'autenticazione mTLS. A differenza della versione Desktop di Postman, che consente di <a href="https://learning.postman.com/docs/sending-requests/authorization/certificates/">configurare i certificati tramite l'interfaccia grafica</a>, la CLI richiede l'uso di file di configurazione JSON.</p>



<p>Per gestire più certificati client in modo centralizzato, creeremo un file di configurazione adatto allo scopo. Questo file conterrà le informazioni necessarie per ogni certificato, inclusi i percorsi dei file PEM per il certificato e la chiave privata, compresa la relativa passphrase.</p>



<p>Chiameremo questo file di configurazione <code>client-certificates.json</code> e lo posizioneremo nella cartella <code>postman-mtls/config/certificates</code>.</p>



<p>A seguire l'esempio di configurazione per i certificati client. In questo caso, abbiamo configurato due certificati, sia per l'ambiente locale che per l'ambiente di test. Questa configurazione è solo un esempio e può essere adattata in base alle esigenze specifiche.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="[
  {
    &quot;name&quot;: &quot;local-certificate-1&quot;,
    &quot;matches&quot;: [&quot;https://localhost:8443/api/v1/connection-info/info&quot;],
    &quot;key&quot;: { &quot;src&quot;: &quot;certificates/client/client_with_device_id_and_roles_key.pem&quot; },
    &quot;cert&quot;: { &quot;src&quot;: &quot;certificates/client/client_with_device_id_and_roles_cert.pem&quot; },
    &quot;passphrase&quot;: &quot;pZAXwq+l1BRlC+3X&quot;
  },
  {
    &quot;name&quot;: &quot;local-certificate-2&quot;,
    &quot;matches&quot;: [&quot;https://localhost:8443/api/v1/connection-info/user-identity&quot;],
    &quot;key&quot;: { &quot;src&quot;: &quot;certificates/client/client_with_device_id_and_roles_1_key.pem&quot; },
    &quot;cert&quot;: { &quot;src&quot;: &quot;certificates/client/client_with_device_id_and_roles_1_cert.pem&quot; },
    &quot;passphrase&quot;: &quot;z93Fl8nhQR8shWTq&quot;
  },
  {
    &quot;name&quot;: &quot;test-certificate-1&quot;,
    &quot;matches&quot;: [&quot;https://blog.quarkus.dontesta.it:8443/api/v1/connection-info/user-identity&quot;],
    &quot;key&quot;: { &quot;src&quot;: &quot;certificates/client/client_new_device_id_key.pem&quot; },
    &quot;cert&quot;: { &quot;src&quot;: &quot;certificates/client/client_new_device_id_cert.pem&quot; },
    &quot;passphrase&quot;: &quot;4l0nJ9nvreqleFnV&quot;
  },
  {
    &quot;name&quot;: &quot;test-certificate-2&quot;,
    &quot;matches&quot;: [&quot;https://blog.quarkus.dontesta.it:8443/api/v1/connection-info/info&quot;],
    &quot;key&quot;: { &quot;src&quot;: &quot;certificates/client/client_with_device_id_and_roles_1_key.pem&quot; },
    &quot;cert&quot;: { &quot;src&quot;: &quot;certificates/client/client_with_device_id_and_roles_1_cert.pem&quot; },
    &quot;passphrase&quot;: &quot;z93Fl8nhQR8shWTq&quot;
  }
]
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #ECEFF4">[</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">name</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">local-certificate-1</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">matches</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">[</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">https://localhost:8443/api/v1/connection-info/info</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">],</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">key</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">src</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">certificates/client/client_with_device_id_and_roles_key.pem</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">cert</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">src</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">certificates/client/client_with_device_id_and_roles_cert.pem</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">passphrase</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">pZAXwq+l1BRlC+3X</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">name</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">local-certificate-2</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">matches</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">[</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">https://localhost:8443/api/v1/connection-info/user-identity</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">],</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">key</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">src</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">certificates/client/client_with_device_id_and_roles_1_key.pem</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">cert</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">src</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">certificates/client/client_with_device_id_and_roles_1_cert.pem</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">passphrase</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">z93Fl8nhQR8shWTq</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">name</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">test-certificate-1</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">matches</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">[</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">https://blog.quarkus.dontesta.it:8443/api/v1/connection-info/user-identity</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">],</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">key</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">src</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">certificates/client/client_new_device_id_key.pem</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">cert</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">src</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">certificates/client/client_new_device_id_cert.pem</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">passphrase</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">4l0nJ9nvreqleFnV</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">name</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">test-certificate-2</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">matches</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">[</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">https://blog.quarkus.dontesta.it:8443/api/v1/connection-info/info</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">],</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">key</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">src</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">certificates/client/client_with_device_id_and_roles_1_key.pem</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">cert</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">src</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">certificates/client/client_with_device_id_and_roles_1_cert.pem</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">passphrase</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">z93Fl8nhQR8shWTq</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #ECEFF4">]</span></span>
<span class="line"></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Config. 3 - Configurazione dei certificati client per mTLS.</span></div>



<p></p>



<p>Poiché il progetto su cui eseguiremo i test è <a href="https://github.com/amusarra/quarkus-mtls-auth">quarkus-mtls-auth</a>, utilizzeremo certificati accettati dai servizi REST implementati in questo progetto. I certificati indicati sono stati generati appositamente per il testing tramite uno script specifico.</p>



<p>Per maggiori informazioni su come sono stati generati i certificati client, fare riferimento all'articolo <a href="https://www.dontesta.it/2024/09/19/implementazione-tls-mutual-authentication-mtls-con-quarkus/">Implementazione di TLS Mutual Authentication (mTLS) con Quarkus</a> e in particolare al capitolo <strong>Step 10 - Generazione di un set di certificati client per eseguire dei test di accesso</strong>.</p>



<h3 class="wp-block-heading" id="come-postman-cli-seleziona-il-certificato-client">Come Postman CLI seleziona il certificato client</h3>



<p>Quando si esegue una collection con Postman CLI e si specifica il file di configurazione dei certificati tramite l'opzione <code>--ssl-client-cert-list</code>, Postman seleziona automaticamente il certificato client da utilizzare per ogni richiesta HTTPS in base al campo <code>matches</code> presente nel file di configurazione.</p>



<p>Il campo <code>matches</code> è un array di URL o pattern che indicano a quali richieste il certificato deve essere associato. Durante l'esecuzione della collection, Postman confronta l'URL della richiesta con i valori definiti in <code>matches</code> per determinare quale certificato utilizzare.  </p>



<ul class="wp-block-list">
<li>Se l'URL della richiesta corrisponde a uno dei valori definiti in <code>matches</code>, Postman utilizza il certificato associato a quella configurazione.</li>



<li>Se nessun certificato corrisponde, la richiesta sarà inviata senza certificato client.</li>
</ul>



<p>Questo meccanismo consente di gestire facilmente più certificati per diversi endpoint o ambienti, senza dover modificare manualmente la configurazione ad ogni esecuzione.</p>



<p>Esempio: se una richiesta viene inviata a <code>https://localhost:8443/api/v1/connection-info/info</code>, Postman CLI cercherà una configurazione con <code>matches</code> che includa esattamente quell'URL e userà il certificato specificato.</p>



<p>Per maggiori dettagli fare riferimento ad <a href="https://learning.postman.com/docs/sending-requests/authorization/certificates/">Add and manage CA and client certificates in Postman</a></p>



<h2 class="wp-block-heading" id="creazione-della-collection-postman">Creazione della collection Postman</h2>



<p>A questo punto possiamo creare la nostra collection Postman contenente le richieste necessarie per interagire con le API protette da mTLS, che in questo caso sono due: <code>/api/v1/connection-info/info</code>e <code>/api/v1/connection-info/user-identity</code>. La prima API restituisce informazioni sulla connessione, mentre la seconda fornisce dettagli sull'identità dell'utente.</p>



<p>Procediamo ora con la creazione del file JSON della collection, che salveremo nella cartella <code>postman-mtls/collections</code> con il nome <code>quarkus-mtls-collection.json</code>. Di seguito è riportato il contenuto del file.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="{
    &quot;info&quot;: {
        &quot;name&quot;: &quot;Quarkus mTLS&quot;,
        &quot;description&quot;: &quot;Collection Postman per il test di servizi REST protetti da un meccanismo di sicurezza di tipo mTLS.&quot;,
        &quot;schema&quot;: &quot;https://schema.getpostman.com/json/collection/v2.1.0/collection.json&quot;
    },
    &quot;item&quot;: [
        {
            &quot;name&quot;: &quot;connection-info/info&quot;,
            &quot;request&quot;: {
                &quot;method&quot;: &quot;GET&quot;,
                &quot;header&quot;: [],
                &quot;url&quot;: {
                    &quot;raw&quot;: &quot;{{base_url}}{{api_connection_info_path}}&quot;,
                    &quot;host&quot;: [
                        &quot;{{base_url}}{{api_connection_info_path}}&quot;
                    ]
                },
                &quot;description&quot;: &quot;La risposta del servizio conterrà un set d'informazioni che riguardano la connessione instaurata.&quot;
            },
            &quot;response&quot;: []
        },
        {
            &quot;name&quot;: &quot;connection-info/user-identity&quot;,
            &quot;request&quot;: {
                &quot;method&quot;: &quot;GET&quot;,
                &quot;header&quot;: [],
                &quot;url&quot;: {
                    &quot;raw&quot;: &quot;{{base_url}}{{api_connection_user_identity}}&quot;,
                    &quot;host&quot;: [
                        &quot;{{base_url}}{{api_connection_user_identity}}&quot;
                    ]
                },
                &quot;description&quot;: &quot;La risposta del servizio conterrà un set d'informazioni che riguardano l'indentità del client che ha richiesto l'accesso alla risorsa.&quot;
            },
            &quot;response&quot;: []
        }
    ]
}
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">info</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">name</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Quarkus mTLS</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Collection Postman per il test di servizi REST protetti da un meccanismo di sicurezza di tipo mTLS.</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">schema</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">https://schema.getpostman.com/json/collection/v2.1.0/collection.json</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">item</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">[</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">name</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">connection-info/info</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">request</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">method</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">GET</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">header</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">[],</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">url</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">                    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">raw</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">{{base_url}}{{api_connection_info_path}}</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">host</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">[</span></span>
<span class="line"><span style="color: #D8DEE9FF">                        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">{{base_url}}{{api_connection_info_path}}</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                    </span><span style="color: #ECEFF4">]</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">La risposta del servizio conterrà un set d&#39;informazioni che riguardano la connessione instaurata.</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">response</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">[]</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">name</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">connection-info/user-identity</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">request</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">method</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">GET</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">header</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">[],</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">url</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">                    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">raw</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">{{base_url}}{{api_connection_user_identity}}</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">host</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">[</span></span>
<span class="line"><span style="color: #D8DEE9FF">                        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">{{base_url}}{{api_connection_user_identity}}</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                    </span><span style="color: #ECEFF4">]</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">La risposta del servizio conterrà un set d&#39;informazioni che riguardano l&#39;indentità del client che ha richiesto l&#39;accesso alla risorsa.</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">response</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">[]</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">]</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Config. 4 - Creazione della collezione Postman per mTLS.</span></div>



<p></p>



<p>All'interno della collection abbiamo utilizzato le variabili definite nell'ambiente, come per esempio <code>base_url</code>, <code>api_connection_info_path</code> e <code>api_connection_user_identity</code>.</p>



<p>Vogliamo rendere la nostra collection ancora più "smart" per il testing automatizzato! Per farlo, aggiungeremo dei test alle richieste, così ogni ambiente avrà i suoi controlli dedicati. Immagina: ogni volta che lanci la collection, Postman CLI si trasforma in un vero e proprio "detective" delle API, pronto a scovare errori e confermare che tutto funzioni come previsto. La tabella qui sotto mostra quali test saranno eseguiti per ogni richiesta, a seconda dell'ambiente attivo. Pronti a scoprire chi supera l’esame?</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Richiesta</th><th>Ambiente</th><th>Test eseguiti</th></tr></thead><tbody><tr><td>connection-info/info</td><td>local</td><td>- Status code = 403</td></tr><tr><td>connection-info/info</td><td>test</td><td>- Status code = 200- Content-Type = application/json;charset=UTF-8- certCommonName = rd.quarkus.dontesta.it</td></tr><tr><td>connection-info/user-identity</td><td>local</td><td>- Status code = 200- Content-Type = application/json;charset=UTF-8- deviceId corretto</td></tr><tr><td>connection-info/user-identity</td><td>test</td><td>- Status code = 401</td></tr></tbody></table></figure>



<p>Tabella 2 - Test automatizzati per ogni richiesta e ambiente</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><strong>Perché i test sono diversi tra gli ambienti?</strong></p>



<p>Un'attenta osservazione della Tabella 2 rivela che i test per la stessa API cambiano a seconda dell'ambiente. Qualcuno potrebbe giustamente obiettare: "I test non dovrebbero essere identici?"</p>



<p>L'obiezione è assolutamente valida, ma in questo contesto la differenza è <strong>intenzionale e strategica</strong>. Non stiamo solo verificando che l'API "funzioni", ma stiamo validando <strong>scenari di autorizzazione specifici</strong> legati ai diversi certificati client usati in ogni ambiente.</p>



<p>Come descritto nella configurazione dei certificati (<code>Config. 3</code>), ogni ambiente associa certificati client differenti alle API. Di conseguenza:</p>



<ul class="wp-block-list">
<li><strong>Ambiente <code>local</code></strong>: Per l'API <code>connection-info/info</code>, ci aspettiamo un <code>403 Forbidden</code>. Questo è un test di sicurezza "negativo": verifichiamo che un client autenticato ma <strong>non autorizzato</strong> venga correttamente respinto.</li>



<li><strong>Ambiente <code>test</code></strong>: Per la stessa API, ci aspettiamo un <code>200 OK</code>. Questo è un test "positivo": verifichiamo che un client con un certificato diverso e <strong>autorizzato</strong> ottenga l'accesso.</li>
</ul>



<p>In sintesi, sfruttiamo gli ambienti per simulare diversi profili di accesso e garantire che le regole di autorizzazione basate sui certificati siano implementate correttamente. Questo approccio va usato con le dovute considerazioni, ma in questo caso specifico è perfettamente giustificato.</p>
</blockquote>



<p>Con riferimento alla tabella precedente, possiamo ora implementare i test all'interno della nostra collezione Postman. A seguire la nuova collection a cui daremo il nome <code>quarkus-mtls-collection-with-test.json</code> e posizioneremo sempre in <code>postman-mtls/collections</code>.</p>



<p>La sezione "event" di ogni richiesta conterrà gli script per l'esecuzione dei test. Gli script di test sono scritti in JavaScript e utilizzano l'API di test di Postman. Per maggiori approfondimenti fare riferimento alla documentazione ufficiale di Postman <a href="https://learning.postman.com/docs/tests-and-scripts/write-scripts/test-scripts/">Write scripts to test API response data in Postman</a>.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="{
    &quot;info&quot;: {
        &quot;name&quot;: &quot;Quarkus mTLS&quot;,
        &quot;description&quot;: &quot;Collection Postman per il test di servizi REST protetti da un meccanismo di sicurezza di tipo mTLS.&quot;,
        &quot;schema&quot;: &quot;https://schema.getpostman.com/json/collection/v2.1.0/collection.json&quot;
    },
    &quot;item&quot;: [
        {
            &quot;name&quot;: &quot;connection-info/info&quot;,
            &quot;request&quot;: {
                &quot;method&quot;: &quot;GET&quot;,
                &quot;header&quot;: [],
                &quot;url&quot;: {
                    &quot;raw&quot;: &quot;{{base_url}}{{api_connection_info_path}}&quot;,
                    &quot;host&quot;: [
                        &quot;{{base_url}}{{api_connection_info_path}}&quot;
                    ]
                },
                &quot;description&quot;: &quot;La risposta del servizio conterrà un set d'informazioni che riguardano la connessione instaurata.&quot;
            },
            &quot;event&quot;: [
                {
                    &quot;listen&quot;: &quot;test&quot;,
                    &quot;script&quot;: {
                        &quot;type&quot;: &quot;text/javascript&quot;,
                        &quot;exec&quot;: [
                            &quot;console.log('Environment attivo:', pm.environment.get('env_name'));&quot;,
                            &quot;if (pm.environment.get('env_name') === 'local') {&quot;,
                            &quot;    pm.test('Status code is 403', function () {&quot;,
                            &quot;        pm.response.to.have.status(403);&quot;,
                            &quot;    });&quot;,
                            &quot;} else if (pm.environment.get('env_name') === 'test') {&quot;,
                            &quot;    pm.test('Status code is 200', function () {&quot;,
                            &quot;        pm.response.to.have.status(200);&quot;,
                            &quot;    });&quot;,
                            &quot;    pm.test('Content-Type is application/json', function () {&quot;,
                            &quot;        pm.response.to.have.header('Content-Type', 'application/json;charset=UTF-8');&quot;,
                            &quot;    });&quot;,
                            &quot;    pm.test('certCommonName is rd.quarkus.dontesta.it', function () {&quot;,
                            &quot;        var jsonData = pm.response.json();&quot;,
                            &quot;        pm.expect(jsonData.server.certCommonName).to.eql('rd.quarkus.dontesta.it');&quot;,
                            &quot;    });&quot;,
                            &quot;}&quot;
                        ]
                    }
                }
            ],
            &quot;response&quot;: []
        },
        {
            &quot;name&quot;: &quot;connection-info/user-identity&quot;,
            &quot;request&quot;: {
                &quot;method&quot;: &quot;GET&quot;,
                &quot;header&quot;: [],
                &quot;url&quot;: {
                    &quot;raw&quot;: &quot;{{base_url}}{{api_connection_user_identity}}&quot;,
                    &quot;host&quot;: [
                        &quot;{{base_url}}{{api_connection_user_identity}}&quot;
                    ]
                },
                &quot;description&quot;: &quot;La risposta del servizio conterrà un set d'informazioni che riguardano l'indentità del client che ha richiesto l'accesso alla risorsa.&quot;
            },
            &quot;event&quot;: [
                {
                    &quot;listen&quot;: &quot;test&quot;,
                    &quot;script&quot;: {
                        &quot;type&quot;: &quot;text/javascript&quot;,
                        &quot;exec&quot;: [
                            &quot;console.log('Environment attivo:', pm.environment.get('env_name'));&quot;,
                            &quot;if (pm.environment.get('env_name') === 'local') {&quot;,
                            &quot;    pm.test('Status code is 200', function () {&quot;,
                            &quot;        pm.response.to.have.status(200);&quot;,
                            &quot;    });&quot;,
                            &quot;    pm.test('Content-Type is application/json', function () {&quot;,
                            &quot;        pm.response.to.have.header('Content-Type', 'application/json;charset=UTF-8');&quot;,
                            &quot;    });&quot;,
                            &quot;    pm.test('deviceId is valid', function () {&quot;,
                            &quot;        var jsonData = pm.response.json();&quot;,
                            &quot;        pm.expect(jsonData.attributes.deviceId).to.eql('MTc1NzAyNTE3OTk3MDAwODAwMCM1MjQwOGJkNC1hZjQzLTQwZjYtODgxZi00YWNjOTQ4OTM3MjEjYW11c2FycmEtbWFjYm9vay1wcm8ubG9jYWwjMmVlNjA0Y2IyYzQ1Yjk0NDkwZDhmOWZiYTU4MTEwNjhkNDk1MmUwNjlkMzRmMzc0MjA5ODAzZmNjMjQ5ZWIxOA==');&quot;,
                            &quot;    });&quot;,
                            &quot;} else if (pm.environment.get('env_name') === 'test') {&quot;,
                            &quot;    pm.test('Status code is 401', function () {&quot;,
                            &quot;        pm.response.to.have.status(401);&quot;,
                            &quot;    });&quot;,
                            &quot;}&quot;
                        ]
                    }
                }
            ],
            &quot;response&quot;: []
        }
    ]
}
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">info</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">name</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Quarkus mTLS</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Collection Postman per il test di servizi REST protetti da un meccanismo di sicurezza di tipo mTLS.</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">schema</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">https://schema.getpostman.com/json/collection/v2.1.0/collection.json</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">item</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">[</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">name</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">connection-info/info</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">request</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">method</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">GET</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">header</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">[],</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">url</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">                    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">raw</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">{{base_url}}{{api_connection_info_path}}</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">host</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">[</span></span>
<span class="line"><span style="color: #D8DEE9FF">                        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">{{base_url}}{{api_connection_info_path}}</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                    </span><span style="color: #ECEFF4">]</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">La risposta del servizio conterrà un set d&#39;informazioni che riguardano la connessione instaurata.</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">event</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">[</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">                    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">listen</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">test</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">script</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">                        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">text/javascript</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">exec</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">[</span></span>
<span class="line"><span style="color: #D8DEE9FF">                            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">console.log(&#39;Environment attivo:&#39;, pm.environment.get(&#39;env_name&#39;));</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">if (pm.environment.get(&#39;env_name&#39;) === &#39;local&#39;) {</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">    pm.test(&#39;Status code is 403&#39;, function () {</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">        pm.response.to.have.status(403);</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">    });</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">} else if (pm.environment.get(&#39;env_name&#39;) === &#39;test&#39;) {</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">    pm.test(&#39;Status code is 200&#39;, function () {</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">        pm.response.to.have.status(200);</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">    });</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">    pm.test(&#39;Content-Type is application/json&#39;, function () {</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">        pm.response.to.have.header(&#39;Content-Type&#39;, &#39;application/json;charset=UTF-8&#39;);</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">    });</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">    pm.test(&#39;certCommonName is rd.quarkus.dontesta.it&#39;, function () {</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">        var jsonData = pm.response.json();</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">        pm.expect(jsonData.server.certCommonName).to.eql(&#39;rd.quarkus.dontesta.it&#39;);</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">    });</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">}</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                        </span><span style="color: #ECEFF4">]</span></span>
<span class="line"><span style="color: #D8DEE9FF">                    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">],</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">response</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">[]</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">name</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">connection-info/user-identity</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">request</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">method</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">GET</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">header</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">[],</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">url</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">                    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">raw</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">{{base_url}}{{api_connection_user_identity}}</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">host</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">[</span></span>
<span class="line"><span style="color: #D8DEE9FF">                        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">{{base_url}}{{api_connection_user_identity}}</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                    </span><span style="color: #ECEFF4">]</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">La risposta del servizio conterrà un set d&#39;informazioni che riguardano l&#39;indentità del client che ha richiesto l&#39;accesso alla risorsa.</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">event</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">[</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">                    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">listen</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">test</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">script</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">                        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">text/javascript</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">exec</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">[</span></span>
<span class="line"><span style="color: #D8DEE9FF">                            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">console.log(&#39;Environment attivo:&#39;, pm.environment.get(&#39;env_name&#39;));</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">if (pm.environment.get(&#39;env_name&#39;) === &#39;local&#39;) {</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">    pm.test(&#39;Status code is 200&#39;, function () {</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">        pm.response.to.have.status(200);</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">    });</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">    pm.test(&#39;Content-Type is application/json&#39;, function () {</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">        pm.response.to.have.header(&#39;Content-Type&#39;, &#39;application/json;charset=UTF-8&#39;);</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">    });</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">    pm.test(&#39;deviceId is valid&#39;, function () {</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">        var jsonData = pm.response.json();</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">        pm.expect(jsonData.attributes.deviceId).to.eql(&#39;MTc1NzAyNTE3OTk3MDAwODAwMCM1MjQwOGJkNC1hZjQzLTQwZjYtODgxZi00YWNjOTQ4OTM3MjEjYW11c2FycmEtbWFjYm9vay1wcm8ubG9jYWwjMmVlNjA0Y2IyYzQ1Yjk0NDkwZDhmOWZiYTU4MTEwNjhkNDk1MmUwNjlkMzRmMzc0MjA5ODAzZmNjMjQ5ZWIxOA==&#39;);</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">    });</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">} else if (pm.environment.get(&#39;env_name&#39;) === &#39;test&#39;) {</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">    pm.test(&#39;Status code is 401&#39;, function () {</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">        pm.response.to.have.status(401);</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">    });</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">}</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                        </span><span style="color: #ECEFF4">]</span></span>
<span class="line"><span style="color: #D8DEE9FF">                    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">],</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">response</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">[]</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">]</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Config. 5 - Aggiunta di test alla collection Postman</span></div>



<p></p>



<p>Ottimo lavoro! Ora che tutte le configurazioni sono pronte (ambienti, certificati e collection Postman sia con che senza test), siamo davvero a un passo dall'esecuzione pratica delle collection. Manca solo l’ultimo step: vedere tutto in azione!</p>



<h2 class="wp-block-heading" id="esecuzione-della-collection-con-postman-cli">Esecuzione della collection con Postman CLI</h2>



<p>Arrivati a questo punto, la struttura del nostro progetto dovrebbe essere simile a quella indicata a seguire.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="postman-mtls/
├── certificates
│   ├── ca
│   │   └── ca_cert.pem
│   └── client
│       ├── client_new_device_id_cert.pem
│       ├── client_new_device_id_key.pem
│       ├── client_new_device_id_key.pem.password
│       ├── client_with_device_id_and_roles_1_cert.pem
│       ├── client_with_device_id_and_roles_1_key.pem
│       ├── client_with_device_id_and_roles_1_key.pem.password
│       ├── client_with_device_id_and_roles_cert.pem
│       ├── client_with_device_id_and_roles_key.pem
│       └── client_with_device_id_and_roles_key.pem.password
├── collections
│   ├── quarkus-mtls-collection-with-test.json
│   └── quarkus-mtls-collection.json
└── config
    ├── certificates
    │   └── client-certificates.json
    └── environments
        ├── local.json
        └── test.json
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #d8dee9ff">postman-mtls/</span></span>
<span class="line"><span style="color: #d8dee9ff">├── certificates</span></span>
<span class="line"><span style="color: #d8dee9ff">│   ├── ca</span></span>
<span class="line"><span style="color: #d8dee9ff">│   │   └── ca_cert.pem</span></span>
<span class="line"><span style="color: #d8dee9ff">│   └── client</span></span>
<span class="line"><span style="color: #d8dee9ff">│       ├── client_new_device_id_cert.pem</span></span>
<span class="line"><span style="color: #d8dee9ff">│       ├── client_new_device_id_key.pem</span></span>
<span class="line"><span style="color: #d8dee9ff">│       ├── client_new_device_id_key.pem.password</span></span>
<span class="line"><span style="color: #d8dee9ff">│       ├── client_with_device_id_and_roles_1_cert.pem</span></span>
<span class="line"><span style="color: #d8dee9ff">│       ├── client_with_device_id_and_roles_1_key.pem</span></span>
<span class="line"><span style="color: #d8dee9ff">│       ├── client_with_device_id_and_roles_1_key.pem.password</span></span>
<span class="line"><span style="color: #d8dee9ff">│       ├── client_with_device_id_and_roles_cert.pem</span></span>
<span class="line"><span style="color: #d8dee9ff">│       ├── client_with_device_id_and_roles_key.pem</span></span>
<span class="line"><span style="color: #d8dee9ff">│       └── client_with_device_id_and_roles_key.pem.password</span></span>
<span class="line"><span style="color: #d8dee9ff">├── collections</span></span>
<span class="line"><span style="color: #d8dee9ff">│   ├── quarkus-mtls-collection-with-test.json</span></span>
<span class="line"><span style="color: #d8dee9ff">│   └── quarkus-mtls-collection.json</span></span>
<span class="line"><span style="color: #d8dee9ff">└── config</span></span>
<span class="line"><span style="color: #d8dee9ff">    ├── certificates</span></span>
<span class="line"><span style="color: #d8dee9ff">    │   └── client-certificates.json</span></span>
<span class="line"><span style="color: #d8dee9ff">    └── environments</span></span>
<span class="line"><span style="color: #d8dee9ff">        ├── local.json</span></span>
<span class="line"><span style="color: #d8dee9ff">        └── test.json</span></span>
<span class="line"><span style="color: #d8dee9ff"></span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Console 4 - Struttura del progetto</span></div>



<p></p>



<p>Prima di eseguire le collection con Postman CLI, è importante assicurarsi che tutte le configurazioni siano corrette e che i certificati siano stati generati e posizionati nei percorsi appropriati.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><strong>Importante</strong>: prima di eseguire i test, assicurati che il progetto <a href="https://github.com/amusarra/quarkus-mtls-auth">quarkus-mtls-auth</a> sia avviato e che le API siano in ascolto sulla porta 8443 (come configurato negli ambienti local e test).<br>Puoi trovare le istruzioni dettagliate nella sezione <a href="https://github.com/amusarra/quarkus-mtls-auth?tab=readme-ov-file#quickstart">Quickstart</a> del repository, dove viene spiegato come avviare il servizio tramite Docker o Podman. Ecco un esempio pratico:</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# Scarica l'immagine aggiornata da Docker Hub
podman pull amusarra/quarkus-mtls-auth:latest

# Avvia il container sulla porta 8443
podman run -p 8443:8443 amusarra/quarkus-mtls-auth:latest
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88"># Scarica l&#39;immagine aggiornata da Docker Hub</span></span>
<span class="line"><span style="color: #88C0D0">podman</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">pull</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">amusarra/quarkus-mtls-auth:latest</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Avvia il container sulla porta 8443</span></span>
<span class="line"><span style="color: #88C0D0">podman</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">run</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-p</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">8443</span><span style="color: #A3BE8C">:8443</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">amusarra/quarkus-mtls-auth:latest</span></span>
<span class="line"></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Bash</span></div>
</blockquote>



<p>Per eseguire le collection con Postman CLI, si utilizza il comando <code>postman collection run</code> specificando il percorso della collection, il file di ambiente tramite l'opzione <code>--environment</code>, il file di configurazione dei certificati tramite l'opzione <code>--ssl-client-cert-list</code>.</p>



<p>Nel nostro caso specifichiamo anche l'opzione <code>--ssl-extra-ca-certs</code>. Questa opzione permette di specificare un file PEM contenente i certificati delle CA che Postman CLI utilizzerà per verificare il certificato del server. Questo è particolarmente utile quando si lavora con server che utilizzano certificati autofirmati o emessi da una CA privata evitando il classico errore: unable to verify the first certificate.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>Il file <code>certificates/ca/ca_cert.pem</code> deve contenere il certificato della CA utilizzata per firmare il certificato del server. Può essere anche un bundle di certificati CA.</p>
</blockquote>



<p>Ecco il comando base per eseguire una collection con Postman CLI usando environment e certificati.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# Comando base per l'esecuzione della collection
# Sostituisci i segnaposto con i valori appropriati
postman collection run collections/.json \
    --environment config/environments/.json \
    --ssl-client-cert-list config/certificates/.json \
    --ssl-extra-ca-certs certificates/ca/.pem
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88"># Comando base per l&#39;esecuzione della collection</span></span>
<span class="line"><span style="color: #616E88"># Sostituisci i segnaposto con i valori appropriati</span></span>
<span class="line"><span style="color: #88C0D0">postman</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">collection</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">run</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">collections/.json</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--environment</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">config/environments/.json</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--ssl-client-cert-list</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">config/certificates/.json</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--ssl-extra-ca-certs</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">certificates/ca/.pem</span></span>
<span class="line"></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Console 4 - Esecuzione della collection con Postman CLI</span></div>



<p></p>



<p>A seguire una serie di comandi (completi) per eseguire le collection che abbiamo creato in precedenza e sui relativi ambienti: local e test.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# Esecuzione della collection senza test per l'ambiente local
postman collection run collections/quarkus-mtls-collection.json \
    --environment config/environments/local.json \
    --ssl-client-cert-list config/certificates/client-certificates.json \
    --ssl-extra-ca-certs certificates/ca/ca_cert.pem

# Esecuzione della collection con test per l'ambiente local
postman collection run collections/quarkus-mtls-collection-with-test.json \
    --environment config/environments/local.json \
    --ssl-client-cert-list config/certificates/client-certificates.json \
    --ssl-extra-ca-certs certificates/ca/ca_cert.pem

# Esecuzione della collection senza test per l'ambiente test
postman collection run collections/quarkus-mtls-collection.json \
    --environment config/environments/test.json \
    --ssl-client-cert-list config/certificates/client-certificates.json \
    --ssl-extra-ca-certs certificates/ca/ca_cert.pem

# Esecuzione della collection con test per l'ambiente test
postman collection run collections/quarkus-mtls-collection-with-test.json \
    --environment config/environments/test.json \
    --ssl-client-cert-list config/certificates/client-certificates.json \
    --ssl-extra-ca-certs certificates/ca/ca_cert.pem
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88"># Esecuzione della collection senza test per l&#39;ambiente local</span></span>
<span class="line"><span style="color: #88C0D0">postman</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">collection</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">run</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">collections/quarkus-mtls-collection.json</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--environment</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">config/environments/local.json</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--ssl-client-cert-list</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">config/certificates/client-certificates.json</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--ssl-extra-ca-certs</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">certificates/ca/ca_cert.pem</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Esecuzione della collection con test per l&#39;ambiente local</span></span>
<span class="line"><span style="color: #88C0D0">postman</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">collection</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">run</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">collections/quarkus-mtls-collection-with-test.json</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--environment</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">config/environments/local.json</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--ssl-client-cert-list</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">config/certificates/client-certificates.json</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--ssl-extra-ca-certs</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">certificates/ca/ca_cert.pem</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Esecuzione della collection senza test per l&#39;ambiente test</span></span>
<span class="line"><span style="color: #88C0D0">postman</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">collection</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">run</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">collections/quarkus-mtls-collection.json</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--environment</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">config/environments/test.json</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--ssl-client-cert-list</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">config/certificates/client-certificates.json</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--ssl-extra-ca-certs</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">certificates/ca/ca_cert.pem</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Esecuzione della collection con test per l&#39;ambiente test</span></span>
<span class="line"><span style="color: #88C0D0">postman</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">collection</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">run</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">collections/quarkus-mtls-collection-with-test.json</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--environment</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">config/environments/test.json</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--ssl-client-cert-list</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">config/certificates/client-certificates.json</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--ssl-extra-ca-certs</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">certificates/ca/ca_cert.pem</span></span>
<span class="line"></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Console 5 - Esempi di esecuzione della collection con e senza test per l'ambiente local e test</span></div>



<p></p>



<p>La figura mostra l'output della Postman CLI durante l'esecuzione della collection con test sull'ambiente di test. Si evidenziano i risultati dei test automatici sulle richieste, lo stato delle asserzioni, il dettaglio delle risposte HTTP ricevute e le statistiche di esecuzione (numero di richieste, test eseguiti, tempo medio di risposta, dati ricevuti, ecc.). Questo tipo di output consente di verificare rapidamente il successo dei test e la correttezza della configurazione mTLS.</p>



<figure class="wp-block-image size-large is-resized"><img decoding="async" loading="lazy" src=" https://github.com/amusarra/quarkus-mtls-auth/raw/8332053f755e8880ad0e84f21f56785aee2c1049/src/main/docs/markdown/article/resources/images/postman_cli_output_env_test_collection_with_test_result_OK.jpg" alt="Esecuzione della collection con test per l'ambiente test" style="aspect-ratio:1;width:864px;height:auto"/><figcaption class="wp-element-caption">Figura 1 - Esecuzione della collection con test per l'ambiente test</figcaption></figure>



<p></p>



<p>Nel caso in cui volessimo ottenere più informazioni in output come per esempio i dettagli delle richieste e delle risposte, possiamo utilizzare l'opzione <code>--verbose</code>.</p>



<figure class="wp-block-image size-large"><img decoding="async" loading="lazy" src="https://github.com/amusarra/quarkus-mtls-auth/raw/refs/heads/main/src/main/docs/markdown/article/resources/images/postman_cli_output_env_test_collection_with_test_result_verbose.jpg" alt="Esecuzione dettagliata della collection con opzione verbose"/><figcaption class="wp-element-caption">Figura 2 - Output dettagliato della collection con l'opzione <code>--verbose</code></figcaption></figure>



<p></p>



<p>La Figura 2 mostra un esempio di output ottenuto con l'opzione <code>--verbose</code> abilitata. In questo caso vengono visualizzati ulteriori dettagli sulle richieste HTTP, sulle risposte ricevute, sulle intestazioni, sui tempi di handshake TLS e sulle statistiche di trasferimento dati. Questo livello di dettaglio è utile per il troubleshooting e per analizzare il comportamento della comunicazione mTLS tra client e server.</p>



<p>Le due immagini seguenti mostrano il caso in cui i test automatizzati sull'endpoint <code>/api/v1/connection-info/info</code> falliscono.</p>



<figure class="wp-block-image size-large"><img decoding="async" loading="lazy" src="https://github.com/amusarra/quarkus-mtls-auth/raw/refs/heads/main/src/main/docs/markdown/article/resources/images/postman_cli_output_env_test_collection_with_test_result_verbose.jpg" alt="Riepilogo esecuzione collection con test falliti"/><figcaption class="wp-element-caption">Figura 3 - Riepilogo esecuzione collection con test falliti</figcaption></figure>



<p></p>



<p>La <strong>prima immagine</strong> evidenzia il riepilogo dell'esecuzione della collection. È mostrato il numero totale di richieste, test-script e asserzioni eseguite, con il dettaglio degli errori. In questo esempio, 3 asserzioni sono fallite:</p>



<ul class="wp-block-list">
<li>Il test sullo status code atteso (200) ha fallito perché la risposta è stata 403 Forbidden.</li>



<li>Il test sulla presenza dell'header <code>Content-Type</code> con valore <code>application/json</code> non è stato superato.</li>



<li>Il test sul valore dell'attributo <code>certCommonName</code> nel JSON di risposta non è stato eseguito correttamente a causa di input vuoto (nessun body JSON restituito).</li>
</ul>



<figure class="wp-block-image size-large"><img decoding="async" loading="lazy" src="https://github.com/amusarra/quarkus-mtls-auth/raw/refs/heads/main/src/main/docs/markdown/article/resources/images/postman_cli_output_env_test_collection_with_test_result_FAIL_verbose.jpg" alt="Dettaglio richiesta/risposta con test falliti"/><figcaption class="wp-element-caption">Figura 4 - Dettaglio richiesta/risposta con test falliti</figcaption></figure>



<p></p>



<p>La <strong>seconda immagine</strong> mostra il dettaglio della richiesta e della risposta. Si vede la richiesta GET verso l'endpoint <code>/api/v1/connection-info/info</code> sull'ambiente di test, che restituisce HTTP 403 Forbidden. Sono riportati i tempi di preparazione, handshake TLS, download e processing.  </p>



<p>È anche mostrato l'output degli script di test, con il dettaglio delle asserzioni fallite (status code, content-type, valore certCommonName), confermando che la risposta non soddisfa i criteri attesi dai test automatizzati.</p>



<p>Queste schermate aiutano a diagnosticare rapidamente i motivi del fallimento dei test e a individuare eventuali problemi di configurazione, autorizzazione o formato della risposta dell'API.</p>



<h2 class="wp-block-heading" id="verifica-tramite-exit-code">Verifica tramite exit code</h2>



<p>Quando si esegue una collection con Postman CLI, il comando restituisce un <strong>exit code</strong> che permette di verificare rapidamente se l'esecuzione è andata a buon fine:</p>



<ul class="wp-block-list">
<li><strong>Exit code 0</strong>: tutti i test sono passati con successo.</li>



<li><strong>Exit code diverso da 0</strong>: almeno un test è fallito oppure si è verificato un errore durante l'esecuzione.</li>
</ul>



<p>Questo comportamento consente di integrare facilmente Postman CLI in pipeline di Continuous Integration/Continuous Delivery (CI/CD) o script di automazione, gestendo il flusso in base al risultato dei test.</p>



<p>Esempio di verifica in bash:</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="postman collection run collections/quarkus-mtls-collection-with-test.json \
    --environment config/environments/test.json \
    --ssl-client-cert-list config/certificates/client-certificates.json \
    --ssl-extra-ca-certs certificates/ca/ca_cert.pem

if [ $? -eq 0 ]; then
    echo &quot;Tutti i test sono passati correttamente.&quot;
else
    echo &quot;Alcuni test sono falliti o si è verificato un errore.&quot;
fi
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">postman</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">collection</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">run</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">collections/quarkus-mtls-collection-with-test.json</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--environment</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">config/environments/test.json</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--ssl-client-cert-list</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">config/certificates/client-certificates.json</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--ssl-extra-ca-certs</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">certificates/ca/ca_cert.pem</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">[</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">$?</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-eq</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">]</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">then</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">echo</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Tutti i test sono passati correttamente.</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #81A1C1">else</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">echo</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Alcuni test sono falliti o si è verificato un errore.</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #81A1C1">fi</span></span>
<span class="line"></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Console 6 - Verifica del buon fine tramite exit code</span></div>



<p></p>



<h2 class="wp-block-heading" id="integrazione-di-postman-cli-in-pipeline-cicd">Integrazione di Postman CLI in pipeline CI/CD</h2>



<p>L'automazione dei test mTLS tramite Postman CLI può essere facilmente integrata in pipeline di CI/CD, come quelle basate su GitHub Actions, GitLab CI, Jenkins, Azure DevOps, ecc.</p>



<h3 class="wp-block-heading" id="esempio-di-utilizzo-in-github-actions">Esempio di utilizzo in GitHub Actions</h3>



<p>Di seguito un esempio di step che esegue una collection Postman e verifica il risultato tramite l'exit code:</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="...
- name: Install Postman CLI
  run: |
    curl -o- &quot;https://dl-cli.pstmn.io/install/linux64.sh&quot; | sh

- name: Run Postman Collection and Generate Report for local environment
  run: |
    postman collection run collections/quarkus-mtls-collection-with-test.json \
    --environment config/environments/local.json \
    --ssl-client-cert-list config/certificates/client-certificates.json \
    --ssl-extra-ca-certs certificates/ca/ca_cert.pem \
    --verbose \
    --reporters html,cli \
    --reporter-html-export postman_report_local.html
...
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">...</span></span>
<span class="line"><span style="color: #88C0D0">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">name:</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Install</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Postman</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">CLI</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">run:</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">|</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">curl</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-o-</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">https://dl-cli.pstmn.io/install/linux64.sh</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">sh</span></span>
<span class="line"></span>
<span class="line"><span style="color: #88C0D0">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">name:</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Run</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Postman</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Collection</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">and</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Generate</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Report</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">for</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">local</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">environment</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">run:</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">|</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">postman</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">collection</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">run</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">collections/quarkus-mtls-collection-with-test.json</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--environment</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">config/environments/local.json</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--ssl-client-cert-list</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">config/certificates/client-certificates.json</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--ssl-extra-ca-certs</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">certificates/ca/ca_cert.pem</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--verbose</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--reporters</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">html,cli</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--reporter-html-export</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">postman_report_local.html</span></span>
<span class="line"><span style="color: #88C0D0">...</span></span>
<span class="line"></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">GitHub Actions 1 - Esempio di step per installare ed eseguire Postman CLI</span></div>



<p></p>



<p>Se uno o più test falliscono, lo step viene marcato come failed e la pipeline si interrompe, garantendo che solo il codice che supera tutti i test venga distribuito.</p>



<h3 class="wp-block-heading" id="quando-lerrore-è-il-nostro-migliore-amico">Quando l'errore è il nostro migliore amico</h3>



<p>Ecco il bello dell'automazione: quando la GitHub Action fallisce, come mostrato nell'immagine a seguire, non è solo una "X" rossa che ci fa storcere il naso. In realtà, quell'errore è stato fondamentale: ci ha subito segnalato che il certificato del servizio (REST API) era scaduto e che le richieste mTLS non potevano andare a buon fine. Meglio scoprirlo ora, in fase di test, che in produzione davanti agli utenti!</p>



<figure class="wp-block-image size-large"><img decoding="async" loading="lazy" src="https://github.com/amusarra/quarkus-mtls-auth/raw/refs/heads/main/src/main/docs/markdown/article/resources/images/github_action_failed_due_to_expired_certificate.jpg" alt="GitHub Action fallita a causa di certificato scaduto"/><figcaption class="wp-element-caption">Figura 5 - GitHub Action fallita a causa di certificato scaduto</figcaption></figure>



<p></p>



<p>Insomma, il fallimento della pipeline è stato un vero alleato: ci ha permesso di intervenire tempestivamente, aggiornare i certificati e garantire la sicurezza e l'affidabilità del servizio. Ricorda: ogni errore ben evidenziato è un passo avanti verso un sistema più robusto!</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>Probabilmente senza questi test automatici non mi sarei mai accorto del certificato scaduto e avrei pubblicato la guida con un bel bug, lasciando il lettore a chiedersi perché non funzionasse nulla!<br>Ecco perché i test sono i veri supereroi delle guide tecniche: ti salvano la reputazione prima ancora che tu prema "pubblica"! <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f604.png" alt="😄" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
</blockquote>



<h3 class="wp-block-heading" id="vantaggi-dellintegrazione">Vantaggi dell'integrazione</h3>



<ul class="wp-block-list">
<li><strong>Automazione completa</strong>: i test mTLS vengono eseguiti automaticamente ad ogni commit, merge o rilascio.</li>



<li><strong>Feedback immediato</strong>: eventuali errori di configurazione, autenticazione o regressioni vengono rilevati subito.</li>



<li><strong>Reportistica</strong>: è possibile esportare report HTML e allegarli agli artefatti della pipeline per una consultazione rapida.</li>



<li><strong>Sicurezza</strong>: si garantisce che le API protette da mTLS siano sempre testate e funzionanti prima della messa in produzione.</li>
</ul>



<p>L'immagine seguente mostra l'esecuzione di Postman CLI in una GitHub Actions, con il riepilogo dei risultati e i report HTML generati come artefatti. Questa integrazione semplifica e automatizza la validazione delle API mTLS nei workflow DevOps.</p>



<figure class="wp-block-image size-large"><img decoding="async" loading="lazy" src="https://github.com/amusarra/quarkus-mtls-auth/raw/refs/heads/main/src/main/docs/markdown/article/resources/images/github_action_artifact_and_summary.jpg" alt="Esecuzione di Postman CLI in GitHub Actions - Summary"/><figcaption class="wp-element-caption">Figura 6 - Esecuzione di Postman CLI in GitHub Actions - Summary</figcaption></figure>



<p></p>



<p>Di seguito un esempio di report HTML generato da Postman CLI usando l'opzione <code>--reporters html</code>.</p>



<figure class="wp-block-image size-large"><img decoding="async" loading="lazy" src="https://github.com/amusarra/quarkus-mtls-auth/raw/refs/heads/main/src/main/docs/markdown/article/resources/images/postman_cli_html_report_overview.jpg" alt="Esempio di report HTML generato da Postman CLI - Summary"/><figcaption class="wp-element-caption">Figura 7 - Report HTML generato da Postman CLI - Summary</figcaption></figure>



<p></p>



<figure class="wp-block-image size-large"><img decoding="async" loading="lazy" src="https://github.com/amusarra/quarkus-mtls-auth/raw/refs/heads/main/src/main/docs/markdown/article/resources/images/postman_cli_html_report_detail_request_1.jpg" alt="Esempio di report HTML generato da Postman CLI - Dettaglio richieste"/><figcaption class="wp-element-caption">Figura 8 - Report HTML generato da Postman CLI - Dettaglio richieste</figcaption></figure>



<p></p>



<p>Questo report mostra in modo grafico e dettagliato lo stato delle richieste, i test eseguiti, le asserzioni superate e fallite, i tempi di risposta e tutte le informazioni utili per la validazione automatica delle API mTLS.</p>



<h2 class="wp-block-heading" id="conclusioni">Conclusioni</h2>



<p>In questa guida abbiamo visto come configurare e utilizzare Postman CLI per testare endpoint protetti da mTLS, sfruttando ambienti, variabili e certificati client multipli.</p>



<p>Abbiamo imparato a:</p>



<ul class="wp-block-list">
<li>Organizzare la struttura di progetto per Postman CLI.</li>



<li>Definire ambienti e variabili per gestire facilmente configurazioni diverse.</li>



<li>Configurare e selezionare certificati client in modo centralizzato tramite file JSON.</li>



<li>Creare collection Postman con test automatizzati che variano in base all'ambiente.</li>



<li>Eseguire le collection da CLI, verificare il risultato tramite exit code e generare report HTML.</li>



<li>Integrare i test mTLS in pipeline CI/CD per garantire la qualità e la sicurezza delle API.</li>
</ul>



<p>Questi strumenti e procedure ci permettono di automatizzare e rendere ripetibile la validazione di API protette da mTLS, migliorando la produttività e la robustezza dei processi di sviluppo e delivery.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><strong>Curiosità:</strong> Postman è sicuramente uno degli strumenti più diffusi per il testing delle API, ma il panorama offre anche valide alternative, alcune delle quali completamente offline e open source. Se sei curioso di scoprire nuovi strumenti, dai un'occhiata anche a Bruno, Hoppscotch e altri client API: potresti trovare la soluzione perfetta per le tue esigenze! Ti consiglio di leggere anche l'articolo <a href="https://theredcode.it/devops/bruno-vs-postman-api-client/">"Bruno vs Postman: un client API offline"</a> scritto da <a href="https://www.linkedin.com/in/serena-sensini/">Serena Sensini</a> e pubblicato su TheRedCode, per approfondire le differenze e scoprire nuove possibilità.</p>
</blockquote>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f381.png" alt="🎁" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Premio per aver seguito la guida fino a qui!</strong></p>



<p>Trovi l'intero progetto pronto all'uso su GitHub:<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f449.png" alt="👉" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <a href="https://github.com/amusarra/postman-mtls">https://github.com/amusarra/postman-mtls</a></p>



<p>Nel repository troverai tutte le configurazioni, gli script, le collection Postman, i certificati di esempio, la GitHub Actions di esempio e molto altro. Puoi clonare il progetto, adattarlo alle tue esigenze e iniziare subito a testare API protette da mTLS con Postman CLI.</p>



<h2 class="wp-block-heading" id="risorse-utili">Risorse utili</h2>



<p>Ecco una raccolta di risorse e riferimenti utili per approfondire i temi trattati nella guida:</p>



<h3 class="wp-block-heading" id="postman">Postman</h3>



<ul class="wp-block-list">
<li><a href="https://learning.postman.com/docs/postman-cli/postman-cli-overview/">Documentazione ufficiale Postman CLI</a></li>



<li><a href="https://learning.postman.com/docs/postman-cli/postman-cli-installation/">Installazione Postman CLI</a></li>



<li><a href="https://learning.postman.com/docs/sending-requests/variables/managing-environments/">Gestione ambienti in Postman</a></li>



<li><a href="https://learning.postman.com/docs/sending-requests/authorization/certificates/">Gestione certificati in Postman</a></li>



<li><a href="https://learning.postman.com/docs/tests-and-scripts/write-scripts/test-scripts/">Scrivere test in Postman</a></li>



<li><a href="https://learning.postman.com/docs/postman-cli/postman-cli-reporters/">Report con Postman CLI</a></li>
</ul>



<h3 class="wp-block-heading" id="github">GitHub</h3>



<ul class="wp-block-list">
<li><a href="https://github.com/amusarra/quarkus-mtls-auth?tab=readme-ov-file#quickstart">Quickstart quarkus-mtls-auth</a></li>



<li><a href="https://github.com/amusarra/postman-mtls">Repository di esempio: postman-mtls</a></li>



<li><a href="https://docs.github.com/en/actions">GitHub Actions Documentation</a></li>
</ul>



<h3 class="wp-block-heading" id="articoli-e-guide">Articoli e Guide</h3>



<ul class="wp-block-list">
<li><a href="https://www.dontesta.it/2024/09/19/implementazione-tls-mutual-authentication-mtls-con-quarkus/">Implementazione di TLS Mutual Authentication (mTLS) con Quarkus</a> - pubblicato sul blog di <a href="https://www.dontesta.it">Antonio Musarra</a></li>



<li><a href="https://open.spotify.com/episode/1vbl5exIO4m8Cekw9vwLeZ?si=a794bebee20c42a8">Autenticazione mTLS con Quarkus</a> - pubblicato sul podcast di Antonio Musarra</li>



<li><a href="https://www.dontesta.it/2020/02/25/liferay-7-2-esempio-di-two-way-ssl-tls-mutual-authentication-client/">Liferay 7.2: Esempio di Two-Way SSL/TLS Mutual Authentication Client</a> - pubblicato sul blog di <a href="https://www.dontesta.it">Antonio Musarra</a></li>



<li><a href="https://www.dontesta.it/2025/05/18/rabbitmq-4-1-mtls-e-amqp-1-0-guida-essenziale-per-sviluppatori/">RabbitMQ 4.1 mTLS e AMQP 1.0: Guida essenziale per sviluppatori</a> - pubblicato sul blog di <a href="https://www.dontesta.it">Antonio Musarra</a></li>
</ul>



<h3 class="wp-block-heading" id="wikipedia">Wikipedia</h3>



<ul class="wp-block-list">
<li><a href="https://en.wikipedia.org/wiki/Mutual_authentication">Mutual TLS (Wikipedia)</a></li>



<li><a href="https://en.wikipedia.org/wiki/Certificate_authority">Certificate Authority (Wikipedia)</a></li>



<li><a href="https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail">Privacy Enhanced Mail (PEM)</a></li>
</ul>



<h3 class="wp-block-heading" id="altre-risorse">Altre Risorse</h3>



<ul class="wp-block-list">
<li><a href="https://www.openssl.org/docs/manmaster/man1/openssl-s_client.html">Debug TLS/SSL con OpenSSL</a></li>
</ul>



<p>Queste risorse ti aiuteranno ad approfondire la configurazione, l'automazione e il troubleshooting di mTLS e Postman CLI.</p>
<p>L'articolo <a href="https://www.dontesta.it/2025/09/09/guida-avanzata-mtls-con-postman-cli-ambienti-e-certificati-multipli/">Guida Avanzata: mTLS con Postman CLI, Ambienti e Certificati Multipli</a> sembra essere il primo su <a href="https://www.dontesta.it">Antonio Musarra&#039;s Blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.dontesta.it/2025/09/09/guida-avanzata-mtls-con-postman-cli-ambienti-e-certificati-multipli/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>RabbitMQ 4.1 mTLS e AMQP 1.0: Guida essenziale per sviluppatori</title>
		<link>https://www.dontesta.it/2025/05/18/rabbitmq-4-1-mtls-e-amqp-1-0-guida-essenziale-per-sviluppatori/</link>
					<comments>https://www.dontesta.it/2025/05/18/rabbitmq-4-1-mtls-e-amqp-1-0-guida-essenziale-per-sviluppatori/#respond</comments>
		
		<dc:creator><![CDATA[Antonio Musarra]]></dc:creator>
		<pubDate>Sun, 18 May 2025 08:17:32 +0000</pubDate>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Protocol]]></category>
		<category><![CDATA[Security]]></category>
		<guid isPermaLink="false">https://www.dontesta.it/?p=5918</guid>

					<description><![CDATA[<p>Nello sviluppo software moderno, in particolare con architetture a microservizi o event-driven, i message broker come RabbitMQ rivestono un ruolo fondamentale. Garantire una comunicazione sicura con il broker e un ambiente di sviluppo quanto&#46;&#46;&#46;</p>
<p>L'articolo <a href="https://www.dontesta.it/2025/05/18/rabbitmq-4-1-mtls-e-amqp-1-0-guida-essenziale-per-sviluppatori/">RabbitMQ 4.1 mTLS e AMQP 1.0: Guida essenziale per sviluppatori</a> sembra essere il primo su <a href="https://www.dontesta.it">Antonio Musarra&#039;s Blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Nello sviluppo software moderno, in particolare con architetture a microservizi o event-driven, i message broker come <a href="https://www.rabbitmq.com/">RabbitMQ</a> rivestono un ruolo fondamentale. Garantire una comunicazione sicura con il broker e un ambiente di sviluppo quanto più simile possibile a quello di produzione è fondamentale per ridurre problemi in fase di deployment.</p>



<p>Questo articolo ti guiderà passo dopo passo nella configurazione di RabbitMQ 4.1 con Mutual TLS (mTLS) per comunicazioni sicure bidirezionali e con il supporto al protocollo <a href="https://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-overview-v1.0-os.html">AMQP 1.0</a>, il tutto gestito tramite Podman. Implementeremo un esempio pratico in Python utilizzando la libreria <a href="https://qpid.apache.org/proton/index.html">Qpid Proton</a>.</p>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f3a7.png" alt="🎧" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Preferisci ascoltare?</strong> Questo articolo è accompagnato da un episodio podcast dedicato che approfondisce gli stessi argomenti. Ascoltalo qui: <a href="https://spotifycreators-web.app.link/e/wfx728cUsTb">RabbitMQ 4.1 mTLS e AMQP 1.0 - Approfondimento Podcast</a></p>



<p>Con mTLS, sia il server RabbitMQ che i client (producer e consumer) si autenticano reciprocamente utilizzando certificati digitali. Questo rafforza ulteriormente la sicurezza rispetto al TLS standard, dove solo il client verifica il server. Utilizzeremo nomi di dominio completi (FQDN - Fully Qualified Domain Name) e <a href="https://en.wikipedia.org/wiki/Subject_Alternative_Name">Subject Alternative Names (SAN)</a> per i certificati TLS server e certificati client dedicati, tutti firmati dalla stessa Certificate Authority (CA).</p>



<p>Per chi volesse seguire passo passo e avere a disposizione tutto il codice sorgente, gli script e il Makefile descritti in questa guida, il progetto completo è disponibile su GitHub: <a href="https://github.com/amusarra/rabbitmq-mtls-poc">https://github.com/amusarra/rabbitmq-mtls-poc</a></p>



<h2 class="wp-block-heading" id="perché-questa-configurazione-è-importante">Perché questa configurazione è importante?</h2>



<p>Configurare mTLS fin dall'ambiente di sviluppo ti permette di:</p>



<ol class="wp-block-list">
<li>Massima sicurezza: Autenticazione reciproca tra client e server.</li>



<li>Individuare problemi di sicurezza in anticipo: Non rimandare la sicurezza all'ultimo minuto.</li>



<li>Abituarsi alle configurazioni reali: Meno sorprese durante il deploy in produzione.</li>



<li>Testare end-to-end in modo realistico: Comprendere l'impatto di mTLS e delle configurazioni di rete.</li>



<li>Utilizzare protocolli moderni: AMQP 1.0 offre interoperabilità e funzionalità avanzate.</li>
</ol>



<h2 class="wp-block-heading" id="prerequisiti">Prerequisiti</h2>



<p>Prima di iniziare, assicurati di avere installato:</p>



<ol class="wp-block-list">
<li>Make (versione &gt;= 3.8): Per la gestione del progetto e l'automazione delle operazioni.</li>



<li>Podman (versione &gt; 5.x): Per la gestione dei container.</li>



<li>OpenSSL (versione &gt;= 3.3): Per la generazione dei certificati TLS.</li>



<li>Python 3 (versione &gt;= 3.12): Per gli script di producer e consumer.</li>



<li>Librerie Python <code>python-qpid-proton</code> e <code>python-dotenv</code> che puoi installare con il comando <code>pip install python-qpid-proton python-dotenv</code>.</li>



<li>Possibilità di modificare il file <code>/etc/hosts</code> per la risoluzione del FQDN locale.</li>
</ol>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><strong>Nota:</strong> Il progetto collegato a questo articolo è stato realizzato e testato su un sistema macOS 15.4.1 24E263 arm64, ma dovrebbe funzionare anche su distribuzioni Linux. Se hai bisogno di aiuto per l'installazione di Podman o OpenSSL, puoi consultare la documentazione ufficiale o chiedere supporto. </p>
</blockquote>



<h2 class="wp-block-heading" id="struttura-del-progetto">Struttura del Progetto</h2>



<p>Il progetto è organizzato per facilitare la gestione di certificati, configurazioni e script di esempio, in modo che tu possa rapidamente avviare un ambiente RabbitMQ sicuro e testare producer/consumer scritti in questo caso in Python.</p>



<p>Ecco una panoramica della struttura tipica del repository:</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="rabbitmq-mtls-poc/
├── certs/
├── rabbitmq_config/
│   └── rabbitmq.conf
└── scripts/
    ├── producer.py
    └── consumer.py
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #d8dee9ff">rabbitmq-mtls-poc/</span></span>
<span class="line"><span style="color: #d8dee9ff">├── certs/</span></span>
<span class="line"><span style="color: #d8dee9ff">├── rabbitmq_config/</span></span>
<span class="line"><span style="color: #d8dee9ff">│   └── rabbitmq.conf</span></span>
<span class="line"><span style="color: #d8dee9ff">└── scripts/</span></span>
<span class="line"><span style="color: #d8dee9ff">    ├── producer.py</span></span>
<span class="line"><span style="color: #d8dee9ff">    └── consumer.py</span></span>
<span class="line"><span style="color: #d8dee9ff"></span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Plaintext</span></div>



<p></p>



<p><strong>Descrizione delle principali cartelle e file:</strong></p>



<ul class="wp-block-list">
<li><code>certs/</code>: Contiene tutti i certificati e le chiavi generate per mTLS. Questa directory è creata automaticamente dal Makefile.</li>



<li><code>rabbitmq_config/</code>: Contiene il file di configurazione di RabbitMQ (<code>rabbitmq.conf</code>) con le impostazioni per mTLS.</li>



<li><code>scripts/</code>: Contiene gli script di esempio Python per il producer e il consumer, che utilizzano la libreria Qpid Proton per comunicare con RabbitMQ.</li>



<li><code>Makefile</code>: Un file di automazione che semplifica la generazione dei certificati e la gestione del container RabbitMQ.</li>



<li><code>README.md</code>: Documentazione del progetto, con istruzioni dettagliate su come configurare e utilizzare RabbitMQ con mTLS.</li>
</ul>



<h2 class="wp-block-heading" id="configurazione-di-rabbitmq-per-mtls">Configurazione di RabbitMQ per mTLS</h2>



<p>Per abilitare la <a href="https://www.rabbitmq.com/docs/ssl">mutua autenticazione TLS (mTLS) in RabbitMQ</a>, è necessario configurare il broker affinché accetti solo connessioni cifrate e richieda la presentazione di un certificato valido anche da parte dei client. Questo garantisce che solo i client autorizzati e dotati di certificato firmato dalla CA possano interagire con RabbitMQ.</p>



<h3 class="wp-block-heading" id="parametri-chiave-nel-file-di-configurazione">Parametri chiave nel file di configurazione</h3>



<p>Nel file <code>rabbitmq.conf</code> (che viene montato nel container RabbitMQ), assicurati di includere le seguenti direttive:</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# Negazione del listener TCP standard
# RabbitMQ non accetterà connessioni non cifrate sulla porta 5672
# Questo è importante per forzare l'uso di TLS
listeners.tcp = none

# Abilita il listener TLS sulla porta 5671
listeners.ssl.default = 5671

# Percorsi dei certificati e della chiave privata del server
ssl_options.cacertfile = /etc/rabbitmq/certs/ca.pem
ssl_options.certfile   = /etc/rabbitmq/certs/server.pem
ssl_options.keyfile    = /etc/rabbitmq/certs/server.key

# Richiedi e verifica il certificato client
ssl_options.verify = verify_peer
ssl_options.fail_if_no_peer_cert = true
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88"># Negazione del listener TCP standard</span></span>
<span class="line"><span style="color: #616E88"># RabbitMQ non accetterà connessioni non cifrate sulla porta 5672</span></span>
<span class="line"><span style="color: #616E88"># Questo è importante per forzare l&#39;uso di TLS</span></span>
<span class="line"><span style="color: #81A1C1">listeners.tcp</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">=</span><span style="color: #D8DEE9FF"> none</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Abilita il listener TLS sulla porta 5671</span></span>
<span class="line"><span style="color: #81A1C1">listeners.ssl.default</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">=</span><span style="color: #D8DEE9FF"> 5671</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Percorsi dei certificati e della chiave privata del server</span></span>
<span class="line"><span style="color: #81A1C1">ssl_options.cacertfile</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">=</span><span style="color: #D8DEE9FF"> /etc/rabbitmq/certs/ca.pem</span></span>
<span class="line"><span style="color: #81A1C1">ssl_options.certfile</span><span style="color: #D8DEE9FF">   </span><span style="color: #ECEFF4">=</span><span style="color: #D8DEE9FF"> /etc/rabbitmq/certs/server.pem</span></span>
<span class="line"><span style="color: #81A1C1">ssl_options.keyfile</span><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">=</span><span style="color: #D8DEE9FF"> /etc/rabbitmq/certs/server.key</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Richiedi e verifica il certificato client</span></span>
<span class="line"><span style="color: #81A1C1">ssl_options.verify</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">=</span><span style="color: #D8DEE9FF"> verify_peer</span></span>
<span class="line"><span style="color: #81A1C1">ssl_options.fail_if_no_peer_cert</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">=</span><span style="color: #D8DEE9FF"> true</span></span>
<span class="line"></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">INI</span></div>



<p></p>



<p>Questa configurazione obbliga RabbitMQ a:</p>



<ul class="wp-block-list">
<li>Accettare solo connessioni cifrate sulla porta 5671.</li>



<li>Presentare il proprio certificato server ai client.</li>



<li>Verificare che ogni client presenti un certificato valido e firmato dalla stessa CA.</li>



<li>Rifiutare le connessioni da client privi di certificato o con certificato non valido.</li>
</ul>



<p>Non è necessario modificare il file di configurazione di RabbitMQ per l'uso di AMQP 1.0, poiché questo protocollo è già supportato nativamente da RabbitMQ a partire dalla versione 4.0.</p>



<h2 class="wp-block-heading" id="cosa-fa-il-makefile-e-come-usarlo">Cosa fa il Makefile e come usarlo</h2>



<p>Il <a href="https://www.gnu.org/software/make/manual/make.html">Makefile</a> è un strumento molto potente che in questo progetto viene utilizzato per automatizzare la generazione dei certificati e la gestione del container RabbitMQ. Grazie a questo file, puoi facilmente creare un ambiente di sviluppo sicuro senza dover eseguire manualmente ogni singolo comando.</p>



<p>Il Makefile è pensato per essere idempotente e facilmente estendibile. Le principali operazioni automatizzate sono:</p>



<ul class="wp-block-list">
<li><strong>Creazione della CA locale</strong>: genera la chiave privata e il certificato della Certificate Authority.</li>



<li><strong>Generazione delle chiavi e CSR per server e client</strong>: per ogni entità (server RabbitMQ, producer, consumer) vengono create chiavi private e richieste di firma.</li>



<li><strong>Firma dei certificati</strong>: la CA firma le CSR, producendo certificati validi per mTLS.</li>



<li><strong>Gestione dei Subject Alternative Names (SAN)</strong>: i certificati server includono i SAN necessari per il corretto funzionamento con FQDN e localhost.</li>



<li><strong>Pulizia dell’ambiente</strong>: con <code>make clean</code> puoi eliminare tutti i certificati e le chiavi generate, riportando il progetto allo stato iniziale.</li>



<li><strong>Avvio e gestione del container RabbitMQ</strong>: il Makefile include anche comandi per avviare, fermare e configurare RabbitMQ in modo semplice e veloce.</li>



<li><strong>Configurazione di utenti e permessi</strong>: tramite comandi <code>rabbitmqctl</code> o API HTTP, il Makefile si occupa di configurare gli utenti, i permessi e i vhost necessari per il corretto funzionamento del broker.</li>



<li><strong>Configurazione della topologia</strong>: crea exchange, queue e binding necessari per il corretto funzionamento degli script di esempio.</li>
</ul>



<h3 class="wp-block-heading" id="principali-target-del-makefile">Principali target del Makefile</h3>



<p>Il Makefile del progetto è stato pensato per semplificare tutte le operazioni ricorrenti durante lo sviluppo e i test. Ecco una panoramica dei target più importanti:</p>



<ul class="wp-block-list">
<li><p><strong>certs</strong><br>Genera tutti i certificati necessari per mTLS: CA, server RabbitMQ, producer e consumer.<br>È il target da eseguire all’inizio per preparare l’ambiente di sicurezza.</p></li>



<li><p><strong>clean</strong><br>Rimuove tutti i certificati e le chiavi generate, riportando il progetto allo stato iniziale.<br>Utile se vuoi rigenerare tutto da zero.</p></li>



<li><p><strong>rabbitmq-pod-start</strong><br>Avvia il container RabbitMQ con la configurazione mTLS, montando i certificati e il file di configurazione.<br>Utilizza Podman (o Docker, se adattato).</p></li>



<li><p><strong>rabbitmq-pod-stop</strong><br>Ferma e rimuove il container RabbitMQ avviato in precedenza.</p></li>



<li><p><strong>rabbitmq-setup-permissions</strong><br>Configura utenti, permessi e vhost all’interno di RabbitMQ tramite comandi <code>rabbitmqctl</code>.<br>Garantisce che i client possano autenticarsi e accedere alle risorse corrette.</p></li>



<li><p><strong>rabbitmq-setup-topology</strong><br>Crea exchange, queue e binding necessari per il corretto funzionamento degli script di esempio.</p></li>



<li><p><strong>rabbitmq-logs</strong><br>Mostra in tempo reale i log del container RabbitMQ, utile per il debug e il monitoraggio.</p></li>



<li><p><strong>all</strong><br>Esegue in sequenza i target fondamentali (<code>certs</code>, <code>rabbitmq-pod-start</code>, <code>rabbitmq-setup-permissions</code>, <code>rabbitmq-setup-topology</code>) per preparare l’intero ambiente con un solo comando.</p></li>
</ul>



<h3 class="wp-block-heading" id="flusso-di-setup-con-makefile">Flusso di Setup con Makefile</h3>



<p>Il Makefile orchestra la creazione dell'intero ambiente di sviluppo sicuro. Ecco una visione d'insieme del processo attivato, ad esempio, dal comando <code>make all</code>:</p>



<div class="wp-block-wp-mermaid-block mermaid">



graph LR
    A[Utente esegue 'make all'] --> B{Makefile};
    B --> C[certs: Genera CA, Cert. Server, Cert. Client];
    C --> D[rabbitmq-pod-start: Avvia container RabbitMQ con mTLS];
    D --> E[rabbitmq-setup-permissions: Configura Utenti e Permessi];
    E --> F[rabbitmq-setup-topology: Crea Exchange, Queue, Binding];
    F --> G[Ambiente Pronto];



</div>



<p>Per avere un'idea visiva dell'intero processo di setup orchestrato dal Makefile, puoi guardare questa breve demo.</p>



<figure class="wp-block-image size-full"><img width="1280" height="827" decoding="async" loading="lazy" src="https://www.dontesta.it/wp-content/uploads/2020/11/registrazione_demo_setup_env_rabbitmq_41_mtls_1.gif" alt="RabbitMQ 4.1 mTLS and AMQP 1.0 - Proof of Concept Demo" class="wp-image-5917"/></figure>



<p></p>



<h4 class="wp-block-heading" id="come-scoprire-tutti-i-target-disponibili">Come scoprire tutti i target disponibili</h4>



<p>Per vedere l’elenco completo dei target e una breve descrizione, puoi eseguire:</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="make help" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">make</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">help</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Bash</span></div>



<p></p>



<h3 class="wp-block-heading" id="personalizzazione-del-makefile">Personalizzazione del Makefile</h3>



<p>Se vuoi aggiungere nuovi certificati client o modificare i parametri dei certificati (ad esempio, cambiare l'FQDN o aggiungere nuovi SAN), puoi modificare le variabili all’inizio del Makefile. Tutte le operazioni sono trasparenti e facilmente adattabili alle tue esigenze.</p>



<p>Vantaggi dell’approccio automatizzato</p>



<ul class="wp-block-list">
<li><strong>Ripetibilità</strong>: Ogni volta che esegui <code>make certs</code>, ottieni gli stessi risultati, riducendo il rischio di errori umani.</li>



<li><strong>Sicurezza</strong>: riduci il rischio di errori manuali nella generazione dei certificati.</li>



<li><strong>Velocità</strong>: Risparmi tempo prezioso, specialmente in ambienti di sviluppo e test.</li>



<li><strong>Facilità di integrazione</strong>: Puoi integrare il Makefile nel tuo processo CI/CD per generare automaticamente i certificati in ambienti di test e produzione.</li>
</ul>



<p>Consulta il Makefile incluso nel repository per tutti i dettagli sulle regole e sulle variabili configurabili.</p>



<h2 class="wp-block-heading" id="gestione-automatica-dei-certificati-con-il-makefile">Gestione automatica dei certificati con il Makefile</h2>



<p>Per semplificare e standardizzare la generazione dei certificati necessari per mTLS, il Makefile include il target <code>certs</code> che automatizza tutte le operazioni critiche: creazione della CA, generazione delle chiavi e delle richieste di firma (CSR), firma dei certificati server e client, e organizzazione dei file nelle cartelle corrette.</p>



<p>Per generare tutti i certificati necessari, ti basta eseguire:</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="make certs" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">make</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">certs</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Bash</span></div>



<p></p>



<p>L'output del comando sarà simile a questo:</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="Generating CA and Server certificates...
CA and Server certificates generated.
Generating Client certificates (Producer and Consumer)...
Producer client certificate generated: certs/order_sender_client.pem
Consumer client certificate generated: certs/delivery_receiver_client.pem
Client certificates generated.
All certificates generated in ./certs/" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #d8dee9ff">Generating CA and Server certificates...</span></span>
<span class="line"><span style="color: #d8dee9ff">CA and Server certificates generated.</span></span>
<span class="line"><span style="color: #d8dee9ff">Generating Client certificates (Producer and Consumer)...</span></span>
<span class="line"><span style="color: #d8dee9ff">Producer client certificate generated: certs/order_sender_client.pem</span></span>
<span class="line"><span style="color: #d8dee9ff">Consumer client certificate generated: certs/delivery_receiver_client.pem</span></span>
<span class="line"><span style="color: #d8dee9ff">Client certificates generated.</span></span>
<span class="line"><span style="color: #d8dee9ff">All certificates generated in ./certs/</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Plaintext</span></div>



<p></p>



<p>Questo comando creerà una directory <code>certs</code> con tutti i file necessari per la configurazione di RabbitMQ e dei client. A seguito della generazione, troverai:</p>



<ul class="wp-block-list">
<li><code>ca.pem</code>: Certificato della CA.</li>



<li><code>server.pem</code>: Certificato del server RabbitMQ.</li>



<li><code>server.key</code>: Chiave privata del server RabbitMQ.</li>



<li><code>order_sender_client.key</code>: Chiave privata usata dallo script <code>producer.py</code> che rappresenta il producer.</li>



<li><code>order_sender_client.pem</code>: Certificato usato dallo script <code>producer.py</code> che rappresenta il producer.</li>



<li><code>delivery_receiver_client.key</code>: Chiave privata usata dallo script <code>consumer.py</code> che rappresenta il consumer.</li>



<li><code>delivery_receiver_client.pem</code>: Certificato usato dallo script <code>consumer.py</code> che rappresenta il consumer.</li>
</ul>



<p>Nella lista precedente ho omesso volutamente il file <code>*.csr</code>, <code>*.srl</code> e <code>*.ext</code>, in quanto non sono necessari per l'esecuzione degli script di esempio. Questi file sono generati durante il processo di creazione dei certificati e possono essere utili per la diagnostica o per la verifica della corretta generazione dei certificati.</p>



<p>La configurazione dei Subject e dei Subject Alternative Names (SAN) sono state impostate in modo da garantire che i certificati siano validi per l'FQDN <code>rabbitmq.labs.dontesta.it</code> e per <code>localhost</code>, allo scopo di testare facilmente sia in locale che in ambienti di sviluppo. A seguire le variabili definite nel Makefile per la deefinizione dei Subject.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# Subject settings
CA_SUBJECT = &quot;/C=IT/ST=Sicilia/L=Bronte/O=Dontesta/OU=DevOps/CN=Dontesta-CA&quot;
SERVER_SUBJECT = &quot;/C=IT/ST=Sicilia/L=Bronte/O=Dontesta/OU=RabbitMQServer/CN=${RABBITMQ_FQDN}&quot;
PRODUCER_SUBJECT = &quot;/C=IT/ST=Sicilia/L=Bronte/O=Dontesta/OU=Client/CN=order_sender_client&quot;
CONSUMER_SUBJECT = &quot;/C=IT/ST=Sicilia/L=Bronte/O=Dontesta/OU=Client/CN=delivery_receiver_client&quot;" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88"># Subject settings</span></span>
<span class="line"><span style="color: #D8DEE9">CA_SUBJECT</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">=</span><span style="color: #D8DEE9FF"> &quot;/C=IT/ST=Sicilia/L=Bronte/O=Dontesta/OU=DevOps/CN=Dontesta-CA&quot;</span></span>
<span class="line"><span style="color: #D8DEE9">SERVER_SUBJECT</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">=</span><span style="color: #D8DEE9FF"> &quot;/C=IT/ST=Sicilia/L=Bronte/O=Dontesta/OU=RabbitMQServer/CN=</span><span style="color: #81A1C1">${</span><span style="color: #D8DEE9">RABBITMQ_FQDN</span><span style="color: #81A1C1">}</span><span style="color: #D8DEE9FF">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9">PRODUCER_SUBJECT</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">=</span><span style="color: #D8DEE9FF"> &quot;/C=IT/ST=Sicilia/L=Bronte/O=Dontesta/OU=Client/CN=order_sender_client&quot;</span></span>
<span class="line"><span style="color: #D8DEE9">CONSUMER_SUBJECT</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">=</span><span style="color: #D8DEE9FF"> &quot;/C=IT/ST=Sicilia/L=Bronte/O=Dontesta/OU=Client/CN=delivery_receiver_client&quot;</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Makefile</span></div>



<p></p>



<p>Nel caso in cui tu voglia generare i certificati per un altro FQDN e Subject, sarà sufficiente eseguire il comando make come segue:</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="make certs \
    RABBITMQ_FQDN=&quot;my.custom.broker.com&quot; \
    CA_SUBJECT=&quot;/C=US/ST=California/L=MyCity/O=MyOrg/OU=DevOps/CN=MyOrg-Custom-CA&quot; \
    SERVER_SUBJECT=&quot;/C=US/ST=California/L=MyCity/O=MyOrg/OU=RabbitMQServer/CN=my.custom.broker.com&quot; \
    PRODUCER_SUBJECT=&quot;/C=US/ST=California/L=MyCity/O=MyOrg/OU=Client/CN=custom_producer.client&quot; \
    CONSUMER_SUBJECT=&quot;/C=US/ST=California/L=MyCity/O=MyOrg/OU=Client/CN=custom_consumer.client&quot;" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">make</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">certs</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">RABBITMQ_FQDN=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">my.custom.broker.com</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">CA_SUBJECT=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">/C=US/ST=California/L=MyCity/O=MyOrg/OU=DevOps/CN=MyOrg-Custom-CA</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">SERVER_SUBJECT=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">/C=US/ST=California/L=MyCity/O=MyOrg/OU=RabbitMQServer/CN=my.custom.broker.com</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">PRODUCER_SUBJECT=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">/C=US/ST=California/L=MyCity/O=MyOrg/OU=Client/CN=custom_producer.client</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">CONSUMER_SUBJECT=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">/C=US/ST=California/L=MyCity/O=MyOrg/OU=Client/CN=custom_consumer.client</span><span style="color: #ECEFF4">&quot;</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Bash</span></div>



<p></p>



<h2 class="wp-block-heading" id="gestione-di-rabbitmq-tramite-makefile">Gestione di RabbitMQ tramite Makefile</h2>



<p>Per rendere ancora più semplice la gestione dell’ambiente di sviluppo, il Makefile include anche un target dedicato all’avvio del container RabbitMQ già configurato per mTLS. In questo modo non dovrai ricordare o scrivere manualmente i comandi <code>podman run</code> o <code>docker run</code>.</p>



<h3 class="wp-block-heading" id="come-avviare-rabbitmq">Come avviare RabbitMQ</h3>



<p>Dopo aver generato i certificati con <code>make certs</code>, puoi avviare RabbitMQ già pronto all’uso (con vhost, utenti, permessi e topologia) usando il comando:</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="make rabbitmq-pod-start rabbitmq-setup-permissions rabbitmq-setup-topology" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">make</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">rabbitmq-pod-start</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">rabbitmq-setup-permissions</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">rabbitmq-setup-topology</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Bash</span></div>



<p></p>



<p>Questo comando eseguirà il container RabbitMQ con le configurazioni corrette e monterà i certificati generati nella directory <code>certs</code> all'interno del container.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><strong>Nota:</strong> prima di eseguire lo start del container RabbitMQ, viene eseguito il target <code>hosts-check</code>, che verifica se il file <code>/etc/hosts</code> contiene la voce ${RABBITMQ_FQDN}. Se non è presente, il comando fallirà. Puoi aggiungere manualmente la riga al file <code>/etc/hosts</code>.</p>
</blockquote>



<p>A seguire un esempio di output del comando:</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="Checking /etc/hosts for entry '127.0.0.1 rabbitmq.labs.dontesta.it'...
/etc/hosts is OK.
Starting RabbitMQ container (rabbitmq-dev-server) with image rabbitmq:4.1-management...
fc79be56d11261b0f193c1e8ca08756da6db005a580528da87e76906be77e25a
Container rabbitmq-dev-server created and started.
Waiting for RabbitMQ in container rabbitmq-dev-server to be ready...
RabbitMQ is ready.
Configuring RabbitMQ vhost, users, and permissions...
podman exec rabbitmq-dev-server rabbitmqctl add_vhost logistics_vhost || echo &quot;Vhost logistics_vhost already exists.&quot;
Adding vhost &quot;logistics_vhost&quot; ...
Creating admin user: rabbit_admin
podman exec rabbitmq-dev-server rabbitmqctl add_user rabbit_admin 'SuperS3cureAdminP@ssw0rd!' || echo &quot;User rabbit_admin already exists.&quot;
Adding user &quot;rabbit_admin&quot; ...
Done. Don't forget to grant the user permissions to some virtual hosts! See 'rabbitmqctl help set_permissions' to learn more.
podman exec rabbitmq-dev-server rabbitmqctl set_user_tags rabbit_admin administrator
Setting tags for user &quot;rabbit_admin&quot; to [administrator] ...
podman exec rabbitmq-dev-server rabbitmqctl set_permissions -p logistics_vhost rabbit_admin &quot;.*&quot; &quot;.*&quot; &quot;.*&quot;
Setting permissions for user &quot;rabbit_admin&quot; in vhost &quot;logistics_vhost&quot; ...
Creating application users...
podman exec rabbitmq-dev-server rabbitmqctl add_user order_sender 'OrderSenderP@ssw0rd' || echo &quot;User order_sender already exists.&quot;
Adding user &quot;order_sender&quot; ...
Done. Don't forget to grant the user permissions to some virtual hosts! See 'rabbitmqctl help set_permissions' to learn more.
podman exec rabbitmq-dev-server rabbitmqctl add_user delivery_receiver 'DeliveryReceiverP@ssw0rd' || echo &quot;User delivery_receiver already exists.&quot;
Adding user &quot;delivery_receiver&quot; ...
Done. Don't forget to grant the user permissions to some virtual hosts! See 'rabbitmqctl help set_permissions' to learn more.
Setting permissions for application users on vhost logistics_vhost...
podman exec rabbitmq-dev-server rabbitmqctl set_permissions -p logistics_vhost order_sender &quot;&quot; &quot;^order_exchange$&quot; &quot;&quot;
Setting permissions for user &quot;order_sender&quot; in vhost &quot;logistics_vhost&quot; ...
podman exec rabbitmq-dev-server rabbitmqctl set_permissions -p logistics_vhost delivery_receiver &quot;&quot; &quot;&quot; &quot;^logistics_queue$&quot;
Setting permissions for user &quot;delivery_receiver&quot; in vhost &quot;logistics_vhost&quot; ...
Vhost, users, and permissions configured.
Configuration topology RabbitMQ (exchange, queue, binding) with user rabbit_admin...
podman exec rabbitmq-dev-server rabbitmqadmin -u rabbit_admin -p 'SuperS3cureAdminP@ssw0rd!' -V logistics_vhost declare exchange name=order_exchange type=direct durable=true || echo &quot;Exchange order_exchange already exists or error.&quot;
exchange declared
podman exec rabbitmq-dev-server rabbitmqadmin -u rabbit_admin -p 'SuperS3cureAdminP@ssw0rd!' -V logistics_vhost declare queue name=logistics_queue durable=true || echo &quot;Queue logistics_queue already exists or error.&quot;
queue declared
podman exec rabbitmq-dev-server rabbitmqadmin -u rabbit_admin -p 'SuperS3cureAdminP@ssw0rd!' -V logistics_vhost declare binding source=&quot;order_exchange&quot; destination_type=&quot;queue&quot; destination=&quot;logistics_queue&quot; routing_key=&quot;new_order_event&quot; || echo &quot;Binding already exists or error.&quot;
binding declared
Topology configured." style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #d8dee9ff">Checking /etc/hosts for entry &#39;127.0.0.1 rabbitmq.labs.dontesta.it&#39;...</span></span>
<span class="line"><span style="color: #d8dee9ff">/etc/hosts is OK.</span></span>
<span class="line"><span style="color: #d8dee9ff">Starting RabbitMQ container (rabbitmq-dev-server) with image rabbitmq:4.1-management...</span></span>
<span class="line"><span style="color: #d8dee9ff">fc79be56d11261b0f193c1e8ca08756da6db005a580528da87e76906be77e25a</span></span>
<span class="line"><span style="color: #d8dee9ff">Container rabbitmq-dev-server created and started.</span></span>
<span class="line"><span style="color: #d8dee9ff">Waiting for RabbitMQ in container rabbitmq-dev-server to be ready...</span></span>
<span class="line"><span style="color: #d8dee9ff">RabbitMQ is ready.</span></span>
<span class="line"><span style="color: #d8dee9ff">Configuring RabbitMQ vhost, users, and permissions...</span></span>
<span class="line"><span style="color: #d8dee9ff">podman exec rabbitmq-dev-server rabbitmqctl add_vhost logistics_vhost || echo &quot;Vhost logistics_vhost already exists.&quot;</span></span>
<span class="line"><span style="color: #d8dee9ff">Adding vhost &quot;logistics_vhost&quot; ...</span></span>
<span class="line"><span style="color: #d8dee9ff">Creating admin user: rabbit_admin</span></span>
<span class="line"><span style="color: #d8dee9ff">podman exec rabbitmq-dev-server rabbitmqctl add_user rabbit_admin &#39;SuperS3cureAdminP@ssw0rd!&#39; || echo &quot;User rabbit_admin already exists.&quot;</span></span>
<span class="line"><span style="color: #d8dee9ff">Adding user &quot;rabbit_admin&quot; ...</span></span>
<span class="line"><span style="color: #d8dee9ff">Done. Don&#39;t forget to grant the user permissions to some virtual hosts! See &#39;rabbitmqctl help set_permissions&#39; to learn more.</span></span>
<span class="line"><span style="color: #d8dee9ff">podman exec rabbitmq-dev-server rabbitmqctl set_user_tags rabbit_admin administrator</span></span>
<span class="line"><span style="color: #d8dee9ff">Setting tags for user &quot;rabbit_admin&quot; to [administrator] ...</span></span>
<span class="line"><span style="color: #d8dee9ff">podman exec rabbitmq-dev-server rabbitmqctl set_permissions -p logistics_vhost rabbit_admin &quot;.*&quot; &quot;.*&quot; &quot;.*&quot;</span></span>
<span class="line"><span style="color: #d8dee9ff">Setting permissions for user &quot;rabbit_admin&quot; in vhost &quot;logistics_vhost&quot; ...</span></span>
<span class="line"><span style="color: #d8dee9ff">Creating application users...</span></span>
<span class="line"><span style="color: #d8dee9ff">podman exec rabbitmq-dev-server rabbitmqctl add_user order_sender &#39;OrderSenderP@ssw0rd&#39; || echo &quot;User order_sender already exists.&quot;</span></span>
<span class="line"><span style="color: #d8dee9ff">Adding user &quot;order_sender&quot; ...</span></span>
<span class="line"><span style="color: #d8dee9ff">Done. Don&#39;t forget to grant the user permissions to some virtual hosts! See &#39;rabbitmqctl help set_permissions&#39; to learn more.</span></span>
<span class="line"><span style="color: #d8dee9ff">podman exec rabbitmq-dev-server rabbitmqctl add_user delivery_receiver &#39;DeliveryReceiverP@ssw0rd&#39; || echo &quot;User delivery_receiver already exists.&quot;</span></span>
<span class="line"><span style="color: #d8dee9ff">Adding user &quot;delivery_receiver&quot; ...</span></span>
<span class="line"><span style="color: #d8dee9ff">Done. Don&#39;t forget to grant the user permissions to some virtual hosts! See &#39;rabbitmqctl help set_permissions&#39; to learn more.</span></span>
<span class="line"><span style="color: #d8dee9ff">Setting permissions for application users on vhost logistics_vhost...</span></span>
<span class="line"><span style="color: #d8dee9ff">podman exec rabbitmq-dev-server rabbitmqctl set_permissions -p logistics_vhost order_sender &quot;&quot; &quot;^order_exchange$&quot; &quot;&quot;</span></span>
<span class="line"><span style="color: #d8dee9ff">Setting permissions for user &quot;order_sender&quot; in vhost &quot;logistics_vhost&quot; ...</span></span>
<span class="line"><span style="color: #d8dee9ff">podman exec rabbitmq-dev-server rabbitmqctl set_permissions -p logistics_vhost delivery_receiver &quot;&quot; &quot;&quot; &quot;^logistics_queue$&quot;</span></span>
<span class="line"><span style="color: #d8dee9ff">Setting permissions for user &quot;delivery_receiver&quot; in vhost &quot;logistics_vhost&quot; ...</span></span>
<span class="line"><span style="color: #d8dee9ff">Vhost, users, and permissions configured.</span></span>
<span class="line"><span style="color: #d8dee9ff">Configuration topology RabbitMQ (exchange, queue, binding) with user rabbit_admin...</span></span>
<span class="line"><span style="color: #d8dee9ff">podman exec rabbitmq-dev-server rabbitmqadmin -u rabbit_admin -p &#39;SuperS3cureAdminP@ssw0rd!&#39; -V logistics_vhost declare exchange name=order_exchange type=direct durable=true || echo &quot;Exchange order_exchange already exists or error.&quot;</span></span>
<span class="line"><span style="color: #d8dee9ff">exchange declared</span></span>
<span class="line"><span style="color: #d8dee9ff">podman exec rabbitmq-dev-server rabbitmqadmin -u rabbit_admin -p &#39;SuperS3cureAdminP@ssw0rd!&#39; -V logistics_vhost declare queue name=logistics_queue durable=true || echo &quot;Queue logistics_queue already exists or error.&quot;</span></span>
<span class="line"><span style="color: #d8dee9ff">queue declared</span></span>
<span class="line"><span style="color: #d8dee9ff">podman exec rabbitmq-dev-server rabbitmqadmin -u rabbit_admin -p &#39;SuperS3cureAdminP@ssw0rd!&#39; -V logistics_vhost declare binding source=&quot;order_exchange&quot; destination_type=&quot;queue&quot; destination=&quot;logistics_queue&quot; routing_key=&quot;new_order_event&quot; || echo &quot;Binding already exists or error.&quot;</span></span>
<span class="line"><span style="color: #d8dee9ff">binding declared</span></span>
<span class="line"><span style="color: #d8dee9ff">Topology configured.</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Plaintext</span></div>



<p></p>



<p>Se vuoi far tutto in un colpo solo, puoi eseguire il comando <code>make all</code>, che eseguirà in sequenza i target <code>certs</code>, <code>rabbitmq-pod-start</code>, <code>rabbitmq-setup-permissions</code> e <code>rabbitmq-setup-topology</code>.</p>



<p>Dall'output del comando di avvio puoi notare che il container RabbitMQ è stato avviato correttamente e che sono stati creati gli utenti, i permessi e la topologia necessaria per il corretto funzionamento degli script di esempio. Puoi anche notare che l'immagine RabbitMQ utilizzata è <code>rabbitmq:4.1-management</code>, che include l'interfaccia di gestione web e gli strumenti di monitoraggio e che il nome del container è <code>rabbitmq-dev-server</code>.</p>



<p>Il nome dell'immagine RabbitMQ è specificato nella variabile <code>PODMAN_IMAGE_NAME</code> del Makefile e il nome del container è specificato nella variabile <code>CONTAINER_NAME</code>. Puoi modificare questi valori se desideri utilizzare un'immagine diversa o un nome di container diverso.</p>



<h3 class="wp-block-heading" id="come-vedere-i-log-di-rabbitmq">Come vedere i log di RabbitMQ</h3>



<p>Puoi visualizzare i log di RabbitMQ in tempo reale con:</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="make rabbitmq-logs" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">make</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">rabbitmq-logs</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Bash</span></div>



<p></p>



<p>Questo comando ti permetterà di monitorare le attività del broker e diagnosticare eventuali problemi. A seguire un esempio di output:</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="2025-05-16 13:22:50.696329+00:00 [info] &lt;0.931.0&gt; accepting AMQP connection 192.168.127.1:59736 -&gt; 10.88.0.39:5671
2025-05-16 13:22:50.716750+00:00 [debug] &lt;0.931.0&gt; User 'order_sender' authenticated successfully by backend rabbit_auth_backend_internal
2025-05-16 13:22:50.718257+00:00 [info] &lt;0.931.0&gt; Connection from AMQP 1.0 container '062a2bba-b46d-46ba-a63c-c8323456ac9c': user 'order_sender' authenticated using SASL mechanism PLAIN and granted access to vhost 'logistics_vhost'
2025-05-16 13:22:50.718347+00:00 [debug] &lt;0.931.0&gt; AMQP 1.0 connection.open frame: hostname = vhost:logistics_vhost, extracted vhost = logistics_vhost, idle-time-out = undefined
2025-05-16 13:22:50.722351+00:00 [debug] &lt;0.931.0&gt; AMQP 1.0 created session process &lt;0.936.0&gt; for channel number 0
2025-05-16 13:22:50.731249+00:00 [debug] &lt;0.931.0&gt; AMQP 1.0 closed session process &lt;0.936.0&gt; with channel number 0
2025-05-16 13:22:50.736862+00:00 [info] &lt;0.931.0&gt; closing AMQP connection (192.168.127.1:59736 -&gt; 10.88.0.39:5671, duration: '40ms')" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #d8dee9ff">2025-05-16 13:22:50.696329+00:00 [info] &lt;0.931.0&gt; accepting AMQP connection 192.168.127.1:59736 -&gt; 10.88.0.39:5671</span></span>
<span class="line"><span style="color: #d8dee9ff">2025-05-16 13:22:50.716750+00:00 [debug] &lt;0.931.0&gt; User &#39;order_sender&#39; authenticated successfully by backend rabbit_auth_backend_internal</span></span>
<span class="line"><span style="color: #d8dee9ff">2025-05-16 13:22:50.718257+00:00 [info] &lt;0.931.0&gt; Connection from AMQP 1.0 container &#39;062a2bba-b46d-46ba-a63c-c8323456ac9c&#39;: user &#39;order_sender&#39; authenticated using SASL mechanism PLAIN and granted access to vhost &#39;logistics_vhost&#39;</span></span>
<span class="line"><span style="color: #d8dee9ff">2025-05-16 13:22:50.718347+00:00 [debug] &lt;0.931.0&gt; AMQP 1.0 connection.open frame: hostname = vhost:logistics_vhost, extracted vhost = logistics_vhost, idle-time-out = undefined</span></span>
<span class="line"><span style="color: #d8dee9ff">2025-05-16 13:22:50.722351+00:00 [debug] &lt;0.931.0&gt; AMQP 1.0 created session process &lt;0.936.0&gt; for channel number 0</span></span>
<span class="line"><span style="color: #d8dee9ff">2025-05-16 13:22:50.731249+00:00 [debug] &lt;0.931.0&gt; AMQP 1.0 closed session process &lt;0.936.0&gt; with channel number 0</span></span>
<span class="line"><span style="color: #d8dee9ff">2025-05-16 13:22:50.736862+00:00 [info] &lt;0.931.0&gt; closing AMQP connection (192.168.127.1:59736 -&gt; 10.88.0.39:5671, duration: &#39;40ms&#39;)</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Plaintext</span></div>



<p></p>



<p>Vedendo questo log è possibile notare che il producer <code>order_sender</code> si è autenticato correttamente e ha aperto una connessione AMQP 1.0 con RabbitMQ. Puoi anche vedere i dettagli della connessione, come l'hostname e il vhost utilizzato.</p>



<h3 class="wp-block-heading" id="come-fermare-e-riavviare-rabbitmq">Come fermare e riavviare RabbitMQ</h3>



<p>Per fermare il container RabbitMQ, puoi eseguire:</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="make rabbitmq-pod-stop" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">make</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">rabbitmq-pod-stop</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Bash</span></div>



<p></p>



<p>Questo comando fermerà il container RabbitMQ in esecuzione mostrando un output simile a questo:</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="Stopping RabbitMQ container (rabbitmq-dev-server)...
rabbitmq-dev-server" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #d8dee9ff">Stopping RabbitMQ container (rabbitmq-dev-server)...</span></span>
<span class="line"><span style="color: #d8dee9ff">rabbitmq-dev-server</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Plaintext</span></div>



<p></p>



<p>Per riavviare il container RabbitMQ, puoi eseguire:</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="make rabbitmq-pod-start" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">make</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">rabbitmq-pod-start</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Bash</span></div>



<p></p>



<p>Questo comando avvierà nuovamente il container RabbitMQ mostrando un output simile a questo:</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="Checking /etc/hosts for entry '127.0.0.1 rabbitmq.labs.dontesta.it'...
/etc/hosts is OK.
Starting RabbitMQ container (rabbitmq-dev-server) with image rabbitmq:4.1-management...
Container rabbitmq-dev-server exists but is not running. Removing it first...
24212a76d62a279e6d65922028aa12a9156e7f209b12ca81d17d6e9cf5473adc
Container rabbitmq-dev-server created and started.
Waiting for RabbitMQ in container rabbitmq-dev-server to be ready...
RabbitMQ is ready." style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #d8dee9ff">Checking /etc/hosts for entry &#39;127.0.0.1 rabbitmq.labs.dontesta.it&#39;...</span></span>
<span class="line"><span style="color: #d8dee9ff">/etc/hosts is OK.</span></span>
<span class="line"><span style="color: #d8dee9ff">Starting RabbitMQ container (rabbitmq-dev-server) with image rabbitmq:4.1-management...</span></span>
<span class="line"><span style="color: #d8dee9ff">Container rabbitmq-dev-server exists but is not running. Removing it first...</span></span>
<span class="line"><span style="color: #d8dee9ff">24212a76d62a279e6d65922028aa12a9156e7f209b12ca81d17d6e9cf5473adc</span></span>
<span class="line"><span style="color: #d8dee9ff">Container rabbitmq-dev-server created and started.</span></span>
<span class="line"><span style="color: #d8dee9ff">Waiting for RabbitMQ in container rabbitmq-dev-server to be ready...</span></span>
<span class="line"><span style="color: #d8dee9ff">RabbitMQ is ready.</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Plaintext</span></div>



<p></p>



<h2 class="wp-block-heading" id="esempio-di-producer-e-consumer-in-python">Esempio di Producer e Consumer in Python</h2>



<p>Vediamo ora come si struttura un tipico producer e un consumer Python che comunicano con RabbitMQ tramite AMQP 1.0 e mTLS, evidenziando solo le parti fondamentali e il loro scopo.</p>



<h3 class="wp-block-heading" id="flusso-di-comunicazione-mtls">Flusso di Comunicazione mTLS</h3>



<p>Il diagramma seguente illustra il flusso di comunicazione sicuro tra il Producer, RabbitMQ e il Consumer, utilizzando mTLS e AMQP 1.0.</p>



<div class="wp-block-wp-mermaid-block mermaid">



sequenceDiagram
    participant P as Producer
    participant R as RabbitMQ (mTLS)
    participant C as Consumer

    P->>R: 1. Connessione AMQPS (mTLS Handshake)
    Note over P,R: Scambio e verifica certificati
    R-->>P: Connessione Sicura Stabilita
    P->>R: 2. Invia Messaggio (Ordine)
    R->>R: 3. Instrada Messaggio (Exchange -> Queue)

    C->>R: 4. Connessione AMQPS (mTLS Handshake)
    Note over C,R: Scambio e verifica certificati
    R-->>C: Connessione Sicura Stabilita
    R-->>C: 5. Consegna Messaggio (Ordine)
    C->>R: 6. Conferma Ricezione (ACK)



</div>



<p></p>



<h3 class="wp-block-heading" id="producer-invio-di-ordini-in-modo-sicuro">Producer: invio di ordini in modo sicuro</h3>



<p><strong>Caso d’uso:</strong><br>Un microservizio producer deve inviare messaggi di <strong>nuovo ordine</strong> a RabbitMQ, garantendo che la comunicazione sia cifrata e autenticata tramite certificati; uno scenario comune in un’architettura a microservizi.</p>



<p><strong>Punti chiave nello script:</strong></p>



<ul class="wp-block-list">
<li><strong>Configurazione SSL/mTLS:</strong><br>Il producer carica i percorsi dei certificati CA, client e chiave privata, e configura Proton per la verifica reciproca.</li>



<li><strong>Connessione protetta:</strong><br>La connessione viene stabilita usando l’URL <code>amqps://</code>, il vhost corretto e il parametro <code>sni</code> per l’<a href="https://it.wikipedia.org/wiki/Server_Name_Indication">SNI (Server Name Indication)</a> TLS.</li>



<li><strong>Generazione ordini random:</strong><br>Prima di inviare, il producer genera un numero configurabile di ordini con dati casuali (ID, descrizione, quantità).</li>



<li><strong>Invio messaggi:</strong><br>Ogni ordine viene serializzato in JSON e inviato all’exchange configurato.<br>La conferma di avvenuta ricezione da parte di RabbitMQ viene gestita tramite callback.</li>
</ul>



<p></p>



<h3 class="wp-block-heading" id="consumer-ricezione-sicura-degli-ordini">Consumer: ricezione sicura degli ordini</h3>



<p><strong>Caso d’uso:</strong><br>Un microservizio consumer si collega a RabbitMQ per ricevere e processare i messaggi degli ordini, sempre in modo autenticato e cifrato; uno scenario comune in un’architettura a microservizi.</p>



<p><strong>Punti chiave nello script:</strong></p>



<ul class="wp-block-list">
<li><strong>Configurazione SSL/mTLS:</strong><br>Anche il consumer carica i propri certificati e configura Proton per la verifica del server e la presentazione del certificato client.</li>



<li><strong>Connessione protetta:</strong><br>Si connette al broker usando le stesse impostazioni di sicurezza del producer.</li>



<li><strong>Ricezione e conferma:</strong><br>Riceve i messaggi dalla coda, li deserializza e li processa.<br>Dopo l’elaborazione, invia una conferma esplicita (ACK) a RabbitMQ per ogni messaggio ricevuto.</li>



<li><strong>Gestione errori:</strong><br>In caso di errore di parsing o elaborazione, il messaggio può essere rilasciato o rifiutato, a seconda della logica implementata.</li>
</ul>



<p><strong>Nota:</strong><br>Entrambi gli script fanno uso delle stesse best practice:</p>



<ul class="wp-block-list">
<li>Percorsi assoluti per i certificati per evitare problemi di path traversal.</li>



<li>Uso di variabili d’ambiente per parametri sensibili.</li>



<li>Separazione chiara tra configurazione di sicurezza e logica applicativa.</li>
</ul>



<p>Questa architettura ti permette di testare end-to-end la sicurezza e la robustezza della tua soluzione RabbitMQ già in fase di sviluppo.</p>



<p></p>



<h2 class="wp-block-heading" id="punti-di-attenzione-amqp-10-mtls-virtual-host-e-sni-con-proton">Punti di attenzione: AMQP 1.0, mTLS, Virtual Host e SNI con Proton</h2>



<p>Quando si lavora con RabbitMQ, AMQP 1.0, mTLS e la libreria Proton, ci sono alcuni aspetti tecnici e trappole comuni che è importante conoscere per evitare errori difficili da diagnosticare.</p>



<h3 class="wp-block-heading" id="1-amqp-10-virtual-host-e-addressing">1. AMQP 1.0, Virtual Host e Addressing</h3>



<ul class="wp-block-list">
<li><strong>Addressing:</strong><br>RabbitMQ utilizza un sistema di addressing basato su virtual host, exchange e queue. È importante comprendere come questi elementi interagiscono tra loro per garantire una corretta instradamento dei messaggi. In particolare l'addressing AMQP 1.0 è diverso da quello di AMQP 0-9-1, introducendo la versione 2 di cui qui <a href="https://www.rabbitmq.com/docs/amqp#address-v2">https://www.rabbitmq.com/docs/amqp#address-v2</a> sono disponibili i dettagli.</li>



<li><strong>Formato del Virtual Host:</strong><br>RabbitMQ, quando utilizza AMQP 1.0, si aspetta che il virtual host venga specificato in un formato particolare (es. <code>vhost:nome_vhost</code>).<br>Se il formato non è corretto, la connessione viene accettata ma il client potrebbe non avere accesso alle risorse desiderate o ricevere errori di autorizzazione perché si collegherà al vhost di default.</li>



<li><strong>Parametro <code>virtual_host</code> in Proton:</strong><br>Il parametro <code>virtual_host</code> passato alla funzione <code>connect()</code> di Proton deve corrispondere esattamente al nome del vhost configurato in RabbitMQ, e deve essere preceduto da <code>vhost:</code> (es. <code>vhost:logistics_vhost</code>).</li>
</ul>



<h3 class="wp-block-heading" id="2-mtls-certificati-e-verifica">2. mTLS: Certificati e Verifica</h3>



<ul class="wp-block-list">
<li><strong>Verifica reciproca:</strong><br>Con mTLS, sia il client che il server devono presentare certificati validi e firmati dalla stessa CA.<br>Se anche solo uno dei due certificati non è valido o non è firmato dalla CA corretta, la connessione TLS fallisce.</li>



<li><strong>Percorsi assoluti:</strong><br>Usa sempre percorsi assoluti per i certificati nei tuoi script, per evitare errori dovuti alla directory di lavoro corrente. È anche una buona pratica per evitare problemi di path traversal.</li>



<li><strong>Subject Alternative Name (SAN):</strong><br>Il certificato server deve includere l'FQDN usato dal client (es. <code>rabbitmq.labs.dontesta.it</code>) nei SAN, altrimenti la verifica fallirà.</li>
</ul>



<h3 class="wp-block-heading" id="3-sni-server-name-indication-e-proton">3. SNI (Server Name Indication) e Proton</h3>



<ul class="wp-block-list">
<li><strong>SNI e verifica del certificato:</strong><br>Proton, per default, può usare il valore di <code>virtual_host</code> anche come SNI nell’handshake TLS.<br>Se il valore di SNI non corrisponde a un SAN valido nel certificato server, la verifica fallisce.</li>



<li><strong>Soluzione:</strong><br>Usa sempre il parametro <code>sni</code> nella chiamata a <code>connect()</code> di Proton per forzare l’SNI corretto (es. il FQDN del server RabbitMQ).<br>Questo permette di separare la logica di autenticazione TLS da quella di routing AMQP.</li>
</ul>



<h3 class="wp-block-heading" id="4-debug-e-risoluzione-dei-problemi">4. Debug e risoluzione dei problemi</h3>



<ul class="wp-block-list">
<li><strong>Errori di handshake TLS:</strong><br>Spesso sono dovuti a mismatch tra SNI e SAN, o a CA non corretta.</li>



<li><strong>Errori di autorizzazione AMQP:</strong><br>Controlla sempre che il vhost sia corretto e che l’utente abbia i permessi necessari.</li>



<li><strong>Log di RabbitMQ:</strong><br>Consulta sempre i log del broker per capire se il problema è lato TLS, autenticazione, permessi o routing AMQP.</li>
</ul>



<p></p>



<p>Quando usi Proton con RabbitMQ in mTLS e AMQP 1.0, presta particolare attenzione a come imposti virtual host e SNI, e assicurati che i certificati siano corretti e ben referenziati. Una configurazione attenta ti eviterà la maggior parte dei problemi tipici di interoperabilità e sicurezza.</p>



<p>Per aumentare il livello di trace e debug, puoi anche abilitare il logging dettagliato in RabbitMQ e nella libreria Proton. Questo ti aiuterà a diagnosticare eventuali problemi di connessione o di autenticazione.</p>



<p>In questo progetto di esempio, RabbitMQ è gia configurato con il livello di log <code>debug</code>, quindi puoi vedere in tempo reale cosa succede quando il producer e il consumer si connettono e inviano/ricevono messaggi.</p>



<p>Per quanto riguarda Proton, puoi abilitare un logging dettagliato eseguendo l'export della variabile d'ambiente PN_TRACE_FRM con il valore <code>1</code> prima di eseguire gli script Python. Questo ti permetterà di vedere i dettagli di trace sul protocol frame. Per maggiori informazioni sul logging di Proton, puoi consultare la <a href="https://github.com/apache/qpid-proton/blob/main/c/docs/logging.md?plain=1">guida sul loggin pubblicata su GitHub</a>.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="export PN_TRACE_FRM=1" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">export</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">PN_TRACE_FRM</span><span style="color: #81A1C1">=</span><span style="color: #B48EAD">1</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Bash</span></div>



<p></p>



<p>In questo modo, potrai ottenere informazioni dettagliate su cosa sta accadendo durante la connessione e l'invio/ricezione dei messaggi. Questo è particolarmente utile per il debug e per comprendere meglio il funzionamento interno di Proton e RabbitMQ.</p>



<p>A seguire un esempio di output del trace:</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="[0x11af7a710]: SASL:FRAME:  -&gt; SASL
[0x11af7a710]: SASL:FRAME:  &lt;- SASL
[0x11af7a710]: AMQP:FRAME:0 &lt;- @sasl-mechanisms(64) [sasl-server-mechanisms=@&lt;symbol&gt;[:PLAIN, :AMQPLAIN, :ANONYMOUS]]
[0x11af7a710]: AMQP:FRAME:0 -&gt; @sasl-init(65) [mechanism=:PLAIN, initial-response=b&quot;\x00order_sender\x00OrderSenderP@ssw0rd&quot;]
[0x11af7a710]: AMQP:FRAME:0 &lt;- @sasl-outcome(68) 
[0x11af7a710]: AMQP:FRAME:  -&gt; AMQP
[0x11af7a710]: AMQP:FRAME:0 -&gt; @open(16) [container-id=&quot;c71222a8-93a9-498c-afac-2956a7b18892&quot;, hostname=&quot;vhost:logistics_vhost&quot;, max-frame-size=0x8000, channel-max=0x7fff]
[0x11af7a710]: AMQP:FRAME:0 -&gt; @begin(17) [next-outgoing-id=0x0, incoming-window=0x7fffffff, outgoing-window=0x7fffffff, handle-max=0x7fffffff]
[0x11af7a710]: AMQP:FRAME:0 -&gt; @attach(18) [name=&quot;c71222a8-93a9-498c-afac-2956a7b18892-/exchanges/order_exchange/new_order_event&quot;, handle=0x0, role=false, snd-settle-mode=0x2, rcv-settle-mode=0x0, source=@source(40) [durable=0x0, timeout=0x0, dynamic=false], target=@target(41) [address=&quot;/exchanges/order_exchange/new_order_event&quot;, durable=0x0, timeout=0x0, dynamic=false], initial-delivery-count=0x0, max-message-size=0x0]
[0x11af7a710]: AMQP:FRAME:  &lt;- AMQP
[0x11af7a710]: AMQP:FRAME:0 &lt;- @open(16) [container-id=&quot;rabbit@rabbitmq&quot;, max-frame-size=0x20000, channel-max=0x3f, idle-time-out=0x7530, offered-capabilities=@&lt;symbol&gt;[:&quot;LINK_PAIR_V1_0&quot;, :ANONYMOUS-RELAY], properties={:node=&quot;rabbit@rabbitmq&quot;, :&quot;cluster_name&quot;=&quot;rabbit@rabbitmq&quot;, :copyright=&quot;Copyright (c) 2007-2025 Broadcom Inc and/or its subsidiaries&quot;, :information=&quot;Licensed under the MPL 2.0. Website: https://rabbitmq.com&quot;, :platform=&quot;Erlang/OTP 27.3.4&quot;, :product=&quot;RabbitMQ&quot;, :version=&quot;4.1.0&quot;}]
[0x11af7a710]: AMQP:FRAME:0 &lt;- @begin(17) [remote-channel=0x0, next-outgoing-id=0xfffffffc, incoming-window=0x190, outgoing-window=0xffffffff, handle-max=0xff]
[0x11af7a710]: AMQP:FRAME:0 &lt;- @attach(18) [name=&quot;c71222a8-93a9-498c-afac-2956a7b18892-/exchanges/order_exchange/new_order_event&quot;, handle=0x0, role=true, snd-settle-mode=0x2, rcv-settle-mode=0x0, source=@source(40) [durable=0x0, timeout=0x0, dynamic=false], target=@target(41) [address=&quot;/exchanges/order_exchange/new_order_event&quot;, durable=0x0, timeout=0x0, dynamic=false], max-message-size=0x1000000]
[0x11af7a710]: AMQP:FRAME:0 &lt;- @flow(19) [next-incoming-id=0x0, incoming-window=0x190, next-outgoing-id=0xfffffffc, outgoing-window=0xffffffff, handle=0x0, delivery-count=0x0, link-credit=0xaa]
[0x11af7a710]: AMQP:FRAME:0 -&gt; @transfer(20) [handle=0x0, delivery-id=0x0, delivery-tag=b&quot;1&quot;, message-format=0x0] (147) \x00SpE\x00Ss\xc0\x19\x07@@@@@@\xa3\x10application/json\x00Sw\xa1l{\x22order_id\x22: \x22ORD_MTLS_3CF4CF72\x22, \x22item_id\x22: \x22ITEM_B_167\x22, \x22description\x22: \x22Brilliant Gadget\x22, \x22quantity\x22: 3}
[0x11af7a710]: AMQP:FRAME:0 &lt;- @disposition(21) [role=true, first=0x0, last=0x4, settled=true, state=@accepted(36) []]
[0x11af7a710]: AMQP:FRAME:0 -&gt; @close(24) []
[0x11af7a710]: AMQP:FRAME:0 &lt;- @close(24) []
[0x11af7a710]:   IO:FRAME:  &lt;- EOS
[0x11af7a710]:   IO:FRAME:  -&gt; EOS" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #d8dee9ff">[0x11af7a710]: SASL:FRAME:  -&gt; SASL</span></span>
<span class="line"><span style="color: #d8dee9ff">[0x11af7a710]: SASL:FRAME:  &lt;- SASL</span></span>
<span class="line"><span style="color: #d8dee9ff">[0x11af7a710]: AMQP:FRAME:0 &lt;- @sasl-mechanisms(64) [sasl-server-mechanisms=@&lt;symbol&gt;[:PLAIN, :AMQPLAIN, :ANONYMOUS]]</span></span>
<span class="line"><span style="color: #d8dee9ff">[0x11af7a710]: AMQP:FRAME:0 -&gt; @sasl-init(65) [mechanism=:PLAIN, initial-response=b&quot;\x00order_sender\x00OrderSenderP@ssw0rd&quot;]</span></span>
<span class="line"><span style="color: #d8dee9ff">[0x11af7a710]: AMQP:FRAME:0 &lt;- @sasl-outcome(68) </span></span>
<span class="line"><span style="color: #d8dee9ff">[0x11af7a710]: AMQP:FRAME:  -&gt; AMQP</span></span>
<span class="line"><span style="color: #d8dee9ff">[0x11af7a710]: AMQP:FRAME:0 -&gt; @open(16) [container-id=&quot;c71222a8-93a9-498c-afac-2956a7b18892&quot;, hostname=&quot;vhost:logistics_vhost&quot;, max-frame-size=0x8000, channel-max=0x7fff]</span></span>
<span class="line"><span style="color: #d8dee9ff">[0x11af7a710]: AMQP:FRAME:0 -&gt; @begin(17) [next-outgoing-id=0x0, incoming-window=0x7fffffff, outgoing-window=0x7fffffff, handle-max=0x7fffffff]</span></span>
<span class="line"><span style="color: #d8dee9ff">[0x11af7a710]: AMQP:FRAME:0 -&gt; @attach(18) [name=&quot;c71222a8-93a9-498c-afac-2956a7b18892-/exchanges/order_exchange/new_order_event&quot;, handle=0x0, role=false, snd-settle-mode=0x2, rcv-settle-mode=0x0, source=@source(40) [durable=0x0, timeout=0x0, dynamic=false], target=@target(41) [address=&quot;/exchanges/order_exchange/new_order_event&quot;, durable=0x0, timeout=0x0, dynamic=false], initial-delivery-count=0x0, max-message-size=0x0]</span></span>
<span class="line"><span style="color: #d8dee9ff">[0x11af7a710]: AMQP:FRAME:  &lt;- AMQP</span></span>
<span class="line"><span style="color: #d8dee9ff">[0x11af7a710]: AMQP:FRAME:0 &lt;- @open(16) [container-id=&quot;rabbit@rabbitmq&quot;, max-frame-size=0x20000, channel-max=0x3f, idle-time-out=0x7530, offered-capabilities=@&lt;symbol&gt;[:&quot;LINK_PAIR_V1_0&quot;, :ANONYMOUS-RELAY], properties={:node=&quot;rabbit@rabbitmq&quot;, :&quot;cluster_name&quot;=&quot;rabbit@rabbitmq&quot;, :copyright=&quot;Copyright (c) 2007-2025 Broadcom Inc and/or its subsidiaries&quot;, :information=&quot;Licensed under the MPL 2.0. Website: https://rabbitmq.com&quot;, :platform=&quot;Erlang/OTP 27.3.4&quot;, :product=&quot;RabbitMQ&quot;, :version=&quot;4.1.0&quot;}]</span></span>
<span class="line"><span style="color: #d8dee9ff">[0x11af7a710]: AMQP:FRAME:0 &lt;- @begin(17) [remote-channel=0x0, next-outgoing-id=0xfffffffc, incoming-window=0x190, outgoing-window=0xffffffff, handle-max=0xff]</span></span>
<span class="line"><span style="color: #d8dee9ff">[0x11af7a710]: AMQP:FRAME:0 &lt;- @attach(18) [name=&quot;c71222a8-93a9-498c-afac-2956a7b18892-/exchanges/order_exchange/new_order_event&quot;, handle=0x0, role=true, snd-settle-mode=0x2, rcv-settle-mode=0x0, source=@source(40) [durable=0x0, timeout=0x0, dynamic=false], target=@target(41) [address=&quot;/exchanges/order_exchange/new_order_event&quot;, durable=0x0, timeout=0x0, dynamic=false], max-message-size=0x1000000]</span></span>
<span class="line"><span style="color: #d8dee9ff">[0x11af7a710]: AMQP:FRAME:0 &lt;- @flow(19) [next-incoming-id=0x0, incoming-window=0x190, next-outgoing-id=0xfffffffc, outgoing-window=0xffffffff, handle=0x0, delivery-count=0x0, link-credit=0xaa]</span></span>
<span class="line"><span style="color: #d8dee9ff">[0x11af7a710]: AMQP:FRAME:0 -&gt; @transfer(20) [handle=0x0, delivery-id=0x0, delivery-tag=b&quot;1&quot;, message-format=0x0] (147) \x00SpE\x00Ss\xc0\x19\x07@@@@@@\xa3\x10application/json\x00Sw\xa1l{\x22order_id\x22: \x22ORD_MTLS_3CF4CF72\x22, \x22item_id\x22: \x22ITEM_B_167\x22, \x22description\x22: \x22Brilliant Gadget\x22, \x22quantity\x22: 3}</span></span>
<span class="line"><span style="color: #d8dee9ff">[0x11af7a710]: AMQP:FRAME:0 &lt;- @disposition(21) [role=true, first=0x0, last=0x4, settled=true, state=@accepted(36) []]</span></span>
<span class="line"><span style="color: #d8dee9ff">[0x11af7a710]: AMQP:FRAME:0 -&gt; @close(24) []</span></span>
<span class="line"><span style="color: #d8dee9ff">[0x11af7a710]: AMQP:FRAME:0 &lt;- @close(24) []</span></span>
<span class="line"><span style="color: #d8dee9ff">[0x11af7a710]:   IO:FRAME:  &lt;- EOS</span></span>
<span class="line"><span style="color: #d8dee9ff">[0x11af7a710]:   IO:FRAME:  -&gt; EOS</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Plaintext</span></div>



<p></p>



<p>Nel caso fosse necessario, puoi sempre consultare la <a href="https://www.rabbitmq.com/">documentazione ufficiale di RabbitMQ</a> e <a href="https://qpid.apache.org/proton/index.html">Qpid Proton</a> per ulteriori dettagli e best practices.</p>



<h2 class="wp-block-heading" id="esecuzione-di-producer-e-consumer-tramite-makefile">Esecuzione di Producer e Consumer tramite Makefile</h2>



<p>Il Makefile non solo automatizza la configurazione dell'ambiente, ma semplifica anche l'esecuzione degli script Python di producer e consumer. Questo è particolarmente utile per testare rapidamente le modifiche o per dimostrazioni.</p>



<h3 class="wp-block-heading" id="installazione-delle-dipendenze-python">Installazione delle dipendenze Python</h3>



<p>Prima di poter eseguire il producer o il consumer, assicurati che:</p>



<ol class="wp-block-list">
<li>L'ambiente RabbitMQ sia completamente configurato e in esecuzione. Puoi ottenere questo risultato con il comando <code>make all</code>. Questo comando si occuperà di generare i certificati, avviare il container RabbitMQ, e configurare vhost, utenti, permessi e la topologia necessaria (exchange, code, binding).</li>



<li>Le dipendenze Python per gli script siano installate. Il Makefile fornisce un target per generare il file <code>requirements.txt</code> usando il comando: <code>make requirements</code>. Una volta generato, puoi installare le dipendenze (preferibilmente in un ambiente virtuale Python) usando il comando: <code>pip install -r requirements.txt</code></li>
</ol>



<p>In questo modo, l'utente viene guidato a installare le dipendenze necessarie prima di tentare di eseguire gli script, prevenendo errori comuni.</p>



<h3 class="wp-block-heading" id="avviare-il-producer">Avviare il Producer</h3>



<p>Per avviare lo script Python che funge da producer e invia messaggi a RabbitMQ, esegui:</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="make producer" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">make</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">producer</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Bash</span></div>



<p></p>



<p>Questo comando eseguirà lo script <code>producer.py</code>, che si connetterà a RabbitMQ utilizzando i certificati generati e inizierà a inviare messaggi di "nuovi ordini" all'exchange configurato (<code>/exchanges/order_exchange/new_order_event</code>).</p>



<p>A seguire un esempio di output del producer:</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="Running Producer Python script...
Producer: Generating 5 random orders...
Producer: Starting container to send 5 message(s)...
Producer: Starting, connecting to amqps://rabbitmq.labs.dontesta.it:5671/, target: /exchanges/order_exchange/new_order_event
Producer: SSL domain configured successfully.
Producer: Attempting mTLS connection to amqps://rabbitmq.labs.dontesta.it:5671/ with user order_sender on vhost vhost:logistics_vhost
Producer: mTLS connection initiated, vhost set to vhost:logistics_vhost
Producer: Sender created for target '/exchanges/order_exchange/new_order_event'
Producer: Message sent (1/5): {'order_id': 'ORD_MTLS_A3737866', 'item_id': 'ITEM_C_561', 'description': 'Cool Gizmo', 'quantity': 8}
Producer: Message sent (2/5): {'order_id': 'ORD_MTLS_FE742F82', 'item_id': 'ITEM_C_970', 'description': 'Cool Gizmo', 'quantity': 4}
Producer: Message sent (3/5): {'order_id': 'ORD_MTLS_07104306', 'item_id': 'ITEM_A_954', 'description': 'Amazing Widget', 'quantity': 4}
Producer: Message sent (4/5): {'order_id': 'ORD_MTLS_2BF2F2CC', 'item_id': 'ITEM_A_238', 'description': 'Amazing Widget', 'quantity': 4}
Producer: Message sent (5/5): {'order_id': 'ORD_MTLS_C22EAF68', 'item_id': 'ITEM_E_438', 'description': 'Elegant Contraption', 'quantity': 7}
Producer: Message accepted by broker. Confirmed: 1/5
Producer: Message accepted by broker. Confirmed: 2/5
Producer: Message accepted by broker. Confirmed: 3/5
Producer: Message accepted by broker. Confirmed: 4/5
Producer: Message accepted by broker. Confirmed: 5/5
Producer: All messages have been confirmed.
Producer: Container execution finished." style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #d8dee9ff">Running Producer Python script...</span></span>
<span class="line"><span style="color: #d8dee9ff">Producer: Generating 5 random orders...</span></span>
<span class="line"><span style="color: #d8dee9ff">Producer: Starting container to send 5 message(s)...</span></span>
<span class="line"><span style="color: #d8dee9ff">Producer: Starting, connecting to amqps://rabbitmq.labs.dontesta.it:5671/, target: /exchanges/order_exchange/new_order_event</span></span>
<span class="line"><span style="color: #d8dee9ff">Producer: SSL domain configured successfully.</span></span>
<span class="line"><span style="color: #d8dee9ff">Producer: Attempting mTLS connection to amqps://rabbitmq.labs.dontesta.it:5671/ with user order_sender on vhost vhost:logistics_vhost</span></span>
<span class="line"><span style="color: #d8dee9ff">Producer: mTLS connection initiated, vhost set to vhost:logistics_vhost</span></span>
<span class="line"><span style="color: #d8dee9ff">Producer: Sender created for target &#39;/exchanges/order_exchange/new_order_event&#39;</span></span>
<span class="line"><span style="color: #d8dee9ff">Producer: Message sent (1/5): {&#39;order_id&#39;: &#39;ORD_MTLS_A3737866&#39;, &#39;item_id&#39;: &#39;ITEM_C_561&#39;, &#39;description&#39;: &#39;Cool Gizmo&#39;, &#39;quantity&#39;: 8}</span></span>
<span class="line"><span style="color: #d8dee9ff">Producer: Message sent (2/5): {&#39;order_id&#39;: &#39;ORD_MTLS_FE742F82&#39;, &#39;item_id&#39;: &#39;ITEM_C_970&#39;, &#39;description&#39;: &#39;Cool Gizmo&#39;, &#39;quantity&#39;: 4}</span></span>
<span class="line"><span style="color: #d8dee9ff">Producer: Message sent (3/5): {&#39;order_id&#39;: &#39;ORD_MTLS_07104306&#39;, &#39;item_id&#39;: &#39;ITEM_A_954&#39;, &#39;description&#39;: &#39;Amazing Widget&#39;, &#39;quantity&#39;: 4}</span></span>
<span class="line"><span style="color: #d8dee9ff">Producer: Message sent (4/5): {&#39;order_id&#39;: &#39;ORD_MTLS_2BF2F2CC&#39;, &#39;item_id&#39;: &#39;ITEM_A_238&#39;, &#39;description&#39;: &#39;Amazing Widget&#39;, &#39;quantity&#39;: 4}</span></span>
<span class="line"><span style="color: #d8dee9ff">Producer: Message sent (5/5): {&#39;order_id&#39;: &#39;ORD_MTLS_C22EAF68&#39;, &#39;item_id&#39;: &#39;ITEM_E_438&#39;, &#39;description&#39;: &#39;Elegant Contraption&#39;, &#39;quantity&#39;: 7}</span></span>
<span class="line"><span style="color: #d8dee9ff">Producer: Message accepted by broker. Confirmed: 1/5</span></span>
<span class="line"><span style="color: #d8dee9ff">Producer: Message accepted by broker. Confirmed: 2/5</span></span>
<span class="line"><span style="color: #d8dee9ff">Producer: Message accepted by broker. Confirmed: 3/5</span></span>
<span class="line"><span style="color: #d8dee9ff">Producer: Message accepted by broker. Confirmed: 4/5</span></span>
<span class="line"><span style="color: #d8dee9ff">Producer: Message accepted by broker. Confirmed: 5/5</span></span>
<span class="line"><span style="color: #d8dee9ff">Producer: All messages have been confirmed.</span></span>
<span class="line"><span style="color: #d8dee9ff">Producer: Container execution finished.</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Plaintext</span></div>



<p></p>



<p>In questo esempio, il producer genera 5 ordini casuali e li invia a RabbitMQ. Ogni messaggio viene confermato dal broker, garantendo che sia stato ricevuto correttamente.</p>



<h3 class="wp-block-heading" id="avviare-il-consumer">Avviare il Consumer</h3>



<p>Per avviare lo script Python che funge da consumer e riceve messaggi da RabbitMQ, esegui:</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="make consumer" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">make</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">consumer</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Bash</span></div>



<p></p>



<p>Questo comando eseguirà lo script <code>consumer.py</code>, che si connetterà a RabbitMQ utilizzando i certificati generati e inizierà a ricevere messaggi dalla coda configurata (<code>/queues/logistics_queue</code>).</p>



<p>A seguire un esempio di output del consumer:</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="Running Consumer Python script...
Consumer: Starting container to receive messages (Ctrl+C to interrupt)...
Consumer: Starting, connecting to amqps://rabbitmq.labs.dontesta.it:5671, source: /queues/logistics_queue
Consumer: SSL domain configured successfully.
Consumer: Attempting mTLS connection to amqps://rabbitmq.labs.dontesta.it:5671 with user delivery_receiver on vhost vhost:logistics_vhost
Consumer: mTLS connection initiated, vhost set to vhost:logistics_vhost
Consumer: Receiver created for source '/queues/logistics_queue'
--------------------
Consumer: New message received! (Total: 1)
Consumer: Content: {'order_id': 'ORD_MTLS_A3737866', 'item_id': 'ITEM_C_561', 'description': 'Cool Gizmo', 'quantity': 8}
Consumer: Order processed.
Consumer: Message confirmed (accepted).
--------------------
--------------------
Consumer: New message received! (Total: 2)
Consumer: Content: {'order_id': 'ORD_MTLS_FE742F82', 'item_id': 'ITEM_C_970', 'description': 'Cool Gizmo', 'quantity': 4}
Consumer: Order processed.
Consumer: Message confirmed (accepted).
--------------------
--------------------
Consumer: New message received! (Total: 3)
Consumer: Content: {'order_id': 'ORD_MTLS_07104306', 'item_id': 'ITEM_A_954', 'description': 'Amazing Widget', 'quantity': 4}
Consumer: Order processed.
Consumer: Message confirmed (accepted).
--------------------
--------------------
Consumer: New message received! (Total: 4)
Consumer: Content: {'order_id': 'ORD_MTLS_2BF2F2CC', 'item_id': 'ITEM_A_238', 'description': 'Amazing Widget', 'quantity': 4}
Consumer: Order processed.
Consumer: Message confirmed (accepted).
--------------------
--------------------
Consumer: New message received! (Total: 5)
Consumer: Content: {'order_id': 'ORD_MTLS_C22EAF68', 'item_id': 'ITEM_E_438', 'description': 'Elegant Contraption', 'quantity': 7}
Consumer: Order processed.
Consumer: Message confirmed (accepted).
--------------------
Consumer: Reception interrupted by user.
Consumer: Container execution finished.
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #d8dee9ff">Running Consumer Python script...</span></span>
<span class="line"><span style="color: #d8dee9ff">Consumer: Starting container to receive messages (Ctrl+C to interrupt)...</span></span>
<span class="line"><span style="color: #d8dee9ff">Consumer: Starting, connecting to amqps://rabbitmq.labs.dontesta.it:5671, source: /queues/logistics_queue</span></span>
<span class="line"><span style="color: #d8dee9ff">Consumer: SSL domain configured successfully.</span></span>
<span class="line"><span style="color: #d8dee9ff">Consumer: Attempting mTLS connection to amqps://rabbitmq.labs.dontesta.it:5671 with user delivery_receiver on vhost vhost:logistics_vhost</span></span>
<span class="line"><span style="color: #d8dee9ff">Consumer: mTLS connection initiated, vhost set to vhost:logistics_vhost</span></span>
<span class="line"><span style="color: #d8dee9ff">Consumer: Receiver created for source &#39;/queues/logistics_queue&#39;</span></span>
<span class="line"><span style="color: #d8dee9ff">--------------------</span></span>
<span class="line"><span style="color: #d8dee9ff">Consumer: New message received! (Total: 1)</span></span>
<span class="line"><span style="color: #d8dee9ff">Consumer: Content: {&#39;order_id&#39;: &#39;ORD_MTLS_A3737866&#39;, &#39;item_id&#39;: &#39;ITEM_C_561&#39;, &#39;description&#39;: &#39;Cool Gizmo&#39;, &#39;quantity&#39;: 8}</span></span>
<span class="line"><span style="color: #d8dee9ff">Consumer: Order processed.</span></span>
<span class="line"><span style="color: #d8dee9ff">Consumer: Message confirmed (accepted).</span></span>
<span class="line"><span style="color: #d8dee9ff">--------------------</span></span>
<span class="line"><span style="color: #d8dee9ff">--------------------</span></span>
<span class="line"><span style="color: #d8dee9ff">Consumer: New message received! (Total: 2)</span></span>
<span class="line"><span style="color: #d8dee9ff">Consumer: Content: {&#39;order_id&#39;: &#39;ORD_MTLS_FE742F82&#39;, &#39;item_id&#39;: &#39;ITEM_C_970&#39;, &#39;description&#39;: &#39;Cool Gizmo&#39;, &#39;quantity&#39;: 4}</span></span>
<span class="line"><span style="color: #d8dee9ff">Consumer: Order processed.</span></span>
<span class="line"><span style="color: #d8dee9ff">Consumer: Message confirmed (accepted).</span></span>
<span class="line"><span style="color: #d8dee9ff">--------------------</span></span>
<span class="line"><span style="color: #d8dee9ff">--------------------</span></span>
<span class="line"><span style="color: #d8dee9ff">Consumer: New message received! (Total: 3)</span></span>
<span class="line"><span style="color: #d8dee9ff">Consumer: Content: {&#39;order_id&#39;: &#39;ORD_MTLS_07104306&#39;, &#39;item_id&#39;: &#39;ITEM_A_954&#39;, &#39;description&#39;: &#39;Amazing Widget&#39;, &#39;quantity&#39;: 4}</span></span>
<span class="line"><span style="color: #d8dee9ff">Consumer: Order processed.</span></span>
<span class="line"><span style="color: #d8dee9ff">Consumer: Message confirmed (accepted).</span></span>
<span class="line"><span style="color: #d8dee9ff">--------------------</span></span>
<span class="line"><span style="color: #d8dee9ff">--------------------</span></span>
<span class="line"><span style="color: #d8dee9ff">Consumer: New message received! (Total: 4)</span></span>
<span class="line"><span style="color: #d8dee9ff">Consumer: Content: {&#39;order_id&#39;: &#39;ORD_MTLS_2BF2F2CC&#39;, &#39;item_id&#39;: &#39;ITEM_A_238&#39;, &#39;description&#39;: &#39;Amazing Widget&#39;, &#39;quantity&#39;: 4}</span></span>
<span class="line"><span style="color: #d8dee9ff">Consumer: Order processed.</span></span>
<span class="line"><span style="color: #d8dee9ff">Consumer: Message confirmed (accepted).</span></span>
<span class="line"><span style="color: #d8dee9ff">--------------------</span></span>
<span class="line"><span style="color: #d8dee9ff">--------------------</span></span>
<span class="line"><span style="color: #d8dee9ff">Consumer: New message received! (Total: 5)</span></span>
<span class="line"><span style="color: #d8dee9ff">Consumer: Content: {&#39;order_id&#39;: &#39;ORD_MTLS_C22EAF68&#39;, &#39;item_id&#39;: &#39;ITEM_E_438&#39;, &#39;description&#39;: &#39;Elegant Contraption&#39;, &#39;quantity&#39;: 7}</span></span>
<span class="line"><span style="color: #d8dee9ff">Consumer: Order processed.</span></span>
<span class="line"><span style="color: #d8dee9ff">Consumer: Message confirmed (accepted).</span></span>
<span class="line"><span style="color: #d8dee9ff">--------------------</span></span>
<span class="line"><span style="color: #d8dee9ff">Consumer: Reception interrupted by user.</span></span>
<span class="line"><span style="color: #d8dee9ff">Consumer: Container execution finished.</span></span>
<span class="line"><span style="color: #d8dee9ff"></span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Plaintext</span></div>



<p></p>



<p>In questo esempio, il consumer riceve i messaggi dalla coda e li elabora uno alla volta. Ogni messaggio viene confermato dopo l'elaborazione, garantendo che non venga perso. Il consumer continua a ricevere messaggi fino a quando non viene interrotto manualmente (Ctrl+C).</p>



<h2 class="wp-block-heading" id="conclusione">Conclusione</h2>



<p>Abbiamo reso la configurazione di RabbitMQ 4.1 più sicura ed efficiente integrando mTLS, che abilita l’autenticazione reciproca tra client e server. Abbiamo mostrato come generare i certificati necessari, configurare RabbitMQ per la verifica dei client, e realizzare due script Python, producer e consumer, capaci di comunicare in modo sicuro tramite AMQP 1.0.</p>



<p>Inoltre, abbiamo evidenziato il valore del Makefile nell’automatizzare la generazione dei certificati e la gestione del container, semplificando il setup e riducendo il rischio di errori manuali.</p>



<p>Sono stati evidenziati alcuni punti critici da tenere a mente quando si lavora con RabbitMQ, AMQP 1.0 e mTLS, come la corretta configurazione dei virtual host, l'uso di SNI e la gestione dei certificati. </p>



<p>Questa configurazione non solo migliora la sicurezza della tua applicazione event-driven, ma ti prepara anche a scenari di produzione reali, dove la sicurezza e l'affidabilità sono fondamentali.</p>
<p>L'articolo <a href="https://www.dontesta.it/2025/05/18/rabbitmq-4-1-mtls-e-amqp-1-0-guida-essenziale-per-sviluppatori/">RabbitMQ 4.1 mTLS e AMQP 1.0: Guida essenziale per sviluppatori</a> sembra essere il primo su <a href="https://www.dontesta.it">Antonio Musarra&#039;s Blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.dontesta.it/2025/05/18/rabbitmq-4-1-mtls-e-amqp-1-0-guida-essenziale-per-sviluppatori/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>GitHub Actions: Build e Push di Immagini Container con Quarkus CLI</title>
		<link>https://www.dontesta.it/2025/02/18/github-actions-build-e-push-di-immagini-container-con-quarkus-cli/</link>
					<comments>https://www.dontesta.it/2025/02/18/github-actions-build-e-push-di-immagini-container-con-quarkus-cli/#respond</comments>
		
		<dc:creator><![CDATA[Antonio Musarra]]></dc:creator>
		<pubDate>Tue, 18 Feb 2025 21:45:37 +0000</pubDate>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Containers]]></category>
		<guid isPermaLink="false">https://www.dontesta.it/?p=5859</guid>

					<description><![CDATA[<p>Questo articolo nasce come compendio dell'articolo&#160;Quarkus: guida avanzata per il deploy su OpenShift&#160;pubblicato su Codemotion Magazine. Qui approfondiamo l'automazione della build e distribuzione di immagini native con GitHub Actions e Quarkus CLI, fornendo una&#46;&#46;&#46;</p>
<p>L'articolo <a href="https://www.dontesta.it/2025/02/18/github-actions-build-e-push-di-immagini-container-con-quarkus-cli/">GitHub Actions: Build e Push di Immagini Container con Quarkus CLI</a> sembra essere il primo su <a href="https://www.dontesta.it">Antonio Musarra&#039;s Blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Questo articolo nasce come compendio dell'articolo&nbsp;<strong><a href="https://bit.ly/4gPhcm5" target="_blank" rel="noreferrer noopener">Quarkus: guida avanzata per il deploy su OpenShift</a></strong>&nbsp;pubblicato su Codemotion Magazine. Qui approfondiamo l'automazione della build e distribuzione di immagini native con <strong>GitHub Actions</strong> e <strong>Quarkus CLI</strong>, fornendo una guida pratica all'implementazione di una pipeline CI/CD efficace.</p>



<p>L'automazione del processo di build e distribuzione di immagini native rappresenta un elemento chiave nell'ottimizzazione del ciclo di sviluppo e rilascio di applicazioni. Questo articolo analizza come&nbsp;GitHub Actions&nbsp;possa essere sfruttato per orchestrare la build e la pubblicazione di immagini native di applicazioni Quarkus, utilizzando&nbsp;Quarkus CLI.</p>



<p>Il workflow descritto è implementato nel progetto&nbsp;<a href="https://github.com/amusarra/quarkus-graphql-quickstart">quarkus-graphql-quickstart</a>&nbsp;e si occupa di generare un'immagine nativa e distribuirla su un container registry. L'obiettivo principale è garantire efficienza, riproducibilità e scalabilità, minimizando l'intervento manuale nel processo di deployment.</p>



<h2 class="wp-block-heading">Configurazione della GitHub Action</h2>



<p>Il workflow è definito nel file&nbsp;<code><a href="https://github.com/amusarra/quarkus-graphql-quickstart/blob/main/.github/workflows/docker_publish_native_quarkus_cli.yml">docker_publish_native_quarkus_cli.yml</a></code>. Di seguito, ne analizziamo le componenti principali, esplorando ogni aspetto in dettaglio.</p>



<p>Nella nostra GitHub Action, utilizziamo&nbsp;Quarkus CLI&nbsp;al posto di&nbsp;Maven&nbsp;per diversi motivi. Quarkus CLI offre un approccio più astratto rispetto a Maven, specialmente quando si lavora con diversi strumenti di build. Ecco alcuni motivi per preferire Quarkus CLI a Maven nelle pipeline:</p>



<ul class="wp-block-list">
<li><strong>Astrazione dello strumento di build:</strong> Quarkus CLI permette di interagire con progetti sia Maven che Gradle allo stesso modo. Questo significa che i comandi rimangono consistenti indipendentemente dal sistema di build sottostante.</li>



<li><strong>Gestione semplificata delle estensioni:</strong> Quarkus CLI fornisce comandi intuitivi per trovare, aggiungere e rimuovere estensioni Quarkus, semplificando la gestione delle dipendenze del progetto.</li>



<li><strong>Coerenza:</strong> L'uso di Quarkus CLI garantisce una maggiore coerenza tra i diversi progetti, specialmente in ambienti dove sia Maven che Gradle sono utilizzati.</li>
</ul>



<p>In sintesi, l'uso di Quarkus CLI può semplificare e uniformare le operazioni di build, rendendo le pipeline più manutenibili e meno dipendenti dallo strumento di build specifico del progetto.</p>



<h3 class="wp-block-heading">Eventi Trigger</h3>



<p>Gli eventi trigger determinano quando la pipeline viene eseguita automaticamente. In questo caso, la pipeline si attiva nei seguenti scenari:</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="on:
  push:
    branches:
      - develop
      - main
  release:
    types: [ published ]" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">on</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #8FBCBB">push</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #8FBCBB">branches</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">develop</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">main</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #8FBCBB">release</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #8FBCBB">types</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">[</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">published</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">]</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">YAML</span></div>



<p></p>



<ul class="wp-block-list">
<li><strong>Push su&nbsp;</strong><code><strong>develop</strong></code><strong>&nbsp;e&nbsp;</strong><code><strong>main</strong></code>: ogni volta che viene effettuato un push su queste branch, il workflow viene avviato per garantire che le ultime modifiche siano costruite e pubblicate immediatamente. Questo aiuta a mantenere aggiornate le immagini e a testare il codice più recente.</li>



<li><strong>Pubblicazione di una release</strong>: quando viene pubblicata una nuova release, la pipeline si avvia automaticamente per costruire e distribuire un'immagine nativa basata sul codice stabile della release. Questo garantisce che le versioni ufficiali dell'applicazione siano immediatamente disponibili per l'uso in produzione.</li>
</ul>



<h3 class="wp-block-heading">Configurazione dei Job</h3>



<p>La configurazione dei job definisce l'ambiente e la strategia di esecuzione della pipeline. In questo caso, il workflow utilizza una matrice di esecuzione per garantire compatibilità su diverse piattaforme e architetture.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="jobs:
  docker:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ 'ubuntu-24.04', 'ubuntu-24.04-arm' ]
        include:
          - os: ubuntu-24.04
            current_platform: 'amd64'
          - os: ubuntu-24.04-arm
            current_platform: 'arm64'" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #8FBCBB">jobs</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #8FBCBB">docker</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #8FBCBB">runs-on</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">${{ matrix.os }}</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #8FBCBB">strategy</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #8FBCBB">matrix</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #8FBCBB">os</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">[</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">ubuntu-24.04</span><span style="color: #ECEFF4">&#39;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">ubuntu-24.04-arm</span><span style="color: #ECEFF4">&#39;</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">]</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #8FBCBB">include</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">os</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ubuntu-24.04</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #8FBCBB">current_platform</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">amd64</span><span style="color: #ECEFF4">&#39;</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">os</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ubuntu-24.04-arm</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #8FBCBB">current_platform</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">arm64</span><span style="color: #ECEFF4">&#39;</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">YAML</span></div>



<p></p>



<p>Ogni job viene eseguito su uno dei due ambienti definiti nella matrice:&nbsp;<strong>Ubuntu 24.04 per AMD64</strong>&nbsp;e&nbsp;<strong>Ubuntu 24.04 per ARM64</strong>. La strategia della matrice permette di eseguire il workflow su entrambe le architetture contemporaneamente, assicurando che il codice sia compatibile sia con sistemi x86_64 che ARM.</p>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/26a0.png" alt="⚠" class="wp-smiley" style="height: 1em; max-height: 1em;" />&nbsp;<strong>Nota:</strong>&nbsp;<em>L'esecuzione su Linux ARM64 è attualmente in anteprima pubblica ed è soggetta a modifiche. L'uso di questa architettura consente di testare e ottimizzare le prestazioni dell'applicazione su dispositivi ARM, sempre più diffusi in ambito cloud e edge computing.</em> Per maggiori informazioni fare riferimento alla documentazione <a href="https://docs.github.com/en/actions/using-github-hosted-runners/using-github-hosted-runners/about-github-hosted-runners">About GitHub-hosted runners</a>.</p>



<p>Questa strategia garantisce compatibilità con diverse architetture hardware, migliorando la portabilità dell'applicazione.</p>



<h2 class="wp-block-heading">Passaggi della Pipeline</h2>



<p>La pipeline è composta da una serie di step che permettono di automatizzare il processo di build e distribuzione dell’applicazione. Ogni step viene eseguito sequenzialmente per garantire che il codice venga recuperato, compilato, testato e infine pubblicato come immagine container.</p>



<h3 class="wp-block-heading">1. Clonazione del Repository</h3>



<p>Il primo step assicura che il codice sorgente più recente sia disponibile per la pipeline.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="- uses: actions/checkout@v3
  with:
    fetch-depth: 0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #ECEFF4">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">uses</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">actions/checkout@v3</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #8FBCBB">with</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #8FBCBB">fetch-depth</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">YAML</span></div>



<p></p>



<p><strong>Cosa fa il primo step?</strong></p>



<ul class="wp-block-list">
<li>Clona l’intero repository, garantendo accesso alla cronologia completa dei commit.</li>



<li>Il valore fetch-depth: 0 permette di recuperare tutti i commit, utile per calcoli di differenza tra versioni.</li>
</ul>



<h3 class="wp-block-heading">2. Configurazione di GraalVM</h3>



<p>GraalVM è essenziale per la creazione di immagini native altamente ottimizzate, riducendo il tempo di avvio e il consumo di memoria dell'applicazione. Per approfondimenti sulla configurazione della GitHub Action <code>graalvm/setup-graalvm@v1</code>, consulta la <a href="https://github.com/graalvm/setup-graalvm">documentazione ufficiale</a>.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="- name: Set up GraalVM
  uses: graalvm/setup-graalvm@v1
  with:
    java-version: '23.0.2'
    distribution: 'graalvm'
    github-token: ${{ secrets.TOKEN_GITHUB }}
    native-image-job-reports: 'true'" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #ECEFF4">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">name</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Set up GraalVM</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #8FBCBB">uses</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">graalvm/setup-graalvm@v1</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #8FBCBB">with</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #8FBCBB">java-version</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">23.0.2</span><span style="color: #ECEFF4">&#39;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #8FBCBB">distribution</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">graalvm</span><span style="color: #ECEFF4">&#39;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #8FBCBB">github-token</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">${{ secrets.TOKEN_GITHUB }}</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #8FBCBB">native-image-job-reports</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">true</span><span style="color: #ECEFF4">&#39;</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">YAML</span></div>



<p></p>



<p><strong>Cosa fa questo secondo step?</strong></p>



<ul class="wp-block-list">
<li>Installa e configura GraalVM per l’ambiente di esecuzione.</li>



<li>Imposta Java 23.0.2 e attiva la generazione di report per la build nativa.</li>
</ul>



<h3 class="wp-block-heading">3. Installazione di JBang e Quarkus CLI</h3>



<p>Quarkus CLI consente di gestire e costruire applicazioni Quarkus in modo efficiente, semplificando la gestione delle dipendenze e delle configurazioni.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="- name: Install JBang and Quarkus CLI
  run: |
    curl -Ls https://sh.jbang.dev | bash -s - trust add https://repo1.maven.org/maven2/io/quarkus/quarkus-cli/
    curl -Ls https://sh.jbang.dev | bash -s - app install --fresh --force quarkus@quarkusio
    echo &quot;PATH=$PATH:/home/runner/.jbang/bin&quot; &gt;&gt; $GITHUB_ENV" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #ECEFF4">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">name</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Install JBang and Quarkus CLI</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #8FBCBB">run</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">|</span></span>
<span class="line"><span style="color: #A3BE8C">    curl -Ls https://sh.jbang.dev | bash -s - trust add https://repo1.maven.org/maven2/io/quarkus/quarkus-cli/</span></span>
<span class="line"><span style="color: #A3BE8C">    curl -Ls https://sh.jbang.dev | bash -s - app install --fresh --force quarkus@quarkusio</span></span>
<span class="line"><span style="color: #A3BE8C">    echo &quot;PATH=$PATH:/home/runner/.jbang/bin&quot; &gt;&gt; $GITHUB_ENV</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">YAML</span></div>



<p></p>



<p>&nbsp;<strong>Cosa fa questo terzo step?</strong></p>



<ul class="wp-block-list">
<li>Installa JBang, un tool per la gestione di script Java.</li>



<li>Installa e configura Quarkus CLI per eseguire build e gestire le dipendenze.</li>
</ul>



<p>Per ulteriori dettagli sull’installazione della Quarkus CLI, consulta la <a href="https://quarkus.io/guides/cli-tooling">documentazione ufficiale</a>.</p>



<h3 class="wp-block-heading">4. Autenticazione su Docker Hub</h3>



<p>Prima di pubblicare l’immagine container, è necessario effettuare l’accesso a Docker Hub.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="- name: Login to Docker Hub
  uses: docker/login-action@v3
  with:
    username: ${{ secrets.DOCKER_USERNAME }}
    password: ${{ secrets.DOCKER_TOKEN }}" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #ECEFF4">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">name</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Login to Docker Hub</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #8FBCBB">uses</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">docker/login-action@v3</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #8FBCBB">with</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #8FBCBB">username</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">${{ secrets.DOCKER_USERNAME }}</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #8FBCBB">password</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">${{ secrets.DOCKER_TOKEN }}</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">YAML</span></div>



<p></p>



<p><strong>Cosa fa questo quarto step?</strong></p>



<ul class="wp-block-list">
<li>Usa le credenziali salvate nei <strong>GitHub Secrets</strong> per effettuare il login a Docker Hub.</li>



<li>Questo passaggio è fondamentale per poter pubblicare l’immagine nel repository remoto.</li>
</ul>



<p>Per approfondimenti sulla gestione dei secrets in GitHub Actions, consulta la <a href="https://docs.github.com/en/actions/security-guides/encrypted-secrets">documentazione ufficiale</a>.</p>



<h3 class="wp-block-heading">5. Creazione dell’artefatto nativo</h3>



<p>Questo step compila l’applicazione in un eseguibile nativo utilizzando Quarkus CLI.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="- name: Build Native Artifact
  run: |
    quarkus build --native" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #ECEFF4">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">name</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Build Native Artifact</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #8FBCBB">run</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">|</span></span>
<span class="line"><span style="color: #A3BE8C">    quarkus build --native</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">YAML</span></div>



<p></p>



<p><strong>Cosa fa questo quinto step?</strong></p>



<ul class="wp-block-list">
<li>Compila il codice sorgente generando un eseguibile nativo altamente performante.</li>



<li>Il codice risultante è ottimizzato per ridurre il consumo di memoria e migliorare il tempo di avvio.</li>
</ul>



<h3 class="wp-block-heading">6. Creazione e pubblicazione dell’immagine Docker</h3>



<p>Infine, il codice compilato viene trasformato in un’immagine container e pubblicato su Docker Hub.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# Build the native image and push the Docker image
- name: Build Native Image and Push Docker Image
  run: |
    quarkus image build --native \
    -Dquarkus.native.additional-build-args=-march=native,-H:BuildOutputJSONFile=/tmp/native-image-build-output.json \
    -Dquarkus.native.container-build=false \
    -Dquarkus.container-image.push=true \
    -Dquarkus.container-image.registry=docker.io \
    -Dquarkus.container-image.username=${{ secrets.DOCKER_USERNAME }} \
    -Dquarkus.container-image.image=${{ secrets.DOCKER_USERNAME }}/${{ github.event.repository.name }}-native:${{ github.ref_name }}-${{ matrix.current_platform }} \
    -Dquarkus.container-image.additional-tags=&quot;latest-${{ matrix.current_platform }}&quot; \
    -Dquarkus.container-image.labels.\&quot;org.opencontainers.image.title\&quot;=&quot;${{ github.event.repository.name }}&quot; \
    -Dquarkus.container-image.labels.\&quot;org.opencontainers.image.description\&quot;=&quot;A native image built with Quarkus CLI&quot; \
    -Dquarkus.container-image.labels.\&quot;org.opencontainers.image.url\&quot;=&quot;https://github.com/${{ github.repository }}&quot; \
    -Dquarkus.container-image.labels.\&quot;org.opencontainers.image.source\&quot;=&quot;https://github.com/${{ github.repository }}&quot; \
    -Dquarkus.container-image.labels.\&quot;org.opencontainers.image.version\&quot;=&quot;${{ github.ref_name }}&quot; \
    -Dquarkus.container-image.labels.\&quot;org.opencontainers.image.created\&quot;=&quot;${{ steps.prep.outputs.created }}&quot; \
    -Dquarkus.container-image.labels.\&quot;org.opencontainers.image.revision\&quot;=&quot;${{ github.sha }}&quot; \
    -Dquarkus.container-image.labels.\&quot;org.opencontainers.image.authors\&quot;=&quot;Antonio Musarra &lt;antonio.musarra@gmail.com&gt;&quot; \
    -Dquarkus.container-image.labels.\&quot;org.opencontainers.image.licenses\&quot;=&quot;MIT&quot;" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88"># Build the native image and push the Docker image</span></span>
<span class="line"><span style="color: #ECEFF4">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">name</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Build Native Image and Push Docker Image</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #8FBCBB">run</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">|</span></span>
<span class="line"><span style="color: #A3BE8C">    quarkus image build --native \</span></span>
<span class="line"><span style="color: #A3BE8C">    -Dquarkus.native.additional-build-args=-march=native,-H:BuildOutputJSONFile=/tmp/native-image-build-output.json \</span></span>
<span class="line"><span style="color: #A3BE8C">    -Dquarkus.native.container-build=false \</span></span>
<span class="line"><span style="color: #A3BE8C">    -Dquarkus.container-image.push=true \</span></span>
<span class="line"><span style="color: #A3BE8C">    -Dquarkus.container-image.registry=docker.io \</span></span>
<span class="line"><span style="color: #A3BE8C">    -Dquarkus.container-image.username=${{ secrets.DOCKER_USERNAME }} \</span></span>
<span class="line"><span style="color: #A3BE8C">    -Dquarkus.container-image.image=${{ secrets.DOCKER_USERNAME }}/${{ github.event.repository.name }}-native:${{ github.ref_name }}-${{ matrix.current_platform }} \</span></span>
<span class="line"><span style="color: #A3BE8C">    -Dquarkus.container-image.additional-tags=&quot;latest-${{ matrix.current_platform }}&quot; \</span></span>
<span class="line"><span style="color: #A3BE8C">    -Dquarkus.container-image.labels.\&quot;org.opencontainers.image.title\&quot;=&quot;${{ github.event.repository.name }}&quot; \</span></span>
<span class="line"><span style="color: #A3BE8C">    -Dquarkus.container-image.labels.\&quot;org.opencontainers.image.description\&quot;=&quot;A native image built with Quarkus CLI&quot; \</span></span>
<span class="line"><span style="color: #A3BE8C">    -Dquarkus.container-image.labels.\&quot;org.opencontainers.image.url\&quot;=&quot;https://github.com/${{ github.repository }}&quot; \</span></span>
<span class="line"><span style="color: #A3BE8C">    -Dquarkus.container-image.labels.\&quot;org.opencontainers.image.source\&quot;=&quot;https://github.com/${{ github.repository }}&quot; \</span></span>
<span class="line"><span style="color: #A3BE8C">    -Dquarkus.container-image.labels.\&quot;org.opencontainers.image.version\&quot;=&quot;${{ github.ref_name }}&quot; \</span></span>
<span class="line"><span style="color: #A3BE8C">    -Dquarkus.container-image.labels.\&quot;org.opencontainers.image.created\&quot;=&quot;${{ steps.prep.outputs.created }}&quot; \</span></span>
<span class="line"><span style="color: #A3BE8C">    -Dquarkus.container-image.labels.\&quot;org.opencontainers.image.revision\&quot;=&quot;${{ github.sha }}&quot; \</span></span>
<span class="line"><span style="color: #A3BE8C">    -Dquarkus.container-image.labels.\&quot;org.opencontainers.image.authors\&quot;=&quot;Antonio Musarra &lt;antonio.musarra@gmail.com&gt;&quot; \</span></span>
<span class="line"><span style="color: #A3BE8C">    -Dquarkus.container-image.labels.\&quot;org.opencontainers.image.licenses\&quot;=&quot;MIT&quot;</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">YAML</span></div>



<p></p>



<p><strong>Cosa fa questo sesto step?</strong></p>



<ul class="wp-block-list">
<li>Crea un’immagine container contenente l’eseguibile nativo.</li>



<li>Applica tag specifici per identificare le versioni dell’immagine.</li>



<li>Applica un set di label Open Containers (come description, url, source, etc.).</li>



<li>Pubblica automaticamente l’immagine su Docker Hub.</li>
</ul>



<p>Per ulteriori dettagli sulle specifiche Open Containers, consulta la <a href="https://opencontainers.org/">documentazione ufficiale</a> e in particolare la sezione <a href="https://github.com/opencontainers/image-spec/blob/main/annotations.md">Annotations</a> sul repository GitHub.</p>



<h2 class="wp-block-heading"><strong>Esecuzione della GitHub Action</strong></h2>



<p>La pipeline di GitHub Actions si avvia automaticamente in risposta a eventi specifici, garantendo un processo di build e deploy completamente automatizzato.</p>



<h3 class="wp-block-heading">1. Quando si Attiva la Pipeline?</h3>



<p>Il workflow viene eseguito nei seguenti scenari:</p>



<ul class="wp-block-list">
<li><strong>Push su develop e main</strong>: ogni modifica su queste branch avvia automaticamente il workflow per garantire che il codice aggiornato venga compilato e pubblicato.</li>



<li><strong>Pubblicazione di una release</strong>: ogni volta che viene creata una nuova release, la pipeline si attiva per generare e distribuire un’immagine nativa della versione stabile.</li>
</ul>



<h3 class="wp-block-heading">2. Monitoraggio dell’Esecuzione</h3>



<p>Una volta avviata, l’esecuzione della pipeline può essere monitorata direttamente dalla scheda <strong>Actions</strong> del repository GitHub. Qui è possibile:</p>



<ul class="wp-block-list">
<li>Osservare lo stato di avanzamento del workflow in tempo reale.</li>



<li>Visualizzare i log dettagliati di ogni step per diagnosticare eventuali problemi.</li>



<li>Identificare rapidamente errori grazie all’evidenziazione dei messaggi di errore e warning.</li>
</ul>



<p>Le immagini a seguire evidenziano il processo automatizzato di build e deployment dell’immagine nativa del progetto su Docker Hub, mostrando, sia il <strong>workflow GitHub Actions completato con successo</strong>, sia il <strong>report dettagliato</strong> della compilazione GraalVM (grazie al parametro <code>native-image-job-reports:true</code>).</p>



<figure class="wp-block-image size-large is-resized"><img width="1024" height="301" decoding="async" loading="lazy" src="https://www.dontesta.it/wp-content/uploads/2025/02/report_github_action_1-1024x301.jpg" alt="Figura 1 - Workflow GitHub Actions completato con successo" class="wp-image-5873" style="width:864px;height:auto" srcset="https://www.dontesta.it/wp-content/uploads/2025/02/report_github_action_1-1024x301.jpg 1024w, https://www.dontesta.it/wp-content/uploads/2025/02/report_github_action_1-300x88.jpg 300w, https://www.dontesta.it/wp-content/uploads/2025/02/report_github_action_1-768x226.jpg 768w, https://www.dontesta.it/wp-content/uploads/2025/02/report_github_action_1-1536x452.jpg 1536w, https://www.dontesta.it/wp-content/uploads/2025/02/report_github_action_1-2048x603.jpg 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">Figura 1 - Workflow GitHub Actions completato con successo</figcaption></figure>



<p></p>



<figure class="wp-block-image size-large"><img width="1024" height="1302" decoding="async" loading="lazy" src="https://www.dontesta.it/wp-content/uploads/2025/02/report_github_action_2-1024x1302.jpg" alt="Figura 2 - Report dettagliato della compilazione GraalVM" class="wp-image-5874" srcset="https://www.dontesta.it/wp-content/uploads/2025/02/report_github_action_2-1024x1302.jpg 1024w, https://www.dontesta.it/wp-content/uploads/2025/02/report_github_action_2-300x381.jpg 300w, https://www.dontesta.it/wp-content/uploads/2025/02/report_github_action_2-768x977.jpg 768w, https://www.dontesta.it/wp-content/uploads/2025/02/report_github_action_2-1208x1536.jpg 1208w, https://www.dontesta.it/wp-content/uploads/2025/02/report_github_action_2.jpg 1414w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">Figura 2 - Report dettagliato della compilazione GraalVM</figcaption></figure>



<p>Puoi vedere i log completi di questo specifico workflow e job <a href="https://github.com/amusarra/quarkus-graphql-quickstart/actions/runs/13394381955/job/37409584528#logs">docker (ubuntu-24.04)</a> di cui a seguire è mostrato l'esempio di ciò che vedresti.</p>



<p></p>



<figure class="wp-block-image size-large"><img width="1024" height="608" decoding="async" loading="lazy" src="https://www.dontesta.it/wp-content/uploads/2025/02/report_github_action_3-1024x608.jpg" alt="Figura 3 - Log del workflow job docker (ubuntu-24-04)" class="wp-image-5877" srcset="https://www.dontesta.it/wp-content/uploads/2025/02/report_github_action_3-1024x608.jpg 1024w, https://www.dontesta.it/wp-content/uploads/2025/02/report_github_action_3-300x178.jpg 300w, https://www.dontesta.it/wp-content/uploads/2025/02/report_github_action_3-768x456.jpg 768w, https://www.dontesta.it/wp-content/uploads/2025/02/report_github_action_3-1536x912.jpg 1536w, https://www.dontesta.it/wp-content/uploads/2025/02/report_github_action_3-2048x1216.jpg 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">Figura 3 - Log del workflow job docker (ubuntu-24-04)</figcaption></figure>



<p>Nel caso in cui avessi installato il <a href="https://github.com/cli/cli" target="_blank" rel="noreferrer noopener">GitHub CLI (gh)</a>, potresti usare per esempio, il comando <code>gh run list -b main --workflow build_via_quarkus_cli.yml</code>, per elencare le esecuzioni del workflow GitHub Actions build_via_quarkus_cli.yml sul branch main.&nbsp;</p>



<p>Questo comando è utile per monitorare rapidamente lo stato delle build eseguite tramite Quarkus CLI senza dover accedere manualmente all’interfaccia web di GitHub Actions. A seguire un esempio di output.</p>



<figure class="wp-block-image size-large"><img width="1024" height="328" decoding="async" loading="lazy" src="https://www.dontesta.it/wp-content/uploads/2025/02/lista_esecuzioni_github_workflow_1-1024x328.jpg" alt="Figura 4 - Output del comando gh run list -b main --workflow build_via_quarkus_cli.yml" class="wp-image-5880" srcset="https://www.dontesta.it/wp-content/uploads/2025/02/lista_esecuzioni_github_workflow_1-1024x328.jpg 1024w, https://www.dontesta.it/wp-content/uploads/2025/02/lista_esecuzioni_github_workflow_1-300x96.jpg 300w, https://www.dontesta.it/wp-content/uploads/2025/02/lista_esecuzioni_github_workflow_1-768x246.jpg 768w, https://www.dontesta.it/wp-content/uploads/2025/02/lista_esecuzioni_github_workflow_1-1536x492.jpg 1536w, https://www.dontesta.it/wp-content/uploads/2025/02/lista_esecuzioni_github_workflow_1-2048x655.jpg 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">Figura 4 - Output del comando gh run list -b main --workflow build_via_quarkus_cli.yml</figcaption></figure>



<p>Al termine del workflow, l’immagine container sarà quindi disponibile nel container registry configurato nel file di workflow, pronta per essere utilizzata in ambienti di sviluppo o produzione. A seguire sono mostrate le due immagini native, una per ARM64 e una per AMD64, contrassegnate dai rispettivi tag.</p>



<p></p>



<figure class="wp-block-image size-large"><img width="1024" height="484" decoding="async" loading="lazy" src="https://www.dontesta.it/wp-content/uploads/2025/02/view_docker_hub_reg-1024x484.jpg" alt="Figura 5 - Immagini container native pubblicate su Docker Hub tramite la GitHub Action" class="wp-image-5881" srcset="https://www.dontesta.it/wp-content/uploads/2025/02/view_docker_hub_reg-1024x484.jpg 1024w, https://www.dontesta.it/wp-content/uploads/2025/02/view_docker_hub_reg-300x142.jpg 300w, https://www.dontesta.it/wp-content/uploads/2025/02/view_docker_hub_reg-768x363.jpg 768w, https://www.dontesta.it/wp-content/uploads/2025/02/view_docker_hub_reg-1536x726.jpg 1536w, https://www.dontesta.it/wp-content/uploads/2025/02/view_docker_hub_reg-2048x968.jpg 2048w, https://www.dontesta.it/wp-content/uploads/2025/02/view_docker_hub_reg-520x245.jpg 520w, https://www.dontesta.it/wp-content/uploads/2025/02/view_docker_hub_reg-720x340.jpg 720w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">Figura 5 - Immagini container native pubblicate su Docker Hub tramite la GitHub Action</figcaption></figure>



<h2 class="wp-block-heading">Conclusioni</h2>



<p>Questa pipeline GitHub Actions automatizza l’intero ciclo di sviluppo, dalla compilazione al rilascio dell’immagine container. L’uso combinato di <strong>Quarkus CLI, GraalVM e Docker</strong> garantisce build efficienti, rapide e compatibili con diverse architetture.</p>



<p>Per approfondire:</p>



<ul class="wp-block-list">
<li><a href="https://quarkus.io/guides/">Documentazione ufficiale di Quarkus</a></li>



<li><a href="https://docs.github.com/en/actions">GitHub Actions</a></li>



<li><a href="https://github.com/amusarra/quarkus-graphql-quickstart">Repository del progetto</a></li>



<li>Metodo classico via <a href="https://github.com/docker/buildx" target="_blank" rel="noreferrer noopener">Buildx</a>: <a href="https://www.youtube.com/watch?v=AGldK5g30Xg" target="_blank" rel="noreferrer noopener">Pubblica su Docker Hub con le GitHub Actions</a> - Canale YouTube <a href="https://www.youtube.com/@EmmeCiLab">EmmeCiLab - Informatica e Matematica</a></li>



<li>Progetto <a href="Graalkus: Let Quarkus fly high with GraalVM. ">Graalkus: Let Quarkus fly high with GraalVM</a>: <a href="https://github.com/fugerit-org/graalkus/blob/d1c045ac5cd462c70a97b11c8d184444694f7938/.github/workflows/docker_publish_native.yml#L60">come creare l'immagine nativa per più piattaforme</a> usando Buildx</li>
</ul>



<p>Se hai domande o suggerimenti, lascia un commento qui sotto!</p>



<p>&nbsp;</p>
<p>L'articolo <a href="https://www.dontesta.it/2025/02/18/github-actions-build-e-push-di-immagini-container-con-quarkus-cli/">GitHub Actions: Build e Push di Immagini Container con Quarkus CLI</a> sembra essere il primo su <a href="https://www.dontesta.it">Antonio Musarra&#039;s Blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.dontesta.it/2025/02/18/github-actions-build-e-push-di-immagini-container-con-quarkus-cli/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Come creare un&#8217;immagine container di Oracle 19c su Apple Silicon</title>
		<link>https://www.dontesta.it/2025/01/06/come-creare-unimmagine-container-di-oracle-19c-su-apple-silicon/</link>
					<comments>https://www.dontesta.it/2025/01/06/come-creare-unimmagine-container-di-oracle-19c-su-apple-silicon/#respond</comments>
		
		<dc:creator><![CDATA[Antonio Musarra]]></dc:creator>
		<pubDate>Mon, 06 Jan 2025 16:54:05 +0000</pubDate>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Containers]]></category>
		<category><![CDATA[Data Base]]></category>
		<category><![CDATA[Oracle]]></category>
		<guid isPermaLink="false">https://www.dontesta.it/?p=5821</guid>

					<description><![CDATA[<p>Per molti sviluppatori, avere Oracle Database in un ambiente di sviluppo locale è una necessità. Tuttavia, con l’avvento dei processori Apple Silicon (M1, M2 e successivi), alcune sfide tecniche possono emergere. Fortunatamente, il progetto&#46;&#46;&#46;</p>
<p>L'articolo <a href="https://www.dontesta.it/2025/01/06/come-creare-unimmagine-container-di-oracle-19c-su-apple-silicon/">Come creare un&#8217;immagine container di Oracle 19c su Apple Silicon</a> sembra essere il primo su <a href="https://www.dontesta.it">Antonio Musarra&#039;s Blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p><br>Per molti sviluppatori, avere <strong>Oracle Database</strong> in un ambiente di sviluppo locale è una necessità. Tuttavia, con l’avvento dei processori <a href="https://it.wikipedia.org/wiki/Apple_Silicon" target="_blank" rel="noreferrer noopener">Apple Silicon</a> (M1, M2 e successivi), alcune sfide tecniche possono emergere. Fortunatamente, il progetto <a href="https://github.com/oracle/docker-images" target="_blank" rel="noreferrer noopener">oracle/docker-images</a> fornisce gli strumenti per creare facilmente un’immagine container di Oracle Database 19c anche su architetture <a href="https://it.wikipedia.org/wiki/Architettura_ARM" target="_blank" rel="noreferrer noopener">ARM</a>. Inoltre, per migliorare la produttività, è possibile eseguire il push dell’immagine su un repository personale, rendendola facilmente accessibile senza doverla ricostruire ogni volta.</p>



<p><br>In questo articolo vedremo:</p>



<ol class="wp-block-list">
<li>Perché configurare Oracle Database in locale</li>



<li>Come creare la tua immagine container per Apple Silicon</li>



<li>Come condividere l’immagine container su un repository</li>



<li>Best practice per ottimizzare l’ambiente</li>
</ol>



<p></p>



<h2 class="wp-block-heading">Perche usare Oracle Database in locale</h2>



<p>Oracle è uno dei database più utilizzati in ambito enterprise. Le ragioni per essere incluso in un ambiente di sviluppo locale sono molteplici e riporto a seguire quelle più comuni.</p>



<ul class="wp-block-list">
<li><strong>Conformità ai requisiti aziendali:</strong> molte applicazioni sono progettate specificamente per Oracle, ed eseguire i test su altri database può portare a errori imprevisti.</li>



<li><strong>Testing di funzionalità avanzate</strong>: alcune caratteristiche, come i <strong>tablespace</strong>, le <strong>partizioni</strong> o <strong>PL/SQL</strong>, richiedono Oracle per essere testate correttamente.</li>



<li><strong>Miglioramento della velocità di sviluppo</strong>: avere un database locale elimina la latenza e la dipendenza da infrastrutture remote, garantendo una velocità di sviluppo e debug significativamente maggiore.</li>
</ul>



<h2 class="wp-block-heading">Come creare un'immagine container di Oracle 19c</h2>



<p>Vedremo adesso come usare gli strumenti messi a disposizione dal progetto <a href="https://github.com/oracle/docker-images" target="_blank" rel="noreferrer noopener">oracle/docker-images</a> per creare facilmente un’immagine container di Oracle Database 19c anche su architetture ARM. </p>



<p>Prima di iniziare con la procedura di creazione, è necessario che siano soddisfatti i seguenti requisiti.</p>



<ol class="wp-block-list">
<li>Mac con Apple Silicon (M1 o M2)</li>



<li><a href="https://www.docker.com/products/docker-desktop/" target="_blank" rel="noreferrer noopener">Docker Desktop</a> installato (versione minima engine 17.09) o <a href="https://podman-desktop.io/" target="_blank" rel="noreferrer noopener">Podman Desktop</a> (versione minima engine 1.6.0)</li>



<li>File binari di Oracle 19c scaricati dal <a href="https://www.oracle.com/database/technologies/oracle19c-linux-arm64-downloads.html" target="_blank" rel="noreferrer noopener">sito ufficiale</a>. Per il download è richiesto essere in posseso di un account Oracle e accettare i termini di licenza.</li>



<li>Storage minino 20-25 Gbyte. Spazio necessario per la build e installazione dell'edizione Enterprise di Oracle.   </li>



<li>Git</li>
</ol>



<p>Ho fatto riferimento alla serie M1 e M2 dei processori Apple Silicon, perché sono quelli per cui ho avuto modo di eseguire il processo di creazione dell'immagine container. I possesori più recenti, M3 e M4 non dovrebbero incontrare problemi.</p>



<p>Personalmente prediligo ormai da tempo l'uso di Podman, ragion per cui, l'immagine container sarà creata usando questo strumento. L'uso di Docker non comporta alcuna differenza in termini di sintassi dei comandi; qualora ne sia presente qualcuna, sarà opportunamente segnalata nel corso dell'articolo.</p>



<p>Procediamo per step con la costruzione dell'immagine container di Oracle 19c. Il primo passo è l'operazione di clone del repository <a href="https://github.com/oracle/docker-images" target="_blank" rel="noreferrer noopener">oracle/docker-images</a>.</p>



<p></p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# Step 1
#  1. Clonazione del repository https://github.com/oracle/docker-images.git
#  2. Cambio directory su docker-images/OracleDatabase/SingleInstance/dockerfiles 
git clone https://github.com/oracle/docker-images.git

cd docker-images/OracleDatabase/SingleInstance/dockerfiles" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88"># Step 1</span></span>
<span class="line"><span style="color: #616E88">#  1. Clonazione del repository https://github.com/oracle/docker-images.git</span></span>
<span class="line"><span style="color: #616E88">#  2. Cambio directory su docker-images/OracleDatabase/SingleInstance/dockerfiles </span></span>
<span class="line"><span style="color: #88C0D0">git</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">clone</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">https://github.com/oracle/docker-images.git</span></span>
<span class="line"></span>
<span class="line"><span style="color: #88C0D0">cd</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">docker-images/OracleDatabase/SingleInstance/dockerfiles</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Console 1 - Clonazione del repository oracle/docker-images</span></div>



<p></p>



<p>Il prossimo passo è il download del file <code>LINUX.ARM64_1919000_db_home.zip</code> dal sito di Oracle che deve poi essere copiato all'interno della directory <code>19.3.0</code>.</p>



<figure class="wp-block-image size-large"><img width="1024" height="311" decoding="async" loading="lazy" src="https://www.dontesta.it/wp-content/uploads/2025/01/download_LINUX.ARM64_1919000_db_home.zip-1024x311.jpg" alt="Figura 1 - Download del file LINUX.ARM64_1919000_db_home.zip dal sito di Oracle" class="wp-image-5841" srcset="https://www.dontesta.it/wp-content/uploads/2025/01/download_LINUX.ARM64_1919000_db_home.zip-1024x311.jpg 1024w, https://www.dontesta.it/wp-content/uploads/2025/01/download_LINUX.ARM64_1919000_db_home.zip-300x91.jpg 300w, https://www.dontesta.it/wp-content/uploads/2025/01/download_LINUX.ARM64_1919000_db_home.zip-768x233.jpg 768w, https://www.dontesta.it/wp-content/uploads/2025/01/download_LINUX.ARM64_1919000_db_home.zip-1536x466.jpg 1536w, https://www.dontesta.it/wp-content/uploads/2025/01/download_LINUX.ARM64_1919000_db_home.zip-2048x622.jpg 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption"><strong>Figura 1</strong> - Download del file LINUX.ARM64_1919000_db_home.zip dal sito di Oracle</figcaption></figure>



<p></p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# File LINUX.ARM64_1919000_db_home.zip scaricato dal sito di Oracle e copiato
# nella directory 19.3.0 
-rw-r--r--@ 1 amusarra  staff   2,2G 24 Dic 13:00 19.3.0/LINUX.ARM64_1919000_db_home.zip" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #d8dee9ff"># File LINUX.ARM64_1919000_db_home.zip scaricato dal sito di Oracle e copiato</span></span>
<span class="line"><span style="color: #d8dee9ff"># nella directory 19.3.0 </span></span>
<span class="line"><span style="color: #d8dee9ff">-rw-r--r--@ 1 amusarra  staff   2,2G 24 Dic 13:00 19.3.0/LINUX.ARM64_1919000_db_home.zip</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Console 2 - File LINUX.ARM64_1919000_db_home.zip in 19.3.0</span></div>



<p></p>



<p>A questo punto passiamo alla costruzione dell'immagine container usando lo script <code>buildContainerImage.sh</code> passando i parametri necessari affinché sia costruita la versione 19.3.0 edizione Enterprise.</p>



<p>Nel caso abbiate scelto di usare Podman, sono necessarie delle operazioni preliminari da eseguire prima di eseguire lo script di creazione dell'immagine container. Occorre fare l'esportazione di due variabili di ambiente: <code>BUILDAH_FORMAT=docker</code> e <code>BUILDAH_ISOLATION=chroot</code>. La prima variabile è richiesta per supportare <code>HEALTHCHECK</code> specificato nel Dockerfile. La seconda variabile è richiesta durante la build dell'immagine container in <a href="https://developers.redhat.com/blog/2020/09/25/rootless-containers-with-podman-the-basics#" target="_blank" rel="noreferrer noopener" class="broken_link">modalità rootless</a>.</p>



<p>A seguire sono indicati i comandi che dobbiamo lanciare dalla nostra console per avviare il processo di creazione dell'immagine container di Oracle 19c edizione Enterprise (flag <code>-e</code> dello script <code>buildContainerImage.sh</code>).</p>



<p><strong>Nota</strong>: Solo l'edizione Enterprise è supportata per le piattaforme ARM64 e di conseguenza Apple Silicon (serie M). Per maggiori informazioni sull'uso dello script, consultare il <a href="https://github.com/oracle/docker-images/blob/main/OracleDatabase/SingleInstance/README.md#how-to-build-and-run" target="_blank" rel="noreferrer noopener">README</a> del progetto oracle/docker-images.</p>



<p></p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# Esportazione di BUILDAH_FORMAT e BUILDAH_ISOLATION solo nel caso in cui
# abbiate scelto di usare Podman.
export BUILDAH_FORMAT=docker
export BUILDAH_ISOLATION=chroot

# Avvio del processo di creazione dell'immagine container di Oracle 19c Enterprise Edition
./buildContainerImage.sh -v 19.3.0 -e" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88"># Esportazione di BUILDAH_FORMAT e BUILDAH_ISOLATION solo nel caso in cui</span></span>
<span class="line"><span style="color: #616E88"># abbiate scelto di usare Podman.</span></span>
<span class="line"><span style="color: #81A1C1">export</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">BUILDAH_FORMAT</span><span style="color: #81A1C1">=</span><span style="color: #A3BE8C">docker</span></span>
<span class="line"><span style="color: #81A1C1">export</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">BUILDAH_ISOLATION</span><span style="color: #81A1C1">=</span><span style="color: #A3BE8C">chroot</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Avvio del processo di creazione dell&#39;immagine container di Oracle 19c Enterprise Edition</span></span>
<span class="line"><span style="color: #88C0D0">./buildContainerImage.sh</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-v</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">19.3</span><span style="color: #A3BE8C">.0</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-e</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Console 3 - Creazione immagine container Oracle</span></div>



<p></p>



<p>Il processo di build impiegherà un po' di tempo, a seconda della velocità della propria connessione alla rete internet e dalle prestazioni del proprio Mac. Quando l'esecuzione dello script <code>buildContainerImage.sh</code> arriverà al termine, sul terminale dovreste vedere un output simile a quello mostrato a seguire.</p>



<p></p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="[3/3] COMMIT oracle/database:19.3.0-ee
--&gt; 337cf702a194
Successfully tagged localhost/oracle/database:19.3.0-ee
337cf702a194caab7145893915ea8616dc5dfa762a335a078cb4613db4acd766


  Oracle Database container image for 'ee' version 19.3.0 is ready to be extended:

    --&gt; oracle/database:19.3.0-ee

  Build completed in 345 seconds." style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #d8dee9ff">[3/3] COMMIT oracle/database:19.3.0-ee</span></span>
<span class="line"><span style="color: #d8dee9ff">--&gt; 337cf702a194</span></span>
<span class="line"><span style="color: #d8dee9ff">Successfully tagged localhost/oracle/database:19.3.0-ee</span></span>
<span class="line"><span style="color: #d8dee9ff">337cf702a194caab7145893915ea8616dc5dfa762a335a078cb4613db4acd766</span></span>
<span class="line"><span style="color: #d8dee9ff"></span></span>
<span class="line"><span style="color: #d8dee9ff"></span></span>
<span class="line"><span style="color: #d8dee9ff">  Oracle Database container image for &#39;ee&#39; version 19.3.0 is ready to be extended:</span></span>
<span class="line"><span style="color: #d8dee9ff"></span></span>
<span class="line"><span style="color: #d8dee9ff">    --&gt; oracle/database:19.3.0-ee</span></span>
<span class="line"><span style="color: #d8dee9ff"></span></span>
<span class="line"><span style="color: #d8dee9ff">  Build completed in 345 seconds.</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Console 4 - Output finale dell'esecuzione dello script buildContainerImage.sh</span></div>



<p></p>



<p>Possiamo verificare la nuova immagine usando il comando <code>podman image ls --filter "reference=localhost/oracle/database:19.3.0-ee"</code> o <code>docker image ls --filter "reference=localhost/oracle/database:19.3.0-ee"</code>, ottenendo un output simile a quello mostrato a seguire.</p>



<p></p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="REPOSITORY                 TAG         IMAGE ID      CREATED         SIZE
localhost/oracle/database  19.3.0-ee   337cf702a194  12 minutes ago  5.6 GB" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #d8dee9ff">REPOSITORY                 TAG         IMAGE ID      CREATED         SIZE</span></span>
<span class="line"><span style="color: #d8dee9ff">localhost/oracle/database  19.3.0-ee   337cf702a194  12 minutes ago  5.6 GB</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Console 5 - Output del comando di verifica dell'immagine Oracle 19c</span></div>



<p></p>



<h3 class="wp-block-heading">Test di avvio del container Oracle</h3>



<p>A questo punto siamo nelle condizioni di poter eseguire un test dell'immagine appena creata avviando l'istanza di Oracle 19c usando il comando indicato a seguire.</p>



<p></p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# Creazione della directory per il volume
# dei dati Oracle
mkdir -p ~/.oracle/oradata

# Avvio dell'istanza Oracle 19c.
# Nel caso di docker basta sostituire podman con docker
podman run --name oracle19c \
  -p 1521 -p 5500:5500 \
	-e ORACLE_SID=MYDEVENV \
	-e ORACLE_PDB=MYDEVPDB1 \
	-e ORACLE_PWD=LwB_27i5Wi8=1 \
	-v ~/.oracle/oradata:/opt/oracle/oradata \
 	oracle/database:19.3.0-ee

# Per avviare il container in background usare l'opzione -d 
podman run -d --name oracle19c \
	-p 1521 -p 5500:5500 \
	-e ORACLE_SID=MYDEVENV \
	-e ORACLE_PDB=MYDEVPDB1 \
	-e ORACLE_PWD=LwB_27i5Wi8=1 \
	-v ~/.oracle/oradata:/opt/oracle/oradata \
 	oracle/database:19.3.0-ee

# Per visualizzare il log
podman logs -f oracle19c" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88"># Creazione della directory per il volume</span></span>
<span class="line"><span style="color: #616E88"># dei dati Oracle</span></span>
<span class="line"><span style="color: #88C0D0">mkdir</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-p</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">~/.oracle/oradata</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Avvio dell&#39;istanza Oracle 19c.</span></span>
<span class="line"><span style="color: #616E88"># Nel caso di docker basta sostituire podman con docker</span></span>
<span class="line"><span style="color: #88C0D0">podman</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">run</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">--name</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">oracle19c</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #A3BE8C">-p</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1521</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-p</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">5500</span><span style="color: #A3BE8C">:5500</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #A3BE8C">-e</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ORACLE_SID=MYDEVENV</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #A3BE8C">-e</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ORACLE_PDB=MYDEVPDB1</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #A3BE8C">-e</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ORACLE_PWD=LwB_27i5Wi8=</span><span style="color: #B48EAD">1</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #A3BE8C">-v</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">~/.oracle/oradata:/opt/oracle/oradata</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF"> 	</span><span style="color: #A3BE8C">oracle/database:19.3.0-ee</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Per avviare il container in background usare l&#39;opzione -d </span></span>
<span class="line"><span style="color: #88C0D0">podman</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">run</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-d</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">--name</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">oracle19c</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #A3BE8C">-p</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1521</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-p</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">5500</span><span style="color: #A3BE8C">:5500</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #A3BE8C">-e</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ORACLE_SID=MYDEVENV</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #A3BE8C">-e</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ORACLE_PDB=MYDEVPDB1</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #A3BE8C">-e</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ORACLE_PWD=LwB_27i5Wi8=</span><span style="color: #B48EAD">1</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">	</span><span style="color: #A3BE8C">-v</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">~/.oracle/oradata:/opt/oracle/oradata</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF"> 	</span><span style="color: #A3BE8C">oracle/database:19.3.0-ee</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Per visualizzare il log</span></span>
<span class="line"><span style="color: #88C0D0">podman</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">logs</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-f</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">oracle19c</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Console 6 - Avvio dell'istanza Oracle 19c su Apple Silicon (ARM)</span></div>



<p></p>



<p>Quando si crea l'istanza Oracle è opportuno impostare i parametri indicati sul comando <code>podman run</code> o <code>docker run</code> (vedi opzione <code>-e</code>) invece di lasciare i valori di default.</p>



<p>Senza specificare il <em>volume</em> (vedi opzione <code>-v</code> del comando <code>podman run</code>) per il database, i dati andrebbero persi ogni qualvolta il container fosse ricreato, situazione solitamente non voluta. </p>



<p>Consultare il <a href="https://github.com/oracle/docker-images/blob/main/OracleDatabase/SingleInstance/README.md#running-oracle-database-in-a-container" target="_blank" rel="noreferrer noopener">README</a> del progetto oracle/docker-images per verificare tutti i parametri disponibili per il database. Questi parametri sono molto utili al fine del tuning sulla base delle proprie esigenze.</p>



<p>Esiste la possibilità alquanto comoda, di poter eseguire script SQL alla fine della fase di inizializzazione del database. Qui <a href="https://github.com/oracle/docker-images/blob/main/OracleDatabase/SingleInstance/README.md#running-scripts-after-setup-and-on-startup" target="_blank" rel="noreferrer noopener">Running scripts after setup and on startup</a> è descritta la modalità d'uso, mentre in questo articolo <a href="https://www.dontesta.it/en/2020/03/15/how-to-setup-docker-container-oracle-database-19c-for-liferay-development-environment/">How to setup Docker container Oracle Database 19c for Liferay Development Environment</a> è possibile vedere un caso pratico.</p>



<p>Il primo avvio può durare da pochi minuti fino ad alcune decine di minuti, a seconda della configurazione. È importante consultare l'output del container per verificare quando il database è effettivamente pronto all'uso (messaggio: DATABASE IS READY TO USE!). I successivi avvii saranno decisamente più veloci.</p>



<p>Volendo potremmo anche monitorare lo status del container usando il comando <code>podman ps -f "name=oracle19c"</code> o <code>docker ps -f "name=oracle19c"</code> verificando il valore della colonna <code>STATUS</code> che dovrebbe essere valorizzata con <code>Up &lt;n&gt; minutes (starting)</code> quando ancora il container è in fase di avvio per poi assumere il valore <code>Up &lt;n&gt; minutes (healthy) </code>una volta che l'istanza Oracle sarà operativa.</p>



<p>Per fare una verifica veloce che tutto sia andato per il verso giusto, eseguiamo un test di connessione usando il comando <code>podman exec -it oracle19c sqlplus system/LwB_27i5Wi8=1</code> per ottenere un output simile a quello indicato a seguire.</p>



<p></p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="SQL*Plus: Release 19.0.0.0.0 - Production on Sat Jan 4 23:03:40 2025
Version 19.19.0.0.0

Copyright (c) 1982, 2023, Oracle.  All rights reserved.

Last Successful login time: Sat Jan 04 2025 22:56:53 +00:00

Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.19.0.0.0

SQL&gt;" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #d8dee9ff">SQL*Plus: Release 19.0.0.0.0 - Production on Sat Jan 4 23:03:40 2025</span></span>
<span class="line"><span style="color: #d8dee9ff">Version 19.19.0.0.0</span></span>
<span class="line"><span style="color: #d8dee9ff"></span></span>
<span class="line"><span style="color: #d8dee9ff">Copyright (c) 1982, 2023, Oracle.  All rights reserved.</span></span>
<span class="line"><span style="color: #d8dee9ff"></span></span>
<span class="line"><span style="color: #d8dee9ff">Last Successful login time: Sat Jan 04 2025 22:56:53 +00:00</span></span>
<span class="line"><span style="color: #d8dee9ff"></span></span>
<span class="line"><span style="color: #d8dee9ff">Connected to:</span></span>
<span class="line"><span style="color: #d8dee9ff">Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production</span></span>
<span class="line"><span style="color: #d8dee9ff">Version 19.19.0.0.0</span></span>
<span class="line"><span style="color: #d8dee9ff"></span></span>
<span class="line"><span style="color: #d8dee9ff">SQL&gt;</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Console 7 - Test di connessione all'istanza Oracle tramite SQLPlus</span></div>



<p></p>



<p>Ultima verifica da poter fare è la connessione alla console Enterprise Manager&nbsp;Database Express disponibile all'indirizzo https://localhost:5500/em accedendo con le credenziali da sysdba.</p>



<figure class="wp-block-image size-large"><img width="1024" height="464" decoding="async" loading="lazy" src="https://www.dontesta.it/wp-content/uploads/2025/01/oracle_oem-1024x464.jpg" alt="Figura 2 - Dashboard della console Enterprise Manager Database Express" class="wp-image-5853" srcset="https://www.dontesta.it/wp-content/uploads/2025/01/oracle_oem-1024x464.jpg 1024w, https://www.dontesta.it/wp-content/uploads/2025/01/oracle_oem-300x136.jpg 300w, https://www.dontesta.it/wp-content/uploads/2025/01/oracle_oem-768x348.jpg 768w, https://www.dontesta.it/wp-content/uploads/2025/01/oracle_oem-1536x695.jpg 1536w, https://www.dontesta.it/wp-content/uploads/2025/01/oracle_oem-2048x927.jpg 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption"><strong>Figura 2</strong> - Dashboard della console Enterprise Manager Database Express</figcaption></figure>



<p>Dopo aver creato l'immagine container di Oracle 19c ed eseguito un test di avvio dell'istanza Oracle, possiamo passare alla pubblicazione su un repository per immagini container.</p>



<p></p>



<h2 class="wp-block-heading">Come condividere l'immagine container su repository</h2>



<p>Per condividere l’immagine con il team o accedervi da altre macchine, possiamo pubblicarla su un repository pubblico o privato. Esistono diversi repository, ma per lo scopo didattico dell'articolo, la scelta ricade su Docker Hub. Qualora non abbiate un account su Docker Hub, è necessario crearlo affinché sia possibile eseguire il push dell'immagine. La creazione dell'account è gratuita seguendo il link <a href="https://app.docker.com/signup?_gl=1*ktdwvh*_ga*OTE1MzkxNTk2LjE3MzI3MDc4NTA.*_ga_XJWPQMJYHQ*MTczNjAzMzcxOS41LjEuMTczNjAzMzcyMC41OS4wLjA." target="_blank" rel="noreferrer noopener">Create your account on Docker Hub</a>.</p>



<p>I passi per poter pubblicare l'immagine su Docker Hub sono:</p>



<ol class="wp-block-list">
<li>eseguire il login su Docker Hub;</li>



<li>eseguire il tag dell'immagine;</li>



<li>eseguire il push dell'immagine.</li>
</ol>



<p>A seguire sono indicati i comandi che devono essere lanciati dalla propria console.</p>



<p></p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# Login su Docker Hub usando Podman
podman login docker.io

# Login su Docker Hub usando Docker
# Sostituisci &lt;your-username&gt; con il tuo nome utente Docker Hub.
docker login -u &lt;your-username&gt;

# Tag dell'immagine (sostituisci podman con docker nel caso usassi Docker)
# Sostituisci &lt;your-dockerhub-username&gt; con il tuo nome utente Docker Hub.
podman tag oracle/database:19.3.0-ee &lt;your-dockerhub-username&gt;/oracle19c:19.3.0

# Push dell'immagine su Docker Hub (sostituisci podman con docker nel caso usassi Docker)
# Sostituisci &lt;your-dockerhub-username&gt; con il tuo nome utente Docker Hub.
podman push &lt;your-dockerhub-username&gt;/oracle19c:19.3.0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88"># Login su Docker Hub usando Podman</span></span>
<span class="line"><span style="color: #88C0D0">podman</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">login</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">docker.io</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Login su Docker Hub usando Docker</span></span>
<span class="line"><span style="color: #616E88"># Sostituisci &lt;your-username&gt; con il tuo nome utente Docker Hub.</span></span>
<span class="line"><span style="color: #88C0D0">docker</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">login</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-u</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;</span><span style="color: #A3BE8C">your-usernam</span><span style="color: #D8DEE9FF">e</span><span style="color: #81A1C1">&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Tag dell&#39;immagine (sostituisci podman con docker nel caso usassi Docker)</span></span>
<span class="line"><span style="color: #616E88"># Sostituisci &lt;your-dockerhub-username&gt; con il tuo nome utente Docker Hub.</span></span>
<span class="line"><span style="color: #88C0D0">podman</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">tag</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">oracle/database:19.3.0-ee</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;</span><span style="color: #A3BE8C">your-dockerhub-usernam</span><span style="color: #D8DEE9FF">e</span><span style="color: #81A1C1">&gt;</span><span style="color: #A3BE8C">/oracle19c:19.3.0</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Push dell&#39;immagine su Docker Hub (sostituisci podman con docker nel caso usassi Docker)</span></span>
<span class="line"><span style="color: #616E88"># Sostituisci &lt;your-dockerhub-username&gt; con il tuo nome utente Docker Hub.</span></span>
<span class="line"><span style="color: #88C0D0">podman</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">push</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;</span><span style="color: #A3BE8C">your-dockerhub-usernam</span><span style="color: #D8DEE9FF">e</span><span style="color: #81A1C1">&gt;</span><span style="color: #A3BE8C">/oracle19c:19.3.0</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Console 8 - Pubblicazione immagine Oracle 19c su Docker Hub</span></div>



<p></p>



<p>Dopo aver eseguito il push dell'immagine di Oracle 19c, accedendo su Docker Hub dovreste vedere la nuova immagine e i dettagli, così come mostrato dalla figura a seguire. In questo caso è opportuno configurare questo specifico repository come privato (che nel piano gratuito è disponibile solo una unità).</p>



<p></p>



<figure class="wp-block-image size-large"><img width="1024" height="604" decoding="async" loading="lazy" src="https://www.dontesta.it/wp-content/uploads/2025/01/docker_hub_oracle_image_details-1024x604.jpg" alt="Figura 3 - Dettagli dell'immagine Oracle 19c caricata su Docker Hub" class="wp-image-5842" srcset="https://www.dontesta.it/wp-content/uploads/2025/01/docker_hub_oracle_image_details-1024x604.jpg 1024w, https://www.dontesta.it/wp-content/uploads/2025/01/docker_hub_oracle_image_details-300x177.jpg 300w, https://www.dontesta.it/wp-content/uploads/2025/01/docker_hub_oracle_image_details-768x453.jpg 768w, https://www.dontesta.it/wp-content/uploads/2025/01/docker_hub_oracle_image_details-1536x906.jpg 1536w, https://www.dontesta.it/wp-content/uploads/2025/01/docker_hub_oracle_image_details.jpg 1988w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption"><strong>Figura </strong>3 - Dettagli dell'immagine Oracle 19c caricata su Docker Hub.</figcaption></figure>



<p></p>



<p>Da questo momento in poi sarà possibile reperire l'immagine di Oracle 19c eseguendo il pull in questo modo: <code>podman pull docker.io/amusarra/oracle19c:19.3.0</code> (o usando il comando <code>docker</code> al posto di <code>podman</code>).</p>



<p></p>



<h2 class="wp-block-heading">Best practice per l’ottimizzazione</h2>



<p>Una volta configurata l’immagine container di Oracle Database 19c, ci sono diverse strategie che possiamo adottare per ottimizzarne l’utilizzo e migliorare la produttività. Di seguito sono indicati una serie di suggerimenti per configurare al meglio l'ambiente di sviluppo.</p>



<ol class="wp-block-list">
<li><strong>Configurazione delle risorse:</strong> imposta limiti di CPU e RAM per evitare che il database monopolizzi le risorse.</li>



<li><strong>Persistenza dei dati:</strong> utilizza volumi per salvare i dati, così da evitare perdite in caso di riavvio del container.</li>



<li><strong>Gestione delle versioni:</strong> utilizza tag specifici per differenziare le versioni dell’immagine (es. 19.3.0-dev o 19.3.0-prod).</li>
</ol>



<p></p>



<h2 class="wp-block-heading">Conclusioni</h2>



<p>Configurare e condividere un’immagine container di Oracle Database 19c per Apple Silicon è un’operazione semplice e pratica. Salvando l’immagine su uno dei repository disponibili (anche gratuitamente), puoi ridurre i tempi di configurazione, migliorare la collaborazione con il tuo team e garantire un ambiente di sviluppo coerente.</p>



<p></p>



<h2 class="wp-block-heading">Risorse</h2>



<p>Per approfondire i concetti trattati in questo articolo e ottimizzare ulteriormente l’utilizzo di Oracle Database su Docker, ecco alcune risorse online utili.</p>



<h3 class="wp-block-heading">Documentazione Ufficiale</h3>



<ul class="wp-block-list">
<li><strong>Oracle Database 19c Documentation</strong>. La documentazione ufficiale di Oracle Database 19c offre informazioni dettagliate sulle funzionalità, configurazioni e parametri avanzati (<a href="https://docs.oracle.com/en/database/oracle/oracle-database/19/index.html" target="_blank" rel="noreferrer noopener">https://docs.oracle.com/en/database/oracle/oracle-database/19/index.html</a>).</li>



<li><strong>Docker</strong>. La guida ufficiale di Docker fornisce una panoramica completa sull’utilizzo di container, volumi, reti e best practice (<a href="https://docs.docker.com/">https://docs.docker.com/</a>).</li>
</ul>



<h3 class="wp-block-heading">Libri</h3>



<ul class="wp-block-list">
<li><strong>Oracle on Docker: Running Oracle Databases in Linux Containers</strong> di Sean Scott. Questo libro affronta i container dal punto di vista di amministratori di database, sviluppatori e amministratori di sistema. Spiega le differenze tra container e macchine virtuali e descrive perché i contenitori offrono maggiore velocità, flessibilità e portabilità, con requisiti di risorse inferiori. Imparerai come l'esecuzione di database Oracle in container integra l'infrastruttura di database esistente e accelera lo sviluppo e comprenderai i vantaggi che offrono per gli ambienti di test e convalida (<a href="https://amzn.to/4iXoJSt" target="_blank" rel="noreferrer noopener">https://amzn.to/4iXoJSt</a>).</li>



<li><strong>Docker: Sviluppare e rilasciare software tramite container</strong> di <a href="https://www.linkedin.com/in/serena-sensini/" target="_blank" rel="noreferrer noopener">Serena Sensini</a>. I container Docker permettono di impacchettare e rilasciare un'applicazione corredata da tutti i suoi componenti funzionali e hanno cambiato la catena di fornitura del software sia nelle piccole che nelle grandi imprese, rivoluzionando il modo in cui società come Spotify, Netflix ed Expedia distribuiscono le loro soluzioni (<a href="https://amzn.to/40kjVz7" target="_blank" rel="noreferrer noopener">https://amzn.to/40kjVz7</a>).&nbsp;</li>
</ul>



<h3 class="wp-block-heading">Progetti e Guide Online</h3>



<ul class="wp-block-list">
<li><strong>Repository Oracle Docker Images</strong>. Questo è il repository GitHub ufficiale di Oracle con istruzioni per la creazione di immagini container per Oracle Database (<a href="https://github.com/oracle/docker-images" target="_blank" rel="noreferrer noopener">https://github.com/oracle/docker-images</a>).</li>



<li><strong>Profiling e Ottimizzazione delle Applicazioni Dockerizzate</strong>. Ottimizzare le performance delle applicazioni containerizzate è essenziale per garantire che le risorse siano utilizzate in modo efficiente, che le applicazioni rispondano rapidamente e che l’infrastruttura possa scalare in modo adeguato (<a href="https://www.codegrind.it/documentazione/docker/profiling-ottimizzazione-performance" target="_blank" rel="noreferrer noopener">https://www.codegrind.it/documentazione/docker/profiling-ottimizzazione-performance</a>).&nbsp;</li>



<li><strong>Pillole di Docker</strong> <a href="https://www.youtube.com/@EmmeCiLab" target="_blank" rel="noreferrer noopener">di EmmeCiLab - Informatica e Matematica</a>. Una raccolta di brevi video per conoscere i fondamenti di Docker (<a href="https://youtube.com/playlist?list=PLCbSCJEIR6CpDJw4MawjHlgbsP3IG376e" target="_blank" rel="noreferrer noopener">https://youtube.com/playlist?list=PLCbSCJEIR6CpDJw4MawjHlgbsP3IG376e</a>)</li>
</ul>


<p>L'articolo <a href="https://www.dontesta.it/2025/01/06/come-creare-unimmagine-container-di-oracle-19c-su-apple-silicon/">Come creare un&#8217;immagine container di Oracle 19c su Apple Silicon</a> sembra essere il primo su <a href="https://www.dontesta.it">Antonio Musarra&#039;s Blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.dontesta.it/2025/01/06/come-creare-unimmagine-container-di-oracle-19c-su-apple-silicon/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Approfondimento sullo standard PKCS#11 e utilizzo con Smart Card</title>
		<link>https://www.dontesta.it/2024/09/22/approfondimento-standard-pkcs11-smart-card/</link>
					<comments>https://www.dontesta.it/2024/09/22/approfondimento-standard-pkcs11-smart-card/#respond</comments>
		
		<dc:creator><![CDATA[Antonio Musarra]]></dc:creator>
		<pubDate>Sun, 22 Sep 2024 16:27:18 +0000</pubDate>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[PKCS#11]]></category>
		<category><![CDATA[Smart Card]]></category>
		<guid isPermaLink="false">https://www.dontesta.it/?p=5799</guid>

					<description><![CDATA[<p>Introduzione a PKCS#11 PKCS#11 (Public-Key Cryptography Standards #11), noto anche come Cryptographic Token Interface Standard, è uno standard sviluppato da RSA Laboratories. Esso definisce un’API (Application Programming Interface) indipendente dalla piattaforma per l’accesso a&#46;&#46;&#46;</p>
<p>L'articolo <a href="https://www.dontesta.it/2024/09/22/approfondimento-standard-pkcs11-smart-card/">Approfondimento sullo standard PKCS#11 e utilizzo con Smart Card</a> sembra essere il primo su <a href="https://www.dontesta.it">Antonio Musarra&#039;s Blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading" id="introduzione-a-pkcs11">Introduzione a PKCS#11</h2>



<p>PKCS#11 (Public-Key Cryptography Standards #11), noto anche come Cryptographic Token Interface Standard, è uno standard sviluppato da RSA Laboratories. Esso definisce un’API (Application Programming Interface) indipendente dalla piattaforma per l’accesso a dispositivi di sicurezza hardware come token crittografici, HSM (Hardware Security Modules) e, soprattutto, Smart Card.</p>



<p>L’obiettivo principale dello standard PKCS#11 è fornire un’interfaccia unificata che consenta alle applicazioni di accedere a chiavi crittografiche e altre operazioni crittografiche senza dover gestire direttamente i dettagli del dispositivo sottostante.</p>



<p>In questo articolo esploreremo i concetti chiave di PKCS#11 e come utilizzarlo per firmare e verificare la firma di un messaggio tramite una Smart Card che in questo caso sarà la "nostrana" <a href="https://sistemats1.sanita.finanze.it/portale/tessera-sanitaria">TS-CNS (Tessera Sanitaria - Carta Nazionale Servizi)</a>. </p>



<h2 class="wp-block-heading" id="pkcs11-e-le-smart-card">PKCS#11 e le Smart Card</h2>



<p>Le Smart Card sono dispositivi fisici che memorizzano in modo sicuro chiavi crittografiche e certificati. Sono utilizzate in una vasta gamma di applicazioni, come la firma digitale, l’autenticazione e la crittografia dei dati. Lo standard PKCS#11 permette alle applicazioni di interfacciarsi con queste Smart Card in maniera sicura e trasparente.</p>



<h3 class="wp-block-heading" id="vantaggi-delluso-delle-smart-card-con-pkcs11">Vantaggi dell'uso delle Smart Card con PKCS#11</h3>



<ol class="wp-block-list">
<li><strong>Sicurezza Hardware</strong>: le Smart Card sono dotate di un chip che esegue tutte le operazioni crittografiche, proteggendo le chiavi private dall’essere esposte al sistema host.</li>



<li><strong>Portabilità</strong>: poiché le chiavi sono memorizzate fisicamente sulla Smart Card, possono essere trasportate in sicurezza e utilizzate su diversi sistemi semplicemente inserendo la carta nel lettore.</li>



<li><strong>Indipendenza dalla piattaforma</strong>: grazie a PKCS#11, le applicazioni possono accedere alle funzionalità crittografiche della Smart Card senza dover implementare codice specifico per ogni dispositivo o sistema operativo.</li>
</ol>



<h2 class="wp-block-heading" id="architettura-e-concetti-chiave-di-pkcs11">Architettura e concetti chiave di PKCS#11</h2>



<p>PKCS#11 è progettato per gestire una vasta gamma di dispositivi crittografici. Definisce una serie di oggetti e operazioni chiave che permettono alle applicazioni di interagire con i token crittografici come le Smart Card. Vediamo alcuni concetti chiave:</p>



<ol class="wp-block-list">
<li><strong>Slot e Token</strong>: uno slot rappresenta l’interfaccia fisica o logica con il dispositivo crittografico (ad esempio, un lettore di Smart Card). Un token è il dispositivo crittografico stesso (ad esempio, la Smart Card inserita nello slot).</li>



<li><strong>Sessioni e Oggetti</strong>: le applicazioni aprono delle sessioni con il token per eseguire operazioni crittografiche. Gli oggetti memorizzati sul token possono essere chiavi crittografiche, certificati, o dati generici.</li>



<li><strong>Meccanismi Crittografici</strong>: PKCS#11 supporta diversi meccanismi crittografici, inclusi RSA, ECC, AES, rendendolo flessibile per diverse applicazioni.</li>



<li><strong>Chiavi e Certificati</strong>: le Smart Card utilizzano chiavi private per la firma digitale o l’autenticazione. Le chiavi pubbliche e i certificati associati possono essere archiviati sulla Smart Card e resi disponibili tramite PKCS#11.</li>
</ol>



<h2 class="wp-block-heading" id="crittografia-a-chiave-asimmetrica-il-classico-esempio-di-alice-e-bob">Crittografia a chiave asimmetrica: il classico esempio di Alice e Bob</h2>



<p>La crittografia a chiave asimmetrica è un metodo di crittografia che utilizza due chiavi differenti: <strong>una chiave pubblica</strong> e <strong>una chiave privata</strong>. <em>Queste due chiavi sono matematicamente collegate tra loro, ma non è possibile risalire alla chiave privata conoscendo solo la chiave pubblica</em>. Cerchiamo di capire in modo semplice come funziona.</p>



<ul class="wp-block-list">
<li><strong>Chiave Pubblica</strong>: può essere condivisa pubblicamente con chiunque. Serve per cifrare i messaggi che solo il proprietario della corrispondente chiave privata può decifrare.</li>



<li><strong>Chiave Privata</strong>: deve essere mantenuta segreta. Viene usata per decifrare i messaggi cifrati con la chiave pubblica e per firmare digitalmente i dati.</li>
</ul>



<p>Facciamo il classico esempio di Alice e Bob. Immaginiamo quindi, Alice e Bob, che vogliono comunicare in modo sicuro utilizzando la crittografia a chiave asimmetrica.</p>



<ol class="wp-block-list">
<li><p>Scambio delle Chiavi:</p>
<ul class="wp-block-list">
<li>Alice e Bob generano ciascuno una coppia di chiavi: una chiave pubblica e una chiave privata.</li>



<li>Alice invia la sua chiave pubblica a Bob.</li>



<li>Bob invia la sua chiave pubblica ad Alice.</li>
</ul>
</li>



<li><p>Alice invia un messaggio cifrato a Bob:</p>
<ul class="wp-block-list">
<li>Alice utilizza la chiave pubblica di Bob per cifrare un messaggio.</li>



<li>Solo Bob, con la sua chiave privata, può decifrare il messaggio.</li>
</ul>
</li>



<li><p>Bob invia un messaggio firmato ad Alice:</p>
<ul class="wp-block-list">
<li>Bob può firmare un messaggio con la sua chiave privata.</li>



<li>Alice può verificare l’autenticità del messaggio usando la chiave pubblica di Bob.</li>
</ul>
</li>
</ol>



<div class="wp-block-wp-mermaid-block mermaid">


sequenceDiagram
    participant Alice
    participant Bob

    Alice->>Bob: Richiesta chiave pubblica
    Bob-->>Alice: Invia chiave pubblica
    Alice->>Alice: Cifra il messaggio con la chiave pubblica di Bob
    Alice->>Bob: Invia messaggio cifrato
    Bob->>Bob: Decifra il messaggio con la sua chiave privata

    Bob->>Alice: Richiesta chiave pubblica
    Alice-->>Bob: Invia chiave pubblica
    Bob->>Bob: Firma il messaggio con la chiave privata
    Bob->>Alice: Invia messaggio firmato
    Alice->>Alice: Verifica la firma con la chiave pubblica di Bob



</div>



<p>Figura 1 - Sequence Diagram di come Alice e Bob si scambiano un messaggio cifrato e firmato utilizzando le chiavi asimmetriche.</p>



<p>Ora, cerchiamo di capire una differenza importante, ovvero, quella esistente tra <strong>cifrare un messaggio</strong> e <strong>firmare un messaggio</strong>.</p>



<p>La <strong>cifratura</strong> e la <strong>firma digitale</strong> sono due concetti fondamentali della crittografia, <em>ma servono a scopi diversi</em>: <strong>la cifratura</strong> protegge la riservatezza di un messaggio, mentre <strong>la firma digitale</strong> garantisce autenticità e integrità.</p>



<h3 class="wp-block-heading" id="cifrare-un-messaggio">Cifrare un Messaggio</h3>



<p><strong>Obiettivo</strong>: proteggere il contenuto del messaggio, mantenendolo segreto e accessibile solo al destinatario autorizzato.</p>



<p>Come funziona:</p>



<ul class="wp-block-list">
<li><strong>Chiave pubblica del destinatario</strong>: usata per cifrare il messaggio.</li>



<li><strong>Chiave privata del destinatario</strong>: usata per decifrare il messaggio.</li>
</ul>



<p>Usando l'approccio della cifratura asimmetrica:</p>



<p>Se Alice vuole inviare un messaggio segreto a Bob, <strong>Alice cifra il messaggio con la chiave pubblica di Bob</strong>. Solo Bob, con la sua chiave privata, potrà <strong>decifrare</strong> il messaggio e leggerne il contenuto.</p>



<p>Questo garantisce che <strong>nessun altro</strong> possa leggere il messaggio, mantenendo la <strong>riservatezza</strong>.</p>



<p>Esempio:</p>



<p>Immagina che Alice invii un'email a Bob con informazioni sensibili. Alice cifra il contenuto con la chiave pubblica di Bob. Anche se qualcun altro intercettasse l'email, non potrebbe decifrarla senza la chiave privata di Bob.</p>



<h3 class="wp-block-heading" id="firmare-un-messaggio">Firmare un Messaggio</h3>



<p><strong>Obiettivo</strong>: garantire che il messaggio provenga realmente dal mittente (autenticità) e che non sia stato alterato (integrità).</p>



<p>Come funziona:</p>



<ul class="wp-block-list">
<li><strong>Chiave privata del mittente</strong>: usata per firmare digitalmente il messaggio.</li>



<li><strong>Chiave pubblica del mittente</strong>: usata dal destinatario per verificare la firma.</li>
</ul>



<p>Usando l'approccio della firma asimmetrica:</p>



<p>Se Bob vuole inviare un messaggio firmato ad Alice, <strong>Bob firma il messaggio con la sua chiave privata</strong>. Alice può verificare la firma utilizzando la <strong>chiave pubblica di Bob</strong>. Se la verifica riesce, Alice sa che il messaggio è autentico (proviene da Bob) e non è stato alterato durante il trasporto (integrità).</p>



<p>Esempio:</p>



<p>Immagina che Bob invii un contratto digitale ad Alice e lo firmi digitalmente con la sua chiave privata. Alice può verificare la firma con la chiave pubblica di Bob per essere sicura che il documento sia stato inviato da Bob e non sia stato modificato.</p>



<p>La tabella a seguire mostra in modo schematico le differenze tra la cifratura e la firma digitale.</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th class="has-text-align-left" data-align="left"><strong>Aspetto</strong></th><th class="has-text-align-left" data-align="left"><strong>Cifratura</strong></th><th class="has-text-align-left" data-align="left"><strong>Firma Digitale</strong></th></tr></thead><tbody><tr><td class="has-text-align-left" data-align="left"><strong>Scopo</strong></td><td class="has-text-align-left" data-align="left">Proteggere la riservatezza del messaggio</td><td class="has-text-align-left" data-align="left">Garantire l'autenticità e l'integrità del messaggio</td></tr><tr><td class="has-text-align-left" data-align="left"><strong>Chiave usata</strong></td><td class="has-text-align-left" data-align="left">Chiave pubblica del destinatario per cifrare</td><td class="has-text-align-left" data-align="left">Chiave privata del mittente per firmare</td></tr><tr><td class="has-text-align-left" data-align="left"><strong>Chiave per verificare</strong></td><td class="has-text-align-left" data-align="left">Chiave privata del destinatario per decifrare</td><td class="has-text-align-left" data-align="left">Chiave pubblica del mittente per verificare</td></tr><tr><td class="has-text-align-left" data-align="left"><strong>Risultato</strong></td><td class="has-text-align-left" data-align="left">Solo il destinatario può leggere il messaggio</td><td class="has-text-align-left" data-align="left">Il destinatario può verificare la provenienza e l'integrità del messaggio</td></tr></tbody></table><figcaption class="wp-element-caption">Tabella 1 - Differenza tra cifratura e firma digitale</figcaption></figure>



<p></p>



<p>Per fare un riepilogo:</p>



<ul class="wp-block-list">
<li><strong>cifrare</strong> serve a <strong>proteggere i dati</strong>, garantendo che solo il destinatario previsto possa leggere il messaggio.</li>



<li><strong>firmare</strong> serve a <strong>garantire autenticità e integrità</strong>, confermando che il messaggio proviene dal mittente e non è stato modificato.</li>
</ul>



<p>In pratica, queste tecniche vengono spesso utilizzate insieme per fornire sicurezza completa: si può cifrare un messaggio per mantenerlo privato e firmarlo digitalmente per garantirne l'autenticità e l'integrità.</p>



<p>Il limite principale della crittografia asimmetrica risiede nelle <strong>prestazioni</strong>. La crittografia asimmetrica è più lenta rispetto a quella simmetrica, per cui spesso viene usata insieme alla crittografia simmetrica per cifrare dati più grandi.</p>



<h2 class="wp-block-heading" id="esempio-pratico-con-pkcs11-e-smart-card">Esempio pratico con PKCS#11 e Smart Card</h2>



<p>Vediamo ora un esempio pratico di come utilizzare PKCS#11 per accedere a una Smart Card e eseguire operazioni di firma digitale.</p>



<h3 class="wp-block-heading" id="requisiti">Requisiti</h3>



<p>Per portare a termine questo esempio, avremo bisogno degli elementi a seguire.</p>



<ol class="wp-block-list">
<li>Una Smart Card compatibile con PKCS#11.</li>



<li>Un certificato digitale per la tua Smart Card.</li>



<li>Un PIN per accedere alla Smart Card.</li>



<li>Un lettore di Smart Card.</li>



<li>Un driver PKCS#11 per la tua Smart Card.</li>



<li>Un ambiente di sviluppo per il linguaggio di programmazione che desideri utilizzare.</li>



<li>Un'API PKCS#11 per il tuo linguaggio di programmazione.</li>



<li>Un'applicazione che utilizzi PKCS#11 per accedere alla Smart Card.</li>



<li>Un ambiente di test per eseguire l'applicazione.</li>
</ol>



<p>In commercio esistono diverse Smart Card compatibili con PKCS#11 ma in questo esempio ho volutamente scelto di usare una Smart Card che credo abbiate tutti (o quasi): la <strong>TS-CNS (Tessera Sanitaria - Carta Nazionale Servizi)</strong>.</p>



<p><strong>Nota</strong>: prima di poter usare il nostro certificato digitale della TS-CNS, è necessario provvedere alla sua attivazione. <a href="https://sistemats1.sanita.finanze.it/portale/modalita-di-accesso-con-ts_cns">Sul portale STS (Sistema Tessera Sanitaria)</a> è possibile trovare tutte le informazioni necessarie per attivare la propria TS-CNS, più altre funzionalità, come per esempio la consultazione delle spese sanitarie. Ogni regione prevede modalità diverse per l'attivazione della TS-CNS, quindi è importante seguire le istruzioni specifiche per la propria regione. Nel caso della regione Lazio è possibile attivare la TS-CNS direttamente presso gli sportelli ASL di appartenenza. Per ulteriori informazioni, è possibile consultare il <a href="https://www.salutelazio.it/tessera-sanitaria-elettronica">sito ufficiale della Regione Lazio</a> nella sezione <em>Come attivate la Carta Nazionale dei Servizi</em>.</p>



<p>Per quanto riguarda il lettore di Smart Card, è possibile utilizzare un lettore USB o integrato nel computer. Personalmente ho utilizzato il lettore USB <a href="https://www.bit4id.com/en/devices/smart-card-reader-minilector-evo/">miniLector EVO</a> prodotto da <a href="https://www.bit4id.com/">bit4id</a>.</p>



<p>Per quanto riguarda il driver PKCS#11, è possibile utilizzare quello fornito dal produttore della Smart Card o utilizzare un driver open source come <a href="https://github.com/OpenSC/OpenSC">OpenSC</a>. Per questo esempio ho utilizzato OpenSC, principalmente perché è open source e supporta una vasta gamma di Smart Card, tra cui la TS-CNS (basta eseguire il comando <code>opensc-tool -c '?'</code>per ottenere la lista dei driver tra cui è presente anche itacns - Italian CNS). Da non dimenticare che OpenSC è disponibile per diverse piattaforme, tra cui <a href="https://github.com/OpenSC/OpenSC/releases/tag/0.26.0-rc1">Linux, macOS e Windows</a>.</p>



<p>Sul linguaggio di programmazione non c'è limite di scelta, in quanto PKCS#11 è supportato da diversi linguaggi di programmazione, tra cui C, C++, Java, Python, ecc. In questo esempio, la scelta ricade su Python, linguaggio molto popolare e facile da usare, soprattutto per chi è alle prime armi con la programmazione.</p>



<p>Le API PKCS#11 per Python sono disponibili tramite il modulo <a href="https://github.com/LudovicRousseau/PyKCS11">PyKCS11</a>, che fornisce un'interfaccia per l'API PKCS#11. Per installare <code>PyKCS11</code>, è possibile utilizzare il gestore di pacchetti <code>pip</code> eseguendo il comando <code>pip install PyKCS11</code>.</p>



<p>Assodato che faremo uso di Python, PyKCS11 e OpenSC per portare a termine questo esempio, il mio ambiente di sviluppo e test è composto da: macOS, Python 3.12.6, PyKCS11 1.5.16 e OpenSC 0.25.1 [gcc  Apple LLVM 15.0.0 (clang-1500.3.9.4)]. Ovviamente, per chi volesse replicare l'esempio su Windows o Linux, basta installare le versioni di Python, PyKCS11 e OpenSC compatibili con il proprio sistema operativo.</p>



<p>A questo punto che abbiamo soddisfatto tutti i requisiti, è giunto il momento di mettere le mani al codice andando a implementare un semplice programma che eseguirà un'operazione di firma digitale usando il nostro certificato presente all'interno della TS-CNS.</p>



<h3 class="wp-block-heading" id="implementazione-dellapplicazione">Implementazione dell'applicazione</h3>



<p>Andremo a realizzare una semplice applicazione che implementa il flusso dove Bob firma un messaggio e Alice verifica la firma (vedi Figura 1). Il programma sarà diviso in due parti: una per la firma digitale (blocco che dovrebbe usare Bob) e una per la verifica della firma (blocco che dovrebbe usare Alice). In questo esempio, utilizzeremo la chiave privata della TS-CNS per firmare il messaggio e la chiave pubblica per verificare la firma.</p>



<p>Non entreremo nel dettaglio di come funziona l'API PKCS#11, ma ci concentreremo sull'utilizzo pratico per firmare e verificare la firma. Lascio a voi la curiosità di approfondire l'API PKCS#11 e come funziona consultando la <a href="https://docs.oasis-open.org/pkcs11/pkcs11-base/v3.0/pkcs11-base-v3.0.html">documentazione ufficiale</a> e la documentazione di <a href="https://pkcs11wrap.sourceforge.io/api/">PyKCS11</a>.</p>



<p><strong>Nota</strong>: Quelli che mostrerò a seguire sono gli snippet di codice per firmare e verificare la firma. <strong>Il codice completo è disponibile su <a href="https://github.com/amusarra/pkcs11-smart-card">GitHub</a>.</strong></p>



<p>Procediamo per step. Il primo passo è inizializzare l'API PKCS#11 e ottenere un handle per la Smart Card. Per far ciò, dobbiamo importare il modulo <code>PyKCS11</code> e creare un oggetto <code>PyKCS11.PyKCS11Lib</code> con il percorso del driver PKCS#11 della nostra Smart Card.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="import PyKCS11

# Percorso della libreria PKCS#11
pkcs11_lib_path = '/opt/homebrew/Cellar/opensc/0.25.1/lib/opensc-pkcs11.so'
if not os.path.exists(pkcs11_lib_path):
   raise PKCS11LibraryNotFound(
      f&quot;Libreria PKCS#11 non trovata. Specifica il percorso manualmente. Percorso attuale: {pkcs11_lib_path}&quot;)

# Carica la libreria PKCS#11
pkcs11 = PyKCS11.PyKCS11Lib()
pkcs11.load(pkcs11_lib_path)" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> PyKCS11</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Percorso della libreria PKCS#11</span></span>
<span class="line"><span style="color: #D8DEE9FF">pkcs11_lib_path </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">/opt/homebrew/Cellar/opensc/0.25.1/lib/opensc-pkcs11.so</span><span style="color: #ECEFF4">&#39;</span></span>
<span class="line"><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">not</span><span style="color: #D8DEE9FF"> os</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">path</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">exists</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">pkcs11_lib_path</span><span style="color: #ECEFF4">):</span></span>
<span class="line"><span style="color: #D8DEE9FF">   </span><span style="color: #81A1C1">raise</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">PKCS11LibraryNotFound</span><span style="color: #ECEFF4">(</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">f</span><span style="color: #A3BE8C">&quot;Libreria PKCS#11 non trovata. Specifica il percorso manualmente. Percorso attuale: </span><span style="color: #EBCB8B">{</span><span style="color: #D8DEE9FF">pkcs11_lib_path</span><span style="color: #EBCB8B">}</span><span style="color: #A3BE8C">&quot;</span><span style="color: #ECEFF4">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Carica la libreria PKCS#11</span></span>
<span class="line"><span style="color: #D8DEE9FF">pkcs11 </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> PyKCS11</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">PyKCS11Lib</span><span style="color: #ECEFF4">()</span></span>
<span class="line"><span style="color: #D8DEE9FF">pkcs11</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">load</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">pkcs11_lib_path</span><span style="color: #ECEFF4">)</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Python</span></div>



<p>Source Code 1 - Inizializzazione dell'API PKCS#11 e caricamento della libreria PKCS#11</p>



<p>Il secondo passo è quello di ottenere lo slot e il token della Smart Card. Dopo aver ottenuto lo slot e il token, possiamo aprire una sessione con la Smart Card e autenticarci con il PIN.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="    # Ottieni la lista degli slot con token presenti
    slots = pkcs11.getSlotList(tokenPresent=True)

    if len(slots) == 0:
        raise NoSmartCardInserted(&quot;Nessuna Smart Card inserita&quot;)

    # Usa il primo slot disponibile
    slot = slots[0]

    # Apri una sessione con la Smart Card
    session = pkcs11.openSession(slot)
    session.login(args.pin)" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #616E88"># Ottieni la lista degli slot con token presenti</span></span>
<span class="line"><span style="color: #D8DEE9FF">    slots </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> pkcs11</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">getSlotList</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9">tokenPresent</span><span style="color: #81A1C1">=True</span><span style="color: #ECEFF4">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">len</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">slots</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">==</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">raise</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">NoSmartCardInserted</span><span style="color: #ECEFF4">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Nessuna Smart Card inserita</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #616E88"># Usa il primo slot disponibile</span></span>
<span class="line"><span style="color: #D8DEE9FF">    slot </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> slots</span><span style="color: #ECEFF4">[</span><span style="color: #B48EAD">0</span><span style="color: #ECEFF4">]</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #616E88"># Apri una sessione con la Smart Card</span></span>
<span class="line"><span style="color: #D8DEE9FF">    session </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> pkcs11</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">openSession</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">slot</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    session</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">login</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">args</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">pin</span><span style="color: #ECEFF4">)</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Python</span></div>



<p>Source Code 2 - Ottenimento dello slot e del token della Smart Card e apertura di una sessione con la Smart Card</p>



<p>Il terzo passo consiste nel caricare la chiave privata per la firma e la chiave pubblica per la verifica della firma. Per fare ciò, dobbiamo ottenere gli oggetti chiave dalla Smart Card utilizzando il loro ID (vedi <code>PyKCS11.CKO_PRIVATE_KEY</code>, <code>PyKCS11.CKO_CERTIFICATE</code> e <code>PyKCS11.CKA_VALUE</code>).</p>



<p>In questo caso siamo certi del fatto che sulla TS-CNS abbiamo un solo certificato e una sola chiave privata, possiamo quindi assumere che in posizione <code>[0]</code> troveremo i nostri oggetti.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="    # Trova la chiave privata sulla Smart Card
    private_key = session.findObjects([(PyKCS11.CKA_CLASS, PyKCS11.CKO_PRIVATE_KEY)])[0]

    # Trova il certificato pubblico sulla Smart Card
    public_cert = session.findObjects([(PyKCS11.CKA_CLASS, PyKCS11.CKO_CERTIFICATE)])[0]

    # Ottieni il certificato pubblico in formato DER
    public_cert_der = session.getAttributeValue(public_cert, [PyKCS11.CKA_VALUE], False)[0]
    public_cert_der = bytes(public_cert_der)

    # Carica il certificato pubblico
    cert = x509.load_der_x509_certificate(public_cert_der, backend=default_backend())

    # Ottieni la chiave pubblica dal certificato
    public_key = cert.public_key()" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #616E88"># Trova la chiave privata sulla Smart Card</span></span>
<span class="line"><span style="color: #D8DEE9FF">    private_key </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> session</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">findObjects</span><span style="color: #ECEFF4">([(</span><span style="color: #D8DEE9FF">PyKCS11</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">CKA_CLASS</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> PyKCS11</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">CKO_PRIVATE_KEY</span><span style="color: #ECEFF4">)])[</span><span style="color: #B48EAD">0</span><span style="color: #ECEFF4">]</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #616E88"># Trova il certificato pubblico sulla Smart Card</span></span>
<span class="line"><span style="color: #D8DEE9FF">    public_cert </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> session</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">findObjects</span><span style="color: #ECEFF4">([(</span><span style="color: #D8DEE9FF">PyKCS11</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">CKA_CLASS</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> PyKCS11</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">CKO_CERTIFICATE</span><span style="color: #ECEFF4">)])[</span><span style="color: #B48EAD">0</span><span style="color: #ECEFF4">]</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #616E88"># Ottieni il certificato pubblico in formato DER</span></span>
<span class="line"><span style="color: #D8DEE9FF">    public_cert_der </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> session</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">getAttributeValue</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">public_cert</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">[</span><span style="color: #D8DEE9FF">PyKCS11</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">CKA_VALUE</span><span style="color: #ECEFF4">],</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">False</span><span style="color: #ECEFF4">)[</span><span style="color: #B48EAD">0</span><span style="color: #ECEFF4">]</span></span>
<span class="line"><span style="color: #D8DEE9FF">    public_cert_der </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">bytes</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">public_cert_der</span><span style="color: #ECEFF4">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #616E88"># Carica il certificato pubblico</span></span>
<span class="line"><span style="color: #D8DEE9FF">    cert </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> x509</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">load_der_x509_certificate</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">public_cert_der</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">backend</span><span style="color: #81A1C1">=</span><span style="color: #88C0D0">default_backend</span><span style="color: #ECEFF4">())</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #616E88"># Ottieni la chiave pubblica dal certificato</span></span>
<span class="line"><span style="color: #D8DEE9FF">    public_key </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> cert</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">public_key</span><span style="color: #ECEFF4">()</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Python</span></div>



<p>Source Code 3 - Caricamento della chiave privata e pubblica dalla Smart Card</p>



<p>Il quarto passo prevede la codifica del messaggio e la sua firma. Per firmare il messaggio, dobbiamo utilizzare la chiave privata e un algoritmo di firma come <code>PyKCS11.CKM_SHA256_RSA_PKCS</code>.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="    # Codifica il messaggio da firmare
    data = args.message.encode()

    # Firma il messaggio usando la chiave privata
    mechanism = PyKCS11.Mechanism(PyKCS11.CKM_SHA256_RSA_PKCS, None)
    signature = session.sign(private_key, data, mechanism)
    signature = bytes(signature)" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #616E88"># Codifica il messaggio da firmare</span></span>
<span class="line"><span style="color: #D8DEE9FF">    data </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> args</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">message</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">encode</span><span style="color: #ECEFF4">()</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #616E88"># Firma il messaggio usando la chiave privata</span></span>
<span class="line"><span style="color: #D8DEE9FF">    mechanism </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> PyKCS11</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">Mechanism</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">PyKCS11</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">CKM_SHA256_RSA_PKCS</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">None</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    signature </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> session</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">sign</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">private_key</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> data</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> mechanism</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    signature </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">bytes</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">signature</span><span style="color: #ECEFF4">)</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Python</span></div>



<p>Source Code 4 - Codifica del messaggio e firma del messaggio</p>



<p>A questo punto abbiamo ottenuto la firma del messaggio (<code>signature = bytes(signature)</code>) che Bob vuole inviare ad Alice. Come ultimo passo, dobbiamo scrivere il blocco di codice che Alice dovrebbe usare per verificare che il messaggio sia stato firmato da Bob.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="   # Verifica la firma usando la chiave pubblica
   try:
      public_key.verify(
         signature,
         data,
         padding.PKCS1v15(),
         hashes.SHA256()
      )
      print(f&quot;{Fore.GREEN}&#x2705; Firma verificata correttamente!&quot;)
   except Exception as e:
      print(f&quot;{Fore.RED}&#x274c; Verifica della firma fallita: {e}&quot;)
   
   # Logout dalla sessione
   session.logout()" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">   </span><span style="color: #616E88"># Verifica la firma usando la chiave pubblica</span></span>
<span class="line"><span style="color: #D8DEE9FF">   </span><span style="color: #81A1C1">try</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">      public_key</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">verify</span><span style="color: #ECEFF4">(</span></span>
<span class="line"><span style="color: #D8DEE9FF">         signature</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">         data</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">         padding</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">PKCS1v15</span><span style="color: #ECEFF4">(),</span></span>
<span class="line"><span style="color: #D8DEE9FF">         hashes</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">SHA256</span><span style="color: #ECEFF4">()</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #88C0D0">print</span><span style="color: #ECEFF4">(</span><span style="color: #81A1C1">f</span><span style="color: #A3BE8C">&quot;</span><span style="color: #EBCB8B">{</span><span style="color: #D8DEE9FF">Fore</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">GREEN</span><span style="color: #EBCB8B">}</span><span style="color: #A3BE8C">&#x2705; Firma verificata correttamente!&quot;</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">   </span><span style="color: #81A1C1">except</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">Exception</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">as</span><span style="color: #D8DEE9FF"> e</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #88C0D0">print</span><span style="color: #ECEFF4">(</span><span style="color: #81A1C1">f</span><span style="color: #A3BE8C">&quot;</span><span style="color: #EBCB8B">{</span><span style="color: #D8DEE9FF">Fore</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">RED</span><span style="color: #EBCB8B">}</span><span style="color: #A3BE8C">&#x274c; Verifica della firma fallita: </span><span style="color: #EBCB8B">{</span><span style="color: #D8DEE9FF">e</span><span style="color: #EBCB8B">}</span><span style="color: #A3BE8C">&quot;</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">   </span></span>
<span class="line"><span style="color: #D8DEE9FF">   </span><span style="color: #616E88"># Logout dalla sessione</span></span>
<span class="line"><span style="color: #D8DEE9FF">   session</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">logout</span><span style="color: #ECEFF4">()</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Python</span></div>



<p>Source Code 5 - Verifica della firma del messaggio</p>



<p>Wow! Abbiamo completato l'implementazione dell'applicazione che esegue un'operazione di firma digitale e verifica della firma utilizzando una Smart Card e l'API PKCS#11. Per fare un riepilogo e inserire nel contesto Bob e Alice, quello che dovrebbe accadere e quanto mostrato dal sequence diagram a seguire.</p>



<div class="wp-block-wp-mermaid-block mermaid">


sequenceDiagram
    participant Bob
    participant SmartCard
    participant Alice

    Bob->>SmartCard: Inserisce la Smart Card
    Bob->>SmartCard: Inserisce il PIN
    SmartCard-->>Bob: Autenticazione riuscita
    Bob->>SmartCard: Firma il messaggio
    SmartCard-->>Bob: Restituisce la firma
    Bob->>Alice: Invia messaggio e firma

    Alice->>Bob: Chiede a Bob la chiave pubblica
    Bob-->>Alice: Restituisce la chiave pubblica
    Alice->>Alice: Verifica la firma con la chiave pubblica
    Alice-->>Alice: Firma verificata correttamente



</div>



<p>Figura 2 - Sequence Diagram di come Alice e Bob si scambiano un messaggio cifrato e firmato utilizzando le chiavi asimmetriche.</p>



<p>Conclusa la fase d'implementazione, passeremo alla fase di test.</p>



<h3 class="wp-block-heading" id="test-dellapplicazione-di-firma-digitale">Test dell'applicazione di firma digitale</h3>



<p>L'applicazione finale è disponibile su <a href="https://github.com/amusarra/pkcs11-smart-card">GitHub</a> e può essere eseguita da riga di comando. Per eseguire l'applicazione, è necessario specificare il PIN della Smart Card e il messaggio da firmare. Ecco un esempio di come eseguire l'applicazione:</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# Installazione dei requirements
pip install -r requirements.txt

# Esegui l'applicazione per firmare un messaggio
./sign-via-ts-cns.py --pin 123456 --message &quot;Prima firma di un messaggio tramite la mia TS-CNS&quot;" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88"># Installazione dei requirements</span></span>
<span class="line"><span style="color: #88C0D0">pip</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">install</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-r</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">requirements.txt</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Esegui l&#39;applicazione per firmare un messaggio</span></span>
<span class="line"><span style="color: #88C0D0">./sign-via-ts-cns.py</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">--pin</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">123456</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">--message</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Prima firma di un messaggio tramite la mia TS-CNS</span><span style="color: #ECEFF4">&quot;</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Bash</span></div>



<p>Console 1 - Esempio di esecuzione dell'applicazione di firma digitale</p>



<p>In output l'applicazione mostrerà la firma generata (in formato esadecimale) e il risultato della verifica della firma. Se la firma è stata verificata correttamente, sarà visualizzato un messaggio di successo, altrimenti verrà visualizzato un messaggio di errore. A seguire un esempio di output dell'applicazione.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="&#x1f50d; Dati da firmare: b'Prima firma di un messaggio tramite la mia TS-CNS'
&#x2705; Firma generata (in esadecimale): b'99be876fb527dbd8e36e9d76f69357e6ef006c737e535b48ed45acd28ebb3b2a14cc7a08cc4902d92194b18b2cc8b61cc2a23747119b6c473fe4757e12ac66c6ce9488354a9fbbb95b003b643295e428b18383328192953c645afe0f9b00e9bf405981da4a52b40f288275023d8aa06e81f88a066888dc29e88a1b6280b5e7c2f26b1e8d5bc469839dcf07128b3e525ad88c9190b76811def76530131246e201a4428b74f65757957e67190ce284b0c8ee89f422b3cf960899467fd1bb66ded6a97999ccf3a2407b07f49af697590b0dac28585c5c3e8b0ca3b3aa1bc47eb1aab2d67a0b0fc1c8cf9bde51512acb9ebed80bf514f6cfe7e9900d2d3541df1f39'
&#x2705; Firma verificata correttamente!" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #d8dee9ff">&#x1f50d; Dati da firmare: b&#39;Prima firma di un messaggio tramite la mia TS-CNS&#39;</span></span>
<span class="line"><span style="color: #d8dee9ff">&#x2705; Firma generata (in esadecimale): b&#39;99be876fb527dbd8e36e9d76f69357e6ef006c737e535b48ed45acd28ebb3b2a14cc7a08cc4902d92194b18b2cc8b61cc2a23747119b6c473fe4757e12ac66c6ce9488354a9fbbb95b003b643295e428b18383328192953c645afe0f9b00e9bf405981da4a52b40f288275023d8aa06e81f88a066888dc29e88a1b6280b5e7c2f26b1e8d5bc469839dcf07128b3e525ad88c9190b76811def76530131246e201a4428b74f65757957e67190ce284b0c8ee89f422b3cf960899467fd1bb66ded6a97999ccf3a2407b07f49af697590b0dac28585c5c3e8b0ca3b3aa1bc47eb1aab2d67a0b0fc1c8cf9bde51512acb9ebed80bf514f6cfe7e9900d2d3541df1f39&#39;</span></span>
<span class="line"><span style="color: #d8dee9ff">&#x2705; Firma verificata correttamente!</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Plaintext</span></div>



<p>Console 2 - Esempio di output dell'applicazione di firma digitale</p>



<p>Quando l'applicazione termina con successo, questa genera tre file:</p>



<ol class="wp-block-list">
<li><code>message_&lt;uuid4&gt;txt</code>: il messaggio originale.</li>



<li><code>signature_&lt;uuid4&gt;.txt</code>: la firma generata.</li>



<li><code>public_cert.pem</code>: la chiave pubblica.</li>
</ol>



<p>Questi file possono essere utilizzati per verificare la firma in un secondo momento o per inviare il messaggio firmato ad altri utenti, come per esempio Alice. Quindi, per fare fede a quanto indicato del sequence diagram di Figura 2, Alice dovrebbe usare questi tre file per verificare la firma del messaggio.</p>



<p>Qual è il modo più semplice per verificare la firma del messaggio? Semplice, usando OpenSSL. Ecco come fare.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# Verifica la firma del messaggio tramite openssl.
openssl dgst -sha256 -verify &lt;(openssl x509 -in public_cert.pem -pubkey -noout) -signature signature_e032b4fe6213486eb9830fe0dacf9f3b.bin message_9789a64270b1443da672a5d1776d6664.txt" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88"># Verifica la firma del messaggio tramite openssl.</span></span>
<span class="line"><span style="color: #88C0D0">openssl</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">dgst</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-sha256</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-verify</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&lt;(</span><span style="color: #88C0D0">openssl</span><span style="color: #A3BE8C"> x509 -in public_cert.pem -pubkey -noout</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-signature</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">signature_e032b4fe6213486eb9830fe0dacf9f3b.bin</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">message_9789a64270b1443da672a5d1776d6664.txt</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Bash</span></div>



<p>Console 3 - Verifica della firma del messaggio tramite OpenSSL</p>



<p>Il risultato atteso dovrebbe essere <code>Verified OK</code>. Se la firma è stata verificata correttamente, significa che l'applicazione ha funzionato correttamente e che la firma è stata generata e verificata con successo.</p>



<p>Nel caso in cui la verifica della firma fallisca, è possibile che ci siano stati errori durante la generazione della firma o magari per qualche motivo per esempio il messaggio originale è stato alterato. Facciamo una simulazione di alterazione del messaggio originale e vediamo cosa succede.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# Altera il messaggio originale
echo &quot;Messaggio alterato&quot; &gt; message_9789a64270b1443da672a5d1776d6664.txt

# Verifica la firma del messaggio tramite openssl.
openssl dgst -sha256 -verify <(openssl x509 -in public_cert.pem -pubkey -noout) -signature signature_e032b4fe6213486eb9830fe0dacf9f3b.bin message_9789a64270b1443da672a5d1776d6664.txt
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88"># Altera il messaggio originale</span></span>
<span class="line"><span style="color: #88C0D0">echo</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Messaggio alterato</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">message_9789a64270b1443da672a5d1776d6664.txt</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Verifica la firma del messaggio tramite openssl.</span></span>
<span class="line"><span style="color: #88C0D0">openssl</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">dgst</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-sha256</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-verify</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&lt;(</span><span style="color: #88C0D0">openssl</span><span style="color: #A3BE8C"> x509 -in public_cert.pem -pubkey -noout</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-signature</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">signature_e032b4fe6213486eb9830fe0dacf9f3b.bin</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">message_9789a64270b1443da672a5d1776d6664.txt</span></span>
<span class="line"></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Bash</span></div>



<p>Console 4 - Verifica della firma del messaggio tramite OpenSSL con messaggio alterato</p>



<p>Il risultato atteso dovrebbe essere <code>Verification Failure</code>. Se la verifica della firma fallisce, significa che il messaggio è stato alterato dopo la firma e quindi la firma non è più valida.</p>



<p>Il programma completo consente di fare anche altro, per scoprirlo basta eseguire il comando <code>./sign-via-ts-cns.py --help</code> per visualizzare l'help dell'applicazione e dovreste vedere qualcosa di simile a quanto mostrato a seguire.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="usage: sign-via-ts-cns.py [-h] --pin PIN --message MESSAGE [--debug] [--signature-file SIGNATURE_FILE] [--message-file MESSAGE_FILE]
                          [--pkcs11-lib PKCS11_LIB]

Script per firmare un messaggio usando una Smart Card

options:
  -h, --help            show this help message and exit
  --pin PIN             PIN della Smart Card
  --message MESSAGE     Messaggio da firmare
  --debug               Abilita i messaggi di debug
  --signature-file SIGNATURE_FILE
                        File in cui salvare la firma
  --message-file MESSAGE_FILE
                        File in cui salvare il messaggio
  --pkcs11-lib PKCS11_LIB
                        Percorso della libreria PKCS#11
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">usage:</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">sign-via-ts-cns.py</span><span style="color: #D8DEE9FF"> [-h] --pin PIN --message MESSAGE </span><span style="color: #ECEFF4">[</span><span style="color: #D8DEE9FF">--debug</span><span style="color: #ECEFF4">]</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">[</span><span style="color: #D8DEE9FF">--signature-file SIGNATURE_FILE</span><span style="color: #ECEFF4">]</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">[</span><span style="color: #D8DEE9FF">--message-file MESSAGE_FILE</span><span style="color: #ECEFF4">]</span></span>
<span class="line"><span style="color: #D8DEE9FF">                          </span><span style="color: #ECEFF4">[</span><span style="color: #D8DEE9FF">--pkcs11-lib PKCS11_LIB</span><span style="color: #ECEFF4">]</span></span>
<span class="line"></span>
<span class="line"><span style="color: #88C0D0">Script</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">per</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">firmare</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">un</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">messaggio</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">usando</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">una</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Smart</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Card</span></span>
<span class="line"></span>
<span class="line"><span style="color: #88C0D0">options:</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">-h,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">--help</span><span style="color: #D8DEE9FF">            </span><span style="color: #A3BE8C">show</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">this</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">help</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">message</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">and</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">exit</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">--pin</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">PIN</span><span style="color: #D8DEE9FF">             </span><span style="color: #A3BE8C">PIN</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">della</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Smart</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Card</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">--message</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">MESSAGE</span><span style="color: #D8DEE9FF">     </span><span style="color: #A3BE8C">Messaggio</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">da</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">firmare</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">--debug</span><span style="color: #D8DEE9FF">               </span><span style="color: #A3BE8C">Abilita</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">i</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">messaggi</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">di</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">debug</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">--signature-file</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">SIGNATURE_FILE</span></span>
<span class="line"><span style="color: #D8DEE9FF">                        </span><span style="color: #88C0D0">File</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">in</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">cui</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">salvare</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">la</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">firma</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">--message-file</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">MESSAGE_FILE</span></span>
<span class="line"><span style="color: #D8DEE9FF">                        </span><span style="color: #88C0D0">File</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">in</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">cui</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">salvare</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">il</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">messaggio</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">--pkcs11-lib</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">PKCS11_LIB</span></span>
<span class="line"><span style="color: #D8DEE9FF">                        </span><span style="color: #88C0D0">Percorso</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">della</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">libreria</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">PKCS#11</span></span>
<span class="line"></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Bash</span></div>



<p>Console 5 - Help dell'applicazione di firma digitale</p>



<p>L'opzione che mi sento di consigliare è <code>--debug</code> che abilita in output ulteriori messaggi utili a capire meglio cosa stia succedendo durante l'esecuzione dell'applicazione. Inoltre, è possibile specificare il percorso della libreria PKCS#11 con l'opzione <code>--pkcs11-lib</code> e i file in cui salvare la firma e il messaggio con le opzioni <code>--signature-file</code> e <code>--message-file</code>.</p>



<p>A seguire il diagramma di sequenza che mostra come l'applicazione interagisce con la Smart Card attraverso la libreria PKCS#11 per firmare un messaggio e verificare la firma.</p>



<div class="wp-block-wp-mermaid-block mermaid">


sequenceDiagram
    participant User
    participant Script
    participant PKCS11Lib
    participant SmartCard

    User ->> Script: Avvia lo script con i parametri
    Script ->> Script: Analizza i parametri di input
    Script ->> PKCS11Lib: Carica la libreria PKCS#11
    Script ->> PKCS11Lib: Ottiene la lista degli slot con token presenti
    PKCS11Lib -->> Script: Lista degli slot
    Script ->> SmartCard: Apre una sessione con la Smart Card
    Script ->> SmartCard: Esegue il login con il PIN
    Script ->> SmartCard: Trova la chiave privata
    SmartCard -->> Script: Chiave privata
    Script ->> SmartCard: Trova il certificato pubblico
    SmartCard -->> Script: Certificato pubblico
    Script ->> SmartCard: Ottiene il certificato pubblico in formato DER
    SmartCard -->> Script: Certificato pubblico (DER)
    Script ->> Script: Carica il certificato pubblico
    Script ->> Script: Salva il certificato pubblico in formato PEM
    Script ->> Script: Ottiene la chiave pubblica dal certificato
    Script ->> Script: Codifica il messaggio da firmare
    Script ->> SmartCard: Firma il messaggio usando la chiave privata
    SmartCard -->> Script: Firma
    Script ->> Script: Salva la firma su file
    Script ->> Script: Salva il messaggio su file
    Script ->> Script: Verifica la firma usando la chiave pubblica
    Script ->> SmartCard: Esegue il logout dalla sessione
    Script ->> User: Termina l'esecuzione



</div>



<p>Figura 3 - Sequence Diagram di come l'applicazione interagisce con la Smart Card attraverso la libreria PKCS#11 per firmare un messaggio e verificare la firma</p>



<h2 class="wp-block-heading" id="utilizzo-in-applicazioni-reali">Utilizzo in applicazioni reali</h2>



<p>Le Smart Card e lo standard PKCS#11 sono utilizzati in molti scenari di sicurezza crittografica.</p>



<ol class="wp-block-list">
<li><strong>Firma Digitale</strong>: le firme digitali eseguite tramite chiavi private su Smart Card sono molto comuni in applicazioni di governo elettronico (e-government) e nei sistemi finanziari.</li>



<li><strong>Autenticazione Forte</strong>: molte aziende e istituzioni richiedono un’autenticazione a due fattori (2FA) basata su Smart Card per l’accesso ai sistemi critici.</li>



<li><strong>Crittografia e Decrittazione</strong>: le Smart Card possono essere utilizzate per cifrare e decifrare documenti o dati sensibili direttamente all’interno del dispositivo, garantendo che le chiavi private non lascino mai la carta.</li>



<li><strong>Infrastruttura PKI</strong>: le Smart Card sono comunemente utilizzate in un’infrastruttura a chiave pubblica (PKI) per la gestione sicura delle identità digitali.</li>
</ol>



<h2 class="wp-block-heading" id="risorse-e-approfondimenti">Risorse e Approfondimenti</h2>



<p>Il repository GitHub <strong>pkcs11-smart-card</strong> con il codice completo dell'applicazione è disponibile al seguente <a href="https://github.com/amusarra/pkcs11-smart-card">link</a>.</p>



<p>Per ulteriori informazioni su PKCS#11 e PyKCS11, consiglio di consultare la documentazione ufficiale: <a href="https://docs.oasis-open.org/pkcs11/pkcs11-base/v3.0/pkcs11-base-v3.0.html">PKCS#11</a> e <a href="https://pkcs11wrap.sourceforge.io/api/">PyKCS11</a>.</p>



<p>Per ulteriori informazioni su OpenSC, consiglio di consultare la documentazione ufficiale: <a href="https://github.com/OpenSC/OpenSC/wiki">OpenSC</a>.</p>



<p>Nel caso in cui si desideri approfondire la programmazione delle Smart Card, consiglio l'ottimo libro di <a href="https://www.ugochirico.com/">Ugo Chirico</a> <a href="https://amzn.to/47DEZCz">Programmazione delle Smart Card</a>.</p>



<p>Per altri temi che riguardano Smart Card e sicurezza informatica, propongo qualche articolo pubblicato sul mio blog personale:</p>



<ol class="wp-block-list">
<li><a href="https://www.dontesta.it/2022/03/11/raspberry-pi-smart-card-mifare-classic-1k-realizzare-sistema-accesso/">Raspberry Pi e Smart Card Mifare Classic 1K: Realizzare un sistema di accesso</a></li>



<li><a href="https://www.dontesta.it/2024/09/19/implementazione-tls-mutual-authentication-mtls-con-quarkus/">Implementazione di TLS Mutual Authentication (mTLS) con Quarkus</a></li>



<li><a href="https://www.dontesta.it/2020/07/17/raspberry-pi-esempio-applicazione-ts-cns-smartcard/">Raspberry Pi – Un esempio di applicazione della TS-CNS</a></li>
</ol>



<h2 class="wp-block-heading" id="conclusioni">Conclusioni</h2>



<p>Lo standard PKCS#11 rappresenta uno strumento potente e flessibile per integrare dispositivi crittografici hardware, come le Smart Card, all’interno di applicazioni moderne. Grazie a questa API standardizzata, gli sviluppatori possono sfruttare le capacità crittografiche avanzate dei token hardware in modo semplice e sicuro, indipendentemente dalla piattaforma sottostante.</p>



<p>In questo articolo, abbiamo esplorato i concetti chiave di PKCS#11 e come utilizzarlo per firmare e verificare la firma di un messaggio tramite una Smart Card. Abbiamo anche visto come sia stato semplice implementare un’applicazione Python che sfrutta l’API PKCS#11 per interagire con una Smart Card, in questo caso la "nostrana" TS-CNS ed eseguire operazioni di firma digitale.</p>
<p>L'articolo <a href="https://www.dontesta.it/2024/09/22/approfondimento-standard-pkcs11-smart-card/">Approfondimento sullo standard PKCS#11 e utilizzo con Smart Card</a> sembra essere il primo su <a href="https://www.dontesta.it">Antonio Musarra&#039;s Blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.dontesta.it/2024/09/22/approfondimento-standard-pkcs11-smart-card/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Implementazione di TLS Mutual Authentication (mTLS) con Quarkus</title>
		<link>https://www.dontesta.it/2024/09/19/implementazione-tls-mutual-authentication-mtls-con-quarkus/</link>
					<comments>https://www.dontesta.it/2024/09/19/implementazione-tls-mutual-authentication-mtls-con-quarkus/#respond</comments>
		
		<dc:creator><![CDATA[Antonio Musarra]]></dc:creator>
		<pubDate>Wed, 18 Sep 2024 23:21:53 +0000</pubDate>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[SSL/TLS]]></category>
		<category><![CDATA[Java Security]]></category>
		<category><![CDATA[mTLS]]></category>
		<category><![CDATA[PKIX]]></category>
		<category><![CDATA[Quarkus]]></category>
		<guid isPermaLink="false">https://www.dontesta.it/?p=5758</guid>

					<description><![CDATA[<p>La sicurezza delle applicazioni web è sempre più critica, soprattutto in contesti in cui le comunicazioni devono essere protette da entrambe le parti coinvolte. In questo contesto, l’autenticazione reciproca TLS (mTLS) offre una soluzione&#46;&#46;&#46;</p>
<p>L'articolo <a href="https://www.dontesta.it/2024/09/19/implementazione-tls-mutual-authentication-mtls-con-quarkus/">Implementazione di TLS Mutual Authentication (mTLS) con Quarkus</a> sembra essere il primo su <a href="https://www.dontesta.it">Antonio Musarra&#039;s Blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<h1 class="wp-block-heading" id="implementazione-di-tls-mutual-authentication-mtls-con-quarkus"></h1>



<p>La sicurezza delle applicazioni web è sempre più critica, soprattutto in contesti in cui le comunicazioni devono essere protette da entrambe le parti coinvolte. In questo contesto, l’<strong>autenticazione reciproca TLS (mTLS)</strong> offre una soluzione solida, garantendo che sia il client sia il server siano autenticati prima di stabilire una connessione sicura. L'obiettivo di questo articolo è quello di guidarvi verso la strada dell'implementazione di mTLS in un’applicazione utilizzando <strong><a href="https://quarkus.io">Quarkus</a></strong>, un framework Java ottimizzato per il cloud.</p>



<h2 class="wp-block-heading" id="cosè-lautenticazione-reciproca-tls-mtls">Cos’è l’autenticazione reciproca TLS (mTLS)?</h2>



<p>L’autenticazione reciproca TLS (o mutual TLS o mTLS) è un’estensione del protocollo <a href="https://it.wikipedia.org/wiki/Transport_Layer_Security">TLS</a> standard. Solitamente TLS viene utilizzato per proteggere le comunicazioni tra client e server, dove solo il server deve presentare un certificato valido per autenticarsi con il client. <strong>Con mTLS, anche il client deve presentare un certificato valido, garantendo così che entrambe le parti siano autentiche</strong>.</p>



<p>Questa autenticazione bidirezionale è particolarmente utile in applicazioni distribuite, microservizi o API, dove sia il client che il server devono fidarsi reciprocamente prima di scambiare dati sensibili.</p>



<p>Il sequence diagram a seguire mostra il processo di autenticazione reciproca TLS (mTLS) tra un client e un server. In particolare, il client invia il proprio certificato al server, che lo verifica prima di stabilire una connessione sicura. Se il certificato del client è valido, il server procede con l’autenticazione e la comunicazione può iniziare (come ultimo step).</p>



<div class="wp-block-wp-mermaid-block mermaid">
sequenceDiagram
    autonumber
    participant Client
    participant Server
    Client->>Server: Client Hello (Supported ciphersuites, Random number)
    Server-->>Client: Server Hello (Chosen ciphersuite, Random number, Request client certificate)
    Server-->>Client: Certificate (Server's certificate)
    Client-->>Client: Verify Server Certificate
    Client->>Server: Client Certificate (Client's certificate)
    Server-->>Server: Verify Client Certificate
    Client->>Server: Client Key Exchange (Premaster secret encrypted with server public key)
    Client->>Server: Finished (Encrypted with session key)
    Server->>Client: Finished (Encrypted with session key)
    Client->>Server: Application Data
    Server->>Client: Application Data
</div>



<p>Figura 1 - Sequence diagramm del processo di autenticazione reciproca TLS (mTLS)</p>



<p>È importate capire che la verifica dei certificati nel contesto mTLS è un processo cruciale per garantire la sicurezza della connessione, impedendo la comunicazione con entità non fidate o malintenzionate. Se una delle verifiche dovesse fallire (ad esempio, il certificato è scaduto o non valido), l’handshake sarà interrotto e la connessione non sarà stabilita.</p>



<p>Vediamo di approfondire quali sono i passaggi chiave per la verifica dei certificati in un contesto mTLS.</p>



<h3 class="wp-block-heading" id="verifica-del-certificato-del-server-da-parte-del-client">Verifica del certificato del server da parte del client</h3>



<p>Quando il server invia il proprio certificato al client, quest’ultimo deve verificarlo attraverso i seguenti passaggi.</p>



<ul class="wp-block-list">
<li><strong>Catena di certificazione (Certificate Chain)</strong>: il client controlla che il certificato ricevuto dal server appartenga a una catena di certificati attendibili. Questo significa che il certificato del server deve essere firmato da un’autorità di certificazione (CA) che è inclusa nell’elenco delle CA fidate del client. La catena di certificazione viene verificata partendo dal certificato del server fino alla CA radice fidata.</li>



<li><strong>Firma del certificato</strong>: il client verifica la firma digitale sul certificato del server. La firma deve essere stata generata dalla CA utilizzando la sua chiave privata. Il client usa la chiave pubblica della CA, inclusa nel certificato della CA, per verificare la firma. Se la firma corrisponde, il certificato non è stato modificato e può essere considerato autentico.</li>



<li><strong>Validità temporale</strong>: il client verifica che il certificato non sia scaduto, controllando le date di validità (notBefore e notAfter) contenute nel certificato.</li>



<li><strong>Revoca del certificato</strong>: il client può verificare se il certificato del server è stato revocato. Questo avviene tramite il controllo delle <strong><a href="https://en.wikipedia.org/wiki/Certificate_revocation_list">CRL (Certificate Revocation List)</a></strong> o utilizzando il protocollo <strong><a href="https://en.wikipedia.org/wiki/Online_Certificate_Status_Protocol">OCSP (Online Certificate Status Protocol)</a></strong> per interrogare in tempo reale lo stato del certificato.</li>



<li><strong>Hostname</strong>: Il client verifica che l’hostname del server corrisponda a quello presente nel certificato (nel campo <strong>Subject</strong> o nel campo <strong><a href="https://en.wikipedia.org/wiki/Public_key_certificate#Subject_Alternative_Name_certificate">Subject Alternative Name</a></strong>). Questo assicura che il certificato sia effettivamente emesso per il server con cui il client sta tentando di comunicare.</li>
</ul>



<h3 class="wp-block-heading" id="verifica-del-certificato-del-client-da-parte-del-server">Verifica del certificato del client da parte del server</h3>



<p>Quando il client invia il proprio certificato al server (se richiesto), il server deve verificarlo con i seguenti passaggi simili a quelli effettuati dal client.</p>



<ul class="wp-block-list">
<li><strong>Catena di certificazione</strong>: il server verifica che il certificato del client appartenga a una catena di certificati attendibili, cioè che sia firmato da una CA che il server riconosce come fidata. Anche qui si controlla la catena fino alla CA radice.</li>



<li><strong>Firma del certificato</strong>: il server verifica la firma digitale sul certificato del client, utilizzando la chiave pubblica della CA che ha emesso il certificato per assicurarsi che la firma sia valida e che il certificato non sia stato alterato.</li>



<li><strong>Validità temporale</strong>: il server controlla che il certificato del client non sia scaduto, verificando le date di inizio e fine validità.</li>



<li><strong>Revoca del certificato</strong>: come nel caso del client, anche il server può effettuare un controllo per verificare se il certificato del client è stato revocato, usando una CRL o il protocollo OCSP.</li>



<li><strong>Identità del client</strong>: in alcuni casi, il server può verificare che il certificato del client corrisponda a un’entità specifica (ad esempio, un’azienda o un dispositivo) che ha diritto di accedere ai servizi del server. Questa verifica può essere basata sui campi presenti nel certificato, come il campo Subject.</li>
</ul>



<h3 class="wp-block-heading" id="crittografia-e-integrità-dei-certificati">Crittografia e integrità dei certificati</h3>



<p>Durante l’handshake, la chiave pubblica contenuta nei certificati viene utilizzata per scambiare in modo sicuro il <strong>premaster secret</strong>, che sarà poi trasformato nella chiave di sessione. Grazie a questo, il client e il server possono essere certi dell’identità reciproca e stabilire una connessione sicura.</p>



<h3 class="wp-block-heading" id="i-cassetti-digitali">I cassetti digitali</h3>



<p>Sì, i certificati utilizzati per l'autenticazione, sia lato client sia lato server, sono memorizzati in <strong>repository specifici</strong> che fungono da <strong>"cassetti digitali"</strong> in cui i certificati sono conservati e verificati durante l'handshake TLS/mTLS. Ecco una panoramica dei principali luoghi dove i certificati sono archiviati e controllati.</p>



<h4 class="wp-block-heading" id="1-truststore">1. Truststore</h4>



<p>Il <strong>truststore</strong> è una raccolta di certificati radice di autorità di certificazione (CA) fidate. Questo è il "cassetto" dove vengono conservati i certificati delle CA che il sistema considera attendibili.</p>



<ul class="wp-block-list">
<li><p><strong>Lato Client</strong>: quando il client riceve il certificato del server, verifica che il certificato sia stato firmato da una delle CA presenti nel truststore. Se il certificato non può essere tracciato a una CA fidata (cioè, se non c'è una catena valida fino a una CA radice nel truststore), la connessione verrà rifiutata.</p></li>



<li><p><strong>Lato Server</strong>: analogamente, il server verifica il certificato del client confrontandolo con le CA presenti nel suo truststore.</p></li>
</ul>



<p>Qualcuno si chiederà dove si trovi il truststore, questo dipende dal sistema operativo.</p>



<ul class="wp-block-list">
<li><p><strong>Sistemi operativi</strong>: il truststore è integrato nel sistema operativo. Ad esempio, su:</p>
<ul class="wp-block-list">
<li><strong>Windows</strong>: i certificati fidati si trovano nel <strong>Certificato Root (CA)</strong> in "Gestione Certificati";
<ul class="wp-block-list">
<li><strong>Linux</strong>: il truststore si trova solitamente in directory come <code>/etc/ssl/certs/</code> o <code>/usr/share/ca-certificates/</code>. La posizione potrebbe differire a seconda della distribuzione Linux;</li>
</ul>
</li>



<li><strong>macOS</strong>: il truststore è gestito tramite il <strong>Keychain Access</strong>, che contiene i certificati radice fidati.</li>
</ul>
</li>



<li><p><strong>Applicazioni</strong>: alcune applicazioni, come browser web o server, mantengono il proprio truststore separato. Ad esempio, i browser come Firefox usano un truststore indipendente da quello del sistema operativo.</p></li>
</ul>



<h4 class="wp-block-heading" id="2-keystore">2. Keystore</h4>



<p>Il <strong>keystore</strong> è il luogo dove sono archiviati i certificati e le chiavi private associate a un'entità (come un server o un client). È simile a un portafoglio digitale che contiene le credenziali usate per identificarsi durante l'handshake.</p>



<ul class="wp-block-list">
<li><p><strong>Lato Server</strong>: il server archivia il proprio certificato e la chiave privata nel keystore. Quando il client richiede il certificato del server, questo viene estratto dal keystore e inviato al client per la verifica.</p></li>



<li><p><strong>Lato Client</strong>: se la verifica del client è obbligatoria (come nel caso dell'mTLS), il client invia il proprio certificato estratto dal keystore quando il server lo richiede. Insieme al certificato, il client utilizza la chiave privata memorizzata nel keystore per firmare i messaggi di autenticazione durante l'handshake.</p></li>
</ul>



<p>Qui la posizione del keystore dipende dal tipo di applicazione e dal sistema operativo.</p>



<ul class="wp-block-list">
<li><strong>Java KeyStore (JKS)</strong>: Java usa un formato keystore specifico chiamato <strong><a href="https://en.wikipedia.org/wiki/Java_KeyStore">JKS</a></strong>. Questo file può contenere certificati e chiavi private ed è ampiamente usato in ambienti Java, come server applicativi (es. Tomcat, Spring Boot).</li>



<li><strong>PKCS#12 (PFX o P12)</strong>: è un <a href="https://en.wikipedia.org/wiki/PKCS_12">formato standard</a> per contenere certificati e chiavi private. Viene usato su diversi sistemi operativi e server. Ad esempio, i file <code>.pfx</code> o <code>.p12</code> possono essere caricati in un server come Apache o NGINX.</li>



<li><strong>Keychain (macOS)</strong>: Su macOS, i certificati e le chiavi private possono essere memorizzati nel <strong>Keychain</strong>.</li>
</ul>



<p>Il formato <strong>JKS</strong> è ancora supportato ma sconsigliato l'uso in favore di <strong>PKCS#12</strong>, soprattutto per nuove implementazioni, poiché offre una migliore sicurezza e compatibilità.</p>



<h4 class="wp-block-heading" id="3-verifica-tramite-crl-o-ocsp">3. Verifica tramite CRL o OCSP</h4>



<p>Dopo aver estratto i certificati dai rispettivi "cassetti" (truststore o keystore), il client o il server possono verificare la validità del certificato, assicurandosi che non sia stato revocato.</p>



<ul class="wp-block-list">
<li><strong>CRL (Certificate Revocation List)</strong>: è un elenco pubblicato dalle CA che elenca i certificati revocati. Durante l'handshake, il client o il server possono consultare questa lista per verificare se il certificato è stato revocato.</li>



<li><strong>OCSP (Online Certificate Status Protocol)</strong>: invece di scaricare un'intera lista, il sistema può interrogare un server OCSP per verificare in tempo reale se un certificato è stato revocato.</li>
</ul>



<p>Volendo fare un riassunto, ecco un elenco dei principali componenti coinvolti nella gestione dei certificati e nella verifica durante l'handshake TLS/mTLS.</p>



<ul class="wp-block-list">
<li><strong>Truststore</strong>: contiene i certificati delle CA radice fidate e viene usato per verificare i certificati ricevuti da client o server.</li>



<li><strong>Keystore</strong>: contiene il certificato dell'entità (client o server) e la relativa chiave privata. Viene usato per l'autenticazione.</li>



<li><strong>CRL/OCSP</strong>: utilizzati per controllare la revoca dei certificati.</li>
</ul>



<p>In questo modo, i certificati sono archiviati e gestiti nei rispettivi "cassetti" (truststore/keystore), e vengono verificati tramite processi di validazione durante l'handshake TLS/mTLS per garantire la sicurezza e l'integrità della connessione.</p>



<p>Vi posso consigliare di esplorare il progetto su GitHub <a href="https://github.com/amusarra/docker-apache-ssl-tls-mutual-authentication">docker-apache-ssl-tls-mutual-authentication</a> e il relativo articolo <a href="http://bit.ly/2Sm5dU7">Docker Image Apache SSL/TLS Mutual Authentication on Azure Cloud</a> per avere un'idea pratica di come implementare mTLS con Apache.</p>



<h2 class="wp-block-heading" id="perché-gestire-mtls-direttamente-sullapplicazione">Perché gestire mTLS direttamente sull'applicazione?</h2>



<p>Sono sicurissimo che qualcuno di voi potrebbe obiettare quanto segue: solitamente in ambienti di produzione, la sicurezza mTLS viene gestita da apparati ad hoc collocati davanti l’applicazione, quindi, quali sono i vantaggi nel configurare mTLS direttamente sull’applicazione?</p>



<p>È vero che in molti ambienti di produzione la sicurezza mTLS viene spesso gestita da dispositivi dedicati, come load balancer o gateway API, collocati davanti all’applicazione. Tuttavia, configurare mTLS direttamente sull’applicazione presenta alcuni vantaggi significativi, specialmente in certi scenari e architetture. Di seguito, esploreremo i motivi per cui questa scelta può essere valida.</p>



<h3 class="wp-block-heading" id="vantaggi-di-configurare-mtls-direttamente-sullapplicazione">Vantaggi di configurare mTLS direttamente sull’applicazione</h3>



<p>A seguire vedremo brevemente quali siano i vantaggi principali nell'adozione di questa scelta.</p>



<h4 class="wp-block-heading" id="1-maggiore-controllo-e-flessibilità">1. Maggiore controllo e flessibilità</h4>



<p>Configurare mTLS direttamente sull’applicazione consente di avere un controllo più granulare su come e quando l’autenticazione reciproca viene applicata. Ad esempio, puoi decidere:</p>



<ul class="wp-block-list">
<li>quali endpoint richiedono mTLS e quali no;</li>



<li>diversificare la gestione dei certificati a livello di servizio o microservizio in base alle esigenze di sicurezza specifiche.</li>
</ul>



<p>Questo tipo di configurazione può essere particolarmente utile in ambienti <strong>multi-tenant</strong> o con <strong>servizi sensibili</strong>, dove i requisiti di sicurezza possono variare da un microservizio all’altro.</p>



<h4 class="wp-block-heading" id="2-difesa-in-profondità">2. Difesa in profondità</h4>



<p>In sicurezza informatica, il principio di <strong>difesa in profondità</strong> (vedi sezione <a href="https://www.cybersecurity360.it/outlook/i-nuovi-standard-degli-iacs-che-cosa-sono-e-a-cosa-servono/">Importanti principi di protezione dell’ISA/IEC 62443</a>) implica la stratificazione di più livelli di protezione. Anche se mTLS viene implementato a livello di gateway o di load balancer, aggiungere un ulteriore strato di sicurezza direttamente nell’applicazione riduce il rischio di compromissioni:</p>



<ul class="wp-block-list">
<li>se l’infrastruttura del gateway viene bypassata o compromessa, l’applicazione richiede comunque l’autenticazione reciproca per accedere.</li>
</ul>



<p>In questo modo, anche se un attaccante riuscisse a superare un dispositivo di sicurezza a monte, troverebbe comunque un altro livello di protezione all’interno dell’applicazione.</p>



<h4 class="wp-block-heading" id="3-sicurezza-end-to-end">3. Sicurezza end-to-end</h4>



<p>Gestendo mTLS a livello dell’applicazione, puoi garantire una <strong>sicurezza end-to-end</strong> tra i client e i microservizi, senza dover delegare la fiducia a dispositivi intermedi. In ambienti distribuiti, soprattutto in scenari di microservizi, questo garantisce che le connessioni siano protette <strong>fino all’applicazione stessa</strong>, non solo fino al gateway.</p>



<ul class="wp-block-list">
<li>I <strong>certificati del client</strong> sono validati direttamente dall’applicazione, eliminando potenziali punti di vulnerabilità legati a configurazioni errate o attacchi intermedi che potrebbero verificarsi tra il gateway e l’applicazione.</li>
</ul>



<h4 class="wp-block-heading" id="4-riduzione-della-complessità-di-infrastruttura">4. Riduzione della complessità di infrastruttura</h4>



<p>In alcune architetture moderne, come quelle <strong>serverless</strong> o <strong>microservizi in ambienti containerizzati</strong>, l’uso di dispositivi dedicati per la gestione della sicurezza può introdurre complessità e aumentare la latenza nelle comunicazioni. Implementare mTLS direttamente sui microservizi può ridurre la dipendenza da questi dispositivi e semplificare l’architettura complessiva:</p>



<ul class="wp-block-list">
<li>in ambienti dinamici, dove i microservizi si scalano rapidamente, l’uso di <strong>service mesh</strong> (ad esempio <a href="https://istio.io/">Istio</a>) o configurazioni centralizzate a livello di applicazione può risultare più gestibile rispetto a delegare tutto ai dispositivi di front-end.</li>
</ul>



<h4 class="wp-block-heading" id="5-ambienti-multi-cloud-o-ibridi">5. Ambienti multi-cloud o ibridi</h4>



<p>In contesti <strong>multi-cloud</strong> o <strong>ibridi</strong>, in cui i servizi sono distribuiti su diversi provider o persino on-premise, configurare mTLS direttamente sulle applicazioni garantisce che la sicurezza sia gestita in modo uniforme, indipendentemente da dove siano eseguite. In questi casi, affidarsi completamente a dispositivi di front-end potrebbe non essere pratico o potrebbe richiedere una complessità aggiuntiva in termini di gestione dei certificati tra provider diversi.</p>



<h4 class="wp-block-heading" id="6-indipendenza-dai-dispositivi-di-rete">6. Indipendenza dai dispositivi di rete</h4>



<p>Affidarsi completamente ai dispositivi dedicati per la gestione di mTLS può comportare un legame tecnologico con una particolare infrastruttura o provider. Gestire la sicurezza mTLS direttamente sull’applicazione riduce la dipendenza da questi dispositivi, offrendo <strong>portabilità</strong> tra ambienti diversi (ad esempio, passare da un cloud provider all’altro senza dover riconfigurare l’infrastruttura di sicurezza a monte).</p>



<h4 class="wp-block-heading" id="7-testing-e-sviluppo-più-sicuri">7. Testing e sviluppo più sicuri</h4>



<p>Configurare mTLS direttamente nell’applicazione permette di simulare e testare scenari di sicurezza anche in ambienti di <strong>sviluppo</strong> o <strong>pre-produzione</strong>, senza dover riprodurre l’intera infrastruttura di produzione. In questo modo, i team di sviluppo possono:</p>



<ul class="wp-block-list">
<li>testare con maggiore precisione le configurazioni di sicurezza che verranno utilizzate in produzione;</li>



<li>implementare flussi di <strong><a href="https://it.wikipedia.org/wiki/DevOps">DevSecOps</a></strong> più fluidi, dove la sicurezza viene verificata in ogni fase del ciclo di vita del software.</li>
</ul>



<h4 class="wp-block-heading" id="8-personalizzazione-della-logica-di-autenticazione">8. Personalizzazione della logica di autenticazione</h4>



<p>In alcuni casi, potrebbe essere necessario <strong>personalizzare la logica di autenticazione</strong> in base alle esigenze specifiche dell’applicazione. Configurare mTLS direttamente nel codice o nelle configurazioni dell’applicazione permette di introdurre logiche personalizzate come:</p>



<ul class="wp-block-list">
<li>validazioni aggiuntive sui certificati;</li>



<li>limitare l’accesso a specifici client in base a metadati contenuti nei certificati.</li>
</ul>



<h3 class="wp-block-heading" id="quando-usare-dispositivi-dedicati-per-la-gestione-di-mtls">Quando usare dispositivi dedicati per la gestione di mTLS?</h3>



<p>Nonostante i vantaggi della configurazione di mTLS direttamente nell’applicazione, ci sono contesti in cui l’uso di dispositivi dedicati rimane una scelta preferibile.</p>



<ul class="wp-block-list">
<li><strong>Scalabilità centralizzata</strong>: in ambienti con molti servizi e microservizi, potrebbe essere più semplice e scalabile gestire mTLS a livello di gateway, piuttosto che applicare la stessa configurazione a decine o centinaia di microservizi.</li>



<li><strong>Performance e ottimizzazione</strong>: gli apparati specializzati (come load balancer hardware) possono essere ottimizzati per gestire rapidamente grandi quantità di connessioni TLS e mTLS, riducendo la latenza e scaricando l’onere crittografico dalle applicazioni.</li>



<li><strong>Amministrazione centralizzata</strong>: in organizzazioni di grandi dimensioni con team separati, delegare la gestione di mTLS a dispositivi dedicati può ridurre la complessità di gestione da parte degli sviluppatori, permettendo ai team di rete e sicurezza di concentrarsi esclusivamente su questi aspetti.</li>
</ul>



<h3 class="wp-block-heading" id="in-conclusione">In conclusione</h3>



<p>Configurare <strong>mTLS direttamente sull’applicazione</strong> in Quarkus offre una serie di vantaggi, tra cui maggiore controllo, flessibilità e sicurezza end-to-end. Questo approccio può essere particolarmente utile in ambienti distribuiti, multi-cloud, o in scenari dove la <strong>difesa in profondità</strong> è un requisito fondamentale.</p>



<p>Sebbene ci siano contesti in cui dispositivi dedicati a monte siano la scelta migliore per la gestione della sicurezza, integrare mTLS a livello di applicazione permette una gestione più granulare e può migliorare la sicurezza in architetture moderne come microservizi e container.</p>



<h2 class="wp-block-heading" id="quale-scenario-andremo-a-implementare">Quale scenario andremo a implementare</h2>



<p>Utilizzando Quarkus andremo a implementare un classico scenario dove una risorsa (in questo caso REST) sia protetta attraverso il meccanismo mTLS. Il sequence diagram mostrato a seguire illustra proprio lo scenario, dove:</p>



<ol class="wp-block-list">
<li>il <strong>Client</strong> inizia la connessione TLS con l’applicazione <strong>Quarkus</strong>;</li>



<li><strong>Quarkus</strong> richiede il certificato del client come parte della procedura di autenticazione reciproca mTLS;</li>



<li>il <strong>Client</strong> invia il proprio certificato;</li>



<li><strong>Quarkus</strong> verifica il certificato del client
<ol class="wp-block-list">
<li>se il certificato è valido, <strong>Quarkus</strong> elabora la richiesta di accesso alla risorsa e restituisce i dati della risorsa;</li>



<li>se il certificato non è valido, <strong>Quarkus</strong> restituisce un errore, negando l’accesso alla risorsa.</li>
</ol>
</li>
</ol>



<p>Sul sequence diagram sono stati omessi volutamente alcune delle fasi del processo TLS Handshake per dare risalato a quelle fasi che contribuisco al meccanismo di mutua autenticazione. Per il processo completo, fare riferimento al capitolo <em>Cos’è l’autenticazione reciproca TLS (mTLS)</em>.</p>



<div class="wp-block-wp-mermaid-block mermaid">
sequenceDiagram
    participant Client
    participant QuarkusApp as Quarkus Application
    
    %% TLS Handshake
    Note over Client, QuarkusApp: TLS Handshake Starts
    Client->>QuarkusApp: Initiate TLS handshake
    QuarkusApp->>Client: Request Client Certificate
    Client->>QuarkusApp: Send Client Certificate
    Note over Client, QuarkusApp: TLS Handshake Complete
    QuarkusApp->>QuarkusApp: Verify Client Certificate via mTLS
    %% Resource Request
    alt Valid Client Certificate
    Client->>QuarkusApp: Request access to /resource
        QuarkusApp->>QuarkusApp: Process the request
        QuarkusApp->>Client: Return /resource data
    else Invalid Client Certificate
        QuarkusApp->>Client: Error: Invalid Client Certificate
    end
</div>



<p>Figura 2 - Sequence diagramm della soluzione di mTLS da implementare tramite Quarkus</p>



<p>Per realizzare la soluzione mostrata nel diagramma precedente, avremo bisogno dei seguenti strumenti software.</p>



<ul class="wp-block-list">
<li>Java 21</li>



<li>Maven (per la gestione del progetto)</li>



<li>Quarks CLI (per l'installazione fare riferimento <a href="https://quarkus.io/guides/cli-tooling">Building Quarkus apps with Quarkus Command Line Interface (CLI)</a>)</li>



<li>Certificati TLS per il client e il server</li>



<li>OpenSSL per gestire la generazione dei certificati</li>
</ul>



<p>Nel corso dell'implementazione andremo a utilizzare diversi componenti di Quarkus che rientrano nel panorama dell'<strong>architettura di sicurezza</strong> di Quarkus e per cui invito a leggere le seguenti risorse.</p>



<ol class="wp-block-list">
<li><a href="https://quarkus.io/guides/security-architecture">Quarkus Security architecture</a></li>



<li><a href="https://quarkus.io/guides/security-overview">Quarkus Security overview</a></li>



<li><a href="https://quarkus.io/guides/security-authentication-mechanisms#built-in-authentication-mechanisms">Built-in authentication mechanisms</a></li>



<li><a href="https://quarkus.io/guides/security-authorize-web-endpoints-reference">Authorization of web endpoints</a></li>



<li><a href="https://quarkus.io/guides/tls-registry-reference">TLS registry reference</a></li>
</ol>



<p>La figura 3 mostra l'architettura di sicurezza di Quarkus, dove ho volutamente evidenziare lo strato che riguarda il componente <strong><a href="https://quarkus.io/guides/security-architecture#securityidentityaugmentor">SecurityIdentityAugmentor</a></strong> perché nel corso dell'articolo vedremo a cosa serve questo componente e come implementare una personalizzazione utile per i nostri scopi.</p>


<div class="wp-block-image">
<figure class="aligncenter size-large"><img width="1024" height="1196" decoding="async" loading="lazy" src="https://www.dontesta.it/wp-content/uploads/2024/09/quarkus-security-architecture-overview-1024x1196.png" alt="" class="wp-image-5766" style="aspect-ratio:1" srcset="https://www.dontesta.it/wp-content/uploads/2024/09/quarkus-security-architecture-overview-1024x1196.png 1024w, https://www.dontesta.it/wp-content/uploads/2024/09/quarkus-security-architecture-overview-300x351.png 300w, https://www.dontesta.it/wp-content/uploads/2024/09/quarkus-security-architecture-overview-768x897.png 768w, https://www.dontesta.it/wp-content/uploads/2024/09/quarkus-security-architecture-overview-1315x1536.png 1315w, https://www.dontesta.it/wp-content/uploads/2024/09/quarkus-security-architecture-overview.png 1520w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">Figura 3 - Quarkus Security Architecture e flow del processo di autenticazione e autorizzazione (fonte Quarkus.io)</figcaption></figure>
</div>


<p></p>



<p>Tra l'elenco delle risorse ho menzionato il <strong>TLS Registry</strong> che utilizzeremo per portare a termine con successo l'implementazione della soluzione.</p>



<p><strong>Cos’è il TLS Registry di Quarkus?</strong> È un'estensione di Quarkus che centralizza la configurazione TLS per l'applicazione. Consente di definire la configurazione TLS in un unico luogo e di farvi riferimento da più punti nell'applicazione. Nel corso dell'articolo vedremo come ci verrà incontro.</p>



<h2 class="wp-block-heading" id="requisiti-dellapplicazione-quarkus">Requisiti dell'applicazione Quarkus</h2>



<p>Siamo certi del fatto che dobbiamo implementare la nostra applicazione per il supporto mTLS. In particolare andremo a implementare quanto descritto in maniera sintetica dalla tabella a seguire.</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th class="has-text-align-left" data-align="left">ID</th><th class="has-text-align-left" data-align="left">Requisito</th><th class="has-text-align-left" data-align="left">Descrizione</th></tr></thead><tbody><tr><td class="has-text-align-left" data-align="left">1</td><td class="has-text-align-left" data-align="left">Autenticazione mTLS</td><td class="has-text-align-left" data-align="left">È richiesto che l'applicazione supporti mTLS come meccanismo di autenticazione utilizzando certificati in formato PEM e PKCS#12.</td></tr><tr><td class="has-text-align-left" data-align="left">2</td><td class="has-text-align-left" data-align="left">Private end-point REST</td><td class="has-text-align-left" data-align="left">È richiesto la realizzazione di due end-point REST il cui accesso deve essere garantito solo ai client che si presentino con un certificato client avente determinate carratteristiche (vedi capitolo <em>Generazione dei certificati</em>).<br><br>Il primo end-point deve essere definito con la URI <code>/v1/connection-info/info</code> con metodo <code>GET</code> e produrre un JSON avente la struttura mostrata al capitolo <em>Struttura JSON di risposta dei servizi REST</em>. La risposta del servizio conterrà un set d'informazioni che riguardano la connessione instaurata.<br><br>Il secondo end-point deve essere definito con la URI  <code>/v1/connection-info/user-identity</code> con metodo <code>GET</code> e produrre un JSON avente la struttura mostrata al capitolo <em>Struttura JSON di risposta dei servizi REST</em>. La risposta del servizio conterrà un set d'informazioni che riguardano l'indentità del client che ha richiesto l'accesso alla risorsa.</td></tr><tr><td class="has-text-align-left" data-align="left">3</td><td class="has-text-align-left" data-align="left">Mapping automatico dei ruoli</td><td class="has-text-align-left" data-align="left">È richiesto che l'applicazione sia capace di mappare attributi specifici del certificato client sui <strong>ruoli</strong> gestisti da Quarkus (vedi <a href="https://quarkus.io/guides/security-authorize-web-endpoints-reference">Authorization of web endpoints</a>). Per i dettagli sulla struttura del certificato client fare riferimento al capitolo <em>Generazione dei certificati</em>.</td></tr><tr><td class="has-text-align-left" data-align="left">4</td><td class="has-text-align-left" data-align="left">Mapping automatico degli attributi d'identità</td><td class="has-text-align-left" data-align="left">È richiesto che l'applicazione sia capace di mappare attributi specifici del certificato client sugli <strong>Identity Attributes</strong> del client che ha richiesto l'accesso alla risorsa. Per i dettagli sulla struttura del certificato client fare riferimento al capitolo <em>Generazione dei certificati</em>.</td></tr><tr><td class="has-text-align-left" data-align="left">5</td><td class="has-text-align-left" data-align="left">Definizione delle policy di accesso ai servizi Rest</td><td class="has-text-align-left" data-align="left">È richiesto che l'applicazione definisca una policy chiamata per esempio <code>role-policy-cert</code> che definisca i ruoli <em>User</em> e <em>Administrator</em> come abilitati per l'accesso alle due risorse REST descritte sul requisito numero 1.</td></tr><tr><td class="has-text-align-left" data-align="left">6_BONUS</td><td class="has-text-align-left" data-align="left">Integrazione Trusted Service List (TSL)</td><td class="has-text-align-left" data-align="left">È richiesto che l'applicazione sia integrata con il <strong>Trusted Service List (TSL)</strong> Italiano per l'acquisizione delle Certification Authority dei fornitori di servizi fiduciari qualificati  e accreditati per il rilascio di certificati digitali. Questa è una predisposizione per consetire poi l'accesso all'applicazione in mTLS tramite per esempio CIE e CNS.</td></tr></tbody></table><figcaption class="wp-element-caption">Tabella 1 - Requisiti che l'applicazione Quarkus deve implementare.</figcaption></figure>



<p></p>



<h3 class="wp-block-heading" id="generazione-dei-certificati">Generazione dei certificati</h3>



<p>Per gestire correttamente la mutua autenticazione allo scopo di fare anche dei test sul nostro ambiente di sviluppo, abbiamo la necessità di disporre dei seguenti certificati <a href="https://en.wikipedia.org/wiki/X.509#Certificates">X.509</a>:</p>



<ol class="wp-block-list">
<li>un certificato di <a href="https://it.wikipedia.org/wiki/Certificate_authority">Certificate Authority (CA)</a>;</li>



<li>un certificato server per il servizio HTTPS, quest'ultimo basato su <a href="https://vertx.io/docs/vertx-core/java/">Vert.x Core</a> integrato all'interno di Quarkus;</li>



<li>un set di <a href="https://en.wikipedia.org/wiki/Client_certificate">certificati client</a> che devono avere specifiche caratteristiche per accedere ai servizi (vedi requisiti tre, quattro e sei).</li>
</ol>



<p>Per il nostro ambiente di sviluppo siamo autonomi nella generazione dei certificati ma al momento vediamo quali sono le caratteriste dei certificati che dovremo generare e che sono mostrate nella tabella a seguire.</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Tipo</th><th>CN</th><th>SAN</th><th>O</th><th>OU</th><th>L</th><th>ST</th><th>C</th><th>Valitità</th><th>Issuer</th></tr></thead><tbody><tr><td>CA</td><td>Dontesta CA</td><td></td><td>Dontesta</td><td>IT Labs</td><td>Bronte</td><td>Catania</td><td>IT</td><td>5 anni</td><td>self</td></tr><tr><td>Server</td><td>rd.quarkus.dontesta.it</td><td>admin.quarkus.dontesta.it, blog.quarkus.dontesta.it, localhost</td><td>Dontesta</td><td>IT Labs</td><td>Bronte</td><td>Catania</td><td>IT</td><td>1 anno</td><td>Dontesta CA, Dontesta</td></tr><tr><td>Client</td><td>#client-id (può essere un qualunque tipo di identificatore)</td><td></td><td>#Organization</td><td>#OrganizationUnit</td><td>#Locality</td><td>#State</td><td>#Country</td><td>#Validity</td><td>#Issuer</td></tr></tbody></table><figcaption class="wp-element-caption">Tabella 2 - Caratteristiche dei certificati da generare</figcaption></figure>



<p></p>



<p><strong>Nota</strong>: gli FQDN (Fully Qualified Domain Name) usati nei certificati sono puramente di esempio e andranno poi sostituiti con quelli reali.</p>



<p>Per soddisfare il requisito tre e quattro, il certificato client deve essere creato con le seguenti caratteristiche:</p>



<ol class="wp-block-list">
<li><strong>clientAuth in extendedKeyUsage</strong>: l’extendedKeyUsage con il valore <strong>clientAuth</strong> indica che il certificato può essere utilizzato per l’autenticazione del client in contesti mTLS o altre situazioni in cui un client deve dimostrare la propria identità a un server. L’**<a href="https://en.wikipedia.org/wiki/Object_identifier">Object Identifier (OID)</a>** associato a clientAuth è 1.3.6.1.5.5.7.3.2, ed è riconosciuto universalmente per identificare certificati che possono essere utilizzati per l’autenticazione dei client;</li>



<li><strong>estensione personalizzate</strong>: per gestire i ruoli e attributi, i certificati client dovranno avere le seguenti estensioni personalizzate:
<ol class="wp-block-list">
<li>1.3.6.1.4.1.99999.1 = ASN1:UTF8String:Role=${ext_cert_role}</li>



<li>1.3.6.1.4.1.99999.2 = ASN1:UTF8String:DeviceId=${ext_cert_device_id}</li>
</ol>
</li>
</ol>



<p>Le due estensioni personalizzate che sono identificate con OID della classe privata <code>1.3.6.1.4.1</code> dove <code>99999</code> rappresenta un numero riservato per un’ipotetica organizzazione, sono usate rispettivamente per indicare <strong>ruoli</strong> e il <strong>deviceId</strong>. I placeholder <code>${ext_cert_role}</code> e <code>${ext_cert_device_id}</code> conterranno i rispettivi valori per Role e DeviceId.</p>



<p>L'estensione personalizzata avente OID  <code>1.3.6.1.4.1.99999.1</code>  deve contenere uno più ruoli attraverso una stringa che dovrà rispettare il pattern <code>^Role=([A-Za-z]+(?:,[A-Za-z]+)*+)$</code>.</p>



<p>L'estensione personalizzata avente OID <code>1.3.6.1.4.1.99999.2</code> deve contenere l'identificativo di un ipotetico deviceId il cui valore deve essere calcolato secondo un regola ben definita e che vedremo successivamente.</p>



<p>In termini di configurazione OpenSSL, a seguire è mostrato un esempio di configurazione da usare per la generazione dei certificati client usando OpenSSL.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="[ client_cert ]
basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = critical, clientAuth
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer

# Estensioni personalizzate
1.3.6.1.4.1.99999.1 = ASN1:UTF8String:Role=${ext_cert_role}
1.3.6.1.4.1.99999.2 = ASN1:UTF8String:DeviceId=${ext_cert_device_id}
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #ECEFF4">[</span><span style="color: #D8DEE9FF"> client_cert </span><span style="color: #ECEFF4">]</span></span>
<span class="line"><span style="color: #81A1C1">basicConstraints</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">=</span><span style="color: #D8DEE9FF"> CA:FALSE</span></span>
<span class="line"><span style="color: #81A1C1">keyUsage</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">=</span><span style="color: #D8DEE9FF"> digitalSignature, keyEncipherment</span></span>
<span class="line"><span style="color: #81A1C1">extendedKeyUsage</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">=</span><span style="color: #D8DEE9FF"> critical, clientAuth</span></span>
<span class="line"><span style="color: #81A1C1">subjectKeyIdentifier</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">=</span><span style="color: #D8DEE9FF"> hash</span></span>
<span class="line"><span style="color: #81A1C1">authorityKeyIdentifier</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">=</span><span style="color: #D8DEE9FF"> keyid,issuer</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Estensioni personalizzate</span></span>
<span class="line"><span style="color: #81A1C1">1.3.6.1.4.1.99999.1</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">=</span><span style="color: #D8DEE9FF"> ASN1:UTF8String:</span><span style="color: #81A1C1">Role</span><span style="color: #ECEFF4">=</span><span style="color: #D8DEE9FF">${ext_cert_role}</span></span>
<span class="line"><span style="color: #81A1C1">1.3.6.1.4.1.99999.2</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">=</span><span style="color: #D8DEE9FF"> ASN1:UTF8String:</span><span style="color: #81A1C1">DeviceId</span><span style="color: #ECEFF4">=</span><span style="color: #D8DEE9FF">${ext_cert_device_id}</span></span>
<span class="line"></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">INI</span></div>



<p>Configurazione 1 - Configurazione di OpenSSL per la generazione dei certificati client</p>



<p>L'extendedKeyUsage clientAuth ha il flag a <strong>critical</strong> perché la sua interpretazione da parte del server TLS è fondamentale; le estensioni personalizzate non sono segnate come critical, per cui il server TLS le ignorerà ma non i componenti di mapping (vedi requisiti tre e quattro).</p>



<p>A seguire è mostrato un estratto della chiave pubblica di un certificato client generato secondo le specifiche discusse in precendenza. La sezione <strong>X509v3 extensions</strong> mostra appunto le estensioni usate, sia quelle standard, sia quelle personalizzate.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            65:ef:ed:e0:55:06:f7:fa:23:75:ea:a5:df:c6:61:ab:75:8c:38:21
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=IT, ST=Catania, L=Bronte, O=Dontesta, OU=IT Labs, CN=Dontesta CA
        Validity
            Not Before: Sep 12 09:47:43 2024 GMT
            Not After : Sep 12 09:47:43 2025 GMT
        Subject: C=IT, ST=Italy, L=Rome, O=Bad Corporation, OU=Community &amp; News, CN=24A5CCC7-EE36-4449-9025-54CED3011920
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus: ...
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Basic Constraints:
                CA:FALSE
            X509v3 Key Usage:
                Digital Signature, Key Encipherment
            X509v3 Extended Key Usage: critical
                TLS Web Client Authentication
            X509v3 Subject Key Identifier:
                AF:06:90:23:56:1B:97:6A:E4:B3:63:4E:E3:F0:8A:24:6E:FE:A3:CD
            X509v3 Authority Key Identifier:
                28:CB:D3:55:FE:FA:AA:6D:34:D4:45:56:9D:A8:68:F1:E4:6D:20:A3
            1.3.6.1.4.1.99999.1:
                ..Role=User,CommunityManager
            1.3.6.1.4.1.99999.2:      ...DeviceId=MTcyNjEzNDQ2MzExMzA3NjAwMCM0MWJmNDAxNC1lNDFlLTQ5YWUtYTU4Mi02NTJiMGEzMzVlMTcjYW11c2FycmEtbWFjYm9vay1wcm8ubG9jYWwjYTdkMmZmNDI0NjJiMGZjYWRhMzM1YjAwN2NhN2E4YTY5NzVkNjZlNmE3MDg3N2M1MzczM2VmYmYzODBkMWQ5Nw==
    Signature Algorithm: sha256WithRSAEncryption
    Signature Value:...
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #d8dee9ff">Certificate:</span></span>
<span class="line"><span style="color: #d8dee9ff">    Data:</span></span>
<span class="line"><span style="color: #d8dee9ff">        Version: 3 (0x2)</span></span>
<span class="line"><span style="color: #d8dee9ff">        Serial Number:</span></span>
<span class="line"><span style="color: #d8dee9ff">            65:ef:ed:e0:55:06:f7:fa:23:75:ea:a5:df:c6:61:ab:75:8c:38:21</span></span>
<span class="line"><span style="color: #d8dee9ff">        Signature Algorithm: sha256WithRSAEncryption</span></span>
<span class="line"><span style="color: #d8dee9ff">        Issuer: C=IT, ST=Catania, L=Bronte, O=Dontesta, OU=IT Labs, CN=Dontesta CA</span></span>
<span class="line"><span style="color: #d8dee9ff">        Validity</span></span>
<span class="line"><span style="color: #d8dee9ff">            Not Before: Sep 12 09:47:43 2024 GMT</span></span>
<span class="line"><span style="color: #d8dee9ff">            Not After : Sep 12 09:47:43 2025 GMT</span></span>
<span class="line"><span style="color: #d8dee9ff">        Subject: C=IT, ST=Italy, L=Rome, O=Bad Corporation, OU=Community &amp; News, CN=24A5CCC7-EE36-4449-9025-54CED3011920</span></span>
<span class="line"><span style="color: #d8dee9ff">        Subject Public Key Info:</span></span>
<span class="line"><span style="color: #d8dee9ff">            Public Key Algorithm: rsaEncryption</span></span>
<span class="line"><span style="color: #d8dee9ff">                Public-Key: (2048 bit)</span></span>
<span class="line"><span style="color: #d8dee9ff">                Modulus: ...</span></span>
<span class="line"><span style="color: #d8dee9ff">                Exponent: 65537 (0x10001)</span></span>
<span class="line"><span style="color: #d8dee9ff">        X509v3 extensions:</span></span>
<span class="line"><span style="color: #d8dee9ff">            X509v3 Basic Constraints:</span></span>
<span class="line"><span style="color: #d8dee9ff">                CA:FALSE</span></span>
<span class="line"><span style="color: #d8dee9ff">            X509v3 Key Usage:</span></span>
<span class="line"><span style="color: #d8dee9ff">                Digital Signature, Key Encipherment</span></span>
<span class="line"><span style="color: #d8dee9ff">            X509v3 Extended Key Usage: critical</span></span>
<span class="line"><span style="color: #d8dee9ff">                TLS Web Client Authentication</span></span>
<span class="line"><span style="color: #d8dee9ff">            X509v3 Subject Key Identifier:</span></span>
<span class="line"><span style="color: #d8dee9ff">                AF:06:90:23:56:1B:97:6A:E4:B3:63:4E:E3:F0:8A:24:6E:FE:A3:CD</span></span>
<span class="line"><span style="color: #d8dee9ff">            X509v3 Authority Key Identifier:</span></span>
<span class="line"><span style="color: #d8dee9ff">                28:CB:D3:55:FE:FA:AA:6D:34:D4:45:56:9D:A8:68:F1:E4:6D:20:A3</span></span>
<span class="line"><span style="color: #d8dee9ff">            1.3.6.1.4.1.99999.1:</span></span>
<span class="line"><span style="color: #d8dee9ff">                ..Role=User,CommunityManager</span></span>
<span class="line"><span style="color: #d8dee9ff">            1.3.6.1.4.1.99999.2:      ...DeviceId=MTcyNjEzNDQ2MzExMzA3NjAwMCM0MWJmNDAxNC1lNDFlLTQ5YWUtYTU4Mi02NTJiMGEzMzVlMTcjYW11c2FycmEtbWFjYm9vay1wcm8ubG9jYWwjYTdkMmZmNDI0NjJiMGZjYWRhMzM1YjAwN2NhN2E4YTY5NzVkNjZlNmE3MDg3N2M1MzczM2VmYmYzODBkMWQ5Nw==</span></span>
<span class="line"><span style="color: #d8dee9ff">    Signature Algorithm: sha256WithRSAEncryption</span></span>
<span class="line"><span style="color: #d8dee9ff">    Signature Value:...</span></span>
<span class="line"><span style="color: #d8dee9ff"></span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Plaintext</span></div>



<p>Configurazione 2 - Estratto della chiave pubblica di un certificato client generato secondo le specifiche.</p>



<h4 class="wp-block-heading" id="algoritmo-per-la-generazione-del-deviceid">Algoritmo per la generazione del DeviceId</h4>



<p>La generazione del DeviceId dovrà avvenire nel modo seguente:</p>



<ol class="wp-block-list">
<li>combina il timestamp corrente, un <a href="https://it.wikipedia.org/wiki/Universally_unique_identifier">UUID (Universally Unique Identifier)</a> generato e l’hostname del dispositivo per creare una stringa unica. Le singole informazioni devono essere separate dal carattere # (hash o diesis);</li>



<li>genera un <a href="https://it.wikipedia.org/wiki/HMAC">HMAC (Hash-based Message Authentication Code)</a> usando SHA-256 e una chiave segreta;</li>



<li>combina queste informazioni e codifica il risultato in Base64.</li>
</ol>



<p>Il processo di verifica, è praticamente l'inverso:</p>



<ol class="wp-block-list">
<li>decodifica un DeviceId codificato in Base64;</li>



<li>separa la stringa combinata e l’HMAC fornito;</li>



<li>rigenera l’HMAC basandosi sulla stringa originale.</li>



<li>confronta l’HMAC calcolato con quello fornito per verificare la validità dell’ID.</li>
</ol>



<p>A seguire è mostrato il flow di quanto descritto in precedenza per generare e verificare il DeviceId.</p>



<div class="wp-block-wp-mermaid-block mermaid">
graph TD
    A((Start)) --> B{Command?}
    B --> |Generate| C[Collect timestamp, UUID, and hostname]
    C --> D[Create combined string]
    D --> E[Generate HMAC SHA-256 with secret key]
    E --> F[Combine with HMAC and encode in Base64]
    F --> G[Return Base64 Device ID]
    B --> |Verify| H[Decode Base64 Device ID]
    H --> I[Extract combined string and provided HMAC]
    I --> J[Recalculate HMAC using secret key]
    J --> K{Compare HMACs}
    K --> |Match| L[Device ID verified]
    K --> |Mismatch| M[Verification failed]
    G --> N((End))
    L --> N
    M --> N
</div>



<p>Figura 4 - Flow per la generazione e verifica del DeviceId.</p>



<p>A seguire è mostrato lo pseudo codice per la generazione del DeviceId. Se fate attenzione, il DeviceId mostrato nell'esempio è quello visibile sulle info del certificato client di esempio mostrato in configurazione 2.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# Combined string
# Generate a unique string based on timestamp, UUID, and hostname
# timestamp=$(date +%s%N)                      # Get the current timestamp with nanoseconds
# uuid=$(uuidgen | tr '[:upper:]' '[:lower:]') # Generate a UUID and convert it to lowercase
# hostname=$(hostname)                         # Use the device's hostname for additional uniqueness
# combined_string=&quot;${timestamp}#${uuid}#${hostname}&quot;
1726134463113076000#41bf4014-e41e-49ae-a582-652b0a335e17#amusarra-macbook-pro.local

# HMAC sha256 with secret key my_secret_key_for_generate_device_id
# Generate an HMAC SHA-256 based on the combined string and the secret key
# hmac=$(echo -n &quot;$combined_string&quot; | openssl dgst -sha256 -hmac &quot;$DEVICE_ID_SECRET_KEY&quot; | awk '{print $2}')
a7d2ff42462b0fcada335b007ca7a8a6975d66e6a70877c53733efbf380d1d97

# Combine the device ID with the HMAC
# device_id=&quot;${combined_string}#${hmac}&quot;
1726134463113076000#41bf4014-e41e-49ae-a582-652b0a335e17#amusarra-macbook-pro.local#a7d2ff42462b0fcada335b007ca7a8a6975d66e6a70877c53733efbf380d1d97

# DeviceId in Base64
# Encode the result using Base64
# encoded_device_id=$(echo -n &quot;$device_id&quot; | base64)
MTcyNjEzNDQ2MzExMzA3NjAwMCM0MWJmNDAxNC1lNDFlLTQ5YWUtYTU4Mi02NTJiMGEzMzVlMTcjYW11c2FycmEtbWFjYm9vay1wcm8ubG9jYWwjYTdkMmZmNDI0NjJiMGZjYWRhMzM1YjAwN2NhN2E4YTY5NzVkNjZlNmE3MDg3N2M1MzczM2VmYmYzODBkMWQ5Nw==
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88"># Combined string</span></span>
<span class="line"><span style="color: #616E88"># Generate a unique string based on timestamp, UUID, and hostname</span></span>
<span class="line"><span style="color: #616E88"># timestamp=$(date +%s%N)                      # Get the current timestamp with nanoseconds</span></span>
<span class="line"><span style="color: #616E88"># uuid=$(uuidgen | tr &#39;[:upper:]&#39; &#39;[:lower:]&#39;) # Generate a UUID and convert it to lowercase</span></span>
<span class="line"><span style="color: #616E88"># hostname=$(hostname)                         # Use the device&#39;s hostname for additional uniqueness</span></span>
<span class="line"><span style="color: #616E88"># combined_string=&quot;${timestamp}#${uuid}#${hostname}&quot;</span></span>
<span class="line"><span style="color: #88C0D0">1726134463113076000#41bf4014-e41e-49ae-a582-652b0a335e17#amusarra-macbook-pro.local</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># HMAC sha256 with secret key my_secret_key_for_generate_device_id</span></span>
<span class="line"><span style="color: #616E88"># Generate an HMAC SHA-256 based on the combined string and the secret key</span></span>
<span class="line"><span style="color: #616E88"># hmac=$(echo -n &quot;$combined_string&quot; | openssl dgst -sha256 -hmac &quot;$DEVICE_ID_SECRET_KEY&quot; | awk &#39;{print $2}&#39;)</span></span>
<span class="line"><span style="color: #88C0D0">a7d2ff42462b0fcada335b007ca7a8a6975d66e6a70877c53733efbf380d1d97</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Combine the device ID with the HMAC</span></span>
<span class="line"><span style="color: #616E88"># device_id=&quot;${combined_string}#${hmac}&quot;</span></span>
<span class="line"><span style="color: #88C0D0">1726134463113076000#41bf4014-e41e-49ae-a582-652b0a335e17#amusarra-macbook-pro.local#a7d2ff42462b0fcada335b007ca7a8a6975d66e6a70877c53733efbf380d1d97</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># DeviceId in Base64</span></span>
<span class="line"><span style="color: #616E88"># Encode the result using Base64</span></span>
<span class="line"><span style="color: #616E88"># encoded_device_id=$(echo -n &quot;$device_id&quot; | base64)</span></span>
<span class="line"><span style="color: #D8DEE9">MTcyNjEzNDQ2MzExMzA3NjAwMCM0MWJmNDAxNC1lNDFlLTQ5YWUtYTU4Mi02NTJiMGEzMzVlMTcjYW11c2FycmEtbWFjYm9vay1wcm8ubG9jYWwjYTdkMmZmNDI0NjJiMGZjYWRhMzM1YjAwN2NhN2E4YTY5NzVkNjZlNmE3MDg3N2M1MzczM2VmYmYzODBkMWQ5Nw</span><span style="color: #81A1C1">=</span><span style="color: #A3BE8C">=</span></span>
<span class="line"></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Bash</span></div>



<p>Source Code 1 - Pseudo codice che mostra la generazione del DeviceId</p>



<p>Volendo implementare uno script per la generazione e verifica del DeviceId, quello a seguire è il sequence diagram.</p>



<figure class="wp-block-image size-large"><img width="1024" height="1066" decoding="async" loading="lazy" src="https://www.dontesta.it/wp-content/uploads/2024/09/sequence_diagram_generate_device_id-1-1024x1066.png" alt="" class="wp-image-5769" srcset="https://www.dontesta.it/wp-content/uploads/2024/09/sequence_diagram_generate_device_id-1-1024x1066.png 1024w, https://www.dontesta.it/wp-content/uploads/2024/09/sequence_diagram_generate_device_id-1-300x312.png 300w, https://www.dontesta.it/wp-content/uploads/2024/09/sequence_diagram_generate_device_id-1-768x800.png 768w, https://www.dontesta.it/wp-content/uploads/2024/09/sequence_diagram_generate_device_id-1-1475x1536.png 1475w, https://www.dontesta.it/wp-content/uploads/2024/09/sequence_diagram_generate_device_id-1-1966x2048.png 1966w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">Figura 5 - Sequence Diagram che mostra il funzionamento di un ipotetico script di generazione e verifica del DeviceId.</figcaption></figure>



<p></p>



<h3 class="wp-block-heading" id="struttura-json-di-risposta-dei-servizi-rest">Struttura JSON di risposta dei servizi REST</h3>



<p>A seguire lo schema del JSON di risposta per il servizio <code>/api/v1/connection-info/user-identity</code> e un esempio dell'istanza.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="{
  &quot;type&quot;: &quot;object&quot;,
  &quot;properties&quot;: {
    &quot;principal&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;A distinguished name (DN) representing the principal.&quot;
    },
    &quot;roles&quot;: {
      &quot;type&quot;: &quot;array&quot;,
      &quot;items&quot;: {
        &quot;type&quot;: &quot;string&quot;
      },
      &quot;description&quot;: &quot;An array of roles assigned to the principal.&quot;
    },
    &quot;attributes&quot;: {
      &quot;type&quot;: &quot;object&quot;,
      &quot;properties&quot;: {
        &quot;deviceId&quot;: {
          &quot;type&quot;: &quot;string&quot;,
          &quot;description&quot;: &quot;An identifier for the device associated with the principal.&quot;
        }
      },
      &quot;required&quot;: [&quot;deviceId&quot;],
      &quot;description&quot;: &quot;Additional attributes related to the principal.&quot;
    },
    &quot;userCN&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;The common name (CN) of the user.&quot;
    }
  },
  &quot;required&quot;: [&quot;principal&quot;, &quot;roles&quot;, &quot;attributes&quot;, &quot;userCN&quot;],
  &quot;description&quot;: &quot;Schema for representing a user principal with roles and attributes.&quot;
}
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">object</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">properties</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">principal</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">string</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">A distinguished name (DN) representing the principal.</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">roles</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">array</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">items</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">string</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">An array of roles assigned to the principal.</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">attributes</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">object</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">properties</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">deviceId</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">string</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">An identifier for the device associated with the principal.</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">required</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">[</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">deviceId</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">],</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Additional attributes related to the principal.</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">userCN</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">string</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">The common name (CN) of the user.</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">required</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">[</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">principal</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">roles</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">attributes</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">userCN</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">],</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Schema for representing a user principal with roles and attributes.</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">JSON</span></div>



<p>Source Code 2 - Schema del JSON di risposta per il servizio <code>/api/v1/connection-info/user-identity</code></p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="{
  &quot;principal&quot;: &quot;CN=24A5CCC7-EE36-4449-9025-54CED3011920,OU=Community &amp; News,O=Bad Corporation,L=Rome,ST=Italy,C=IT&quot;,
  &quot;roles&quot;: [
    &quot;User&quot;,
    &quot;CommunityManager&quot;
  ],
  &quot;attributes&quot;: {
    &quot;deviceId&quot;: &quot;MTcyNjEzNDQ2MzExMzA3NjAwMCM0MWJmNDAxNC1lNDFlLTQ5YWUtYTU4Mi02NTJiMGEzMzVlMTcjYW11c2FycmEtbWFjYm9vay1wcm8ubG9jYWwjYTdkMmZmNDI0NjJiMGZjYWRhMzM1YjAwN2NhN2E4YTY5NzVkNjZlNmE3MDg3N2M1MzczM2VmYmYzODBkMWQ5Nw==&quot;
  },
  &quot;userCN&quot;: &quot;24A5CCC7-EE36-4449-9025-54CED3011920&quot;
}
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">principal</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">CN=24A5CCC7-EE36-4449-9025-54CED3011920,OU=Community &amp; News,O=Bad Corporation,L=Rome,ST=Italy,C=IT</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">roles</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">[</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">User</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">CommunityManager</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">],</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">attributes</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">deviceId</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">MTcyNjEzNDQ2MzExMzA3NjAwMCM0MWJmNDAxNC1lNDFlLTQ5YWUtYTU4Mi02NTJiMGEzMzVlMTcjYW11c2FycmEtbWFjYm9vay1wcm8ubG9jYWwjYTdkMmZmNDI0NjJiMGZjYWRhMzM1YjAwN2NhN2E4YTY5NzVkNjZlNmE3MDg3N2M1MzczM2VmYmYzODBkMWQ5Nw==</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">userCN</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">24A5CCC7-EE36-4449-9025-54CED3011920</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">JSON</span></div>



<p>Source Code 3 - Esempio di risposta JSON del servizio <code>/api/v1/connection-info/user-identity</code></p>



<p>A seguire lo schema del JSON di risposta per il servizio <code>/api/v1/connection-info/info</code> e un esempio dell'istanza.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(3 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="{
  &quot;type&quot;: &quot;object&quot;,
  &quot;properties&quot;: {
    &quot;httpRequestHeaders&quot;: {
      &quot;type&quot;: &quot;object&quot;,
      &quot;properties&quot;: {
        &quot;user-agent&quot;: {
          &quot;type&quot;: &quot;string&quot;,
          &quot;description&quot;: &quot;User agent string of the HTTP request.&quot;
        },
        &quot;accept&quot;: {
          &quot;type&quot;: &quot;string&quot;,
          &quot;description&quot;: &quot;Accept header of the HTTP request.&quot;
        }
      },
      &quot;required&quot;: [&quot;user-agent&quot;, &quot;accept&quot;],
      &quot;description&quot;: &quot;Headers of the HTTP request.&quot;
    },
    &quot;server&quot;: {
      &quot;type&quot;: &quot;object&quot;,
      &quot;properties&quot;: {
        &quot;notAfter&quot;: {
          &quot;type&quot;: &quot;string&quot;,
          &quot;description&quot;: &quot;Expiration date of the server's certificate.&quot;
        },
        &quot;keyAlgorithm&quot;: {
          &quot;type&quot;: &quot;string&quot;,
          &quot;description&quot;: &quot;Algorithm used for the server's key.&quot;
        },
        &quot;keySize&quot;: {
          &quot;type&quot;: &quot;integer&quot;,
          &quot;description&quot;: &quot;Size of the server's key in bits.&quot;
        },
        &quot;certCommonName&quot;: {
          &quot;type&quot;: &quot;string&quot;,
          &quot;description&quot;: &quot;Common name of the server's certificate.&quot;
        },
        &quot;certIssuer&quot;: {
          &quot;type&quot;: &quot;string&quot;,
          &quot;description&quot;: &quot;Issuer of the server's certificate.&quot;
        },
        &quot;subjectAlternativeNames&quot;: {
          &quot;type&quot;: &quot;array&quot;,
          &quot;items&quot;: {
            &quot;type&quot;: &quot;array&quot;,
            &quot;items&quot;: [
              { &quot;type&quot;: &quot;integer&quot; },
              { &quot;type&quot;: &quot;string&quot; }
            ]
          },
          &quot;description&quot;: &quot;Subject alternative names in the server's certificate.&quot;
        },
        &quot;certSubject&quot;: {
          &quot;type&quot;: &quot;string&quot;,
          &quot;description&quot;: &quot;Subject of the server's certificate.&quot;
        },
        &quot;certSerialNumber&quot;: {
          &quot;type&quot;: &quot;string&quot;,
          &quot;description&quot;: &quot;Serial number of the server's certificate.&quot;
        },
        &quot;certPEM&quot;: {
          &quot;type&quot;: &quot;string&quot;,
          &quot;description&quot;: &quot;PEM encoded server certificate.&quot;
        },
        &quot;customExtensions&quot;: {
          &quot;type&quot;: &quot;object&quot;,
          &quot;description&quot;: &quot;Custom extensions for the server's certificate.&quot;
        },
        &quot;notBefore&quot;: {
          &quot;type&quot;: &quot;string&quot;,
          &quot;description&quot;: &quot;Start date of validity for the server's certificate.&quot;
        }
      },
      &quot;required&quot;: [
        &quot;notAfter&quot;,
        &quot;keyAlgorithm&quot;,
        &quot;keySize&quot;,
        &quot;certCommonName&quot;,
        &quot;certIssuer&quot;,
        &quot;subjectAlternativeNames&quot;,
        &quot;certSubject&quot;,
        &quot;certSerialNumber&quot;,
        &quot;certPEM&quot;,
        &quot;notBefore&quot;
      ],
      &quot;description&quot;: &quot;Details about the server's certificate and key.&quot;
    },
    &quot;protocol&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;Protocol used for the connection (e.g., TLS version).&quot;
    },
    &quot;httpProtocol&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;HTTP protocol version (e.g., HTTP/2).&quot;
    },
    &quot;clientPort&quot;: {
      &quot;type&quot;: &quot;integer&quot;,
      &quot;description&quot;: &quot;Port number used by the client.&quot;
    },
    &quot;isSecure&quot;: {
      &quot;type&quot;: &quot;boolean&quot;,
      &quot;description&quot;: &quot;Indicates if the connection is secure.&quot;
    },
    &quot;client&quot;: {
      &quot;type&quot;: &quot;object&quot;,
      &quot;properties&quot;: {
        &quot;notAfter&quot;: {
          &quot;type&quot;: &quot;string&quot;,
          &quot;description&quot;: &quot;Expiration date of the client's certificate.&quot;
        },
        &quot;keyAlgorithm&quot;: {
          &quot;type&quot;: &quot;string&quot;,
          &quot;description&quot;: &quot;Algorithm used for the client's key.&quot;
        },
        &quot;keySize&quot;: {
          &quot;type&quot;: &quot;integer&quot;,
          &quot;description&quot;: &quot;Size of the client's key in bits.&quot;
        },
        &quot;certCommonName&quot;: {
          &quot;type&quot;: &quot;string&quot;,
          &quot;description&quot;: &quot;Common name of the client's certificate.&quot;
        },
        &quot;certIssuer&quot;: {
          &quot;type&quot;: &quot;string&quot;,
          &quot;description&quot;: &quot;Issuer of the client's certificate.&quot;
        },
        &quot;subjectAlternativeNames&quot;: {
          &quot;type&quot;: &quot;null&quot;,
          &quot;description&quot;: &quot;Subject alternative names in the client's certificate, if any.&quot;
        },
        &quot;certSubject&quot;: {
          &quot;type&quot;: &quot;string&quot;,
          &quot;description&quot;: &quot;Subject of the client's certificate.&quot;
        },
        &quot;certSerialNumber&quot;: {
          &quot;type&quot;: &quot;string&quot;,
          &quot;description&quot;: &quot;Serial number of the client's certificate.&quot;
        },
        &quot;certPEM&quot;: {
          &quot;type&quot;: &quot;string&quot;,
          &quot;description&quot;: &quot;PEM encoded client certificate.&quot;
        },
        &quot;customExtensions&quot;: {
          &quot;type&quot;: &quot;object&quot;,
          &quot;properties&quot;: {
            &quot;role&quot;: {
              &quot;type&quot;: &quot;string&quot;,
              &quot;description&quot;: &quot;Custom role information in the client's certificate.&quot;
            },
            &quot;deviceId&quot;: {
              &quot;type&quot;: &quot;string&quot;,
              &quot;description&quot;: &quot;Custom device ID information in the client's certificate.&quot;
            }
          },
          &quot;description&quot;: &quot;Custom extensions for the client's certificate.&quot;
        },
        &quot;notBefore&quot;: {
          &quot;type&quot;: &quot;string&quot;,
          &quot;description&quot;: &quot;Start date of validity for the client's certificate.&quot;
        }
      },
      &quot;required&quot;: [
        &quot;notAfter&quot;,
        &quot;keyAlgorithm&quot;,
        &quot;keySize&quot;,
        &quot;certCommonName&quot;,
        &quot;certIssuer&quot;,
        &quot;certSubject&quot;,
        &quot;certSerialNumber&quot;,
        &quot;certPEM&quot;,
        &quot;notBefore&quot;
      ],
      &quot;description&quot;: &quot;Details about the client's certificate and key.&quot;
    },
    &quot;userAgent&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;User agent string used by the client.&quot;
    },
    &quot;cipherSuite&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;Cipher suite used for the connection.&quot;
    },
    &quot;clientAddress&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;Address and port of the client.&quot;
    }
  },
  &quot;required&quot;: [
    &quot;httpRequestHeaders&quot;,
    &quot;server&quot;,
    &quot;protocol&quot;,
    &quot;httpProtocol&quot;,
    &quot;clientPort&quot;,
    &quot;isSecure&quot;,
    &quot;client&quot;,
    &quot;userAgent&quot;,
    &quot;cipherSuite&quot;,
    &quot;clientAddress&quot;
  ],
  &quot;description&quot;: &quot;Schema representing a network connection including server and client details, protocols, and certificates.&quot;
}
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">object</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">properties</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">httpRequestHeaders</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">object</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">properties</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">user-agent</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">string</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">User agent string of the HTTP request.</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">accept</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">string</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Accept header of the HTTP request.</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">required</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">[</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">user-agent</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">accept</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">],</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Headers of the HTTP request.</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">server</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">object</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">properties</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">notAfter</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">string</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Expiration date of the server&#39;s certificate.</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">keyAlgorithm</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">string</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Algorithm used for the server&#39;s key.</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">keySize</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">integer</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Size of the server&#39;s key in bits.</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">certCommonName</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">string</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Common name of the server&#39;s certificate.</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">certIssuer</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">string</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Issuer of the server&#39;s certificate.</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">subjectAlternativeNames</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">array</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">items</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">array</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">items</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">[</span></span>
<span class="line"><span style="color: #D8DEE9FF">              </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">integer</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">              </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">string</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">]</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Subject alternative names in the server&#39;s certificate.</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">certSubject</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">string</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Subject of the server&#39;s certificate.</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">certSerialNumber</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">string</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Serial number of the server&#39;s certificate.</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">certPEM</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">string</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">PEM encoded server certificate.</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">customExtensions</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">object</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Custom extensions for the server&#39;s certificate.</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">notBefore</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">string</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Start date of validity for the server&#39;s certificate.</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">required</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">[</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">notAfter</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">keyAlgorithm</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">keySize</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">certCommonName</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">certIssuer</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">subjectAlternativeNames</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">certSubject</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">certSerialNumber</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">certPEM</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">notBefore</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">],</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Details about the server&#39;s certificate and key.</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">protocol</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">string</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Protocol used for the connection (e.g., TLS version).</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">httpProtocol</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">string</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">HTTP protocol version (e.g., HTTP/2).</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">clientPort</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">integer</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Port number used by the client.</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">isSecure</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">boolean</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Indicates if the connection is secure.</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">client</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">object</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">properties</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">notAfter</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">string</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Expiration date of the client&#39;s certificate.</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">keyAlgorithm</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">string</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Algorithm used for the client&#39;s key.</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">keySize</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">integer</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Size of the client&#39;s key in bits.</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">certCommonName</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">string</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Common name of the client&#39;s certificate.</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">certIssuer</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">string</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Issuer of the client&#39;s certificate.</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">subjectAlternativeNames</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">null</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Subject alternative names in the client&#39;s certificate, if any.</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">certSubject</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">string</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Subject of the client&#39;s certificate.</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">certSerialNumber</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">string</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Serial number of the client&#39;s certificate.</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">certPEM</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">string</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">PEM encoded client certificate.</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">customExtensions</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">object</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">properties</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">role</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">              </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">string</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">              </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Custom role information in the client&#39;s certificate.</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">deviceId</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">              </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">string</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">              </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Custom device ID information in the client&#39;s certificate.</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Custom extensions for the client&#39;s certificate.</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">notBefore</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">string</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Start date of validity for the client&#39;s certificate.</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">required</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">[</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">notAfter</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">keyAlgorithm</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">keySize</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">certCommonName</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">certIssuer</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">certSubject</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">certSerialNumber</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">certPEM</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">notBefore</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">],</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Details about the client&#39;s certificate and key.</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">userAgent</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">string</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">User agent string used by the client.</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">cipherSuite</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">string</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Cipher suite used for the connection.</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">clientAddress</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">string</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Address and port of the client.</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">required</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">[</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">httpRequestHeaders</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">server</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">protocol</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">httpProtocol</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">clientPort</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">isSecure</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">client</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">userAgent</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">cipherSuite</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">clientAddress</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">],</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">description</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Schema representing a network connection including server and client details, protocols, and certificates.</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">JSON</span></div>



<p>Source Code 4 - Schema del JSON di risposta per il servizio <code>/api/v1/connection-info/info</code></p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="{
  &quot;httpRequestHeaders&quot;: {
    &quot;user-agent&quot;: &quot;curl/8.7.1&quot;,
    &quot;accept&quot;: &quot;*/*&quot;
  },
  &quot;server&quot;: {
    &quot;notAfter&quot;: &quot;Sun Sep 07 00:16:21 CEST 2025&quot;,
    &quot;keyAlgorithm&quot;: &quot;RSA&quot;,
    &quot;keySize&quot;: 2048,
    &quot;certCommonName&quot;: &quot;rd.quarkus.dontesta.it&quot;,
    &quot;certIssuer&quot;: &quot;CN=Dontesta CA,OU=IT Labs,O=Dontesta,L=Bronte,ST=Catania,C=IT&quot;,
    &quot;subjectAlternativeNames&quot;: [
      [
        2,
        &quot;admin.quarkus.dontesta.it&quot;
      ],
      [
        2,
        &quot;blog.quarkus.dontesta.it&quot;
      ],
      [
        2,
        &quot;localhost&quot;
      ]
    ],
    &quot;certSubject&quot;: &quot;CN=rd.quarkus.dontesta.it,OU=IT Labs,O=Dontesta,L=Bronte,ST=Catania,C=IT&quot;,
    &quot;certSerialNumber&quot;: &quot;581958667903693191343101950434363490497173665817&quot;,
    &quot;certPEM&quot;: &quot;<certPEM&gt;&quot;,
    &quot;customExtensions&quot;: {},
    &quot;notBefore&quot;: &quot;Sat Sep 07 00:16:21 CEST 2024&quot;
  },
  &quot;protocol&quot;: &quot;TLSv1.3&quot;,
  &quot;httpProtocol&quot;: &quot;HTTP_2&quot;,
  &quot;clientPort&quot;: 54845,
  &quot;isSecure&quot;: true,
  &quot;client&quot;: {
    &quot;notAfter&quot;: &quot;Fri Sep 12 11:47:43 CEST 2025&quot;,
    &quot;keyAlgorithm&quot;: &quot;RSA&quot;,
    &quot;keySize&quot;: 2048,
    &quot;certCommonName&quot;: &quot;24A5CCC7-EE36-4449-9025-54CED3011920&quot;,
    &quot;certIssuer&quot;: &quot;CN=Dontesta CA,OU=IT Labs,O=Dontesta,L=Bronte,ST=Catania,C=IT&quot;,
    &quot;subjectAlternativeNames&quot;: null,
    &quot;certSubject&quot;: &quot;CN=24A5CCC7-EE36-4449-9025-54CED3011920,OU=Community &amp; News,O=Bad Corporation,L=Rome,ST=Italy,C=IT&quot;,
    &quot;certSerialNumber&quot;: &quot;581958667903693191343101950434363490497173665825&quot;,
    &quot;certPEM&quot;: &quot;<certPEM&gt;&quot;,
    &quot;customExtensions&quot;: {
      &quot;role&quot;: &quot;Role=User,CommunityManager&quot;,
      &quot;deviceId&quot;: &quot;DeviceId=MTcyNjEzNDQ2MzExMzA3NjAwMCM0MWJmNDAxNC1lNDFlLTQ5YWUtYTU4Mi02NTJiMGEzMzVlMTcjYW11c2FycmEtbWFjYm9vay1wcm8ubG9jYWwjYTdkMmZmNDI0NjJiMGZjYWRhMzM1YjAwN2NhN2E4YTY5NzVkNjZlNmE3MDg3N2M1MzczM2VmYmYzODBkMWQ5Nw==&quot;
    },
    &quot;notBefore&quot;: &quot;Thu Sep 12 11:47:43 CEST 2024&quot;
  },
  &quot;userAgent&quot;: &quot;curl/8.7.1&quot;,
  &quot;cipherSuite&quot;: &quot;TLS_AES_256_GCM_SHA384&quot;,
  &quot;clientAddress&quot;: &quot;127.0.0.1:54845&quot;
}
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">httpRequestHeaders</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">user-agent</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">curl/8.7.1</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">accept</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">*/*</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">server</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">notAfter</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Sun Sep 07 00:16:21 CEST 2025</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">keyAlgorithm</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">RSA</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">keySize</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">2048</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">certCommonName</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">rd.quarkus.dontesta.it</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">certIssuer</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">CN=Dontesta CA,OU=IT Labs,O=Dontesta,L=Bronte,ST=Catania,C=IT</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">subjectAlternativeNames</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">[</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">[</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #B48EAD">2</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">admin.quarkus.dontesta.it</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">],</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">[</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #B48EAD">2</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">blog.quarkus.dontesta.it</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">],</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">[</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #B48EAD">2</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">localhost</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">]</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">],</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">certSubject</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">CN=rd.quarkus.dontesta.it,OU=IT Labs,O=Dontesta,L=Bronte,ST=Catania,C=IT</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">certSerialNumber</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">581958667903693191343101950434363490497173665817</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">certPEM</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">&lt;certPEM&gt;</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">customExtensions</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{},</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">notBefore</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Sat Sep 07 00:16:21 CEST 2024</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">protocol</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">TLSv1.3</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">httpProtocol</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">HTTP_2</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">clientPort</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">54845</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">isSecure</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">true</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">client</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">notAfter</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Fri Sep 12 11:47:43 CEST 2025</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">keyAlgorithm</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">RSA</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">keySize</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">2048</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">certCommonName</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">24A5CCC7-EE36-4449-9025-54CED3011920</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">certIssuer</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">CN=Dontesta CA,OU=IT Labs,O=Dontesta,L=Bronte,ST=Catania,C=IT</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">subjectAlternativeNames</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">null</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">certSubject</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">CN=24A5CCC7-EE36-4449-9025-54CED3011920,OU=Community &amp; News,O=Bad Corporation,L=Rome,ST=Italy,C=IT</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">certSerialNumber</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">581958667903693191343101950434363490497173665825</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">certPEM</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">&lt;certPEM&gt;</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">customExtensions</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">role</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Role=User,CommunityManager</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">deviceId</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">DeviceId=MTcyNjEzNDQ2MzExMzA3NjAwMCM0MWJmNDAxNC1lNDFlLTQ5YWUtYTU4Mi02NTJiMGEzMzVlMTcjYW11c2FycmEtbWFjYm9vay1wcm8ubG9jYWwjYTdkMmZmNDI0NjJiMGZjYWRhMzM1YjAwN2NhN2E4YTY5NzVkNjZlNmE3MDg3N2M1MzczM2VmYmYzODBkMWQ5Nw==</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">notBefore</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Thu Sep 12 11:47:43 CEST 2024</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">},</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">userAgent</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">curl/8.7.1</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">cipherSuite</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">TLS_AES_256_GCM_SHA384</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">&quot;</span><span style="color: #8FBCBB">clientAddress</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">127.0.0.1:54845</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">JSON</span></div>



<p>Source Code 5 - Esempio di risposta JSON del servizio <code>/api/v1/connection-info/info</code></p>



<h2 class="wp-block-heading" id="requisiti-software">Requisiti software</h2>



<p>Per sviluppare la nostra soluzione mTLS, abbiamo necessità di un set di strumenti software che potremmo dividere in due categorie.</p>



<ol class="wp-block-list">
<li><strong>Sviluppo</strong>
<ol class="wp-block-list">
<li>Java 21</li>



<li>Maven 3.9.x</li>



<li>Quarkus 3.14.x</li>



<li>Quarkus CLI (opzionale ma consigliato)</li>



<li>Git (opzionale ma consigliato)</li>
</ol>
</li>



<li><strong>Gestione certificati TLS</strong> (opzionali ma consigliato)
<ol class="wp-block-list">
<li>bash 5.2.x | zsh 5.x | GitBash 2.46</li>



<li>OpenSSL 3.x</li>



<li>Curl 8.x</li>



<li>Java KeyTool (in genere installato con la JDK)</li>



<li>XmlStarlet è un insieme di strumenti da riga di comando progettato per la manipolazione di documenti XML. Viene utilizzato per analizzare, modificare, convertire e validare file XML, ed è particolarmente utile per chi lavora con grandi quantità di dati XML o deve automatizzare operazioni su questi file.</li>
</ol>
</li>
</ol>



<p>La versione del framework di Quarkus deve essere dalla 3.14 in poi, questo perché alcune delle funzionalità, come per esempio il TSL Registry è stato introdotto dalla versione 3.14.0.</p>



<p>La <a href="https://quarkus.io/get-started/">Quarkus CLI</a> è opzionale in quanto la maggior parte delle operazioni possono essere eseguite attraverso Maven e il plugin di Quarkus. Nel corso di questo articolo utilizzeremo però la Quarkus CLI.</p>



<p>Git è opzionale ma consigliato se volete seguire gli step di questo articolo e clonare il repository del progetto completo.</p>



<p>Per quanto riguarda i tool indicati per la gestione dei certificati TLS, non sono obbligatori ma ritengo utile l'installazione per provare con mano la gestione dei certificati TLS (client e server).</p>



<p>La gestione dei certificati TLS è in genere demandata a organi specifici all'interno di un'organizzazione ma noi sviluppatori dobbiamo essere "smart" ed essere capaci di gestire i certificati TLS per il nostro ambiente di sviluppo. Quarkus, in tal senso ha aggiunto dei tool <a href="https://quarkus.io/guides/tls-registry-reference#quarkus-cli-commands-and-development-ca-certificate-authority">Quarkus CLI commands and development CA (Certificate Authority)</a> e <a href="https://quarkus.io/guides/tls-registry-reference#lets-encrypt">Automatic certificate management with Let’s Encrypt</a> per la gestione dei certificati TLS che però hanno qualche limite in termini di flessibilità, per questo motivo ho deciso di realizzare un tool ad hoc che vedremo poi nel corso di questo articolo.</p>



<p>Soddisfati i requisiti software, siamo nelle condizioni di poter iniziare a creare il nostro progetto software step by step e che rispetti i requisiti descritti al capitolo <em>Requisiti dell'applicazione Quarkus</em>.</p>



<h2 class="wp-block-heading" id="implementazione-della-soluzione">Implementazione della soluzione</h2>



<p>Adesso che abbiamo raccolto tutti i pezzi, possiamo finalmente mettere le mani al codice realizzando l'applicazione Quarkus e che soddisfi i requisiti descritti al capitolo <em>Requisiti dell'applicazione Quarkus</em>. Gli step da seguire per implemetare i requisiti dall'uno al cinque sono indicati a seguire. Per quanto riguarda il requisito bonus, lo affronteremo a parte.</p>



<ol class="wp-block-list">
<li>Creazione dell'applicazione Quarkus tramite CLI specificando le estensioni necessarie.</li>



<li>Generazione del certificato di Certification Authority.</li>



<li>Generazione del certificato Server rilasciato dalla CA (creata alla step precedente).</li>



<li>Configurazione di Quarkus per l'attivazione di HTTPS.</li>



<li>Test della configurazione HTTPS/TLS.</li>



<li>Abilitazione del mTLS.</li>



<li>Implementazione dei componenti <a href="https://quarkus.io/guides/security-architecture#securityidentityaugmentor">SecurityIdentityAugmentor</a> per il mapping dei ruoli e attributi.</li>



<li>Implementazione dei servizi REST.</li>



<li>Configurazione delle policy di accesso ai servizi REST.</li>



<li>Generazione di un set di certificati client per eseguire dei test di accesso (positivi e negativi).</li>



<li>Test della configurazione mTLS.</li>
</ol>



<p>Durante l'esecuzione degli step faremo riferimento al repository GitHub <a href="https://github.com/amusarra/quarkus-mtls-auth-tutorial">quarkus-mtls-auth-tutorial</a> attraverso l'uso di tag per identificare gli step, per cui basta effettuare il clone in questo modo: <code>git clone -b &lt;nome-tag&gt; https://github.com/amusarra/quarkus-mtls-auth-tutorial.git</code>.</p>



<p>Tra il repository dedicato al tutorial e quello contenente il progetto completo della soluzione (disponibile sul repository GitHub <a href="https://github.com/amusarra/quarkus-mtls-auth">Quarkus mTLS Auth</a>), potreste notare delle differenze come per esempio la presenza degli unit-test ma i livello di funzionalità sono gli stessi.</p>



<h3 class="wp-block-heading" id="step-1---creazione-dellapplicazione-quarkus-via-cli">Step 1 - Creazione dell'applicazione Quarkus via CLI</h3>



<p>Il tag di riferimento per questo step è <a href="https://github.com/amusarra/quarkus-mtls-auth-tutorial/tree/tutorial-step-1-create-project">tutorial-step-1-create-project</a>.</p>



<p>Le estensioni Quarkus di cui abbiamo bisogno sono:</p>



<ol class="wp-block-list">
<li>io.quarkus:quarkus-vertx</li>



<li>io.quarkus:quarkus-arc</li>



<li>io.quarkus:quarkus-rest</li>



<li>io.quarkus:quarkus-rest-jackson</li>



<li>io.quarkus:quarkus-security</li>



<li>io.quarkus:quarkus-elytron-security-common</li>
</ol>



<p>Procediamo con la creazione del progetto Quarkus tramite la CLI e le estensioni indicate. Per fare ciò, eseguire il comando a seguire (non necessario nel caso in cui abbiate eseguito il clone del repository GitHub <code>quarkus-mtls-auth-tutorial</code> con il tag di riferimento per questo step).</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# Create initial Quarkus project via Quarkus CLI
quarkus create app it.dontesta.quarkus.tls.auth:tls-mutual-auth \
    --extension='quarkus-vertx' \
    --extension='quarkus-arc' \
    --extension='quarkus-rest' \
    --extension='quarkus-rest-jackson' \
    --extension='quarkus-security' \
    --extension='quarkus-elytron-security-common' \
    --no-code
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88"># Create initial Quarkus project via Quarkus CLI</span></span>
<span class="line"><span style="color: #88C0D0">quarkus</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">create</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">app</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">it.dontesta.quarkus.tls.auth:tls-mutual-auth</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--extension=</span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">quarkus-vertx</span><span style="color: #ECEFF4">&#39;</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--extension=</span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">quarkus-arc</span><span style="color: #ECEFF4">&#39;</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--extension=</span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">quarkus-rest</span><span style="color: #ECEFF4">&#39;</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--extension=</span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">quarkus-rest-jackson</span><span style="color: #ECEFF4">&#39;</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--extension=</span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">quarkus-security</span><span style="color: #ECEFF4">&#39;</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--extension=</span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">quarkus-elytron-security-common</span><span style="color: #ECEFF4">&#39;</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--no-code</span></span>
<span class="line"></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Bash</span></div>



<p>Console 1 - Creazione del progetto Quarkus con le estensioni necessarie</p>



<p>Al termine dell'esecuzione del comando di creazione dell'applicazione Quarkus, dovremmo avere la directory <code>tls-mutual-auth</code> avente la struttura a mostrata a seguire.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="tls-mutual-auth
├── README.md
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
    └── main
        ├── docker
        │   ├── Dockerfile.jvm
        │   ├── Dockerfile.legacy-jar
        │   ├── Dockerfile.native
        │   └── Dockerfile.native-micro
        ├── java
        └── resources
            └── application.properties

6 directories, 9 files
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">tls-mutual-auth</span></span>
<span class="line"><span style="color: #88C0D0">├──</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">README.md</span></span>
<span class="line"><span style="color: #88C0D0">├──</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">mvnw</span></span>
<span class="line"><span style="color: #88C0D0">├──</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">mvnw.cmd</span></span>
<span class="line"><span style="color: #88C0D0">├──</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">pom.xml</span></span>
<span class="line"><span style="color: #88C0D0">└──</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">src</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">└──</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">main</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">├──</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">docker</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">│  </span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">├──</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Dockerfile.jvm</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">│  </span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">├──</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Dockerfile.legacy-jar</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">│  </span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">├──</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Dockerfile.native</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">│  </span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">└──</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Dockerfile.native-micro</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">├──</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">java</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">└──</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">resources</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #88C0D0">└──</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">application.properties</span></span>
<span class="line"></span>
<span class="line"><span style="color: #88C0D0">6</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">directories,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">9</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">files</span></span>
<span class="line"></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Bash</span></div>



<p>Console 2 - Struttura del progetto Quarkus creato tramite la CLI</p>



<h3 class="wp-block-heading" id="step-2---generazione-del-certificato-di-certification-authority">Step 2 - Generazione del certificato di Certification Authority</h3>



<p>Il tag di riferimento per questo step è <a href="https://github.com/amusarra/quarkus-mtls-auth-tutorial/tree/tutorial-step-2-gen-cert-ca">tutorial-step-2-generate-ca</a>.</p>



<p>Per generare il certificato della <strong>Certification Authority</strong> secondo quanto indicato in tabella 2, procederemo utilizzando lo script <code>certs_manager.sh</code>. Questo script è stato creato appositamente per questo tutorial e si trova all'interno del progetto Quarkus.</p>



<p>Per eseguire lo script sulla propria macchina di sviluppo, è necessario che i requisiti software per <em>Gestione certificati TLS</em> (vedi capitolo <em>Requisiti software</em>) siano soddisfatti.</p>



<p>Per generare il certificato della CA dobbiamo eseguire il comando a seguire dalla home del progetto. L'esecuzione del comando indicato (che si trova in <code>src/main/shell/certs-manager/certs_manager.sh</code>), creerà all'interno della directory <code>src/main/resources/certs</code> i seguenti file:</p>



<ol class="wp-block-list">
<li>ca_private_key.pem: chiave privata del certificato in formato <a href="https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail">PEM (Privacy-Enhanced Mail)</a>;</li>



<li>ca_private_key.pem.password: file contenente la password della chiave private;</li>



<li>ca_cert.pem: chiave certificato in formato PEM;</li>



<li>ca_cert.p12: formato PKCS#12 del certificato.</li>
</ol>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# Generate the CA
./src/main/shell/certs-manager/certs_manager.sh generate-ca --working-dir src/main/resources/certs \
    --private-key-file ca_private_key.pem \
    --ca-certificate-file ca_cert.pem \
    --validity-days 1825 \
    --country IT \
    --state Catania \
    --locality &quot;Bronte&quot; \
    --organization Dontesta \
    --organizational-unit &quot;IT Labs&quot; \
    --common-name &quot;Dontesta CA&quot; \
    --output-p12-file ca_cert.p12
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88"># Generate the CA</span></span>
<span class="line"><span style="color: #88C0D0">./src/main/shell/certs-manager/certs_manager.sh</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">generate-ca</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">--working-dir</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">src/main/resources/certs</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--private-key-file</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ca_private_key.pem</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--ca-certificate-file</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ca_cert.pem</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--validity-days</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1825</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--country</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">IT</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--state</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Catania</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--locality</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Bronte</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--organization</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Dontesta</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--organizational-unit</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">IT Labs</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--common-name</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Dontesta CA</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--output-p12-file</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ca_cert.p12</span></span>
<span class="line"></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Bash</span></div>



<p>Console 3 - Generazione della CA</p>



<p>L'esecuzione del comando precedente, dovrebbe produrre un output simile a quello mostrato a seguire. Ricordate di prendere nota della password del file <code>ca_cert.p12</code> che dovremo poi impostare sulla configurazione dell'applicazione Quarkus.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="&#x2705; OpenSSL version 3.3.2 is suitable.
&#x1f511; Generating the private key...
..+.+...............+...........+...+++++++++++++++++++++++++++++++++++++++*..+.....+....+.........+.....+......+...+.+..+.......+..+...+.+...............+..+.........+.+..+.............+........+.+...+++++++++++++++++++++++++++++++++++++++*......+....+...+......+.+........................+...+...++++++
Private key password: 57t4Qb1IaGDSZSdv
&#x1f4dc; Generating the CA certificate...
&#x2705; CA certificate generated successfully!
&#x1f50d; Verifying the Certificate Issuer...
&#x2705; Certificate Issuer: issuer=C=IT, ST=Catania, L=Bronte, O=Dontesta, OU=IT Labs, CN=Dontesta CA
&#x1f50d; Verifying the Certificate Serial...
&#x2705; Certificate Serial (hex): serial=79FE005459C8FD77ABD0038B1383431380D97BD3
&#x1f50d; Verifying the Certificate Subject...
&#x2705; Certificate Subject: subject=C=IT, ST=Catania, L=Bronte, O=Dontesta, OU=IT Labs, CN=Dontesta CA
&#x1f512; Generating the p12 file...
&#x2705; p12 file generated successfully!
p12 file: src/main/resources/certs/ca_cert.p12
p12 password: bdo6zkObhUDsa3aL
All files generated in: src/main/resources/certs
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">&#x2705;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">OpenSSL</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">version</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">3.3</span><span style="color: #A3BE8C">.2</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">is</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">suitable.</span></span>
<span class="line"><span style="color: #88C0D0">&#x1f511;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Generating</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">the</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">private</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">key...</span></span>
<span class="line"><span style="color: #88C0D0">..</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">...............</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">...........</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">...</span><span style="color: #D8DEE9FF">+++++++++++++++++++++++++++++++++++++++*</span><span style="color: #88C0D0">..</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.....</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">....</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.........</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.....</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">......</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">...</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">..</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.......</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">..</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">...</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">...............</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">..</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.........</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">..</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.............</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">........</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">...</span><span style="color: #D8DEE9FF">+++++++++++++++++++++++++++++++++++++++*</span><span style="color: #88C0D0">......</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">....</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">...</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">......</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">........................</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">...</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">...</span><span style="color: #D8DEE9FF">++++++</span></span>
<span class="line"><span style="color: #88C0D0">Private</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">key</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">password:</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">57</span><span style="color: #A3BE8C">t4Qb1IaGDSZSdv</span></span>
<span class="line"><span style="color: #88C0D0">&#x1f4dc;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Generating</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">the</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">CA</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">certificate...</span></span>
<span class="line"><span style="color: #88C0D0">&#x2705;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">CA</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">certificate</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">generated</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">successfully!</span></span>
<span class="line"><span style="color: #88C0D0">&#x1f50d;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Verifying</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">the</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Certificate</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Issuer...</span></span>
<span class="line"><span style="color: #88C0D0">&#x2705;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Certificate</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Issuer:</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">issuer=C=IT,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ST=Catania,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">L=Bronte,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">O=Dontesta,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">OU=IT</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Labs,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">CN=Dontesta</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">CA</span></span>
<span class="line"><span style="color: #88C0D0">&#x1f50d;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Verifying</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">the</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Certificate</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Serial...</span></span>
<span class="line"><span style="color: #88C0D0">&#x2705;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Certificate</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Serial</span><span style="color: #D8DEE9FF"> (hex): serial=79FE005459C8FD77ABD0038B1383431380D97BD3</span></span>
<span class="line"><span style="color: #88C0D0">&#x1f50d;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Verifying</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">the</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Certificate</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Subject...</span></span>
<span class="line"><span style="color: #88C0D0">&#x2705;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Certificate</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Subject:</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">subject=C=IT,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ST=Catania,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">L=Bronte,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">O=Dontesta,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">OU=IT</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Labs,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">CN=Dontesta</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">CA</span></span>
<span class="line"><span style="color: #88C0D0">&#x1f512;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Generating</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">the</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">p12</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">file...</span></span>
<span class="line"><span style="color: #88C0D0">&#x2705;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">p12</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">file</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">generated</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">successfully!</span></span>
<span class="line"><span style="color: #88C0D0">p12</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">file:</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">src/main/resources/certs/ca_cert.p12</span></span>
<span class="line"><span style="color: #88C0D0">p12</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">password:</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">bdo6zkObhUDsa3aL</span></span>
<span class="line"><span style="color: #88C0D0">All</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">files</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">generated</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">in:</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">src/main/resources/certs</span></span>
<span class="line"></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Bash</span></div>



<p>Console 4 - Output del comando che ha generato il certificato della CA.</p>



<h3 class="wp-block-heading" id="step-3---generazione-del-certificato-server-rilasciato-dalla-ca">Step 3 - Generazione del certificato Server rilasciato dalla CA</h3>



<p>Per generare il certificato server firmato dalla CA appena creata, utilizzeremo sempre lo stesso script <code>cert-manager.sh</code> ma con parametri diversi. Il comando da eseguire è indicato a seguire. L'esecuzione del comando indicato, creerà all'interno della directory <code>src/main/resources/certs</code> i seguenti file:</p>



<ol class="wp-block-list">
<li>server_private_key.pem: chiave privata del certificato in formato PEM;</li>



<li>server_csr.pem: <a href="https://it.wikipedia.org/wiki/Certificate_Signing_Request">Certificate Signing Request (CSR)</a> del certificato in formato PEM;</li>



<li>server_cert.pem: certificato del server in formato PEM;</li>



<li>server_cert.p12: formato PKCS#12 del certificato.</li>
</ol>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# Generate the Server certificate
./src/main/shell/certs-manager/certs_manager.sh generate-server --working-dir src/main/resources/certs \
    --private-key-file server_private_key.pem \
    --csr-file server_csr.pem \
    --server-cert-file server_cert.pem \
    --ca-cert-file ca_cert.pem \
    --ca-key-file ca_private_key.pem \
    --ca-key-password &quot;$(cat src/main/resources/certs/ca_private_key.pem.password)&quot; \
    --validity-days 365 \
    --country IT \
    --state Italy \
    --locality &quot;Bronte (CT)&quot; \
    --organization Dontesta \
    --organizational-unit &quot;IT Labs&quot; \
    --common-name &quot;rd.quarkus.dontesta.it&quot; \
    --san-domains &quot;DNS:admin.quarkus.dontesta.it,DNS:blog.quarkus.dontesta.it,DNS:localhost&quot; \
    --output-p12-file server_cert.p12
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88"># Generate the Server certificate</span></span>
<span class="line"><span style="color: #88C0D0">./src/main/shell/certs-manager/certs_manager.sh</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">generate-server</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">--working-dir</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">src/main/resources/certs</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--private-key-file</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">server_private_key.pem</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--csr-file</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">server_csr.pem</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--server-cert-file</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">server_cert.pem</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--ca-cert-file</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ca_cert.pem</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--ca-key-file</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ca_private_key.pem</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--ca-key-password</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;$(</span><span style="color: #88C0D0">cat</span><span style="color: #A3BE8C"> src/main/resources/certs/ca_private_key.pem.password</span><span style="color: #ECEFF4">)&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--validity-days</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">365</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--country</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">IT</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--state</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Italy</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--locality</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Bronte (CT)</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--organization</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Dontesta</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--organizational-unit</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">IT Labs</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--common-name</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">rd.quarkus.dontesta.it</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--san-domains</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">DNS:admin.quarkus.dontesta.it,DNS:blog.quarkus.dontesta.it,DNS:localhost</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--output-p12-file</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">server_cert.p12</span></span>
<span class="line"></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Bash</span></div>



<p>Console 5 - Generazione del certificato server firmato dalla CA</p>



<p>L'esecuzione del comando precedente, dovrebbe produrre un output simile a quello mostrato a seguire. Ricordate di prendere nota della password del file <code>server_cert.p12</code> che dovremo poi impostare sulla configurazione dell'applicazione Quarkus.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="&#x2705; OpenSSL version 3.3.2 is suitable.
&#x1f511; Generating the private key...
....+++++++++++++++++++++++++++++++++++++++*.......+.....+.+.....+..........+..+.+..............+.......+........+..........+...+..+.+...........+...+.+......+...+............+...+........+..+..............++++++
Private key password: k/6lEQi/Abxm6lLu
&#x1f4dd; Creating OpenSSL config file for SAN...
&#x2705; OpenSSL config file created for SAN.
&#x1f4d1; Generating the CSR...
&#x1f50f; Generating the server certificate...
Certificate request self-signature ok
subject=C=IT, ST=Italy, L=Bronte (CT), O=Dontesta, OU=IT Labs, CN=rd.quarkus.dontesta.it
&#x1f50d; Verifying the Certificate Issuer...
&#x2705; Certificate Issuer: issuer=C=IT, ST=Catania, L=Bronte, O=Dontesta, OU=IT Labs, CN=Dontesta CA
&#x1f50d; Verifying the Certificate Serial...
&#x2705; Certificate Serial (hex): serial=41FB7FC18FABB3A846893339E25D3CAD399A92BE
&#x1f50d; Verifying the Certificate Subject...
&#x2705; Certificate Subject: subject=C=IT, ST=Italy, L=Bronte (CT), O=Dontesta, OU=IT Labs, CN=rd.quarkus.dontesta.it
&#x1f512; Generating the p12 file...
&#x2705; p12 file generated successfully!
p12 file: src/main/resources/certs/server_cert.p12
p12 password: NWiOJRmJ26D8RTYD
All files generated in: src/main/resources/certs
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">&#x2705;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">OpenSSL</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">version</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">3.3</span><span style="color: #A3BE8C">.2</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">is</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">suitable.</span></span>
<span class="line"><span style="color: #88C0D0">&#x1f511;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Generating</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">the</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">private</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">key...</span></span>
<span class="line"><span style="color: #88C0D0">....</span><span style="color: #D8DEE9FF">+++++++++++++++++++++++++++++++++++++++*</span><span style="color: #88C0D0">.......</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.....</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.....</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">..........</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">..</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">..............</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.......</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">........</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">..........</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">...</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">..</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">...........</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">...</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">......</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">...</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">............</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">...</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">........</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">..</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">..............</span><span style="color: #D8DEE9FF">++++++</span></span>
<span class="line"><span style="color: #88C0D0">Private</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">key</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">password:</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">k/6lEQi/Abxm6lLu</span></span>
<span class="line"><span style="color: #88C0D0">&#x1f4dd;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Creating</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">OpenSSL</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">config</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">file</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">for</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">SAN...</span></span>
<span class="line"><span style="color: #88C0D0">&#x2705;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">OpenSSL</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">config</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">file</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">created</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">for</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">SAN.</span></span>
<span class="line"><span style="color: #88C0D0">&#x1f4d1;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Generating</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">the</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">CSR...</span></span>
<span class="line"><span style="color: #88C0D0">&#x1f50f;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Generating</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">the</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">server</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">certificate...</span></span>
<span class="line"><span style="color: #88C0D0">Certificate</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">request</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">self-signature</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ok</span></span>
<span class="line"><span style="color: #D8DEE9">subject</span><span style="color: #81A1C1">=</span><span style="color: #A3BE8C">C=IT,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ST</span><span style="color: #81A1C1">=</span><span style="color: #A3BE8C">Italy,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">L</span><span style="color: #81A1C1">=</span><span style="color: #A3BE8C">Bronte</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">CT</span><span style="color: #ECEFF4">)</span><span style="color: #88C0D0">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">O=Dontesta,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">OU=IT</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Labs,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">CN=rd.quarkus.dontesta.it</span></span>
<span class="line"><span style="color: #88C0D0">&#x1f50d;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Verifying</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">the</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Certificate</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Issuer...</span></span>
<span class="line"><span style="color: #88C0D0">&#x2705;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Certificate</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Issuer:</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">issuer=C=IT,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ST=Catania,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">L=Bronte,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">O=Dontesta,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">OU=IT</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Labs,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">CN=Dontesta</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">CA</span></span>
<span class="line"><span style="color: #88C0D0">&#x1f50d;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Verifying</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">the</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Certificate</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Serial...</span></span>
<span class="line"><span style="color: #88C0D0">&#x2705;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Certificate</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Serial</span><span style="color: #D8DEE9FF"> (hex): serial=41FB7FC18FABB3A846893339E25D3CAD399A92BE</span></span>
<span class="line"><span style="color: #88C0D0">&#x1f50d;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Verifying</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">the</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Certificate</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Subject...</span></span>
<span class="line"><span style="color: #88C0D0">&#x2705;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Certificate</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Subject:</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">subject=C=IT,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ST=Italy,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">L=Bronte</span><span style="color: #D8DEE9FF"> (CT), O=Dontesta, OU=IT Labs, CN=rd.quarkus.dontesta.it</span></span>
<span class="line"><span style="color: #88C0D0">&#x1f512;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Generating</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">the</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">p12</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">file...</span></span>
<span class="line"><span style="color: #88C0D0">&#x2705;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">p12</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">file</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">generated</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">successfully!</span></span>
<span class="line"><span style="color: #88C0D0">p12</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">file:</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">src/main/resources/certs/server_cert.p12</span></span>
<span class="line"><span style="color: #88C0D0">p12</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">password:</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">NWiOJRmJ26D8RTYD</span></span>
<span class="line"><span style="color: #88C0D0">All</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">files</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">generated</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">in:</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">src/main/resources/certs</span></span>
<span class="line"></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Bash</span></div>



<p>Console 6 - Output del comando che ha generato il certificato del server firmato dalla CA.</p>



<p>Per maggiori informazioni sullo script <code>certs_manager.sh</code>, eseguire il comando <code>./src/main/shell/certs-manager/certs_manager.sh</code> per ottenere la lista dei parametri che gestisce e la loro descrizione.</p>



<h3 class="wp-block-heading" id="step-4---configurazione-di-quarkus-per-lattivazione-di-https">Step 4 - Configurazione di Quarkus per l'attivazione di HTTPS</h3>



<p>Il tag di riferimento per questo step è <a href="https://github.com/amusarra/quarkus-mtls-auth-tutorial/tree/tutorial-step-4-config-tls-1/src/main/resources">tutorial-step-4-configure-https</a>.</p>



<p>Adesso che abbiamo generato i certificati della CA e del server, possiamo procedere con la configurazione di Quarkus per l'attivazione di HTTPS. Per fare ciò, dobbiamo modificare il file <code>src/main/resources/application.properties</code> aggiungendo le proprietà necessarie affinché:</p>



<ol class="wp-block-list">
<li>l'applicazione Quarkus utilizzi il certificato PKCS#12 del server;</li>



<li>l'applicazione Quarkus utilizzi il certificato PEM della CA per essere aggiunto al truststore;</li>



<li>l'applicazione Quarkus accetti solo richieste HTTPS;</li>



<li>l'applicazione Quarkus utilizzi solo il protocollo <a href="https://en.wikipedia.org/wiki/Transport_Layer_Security">TLSv1.3</a>;</li>



<li>l'applicazione Quarkus utilizzi la configurazione TLS denominata <code>https</code>.</li>
</ol>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="#
# Section to configure the server to use HTTPS using the TLS registry,
# which was introduced in Quarkus 3.14 (https://quarkus.io/blog/quarkus-3-14-1-released/)
# For more information on the TLS registry, see https://quarkus.io/guides/tls-registry-reference
#

# Setting the key-store path. The key-store file is located in the `certs` directory
# inside the resources directory.
quarkus.tls.https.key-store.p12.path=certs/server_cert.p12

# Setting the key-store password.
# The password is stored in the `application.properties` file.
# In a development environment, the password may be changed when regenerating the key-store (e.g., using the `mvn clean` command).
# In a production environment, it is recommended to use a secure password storage mechanism.
quarkus.tls.https.key-store.p12.password=NWiOJRmJ26D8RTYD

# Setting the trust-store path.
# The trust-store file is located in the `certs` directory
# inside the resources directory.
quarkus.tls.https.trust-store.pem.certs=certs/ca_cert.pem

# Disabling insecure requests, only HTTPS requests are allowed.
quarkus.http.insecure-requests=disabled

# Setting the only supported TLS protocol to TLSv1.3.
quarkus.tls.https.protocols=TLSv1.3

# Setting the TLS configuration name to `https`.
quarkus.http.tls-configuration-name=https
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88">#</span></span>
<span class="line"><span style="color: #616E88"># Section to configure the server to use HTTPS using the TLS registry,</span></span>
<span class="line"><span style="color: #616E88"># which was introduced in Quarkus 3.14 (https://quarkus.io/blog/quarkus-3-14-1-released/)</span></span>
<span class="line"><span style="color: #616E88"># For more information on the TLS registry, see https://quarkus.io/guides/tls-registry-reference</span></span>
<span class="line"><span style="color: #616E88">#</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Setting the key-store path. The key-store file is located in the `certs` directory</span></span>
<span class="line"><span style="color: #616E88"># inside the resources directory.</span></span>
<span class="line"><span style="color: #88C0D0">quarkus.tls.https.key-store.p12.path</span><span style="color: #D8DEE9FF">=certs/server_cert.p12</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Setting the key-store password.</span></span>
<span class="line"><span style="color: #616E88"># The password is stored in the `application.properties` file.</span></span>
<span class="line"><span style="color: #616E88"># In a development environment, the password may be changed when regenerating the key-store (e.g., using the `mvn clean` command).</span></span>
<span class="line"><span style="color: #616E88"># In a production environment, it is recommended to use a secure password storage mechanism.</span></span>
<span class="line"><span style="color: #88C0D0">quarkus.tls.https.key-store.p12.password</span><span style="color: #D8DEE9FF">=NWiOJRmJ26D8RTYD</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Setting the trust-store path.</span></span>
<span class="line"><span style="color: #616E88"># The trust-store file is located in the `certs` directory</span></span>
<span class="line"><span style="color: #616E88"># inside the resources directory.</span></span>
<span class="line"><span style="color: #88C0D0">quarkus.tls.https.trust-store.pem.certs</span><span style="color: #D8DEE9FF">=certs/ca_cert.pem</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Disabling insecure requests, only HTTPS requests are allowed.</span></span>
<span class="line"><span style="color: #88C0D0">quarkus.http.insecure-requests</span><span style="color: #D8DEE9FF">=disabled</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Setting the only supported TLS protocol to TLSv1.3.</span></span>
<span class="line"><span style="color: #88C0D0">quarkus.tls.https.protocols</span><span style="color: #D8DEE9FF">=TLSv1.3</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Setting the TLS configuration name to `https`.</span></span>
<span class="line"><span style="color: #88C0D0">quarkus.http.tls-configuration-name</span><span style="color: #D8DEE9FF">=https</span></span>
<span class="line"></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Bash</span></div>



<p>Application Properties 1 - Configurazione di Quarkus per l'attivazione di HTTPS</p>



<p>In questa configurazione sono state utilizzate le proprietà che fanno parte del componente Quarkus TLS Registry e in particolare la caratteristica delle <strong>named configuration</strong> che nel nostro caso si chiama <code>https</code> , definita dalla proprietà <code>quarkus.http.tls-configuration-name</code> nel file <code>application.properties</code>. Questa possibilità è stata introdotta in Quarkus 3.14 e permette di configurare in modo centralizzato le configurazioni TLS per l'applicazione Quarkus. Per maggiori informazioni, vi rimando alla <a href="https://quarkus.io/guides/tls-registry-reference">documentazione ufficiale</a>.</p>



<p>Adesso che abbiamo configurato l'applicazione Quarkus per l'attivazione del protocollo HTTPS, potremo procedere con il test della configurazione HTTPS/TLS.</p>



<h3 class="wp-block-heading" id="step-5---test-della-configurazione-httpstls">Step 5 - Test della configurazione HTTPS/TLS</h3>



<p>Per testare la configurazione HTTPS/TLS, possiamo eseguire il comando <code>quarkus:dev</code> e verificare che l'applicazione Quarkus sia in esecuzione e che accetti solo richieste HTTPS.</p>



<p>Dall'output del comando <code>quarkus:dev</code>, dovremmo notare che l'applicazione Quarkus è in esecuzione e accetti solo richieste HTTPS sulla porta 8443. L'output del comando <code>quarkus:dev</code> dovrebbe essere simile a quello mostrato a seguire.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="__  ____  __  _____   ___  __ ____  ______
 --/ __ \/ / / / _ | / _ \/ //_/ / / / __/
 -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/
2024-09-12 18:32:13,818 INFO  [io.quarkus] (Quarkus Main Thread) tls-mutual-auth 1.0.0-SNAPSHOT on JVM (powered by Quarkus 3.14.3) started in 1.390s. Listening on: https://localhost:8443

2024-09-12 18:32:13,821 INFO  [io.quarkus] (Quarkus Main Thread) Profile dev activated. Live Coding activated.
2024-09-12 18:32:13,823 INFO  [io.quarkus] (Quarkus Main Thread) Installed features: [cdi, rest, rest-jackson, security, smallrye-context-propagation, vertx]
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">__</span><span style="color: #D8DEE9FF">  </span><span style="color: #A3BE8C">____</span><span style="color: #D8DEE9FF">  </span><span style="color: #A3BE8C">__</span><span style="color: #D8DEE9FF">  </span><span style="color: #A3BE8C">_____</span><span style="color: #D8DEE9FF">   </span><span style="color: #A3BE8C">___</span><span style="color: #D8DEE9FF">  </span><span style="color: #A3BE8C">__</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">____</span><span style="color: #D8DEE9FF">  </span><span style="color: #A3BE8C">______</span></span>
<span class="line"><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">--/</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">__</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\/</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">_</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">/</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">_</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\/</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">//_/</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">__/</span></span>
<span class="line"><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">-/</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/_/</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/_/</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">__</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">|</span><span style="color: #88C0D0">/</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">_/</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">,</span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/_/</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/</span><span style="color: #EBCB8B">\ \</span></span>
<span class="line"><span style="color: #D8DEE9FF">--</span><span style="color: #EBCB8B">\_</span><span style="color: #D8DEE9FF">__</span><span style="color: #EBCB8B">\_\_</span><span style="color: #D8DEE9FF">___/_/ </span><span style="color: #81A1C1">|</span><span style="color: #88C0D0">_/_/</span><span style="color: #81A1C1">|</span><span style="color: #88C0D0">_/_/</span><span style="color: #81A1C1">|</span><span style="color: #88C0D0">_</span><span style="color: #81A1C1">|</span><span style="color: #88C0D0">\____/___/</span></span>
<span class="line"><span style="color: #88C0D0">2024-09-12</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">18</span><span style="color: #A3BE8C">:32:13,818</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">INFO</span><span style="color: #D8DEE9FF">  [io.quarkus] </span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">Quarkus</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Main</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Thread</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> tls-mutual-auth 1.0.0-SNAPSHOT on JVM </span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">powered</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">by</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Quarkus</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">3.14</span><span style="color: #A3BE8C">.3</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> started </span><span style="color: #81A1C1">in</span><span style="color: #D8DEE9FF"> 1.390s. Listening on: https://localhost:8443</span></span>
<span class="line"></span>
<span class="line"><span style="color: #88C0D0">2024-09-12</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">18</span><span style="color: #A3BE8C">:32:13,821</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">INFO</span><span style="color: #D8DEE9FF">  [io.quarkus] </span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">Quarkus</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Main</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Thread</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> Profile dev activated. Live Coding activated.</span></span>
<span class="line"><span style="color: #88C0D0">2024-09-12</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">18</span><span style="color: #A3BE8C">:32:13,823</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">INFO</span><span style="color: #D8DEE9FF">  [io.quarkus] </span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">Quarkus</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Main</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Thread</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> Installed features: </span><span style="color: #ECEFF4">[</span><span style="color: #D8DEE9FF">cdi, rest, rest-jackson, security, smallrye-context-propagation, vertx</span><span style="color: #ECEFF4">]</span></span>
<span class="line"></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Bash</span></div>



<p>Console 7 - Output del comando <code>quarkus:dev</code> che mostra l'applicazione Quarkus in esecuzione</p>



<p>Se l’applicazione Quarkus è in esecuzione e accetta solo richieste HTTPS, il comando <code>curl</code> dovrebbe restituire un messaggio di errore che indica il rifiuto della connessione. Questo comportamento è quello atteso, poiché l’applicazione è configurata per accettare esclusivamente richieste HTTPS.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# Verify that the application is running and only accepts HTTPS requests.
# The command should return an error message indicating that the connection was refused.
curl -k http://localhost:8080
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88"># Verify that the application is running and only accepts HTTPS requests.</span></span>
<span class="line"><span style="color: #616E88"># The command should return an error message indicating that the connection was refused.</span></span>
<span class="line"><span style="color: #88C0D0">curl</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-k</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">http://localhost:8080</span></span>
<span class="line"></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Bash</span></div>



<p>Console 8 - Test della configurazione HTTPS/TLS</p>



<p>Verifichiamo ora che l’applicazione Quarkus accetti richieste HTTPS. A tal fine, possiamo utilizzare il comando <code>curl</code> per inviare una richiesta HTTPS. Il comando dovrebbe restituire una risposta dall’applicazione.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# Verify that the application is running and accepts HTTPS requests.
# The command should return a response from the application.
curl -k -v https://localhost:8443
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88"># Verify that the application is running and accepts HTTPS requests.</span></span>
<span class="line"><span style="color: #616E88"># The command should return a response from the application.</span></span>
<span class="line"><span style="color: #88C0D0">curl</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-k</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-v</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">https://localhost:8443</span></span>
<span class="line"></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Bash</span></div>



<p>Console 9 - Test della configurazione HTTPS/TLS</p>



<p>L'output del comando <code>curl</code> dovrebbe essere simile a quello mostrato a seguire.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="* Host localhost:8443 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
*   Trying [::1]:8443...
* connect to ::1 port 8443 from ::1 port 56576 failed: Connection refused
*   Trying 127.0.0.1:8443...
* Connected to localhost (127.0.0.1) port 8443
* ALPN: curl offers h2,http/1.1
* (304) (OUT), TLS handshake, Client hello (1):
* (304) (IN), TLS handshake, Server hello (2):
* (304) (IN), TLS handshake, Unknown (8):
* (304) (IN), TLS handshake, Certificate (11):
* (304) (IN), TLS handshake, CERT verify (15):
* (304) (IN), TLS handshake, Finished (20):
* (304) (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / AEAD-AES256-GCM-SHA384 / [blank] / UNDEF
* ALPN: server accepted h2
* Server certificate:
*  subject: C=IT; ST=Italy; L=Bronte (CT); O=Dontesta; OU=IT Labs; CN=rd.quarkus.dontesta.it
*  start date: Sep 12 16:13:44 2024 GMT
*  expire date: Sep 12 16:13:44 2025 GMT
*  issuer: C=IT; ST=Catania; L=Bronte; O=Dontesta; OU=IT Labs; CN=Dontesta CA
*  SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.
* using HTTP/2
* [HTTP/2] [1] OPENED stream for https://localhost:8443/
* [HTTP/2] [1] [:method: GET]
* [HTTP/2] [1] [:scheme: https]
* [HTTP/2] [1] [:authority: localhost:8443]
* [HTTP/2] [1] [:path: /]
* [HTTP/2] [1] [user-agent: curl/8.7.1]
* [HTTP/2] [1] [accept: */*]
&gt; GET / HTTP/2
&gt; Host: localhost:8443
&gt; User-Agent: curl/8.7.1
&gt; Accept: */*
&gt;
* Request completely sent off
< HTTP/2 302
< location: /q/dev-ui/welcome
< content-length: 0
<
* Connection #0 to host localhost left intact
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #d8dee9ff">* Host localhost:8443 was resolved.</span></span>
<span class="line"><span style="color: #d8dee9ff">* IPv6: ::1</span></span>
<span class="line"><span style="color: #d8dee9ff">* IPv4: 127.0.0.1</span></span>
<span class="line"><span style="color: #d8dee9ff">*   Trying [::1]:8443...</span></span>
<span class="line"><span style="color: #d8dee9ff">* connect to ::1 port 8443 from ::1 port 56576 failed: Connection refused</span></span>
<span class="line"><span style="color: #d8dee9ff">*   Trying 127.0.0.1:8443...</span></span>
<span class="line"><span style="color: #d8dee9ff">* Connected to localhost (127.0.0.1) port 8443</span></span>
<span class="line"><span style="color: #d8dee9ff">* ALPN: curl offers h2,http/1.1</span></span>
<span class="line"><span style="color: #d8dee9ff">* (304) (OUT), TLS handshake, Client hello (1):</span></span>
<span class="line"><span style="color: #d8dee9ff">* (304) (IN), TLS handshake, Server hello (2):</span></span>
<span class="line"><span style="color: #d8dee9ff">* (304) (IN), TLS handshake, Unknown (8):</span></span>
<span class="line"><span style="color: #d8dee9ff">* (304) (IN), TLS handshake, Certificate (11):</span></span>
<span class="line"><span style="color: #d8dee9ff">* (304) (IN), TLS handshake, CERT verify (15):</span></span>
<span class="line"><span style="color: #d8dee9ff">* (304) (IN), TLS handshake, Finished (20):</span></span>
<span class="line"><span style="color: #d8dee9ff">* (304) (OUT), TLS handshake, Finished (20):</span></span>
<span class="line"><span style="color: #d8dee9ff">* SSL connection using TLSv1.3 / AEAD-AES256-GCM-SHA384 / [blank] / UNDEF</span></span>
<span class="line"><span style="color: #d8dee9ff">* ALPN: server accepted h2</span></span>
<span class="line"><span style="color: #d8dee9ff">* Server certificate:</span></span>
<span class="line"><span style="color: #d8dee9ff">*  subject: C=IT; ST=Italy; L=Bronte (CT); O=Dontesta; OU=IT Labs; CN=rd.quarkus.dontesta.it</span></span>
<span class="line"><span style="color: #d8dee9ff">*  start date: Sep 12 16:13:44 2024 GMT</span></span>
<span class="line"><span style="color: #d8dee9ff">*  expire date: Sep 12 16:13:44 2025 GMT</span></span>
<span class="line"><span style="color: #d8dee9ff">*  issuer: C=IT; ST=Catania; L=Bronte; O=Dontesta; OU=IT Labs; CN=Dontesta CA</span></span>
<span class="line"><span style="color: #d8dee9ff">*  SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.</span></span>
<span class="line"><span style="color: #d8dee9ff">* using HTTP/2</span></span>
<span class="line"><span style="color: #d8dee9ff">* [HTTP/2] [1] OPENED stream for https://localhost:8443/</span></span>
<span class="line"><span style="color: #d8dee9ff">* [HTTP/2] [1] [:method: GET]</span></span>
<span class="line"><span style="color: #d8dee9ff">* [HTTP/2] [1] [:scheme: https]</span></span>
<span class="line"><span style="color: #d8dee9ff">* [HTTP/2] [1] [:authority: localhost:8443]</span></span>
<span class="line"><span style="color: #d8dee9ff">* [HTTP/2] [1] [:path: /]</span></span>
<span class="line"><span style="color: #d8dee9ff">* [HTTP/2] [1] [user-agent: curl/8.7.1]</span></span>
<span class="line"><span style="color: #d8dee9ff">* [HTTP/2] [1] [accept: */*]</span></span>
<span class="line"><span style="color: #d8dee9ff">&gt; GET / HTTP/2</span></span>
<span class="line"><span style="color: #d8dee9ff">&gt; Host: localhost:8443</span></span>
<span class="line"><span style="color: #d8dee9ff">&gt; User-Agent: curl/8.7.1</span></span>
<span class="line"><span style="color: #d8dee9ff">&gt; Accept: */*</span></span>
<span class="line"><span style="color: #d8dee9ff">&gt;</span></span>
<span class="line"><span style="color: #d8dee9ff">* Request completely sent off</span></span>
<span class="line"><span style="color: #d8dee9ff">&lt; HTTP/2 302</span></span>
<span class="line"><span style="color: #d8dee9ff">&lt; location: /q/dev-ui/welcome</span></span>
<span class="line"><span style="color: #d8dee9ff">&lt; content-length: 0</span></span>
<span class="line"><span style="color: #d8dee9ff">&lt;</span></span>
<span class="line"><span style="color: #d8dee9ff">* Connection #0 to host localhost left intact</span></span>
<span class="line"><span style="color: #d8dee9ff"></span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Plaintext</span></div>



<p>Console 10 - Output del comando <code>curl</code> che ha testato la configurazione HTTPS/TLS</p>



<p>I più attenti avranno notato dall'output del comando precedente le seguenti informazioni:</p>



<ol class="wp-block-list">
<li>la connessione TLS è stata stabilita con successo utilizzando il protocollo TLSv1.3;</li>



<li>grazie a <strong><a href="https://en.wikipedia.org/wiki/Application-Layer_Protocol_Negotiation">ALPN</a></strong>, il server ha accettato il protocollo HTTP/2. Su Quarkus il protocollo HTTP/2 è abilitato di default;</li>



<li>il server ha risposto con il certificato del server creato in precedenza e firmato dalla CA sempre creata in precedenza.</li>
</ol>



<p>Dobbiamo eseguire l’ultimo test, ovvero, verificare che l’applicazione Quarkus accetti solo connessioni HTTPS con protocollo TLSv1.3. Questa volta utilizzeremo il comando OpenSSL, come indicato di seguito.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# Verify that the application only accepts HTTPS requests with the TLSv1.3 protocol.
# The command should return an error message indicating that the connection was refused.
openssl s_client -connect localhost:8443 -servername rd.quarkus.dontesta.it -showcerts -tls1_2" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88"># Verify that the application only accepts HTTPS requests with the TLSv1.3 protocol.</span></span>
<span class="line"><span style="color: #616E88"># The command should return an error message indicating that the connection was refused.</span></span>
<span class="line"><span style="color: #88C0D0">openssl</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">s_client</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-connect</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">localhost:8443</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-servername</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">rd.quarkus.dontesta.it</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-showcerts</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-tls1_2</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Bash</span></div>



<p>Console 11 - Test della configurazione HTTPS/TLS</p>



<p>In questo caso il comando <code>openssl</code> dovrebbe restituire un messaggio di errore che indica che la connessione è stata rifiutata e in particolare <code>tlsv1 alert protocol version:ssl/record/rec_layer_s3.c:907:SSL alert number 70</code>. Questo è il comportamento atteso poiché l'applicazione Quarkus accetta solo richieste HTTPS con il protocollo TLSv1.3.</p>



<h3 class="wp-block-heading" id="step-6---abilitazione-del-mtls">Step 6 - Abilitazione del mTLS</h3>



<p>Il tag di riferimento per questo step è <a href="https://github.com/amusarra/quarkus-mtls-auth-tutorial/tree/tutorial-step-6-config-tls-2/src/main/resources">tutorial-step-6-enable-mtls</a>.</p>



<p>Abbiamo configurato l'applicazione Quarkus per l'attivazione di HTTPS e verificato che l'applicazione accetti solo richieste HTTPS. Ora, potremo procedere con l'abilitazione del mTLS. Per fare ciò, occorre modificare il file <code>src/main/resources/application.properties</code> aggiungendo le proprietà necessarie affinché l'applicazione Quarkus sia configurata per il supporto di mTLS.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="#
# Section to configure the server for mTLS authentication mechanism.
# For more information see Authentication mechanisms in Quarkus https://quarkus.io/guides/tls-registry-reference#mtls
# and configuring mTLS in Quarkus https://quarkus.io/guides/tls-registry-reference#configuring-mtls
#

# Enabling the mTLS authentication mechanism.
# The server requires clients to authenticate themselves using a client certificate.
# The value can be one of the following:
#- `NONE`: no client authentication is required.
#- `REQUEST`: authentication is requested but not required.
#- `REQUIRED`: authentication is required.
quarkus.http.ssl.client-auth=REQUIRED" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88">#</span></span>
<span class="line"><span style="color: #616E88"># Section to configure the server for mTLS authentication mechanism.</span></span>
<span class="line"><span style="color: #616E88"># For more information see Authentication mechanisms in Quarkus https://quarkus.io/guides/tls-registry-reference#mtls</span></span>
<span class="line"><span style="color: #616E88"># and configuring mTLS in Quarkus https://quarkus.io/guides/tls-registry-reference#configuring-mtls</span></span>
<span class="line"><span style="color: #616E88">#</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Enabling the mTLS authentication mechanism.</span></span>
<span class="line"><span style="color: #616E88"># The server requires clients to authenticate themselves using a client certificate.</span></span>
<span class="line"><span style="color: #616E88"># The value can be one of the following:</span></span>
<span class="line"><span style="color: #616E88">#- `NONE`: no client authentication is required.</span></span>
<span class="line"><span style="color: #616E88">#- `REQUEST`: authentication is requested but not required.</span></span>
<span class="line"><span style="color: #616E88">#- `REQUIRED`: authentication is required.</span></span>
<span class="line"><span style="color: #88C0D0">quarkus.http.ssl.client-auth</span><span style="color: #D8DEE9FF">=REQUIRED</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Bash</span></div>



<p>Application Properties 2 - Abilitazione del mTLS</p>



<p>Per impostazione predefinita l'applicazione Quarkus è configurata per non richiedere l'autenticazione del client. Per abilitare l'autenticazione del client, dobbiamo impostare la proprietà <code>quarkus.http.ssl.client-auth</code> su <code>REQUEST</code> o <code>REQUIRED</code>. In questo caso, impostiamo la proprietà su <code>REQUIRED</code> alfine di richiedere l'autenticazione del client.</p>



<p>Una volta applicata la nuova configurazione, il primo risultato atteso è che l'applicazione Quarkus accetti solo richieste HTTPS con protocollo TLSv1.3 e richieda l'autenticazione del client. Per fare una verifica, è sufficiente eseguire il comando <code>curl</code> come indicato a seguire.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# Verify that the application only accepts HTTPS requests with the TLSv1.3 protocol and requires client authentication.
curl -k -v https://localhost:8443" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88"># Verify that the application only accepts HTTPS requests with the TLSv1.3 protocol and requires client authentication.</span></span>
<span class="line"><span style="color: #88C0D0">curl</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-k</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-v</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">https://localhost:8443</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Bash</span></div>



<p>Console 12 - Test della configurazione mTLS</p>



<p>L'output del comando <code>curl</code> dovrebbe essere simile a quello mostrato a seguire che indica che la connessione è stata rifiutata.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="* Host localhost:8443 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
*   Trying [::1]:8443...
* connect to ::1 port 8443 from ::1 port 62500 failed: Connection refused
*   Trying 127.0.0.1:8443...
* Connected to localhost (127.0.0.1) port 8443
* ALPN: curl offers h2,http/1.1
* (304) (OUT), TLS handshake, Client hello (1):
* (304) (IN), TLS handshake, Server hello (2):
* (304) (IN), TLS handshake, Unknown (8):
* (304) (IN), TLS handshake, Request CERT (13):
* (304) (IN), TLS handshake, Certificate (11):
* (304) (IN), TLS handshake, CERT verify (15):
* (304) (IN), TLS handshake, Finished (20):
* (304) (OUT), TLS handshake, Certificate (11):
* (304) (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / AEAD-AES256-GCM-SHA384 / [blank] / UNDEF
* ALPN: server accepted h2
* Server certificate:
*  subject: C=IT; ST=Italy; L=Bronte (CT); O=Dontesta; OU=IT Labs; CN=rd.quarkus.dontesta.it
*  start date: Sep 12 16:13:44 2024 GMT
*  expire date: Sep 12 16:13:44 2025 GMT
*  issuer: C=IT; ST=Catania; L=Bronte; O=Dontesta; OU=IT Labs; CN=Dontesta CA
*  SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.
* using HTTP/2
* [HTTP/2] [1] OPENED stream for https://localhost:8443/
* [HTTP/2] [1] [:method: GET]
* [HTTP/2] [1] [:scheme: https]
* [HTTP/2] [1] [:authority: localhost:8443]
* [HTTP/2] [1] [:path: /]
* [HTTP/2] [1] [user-agent: curl/8.7.1]
* [HTTP/2] [1] [accept: */*]
&gt; GET / HTTP/2
&gt; Host: localhost:8443
&gt; User-Agent: curl/8.7.1
&gt; Accept: */*
&gt;
* Request completely sent off
* LibreSSL SSL_read: LibreSSL/3.3.6: error:1404C412:SSL routines:ST_OK:sslv3 alert bad certificate, errno 0
* Failed receiving HTTP2 data: 56(Failure when receiving data from the peer)
* Connection #0 to host localhost left intact
curl: (56) LibreSSL SSL_read: LibreSSL/3.3.6: error:1404C412:SSL routines:ST_OK:sslv3 alert bad certificate, errno 0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #d8dee9ff">* Host localhost:8443 was resolved.</span></span>
<span class="line"><span style="color: #d8dee9ff">* IPv6: ::1</span></span>
<span class="line"><span style="color: #d8dee9ff">* IPv4: 127.0.0.1</span></span>
<span class="line"><span style="color: #d8dee9ff">*   Trying [::1]:8443...</span></span>
<span class="line"><span style="color: #d8dee9ff">* connect to ::1 port 8443 from ::1 port 62500 failed: Connection refused</span></span>
<span class="line"><span style="color: #d8dee9ff">*   Trying 127.0.0.1:8443...</span></span>
<span class="line"><span style="color: #d8dee9ff">* Connected to localhost (127.0.0.1) port 8443</span></span>
<span class="line"><span style="color: #d8dee9ff">* ALPN: curl offers h2,http/1.1</span></span>
<span class="line"><span style="color: #d8dee9ff">* (304) (OUT), TLS handshake, Client hello (1):</span></span>
<span class="line"><span style="color: #d8dee9ff">* (304) (IN), TLS handshake, Server hello (2):</span></span>
<span class="line"><span style="color: #d8dee9ff">* (304) (IN), TLS handshake, Unknown (8):</span></span>
<span class="line"><span style="color: #d8dee9ff">* (304) (IN), TLS handshake, Request CERT (13):</span></span>
<span class="line"><span style="color: #d8dee9ff">* (304) (IN), TLS handshake, Certificate (11):</span></span>
<span class="line"><span style="color: #d8dee9ff">* (304) (IN), TLS handshake, CERT verify (15):</span></span>
<span class="line"><span style="color: #d8dee9ff">* (304) (IN), TLS handshake, Finished (20):</span></span>
<span class="line"><span style="color: #d8dee9ff">* (304) (OUT), TLS handshake, Certificate (11):</span></span>
<span class="line"><span style="color: #d8dee9ff">* (304) (OUT), TLS handshake, Finished (20):</span></span>
<span class="line"><span style="color: #d8dee9ff">* SSL connection using TLSv1.3 / AEAD-AES256-GCM-SHA384 / [blank] / UNDEF</span></span>
<span class="line"><span style="color: #d8dee9ff">* ALPN: server accepted h2</span></span>
<span class="line"><span style="color: #d8dee9ff">* Server certificate:</span></span>
<span class="line"><span style="color: #d8dee9ff">*  subject: C=IT; ST=Italy; L=Bronte (CT); O=Dontesta; OU=IT Labs; CN=rd.quarkus.dontesta.it</span></span>
<span class="line"><span style="color: #d8dee9ff">*  start date: Sep 12 16:13:44 2024 GMT</span></span>
<span class="line"><span style="color: #d8dee9ff">*  expire date: Sep 12 16:13:44 2025 GMT</span></span>
<span class="line"><span style="color: #d8dee9ff">*  issuer: C=IT; ST=Catania; L=Bronte; O=Dontesta; OU=IT Labs; CN=Dontesta CA</span></span>
<span class="line"><span style="color: #d8dee9ff">*  SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.</span></span>
<span class="line"><span style="color: #d8dee9ff">* using HTTP/2</span></span>
<span class="line"><span style="color: #d8dee9ff">* [HTTP/2] [1] OPENED stream for https://localhost:8443/</span></span>
<span class="line"><span style="color: #d8dee9ff">* [HTTP/2] [1] [:method: GET]</span></span>
<span class="line"><span style="color: #d8dee9ff">* [HTTP/2] [1] [:scheme: https]</span></span>
<span class="line"><span style="color: #d8dee9ff">* [HTTP/2] [1] [:authority: localhost:8443]</span></span>
<span class="line"><span style="color: #d8dee9ff">* [HTTP/2] [1] [:path: /]</span></span>
<span class="line"><span style="color: #d8dee9ff">* [HTTP/2] [1] [user-agent: curl/8.7.1]</span></span>
<span class="line"><span style="color: #d8dee9ff">* [HTTP/2] [1] [accept: */*]</span></span>
<span class="line"><span style="color: #d8dee9ff">&gt; GET / HTTP/2</span></span>
<span class="line"><span style="color: #d8dee9ff">&gt; Host: localhost:8443</span></span>
<span class="line"><span style="color: #d8dee9ff">&gt; User-Agent: curl/8.7.1</span></span>
<span class="line"><span style="color: #d8dee9ff">&gt; Accept: */*</span></span>
<span class="line"><span style="color: #d8dee9ff">&gt;</span></span>
<span class="line"><span style="color: #d8dee9ff">* Request completely sent off</span></span>
<span class="line"><span style="color: #d8dee9ff">* LibreSSL SSL_read: LibreSSL/3.3.6: error:1404C412:SSL routines:ST_OK:sslv3 alert bad certificate, errno 0</span></span>
<span class="line"><span style="color: #d8dee9ff">* Failed receiving HTTP2 data: 56(Failure when receiving data from the peer)</span></span>
<span class="line"><span style="color: #d8dee9ff">* Connection #0 to host localhost left intact</span></span>
<span class="line"><span style="color: #d8dee9ff">curl: (56) LibreSSL SSL_read: LibreSSL/3.3.6: error:1404C412:SSL routines:ST_OK:sslv3 alert bad certificate, errno 0</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Plaintext</span></div>



<p>Console 13 - Output del comando <code>curl</code> che ha testato la configurazione mTLS</p>



<p>Dall'output del comando è possibile notare la richiesta del certificato client da parte del server (<code>(304) (IN), TLS handshake, Request CERT (13)</code>). Il server ha rifiutato la connessione poiché non è stato fornito un certificato client valido (in questo caso nessun certificato è stato inviato). Questo è il comportamento atteso poiché l'applicazione Quarkus richiede obbligatoriamente l'autenticazione del client.</p>



<p>A questo punto, abbiamo configurato l’applicazione Quarkus per l’attivazione di mTLS e verificato che accetti solo richieste HTTPS con protocollo TLSv1.3, richiedendo l’autenticazione del client. Adesso possiamo procedere con l'implementazione dei componenti <code>SecurityIdentityAugmentor</code> per il mapping dei ruoli e attributi.</p>



<h3 class="wp-block-heading" id="step-7---implementazione-dei-componenti-securityidentityaugmentor">Step 7 - Implementazione dei componenti SecurityIdentityAugmentor</h3>



<p>Il tag di riferimento per questo step è <a href="https://github.com/amusarra/quarkus-mtls-auth-tutorial/tree/tutorial-step-7-impl-security-identity-augmentor/src/main/resources">tutorial-step-7-impl-security-identity-augmentor</a>.</p>



<p>Al momento, l’applicazione Quarkus è configurata per supportare l’autenticazione via mTLS. Tuttavia, dobbiamo ancora soddisfare il resto dei requisiti, quindi procederemo con l’implementazione dei componenti <code>SecurityIdentityAugmentor</code> per il mapping di ruoli e attributi.</p>



<p>Ricordiamo che ruoli e attributi sono informazioni che dobbiamo estrarre dal certificato client per poterli utilizzare all'interno dell'applicazione Quarkus. L'OID che identifica i ruoli è <code>1.3.6.1.4.1.99999.1</code>, mentre  <code>1.3.6.1.4.1.99999.2</code> identifica l'attributo DeviceId.</p>



<p>I componenti <code>SecurityIdentityAugmentor</code> che implementeremo dovranno verificare che i valori degli OID siano presenti nel certificato del client e, in caso affermativo, estrarli e aggiungerli all’oggetto <code>SecurityIdentity</code> di Quarkus. Qualora i valori degli OID non rispettino le regole di validazione (vedi pattern per l’OID dei ruoli, capitolo <em>Generazione dei certificati</em> e capitolo <em>Algoritmo per la generazione del DeviceId</em>), il componente <code>SecurityIdentityAugmentor</code> dovrà rifiutare la richiesta di autenticazione.</p>



<p>Per raggiungere l'obiettivo andremo a implementare tre classi.</p>



<ol class="wp-block-list">
<li><strong>AttributesAugmentor</strong>: classe che implementa l'interfaccia <code>io.quarkus.security.identity.SecurityIdentityAugmentor</code> e sovrascrive il metodo <code>augment</code> per estrarre il valore dell'OID <code>1.3.6.1.4.1.99999.2</code> (DeviceId) e renderlo disponibile sull'oggetto <code>io.quarkus.security.identity.SecurityIdentity</code>.</li>



<li><strong>RolesAugmentor</strong>: classe che implementa l'interfaccia <code>io.quarkus.security.identity.SecurityIdentityAugmentor</code> e sovrascrive il metodo <code>augment</code> per estrarre il valore dell'OID <code>1.3.6.1.4.1.99999.1</code> (ruoli) e renderlo disponibile sull'oggetto <code>io.quarkus.security.identity.SecurityIdentity</code>.</li>



<li><strong>OidSecurityIdentityAugmentor</strong>: classe che implementa l'interfaccia <code>io.quarkus.security.identity.SecurityIdentityAugmentor</code> e sovrascrive il metodo <code>augment</code> per verificare che il valore dell'OID che identifica il DeviceId sia presente e valido secondo l'algoritmo descritto nel capitolo <em>Algoritmo per la generazione del DeviceId</em>.</li>
</ol>



<p>Le classi <code>AttributesAugmentor</code>, <code>RolesAugmentor</code> e <code>OidSecurityIdentityAugmentor</code> fanno parte del package <a href="https://github.com/amusarra/quarkus-mtls-auth-tutorial/tree/tutorial-step-7-impl-security-identity-augmentor/src/main/java/it/dontesta/quarkus/tls/auth/ws/security/identity">it.dontesta.quarkus.tls.auth.ws.security.identity</a>. A seguire i sequence diagram che illustrano il flusso di esecuzione delle classi implementate.</p>



<p>Il primo sequence diagram per <code>AttributesAugmentor.augment()</code> prevede i seguenti attori.</p>



<ol class="wp-block-list">
<li><strong>Client</strong>: il sistema o servizio che invoca la classe per l’operazione di autenticazione.</li>



<li><strong>AttributesAugmentor</strong>: la classe principale che manipola il <code>SecurityIdentity</code> e ne arricchisce gli attributi con informazioni dal certificato.</li>



<li><strong>CertificateCredential</strong>: un oggetto che contiene il certificato X.509 dal quale vengono estratti gli attributi.</li>



<li><strong>SecurityIdentity</strong>: l’identità di sicurezza che viene aumentata con nuovi attributi.</li>



<li><strong>QuarkusSecurityIdentity.Builder</strong>: il costruttore utilizzato per modificare e creare una nuova istanza di <code>SecurityIdentity</code> arricchita.</li>



<li><strong>CertificateUtil</strong>: utility che decodifica il valore del certificato.</li>



<li><strong>X509Certificate</strong>: il certificato dal quale viene estratto l’ID del dispositivo.</li>
</ol>



<div class="wp-block-wp-mermaid-block mermaid">
sequenceDiagram
   participant Client
   participant AttributesAugmentor
   participant SecurityIdentity
   participant CertificateCredential
   participant X509Certificate
   participant CertificateUtil
   participant QuarkusSecurityIdentityBuilder as QuarkusSecurityIdentity.Builder
   Client->>AttributesAugmentor: augment(identity, context)
   AttributesAugmentor->>SecurityIdentity: getCredential(CertificateCredential)
   SecurityIdentity-->>AttributesAugmentor: CertificateCredential
   AttributesAugmentor->>CertificateCredential: getCertificate()
   CertificateCredential-->>AttributesAugmentor: X509Certificate
   alt Certificate is null
      AttributesAugmentor-->>Client: SecurityIdentity (no augmentation)
   else Certificate is present
      AttributesAugmentor->>AttributesAugmentor: extractAttributesFromCertificate(X509Certificate)
      AttributesAugmentor->>X509Certificate: getExtensionValue(OID_DEVICE_ID)
      alt OID not found
         AttributesAugmentor-->>Client: SecurityIdentity (no augmentation)
      else OID found
         X509Certificate-->>AttributesAugmentor: byte[]
         AttributesAugmentor->>CertificateUtil: decodeExtensionValue(byte[])
         CertificateUtil-->>AttributesAugmentor: deviceId
         alt deviceId is null
            AttributesAugmentor-->>Client: SecurityIdentity (no augmentation)
         else deviceId is valid
            AttributesAugmentor->>QuarkusSecurityIdentityBuilder: addAttribute("deviceId", deviceId)
         end
      end
      AttributesAugmentor->>QuarkusSecurityIdentityBuilder: build()
      QuarkusSecurityIdentityBuilder-->>AttributesAugmentor: SecurityIdentity
      AttributesAugmentor-->>Client: SecurityIdentity
   end
   opt Error during extraction
      AttributesAugmentor->>AttributesAugmentor: throw SecurityException
      AttributesAugmentor-->>Client: SecurityException
   end
</div>



<p>Figura 6 - Sequence Diagram del flusso di esecuzione di <code>AttributesAugmentor.augment()</code>.</p>



<p>Il secondo sequence diagram per <code>RolesAugmentor.augment()</code> prevede gli stessi attori del diagramma precedente con <code>RolesAugmentor</code> al posto di <code>AttributesAugmentor</code> che manipola il <code>SecurityIdentity</code> e ne arricchisce i ruoli con informazioni dal certificato.</p>



<div class="wp-block-wp-mermaid-block mermaid">
sequenceDiagram
    participant Client
    participant RolesAugmentor
    participant SecurityIdentity
    participant CertificateCredential
    participant X509Certificate
    participant CertificateUtil
    participant QuarkusSecurityIdentityBuilder as QuarkusSecurityIdentity.Builder
    Client->>RolesAugmentor: augment(identity, context)
    RolesAugmentor->>SecurityIdentity: getCredential(CertificateCredential)
    SecurityIdentity-->>RolesAugmentor: CertificateCredential
    RolesAugmentor->>CertificateCredential: getCertificate()
    CertificateCredential-->>RolesAugmentor: X509Certificate
    alt Certificate is null
        RolesAugmentor-->>Client: SecurityIdentity (no augmentation)
    else Certificate is present
        RolesAugmentor->>RolesAugmentor: extractRolesFromCertificate(X509Certificate)
        RolesAugmentor->>X509Certificate: getExtensionValue(OID_ROLES)
        alt OID not found
            RolesAugmentor-->>Client: SecurityIdentity (no augmentation)
        else OID found
            X509Certificate-->>RolesAugmentor: byte[]
            RolesAugmentor->>CertificateUtil: decodeExtensionValue(byte[])
            CertificateUtil-->>RolesAugmentor: decodedRoles
            alt decodedRoles is null
                RolesAugmentor-->>Client: SecurityIdentity (no augmentation)
            else decodedRoles matches pattern
                RolesAugmentor->>RolesAugmentor: Add roles to set
                RolesAugmentor->>QuarkusSecurityIdentityBuilder: addRoles(extracted roles)
            else decodedRoles does not match pattern
                RolesAugmentor->>RolesAugmentor: throw SecurityException
                RolesAugmentor-->>Client: SecurityException
            end
        end
        RolesAugmentor->>QuarkusSecurityIdentityBuilder: build()
        QuarkusSecurityIdentityBuilder-->>RolesAugmentor: SecurityIdentity
        RolesAugmentor-->>Client: SecurityIdentity
    end
    opt Error during extraction
        RolesAugmentor->>RolesAugmentor: throw SecurityException
        RolesAugmentor-->>Client: SecurityException
    end
</div>



<p>Figura 7 - Sequence Diagrama del flusso di esecuzione di <code>RolesAugmentor.augment()</code>.</p>



<p>Il terzo diagramma di sequenza relativo a <code>OidSecurityIdentityAugmentor.augment()</code> evidenzia che, in questo caso, il componente non agisce direttamente su <code>SecurityIdentity</code>, ma si limita a verificare che il valore dell’OID che identifica il DeviceId sia presente e valido secondo l’algoritmo descritto nel capitolo <em>Algoritmo per la generazione del DeviceId</em>.</p>



<div class="wp-block-wp-mermaid-block mermaid">
sequenceDiagram
    participant Client
    participant OidSecurityIdentityAugmentor
    participant SecurityIdentity
    participant CertificateCredential
    participant X509Certificate
    participant CertificateUtil
    participant DeviceIdUtil
    Client->>OidSecurityIdentityAugmentor: augment(identity, context)
    OidSecurityIdentityAugmentor->>SecurityIdentity: getCredential(CertificateCredential)
    SecurityIdentity-->>OidSecurityIdentityAugmentor: CertificateCredential
    alt CertificateCredential is null
        OidSecurityIdentityAugmentor-->>Client: throw SecurityException("Client certificate not found")
    else CertificateCredential is present
        OidSecurityIdentityAugmentor->>CertificateCredential: getCertificate()
        CertificateCredential-->>OidSecurityIdentityAugmentor: X509Certificate
        OidSecurityIdentityAugmentor->>X509Certificate: getExtensionValue(AttributesAugmentor.OID_DEVICE_ID)
        alt OID is null
            OidSecurityIdentityAugmentor-->>Client: throw SecurityException("Invalid certificate OID missing for DeviceId")
        else OID is present
            X509Certificate-->>OidSecurityIdentityAugmentor: oidValueFromCert
            OidSecurityIdentityAugmentor->>CertificateUtil: decodeExtensionValue(oidValueFromCert)
            CertificateUtil-->>OidSecurityIdentityAugmentor: decoded OID value
            OidSecurityIdentityAugmentor->>OidSecurityIdentityAugmentor: remove OID prefix and trim value
            OidSecurityIdentityAugmentor->>DeviceIdUtil: verifyDeviceId(oidValue)
            alt DeviceId is not valid
                DeviceIdUtil-->>OidSecurityIdentityAugmentor: false
                OidSecurityIdentityAugmentor-->>Client: throw SecurityException("Invalid certificate OID value")
            else DeviceId is valid
                DeviceIdUtil-->>OidSecurityIdentityAugmentor: true
                OidSecurityIdentityAugmentor-->>Client: return identity
            end
        end
    end
</div>



<p>Figura 8 - Sequence Diagram del flusso di esecuzione di <code>OidSecurityIdentityAugmentor.augment()</code>.</p>



<p>Nel nostro caso, abbiamo registrato più di una <code>SecurityIdentityAugmentor</code> personalizzata nell’applicazione Quarkus. Queste saranno considerate paritetiche e invocate in ordine casuale. Tuttavia, è possibile imporre un ordine implementando il metodo <code>SecurityIdentityAugmentor#priority</code>. Gli Augmentor con priorità più alta saranno invocati per primi.</p>



<p>Nella classe <code>OidSecurityIdentityAugmentor</code> abbiamo implementato il metodo di priorità impostando un valore intero pari a dieci, per garantire che il controllo sull’OID del DeviceId sia eseguito prima degli altri. In caso di errore, sarà lanciata un’eccezione <code>SecurityException</code> e l’autenticazione fallirà (vedi sequence diagram di figura 8).</p>



<p><strong>Nota</strong>: i <code>SecurityIdentityAugmentor</code> in Quarkus sono a livello globale, ma è possibile configurarli in modo condizionale o personalizzato in base a specifiche esigenze, anche se non esiste una configurazione diretta per attivarli basandosi esclusivamente sul nome di una configurazione TLS.</p>



<h3 class="wp-block-heading" id="step-8---implementazione-dei-servizi-rest">Step 8 - Implementazione dei servizi REST</h3>



<p>Il tag di riferimento per questo step è <a href="https://github.com/amusarra/quarkus-mtls-auth-tutorial/tree/tutorial-step-8-impl-service-rest/src/main/java/it/dontesta/quarkus/tls/auth/ws/security/identity">tutorial-step-8-impl-rest-services</a>.</p>



<p>L’impostazione dell’autenticazione mTLS è stata completata con successo. Ora possiamo procedere con la realizzazione dei servizi REST che utilizzeranno tale autenticazione. A tal fine, creeremo i servizi REST definiti nel secondo requisito, descritto nella tabella 1 del capitolo <em>Requisiti dell’applicazione Quarkus</em>.</p>



<p>I servizi REST che andremo a realizzare troveranno spazio all'interno del package <a href="https://github.com/amusarra/quarkus-mtls-auth-tutorial/tree/tutorial-step-8-impl-service-rest/src/main/java/it/dontesta/quarkus/tls/auth/ws/resources/endpoint/v1">it.dontesta.quarkus.tls.auth.ws.resources.endpoint.v1</a> e saranno implementati dalla classe <a href="https://github.com/amusarra/quarkus-mtls-auth-tutorial/blob/tutorial-step-8-impl-service-rest/src/main/java/it/dontesta/quarkus/tls/auth/ws/resources/endpoint/v1/ConnectionInfoResourceEndPoint.java">ConnectionInfoResourceEndPoint</a>.</p>



<p>La classe <code>ConnectionInfoResourceEndPoint</code> implementerà i seguenti metodi:</p>



<ol class="wp-block-list">
<li><code>@GET /v1/connection-info/info</code>: metodo che restituirà le informazioni di connessione del client;</li>



<li><code>@GET /v1/connection-info/user-identity</code>: metodo che restituirà le informazioni circa l'identità del client che ha effettuato la richiesta.</li>
</ol>



<p>Le risposte dei metodi saranno in formato JSON e conterranno le informazioni richieste e conformi agli schemi JSON definiti nel capitolo <em>Struttura JSON di risposta dei servizi Rest</em>.</p>



<p>Il sequence diagram mostra il flusso di esecuzione del metodo <code>ConnectionInfoResourceEndPoint.getConnectionInfo()</code>. Gli attori coinvolti nel diagramma sono:</p>



<ol class="wp-block-list">
<li><strong>Client</strong>: il sistema o servizio che invoca il metodo <code>getConnectionInfo()</code> sull'endpoint <code>ConnectionInfoResourceEndPoint</code>.</li>



<li><strong>ConnectionInfoResourceEndPoint</strong>: la classe che gestisce la richiesta del client e costruisce l'oggetto <code>connectionInfo</code>.</li>



<li><strong>RoutingContext</strong>: contesto di routing che fornisce informazioni sulla richiesta HTTP.</li>



<li><strong>HttpServerRequest</strong>: rappresenta la richiesta HTTP ricevuta dal server.</li>



<li><strong>SSLSession</strong>: rappresenta la sessione TLS/SSL, utilizzata per ottenere informazioni di sicurezza aggiuntive se la connessione è sicura.</li>
</ol>



<p>Questi attori collaborano per ottenere e restituire le informazioni di connessione in risposta alla richiesta del client.</p>



<div class="wp-block-wp-mermaid-block mermaid">
sequenceDiagram
   participant Client
   participant ConnectionInfoResourceEndPoint
   participant RoutingContext
   participant HttpServerRequest
   participant SSLSession
   Client->>ConnectionInfoResourceEndPoint: GET /v1/connection-info/info
   ConnectionInfoResourceEndPoint->>RoutingContext: @Context RoutingContext
   RoutingContext-->>ConnectionInfoResourceEndPoint: routingContext
   ConnectionInfoResourceEndPoint->>HttpServerRequest: request()
   HttpServerRequest-->>ConnectionInfoResourceEndPoint: HttpServerRequest
   ConnectionInfoResourceEndPoint->>ConnectionInfoResourceEndPoint: Create connectionInfo map
   ConnectionInfoResourceEndPoint->>ConnectionInfoResourceEndPoint: Add basic connection details
   ConnectionInfoResourceEndPoint->>ConnectionInfoResourceEndPoint: Add client address and port information
   alt request.isSSL() is true
      ConnectionInfoResourceEndPoint->>HttpServerRequest: sslSession()
      HttpServerRequest-->>ConnectionInfoResourceEndPoint: SSLSession
      alt sslSession is not null
         ConnectionInfoResourceEndPoint->>ConnectionInfoResourceEndPoint: Add SSL-specific details
         ConnectionInfoResourceEndPoint->>SSLSession: getProtocol()
         SSLSession-->>ConnectionInfoResourceEndPoint: protocol
         ConnectionInfoResourceEndPoint->>SSLSession: getCipherSuite()
         SSLSession-->>ConnectionInfoResourceEndPoint: cipherSuite
         ConnectionInfoResourceEndPoint->>SSLSession: getLocalCertificates()
         SSLSession-->>ConnectionInfoResourceEndPoint: serverCerts
         ConnectionInfoResourceEndPoint->>SSLSession: getPeerCertificates()
         SSLSession-->>ConnectionInfoResourceEndPoint: clientCerts
      end
   end
   ConnectionInfoResourceEndPoint-->>Client: Response.ok(connectionInfo).build()
</div>



<p>Figura 9 - Sequence Diagram del flusso di esecuzione di <code>ConnectionInfoResourceEndPoint.info()</code>.</p>



<p>Il sequence diagram mostra il flusso di esecuzione del metodo <code>ConnectionInfoResourceEndPoint.getUserIdentity()</code>. Gli attori coinvolti nel diagramma sono:</p>



<ol class="wp-block-list">
<li><strong>Client</strong>: il sistema o servizio che invoca il metodo <code>getUserIdentity()</code> sull'endpoint <code>ConnectionInfoResourceEndPoint</code>.</li>



<li><strong>ConnectionInfoResourceEndPoint</strong>: la classe che gestisce la richiesta del client e costruisce l'oggetto <code>securityIdentityInfo</code>.</li>



<li><strong>SecurityIdentity</strong>: l'identità di sicurezza che contiene le informazioni dell'utente autenticato.</li>



<li><strong>CertificateCredential</strong>: un oggetto che contiene il certificato X.509 dal quale vengono estratti gli attributi.</li>



<li><strong>X509Certificate</strong>: il certificato dal quale vengono estratti gli attributi.</li>
</ol>



<p>Questi attori collaborano per ottenere e restituire le informazioni di identità dell'utente in risposta alla richiesta del client.</p>



<div class="wp-block-wp-mermaid-block mermaid">
sequenceDiagram
   participant Client
   participant ConnectionInfoResourceEndPoint
   participant SecurityIdentity
   participant CertificateCredential
   participant X509Certificate
   Client->>ConnectionInfoResourceEndPoint: GET /v1/connection-info/user-identity
   ConnectionInfoResourceEndPoint->>SecurityIdentity: @Context SecurityIdentity
   SecurityIdentity-->>ConnectionInfoResourceEndPoint: securityIdentity
   ConnectionInfoResourceEndPoint->>ConnectionInfoResourceEndPoint: Create securityIdentityInfo map
   ConnectionInfoResourceEndPoint->>ConnectionInfoResourceEndPoint: Add principal, roles, and attributes
   ConnectionInfoResourceEndPoint->>SecurityIdentity: getCredential(CertificateCredential.class)
   SecurityIdentity-->>ConnectionInfoResourceEndPoint: CertificateCredential
   ConnectionInfoResourceEndPoint->>CertificateCredential: getCertificate()
   CertificateCredential-->>ConnectionInfoResourceEndPoint: X509Certificate
   ConnectionInfoResourceEndPoint->>X509Certificate: getCommonName()
   X509Certificate-->>ConnectionInfoResourceEndPoint: userCN
   ConnectionInfoResourceEndPoint->>ConnectionInfoResourceEndPoint: Add userCN to securityIdentityInfo
   ConnectionInfoResourceEndPoint-->>Client: Response.ok(securityIdentityInfo).build()
</div>



<p>Figura 10 - Sequence Diagram del flusso di esecuzione di <code>ConnectionInfoResourceEndPoint.getUserIdentity()</code>.</p>



<h3 class="wp-block-heading" id="step-9---configurazione-delle-policy-di-accesso-ai-servizi-rest">Step 9 - Configurazione delle policy di accesso ai servizi REST</h3>



<p>Il tag di riferimento per questo step è <a href="https://github.com/amusarra/quarkus-mtls-auth-tutorial/blob/tutorial-step-9-config-policy/src/main/java/it/dontesta/quarkus/tls/auth/ws/resources/endpoint/v1/ConnectionInfoResourceEndPoint.java">tutorial-step-9-config-rest-services</a>.</p>



<p>Ora che abbiamo implementato i servizi REST, possiamo procedere con la configurazione delle policy di accesso. A tal fine, creeremo le policy di accesso ai servizi REST definite nel terzo requisito e descritto nella tabella 1 del capitolo <em>Requisiti dell’applicazione Quarkus</em>.</p>



<p>Configurare le policy di accesso significa definire quali ruoli possono accedere ai servizi REST. Nel nostro caso, i ruoli sono due: <code>Administartor</code> e <code>User</code>. Questa configurazione può essere effettuata modificando il file <code>application.properties</code> aggiungendo le proprietà indicate di seguito.</p>



<p>Tramite la configurazione abbiamo definito:</p>



<ol class="wp-block-list">
<li>un set di permessi <code>certauthenticated</code> che
<ol class="wp-block-list">
<li>si applicano alle risorse REST di tipo JAX-RS;</li>



<li>si applicano ai metodi <code>GET</code> e <code>POST</code>;</li>



<li>si applicano ai servizi REST <code>/api/v1/connection-info/*</code>;</li>



<li>utilizzano la policy <code>role-policy-cert</code> per il controllo degli accessi;</li>
</ol>
</li>



<li>la policy <code>role-policy-cert</code> che
<ol class="wp-block-list">
<li>definisce i ruoli <code>User</code> e <code>Administrator</code> che possono accedere ai servizi REST.</li>
</ol>
</li>
</ol>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="#
# Section to configure the server for the role-based access control mechanism.
# For more information see Mapping certificate attributes to roles in Quarkus
# https://quarkus.io/guides/security-authentication-mechanisms#map-certificate-attributes-to-roles
# In this case using the `RolesAugmentor` class to map the certificate attributes to roles.
# The custom role as an extension in the client certificate is identified by the custom OID 1.3.6.1.4.1.99999.1
#

# Whether permission check should be applied on all matching paths, or paths specific for the Jakarta REST resources.
quarkus.http.auth.permission.certauthenticated.applies-to=jaxrs

# The methods that this permission set applies to.
quarkus.http.auth.permission.certauthenticated.methods=GET,POST

# The paths that this permission set applies to.
quarkus.http.auth.permission.certauthenticated.paths=/api/v1/connection-info/*

# The policy to use for the permission check.
quarkus.http.auth.permission.certauthenticated.policy=role-policy-cert

# The roles allowed to access the resource.
quarkus.http.auth.policy.role-policy-cert.roles-allowed=User,Administrator" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88">#</span></span>
<span class="line"><span style="color: #616E88"># Section to configure the server for the role-based access control mechanism.</span></span>
<span class="line"><span style="color: #616E88"># For more information see Mapping certificate attributes to roles in Quarkus</span></span>
<span class="line"><span style="color: #616E88"># https://quarkus.io/guides/security-authentication-mechanisms#map-certificate-attributes-to-roles</span></span>
<span class="line"><span style="color: #616E88"># In this case using the `RolesAugmentor` class to map the certificate attributes to roles.</span></span>
<span class="line"><span style="color: #616E88"># The custom role as an extension in the client certificate is identified by the custom OID 1.3.6.1.4.1.99999.1</span></span>
<span class="line"><span style="color: #616E88">#</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Whether permission check should be applied on all matching paths, or paths specific for the Jakarta REST resources.</span></span>
<span class="line"><span style="color: #88C0D0">quarkus.http.auth.permission.certauthenticated.applies-to</span><span style="color: #D8DEE9FF">=jaxrs</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># The methods that this permission set applies to.</span></span>
<span class="line"><span style="color: #88C0D0">quarkus.http.auth.permission.certauthenticated.methods</span><span style="color: #D8DEE9FF">=GET,POST</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># The paths that this permission set applies to.</span></span>
<span class="line"><span style="color: #88C0D0">quarkus.http.auth.permission.certauthenticated.paths</span><span style="color: #D8DEE9FF">=/api/v1/connection-info/*</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># The policy to use for the permission check.</span></span>
<span class="line"><span style="color: #88C0D0">quarkus.http.auth.permission.certauthenticated.policy</span><span style="color: #D8DEE9FF">=role-policy-cert</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># The roles allowed to access the resource.</span></span>
<span class="line"><span style="color: #88C0D0">quarkus.http.auth.policy.role-policy-cert.roles-allowed</span><span style="color: #D8DEE9FF">=User,Administrator</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Bash</span></div>



<p>Application Properties 3 - Configurazione delle policy di accesso ai servizi REST</p>



<p>Adesso che abbiamo configurato le policy di accesso ai servizi REST, potremo procedere con il test dell’applicazione Quarkus con lo scopo di verificare che l’autenticazione mTLS funzioni correttamente e che le policy di accesso siano rispettate.</p>



<h3 class="wp-block-heading" id="step-10---generazione-di-un-set-di-certificati-client-per-eseguire-dei-test-di-accesso">Step 10 - Generazione di un set di certificati client per eseguire dei test di accesso</h3>



<p>Il tag di riferimento per questo step è <a href="https://github.com/amusarra/quarkus-mtls-auth-tutorial/blob/tutorial-step-10-gen-cert-client/src/main/java/it/dontesta/quarkus/tls/auth/ws/resources/endpoint/v1/ConnectionInfoResourceEndPoint.java">tutorial-step-10-generate-client-certificates</a>.</p>



<p>Prima di procedere con i test dei servizi REST, dobbiamo generare un set di certificati client. Questi certificati saranno utilizzati per testare l’autenticazione mTLS e le policy di accesso ai servizi REST.</p>



<p>Per generare i certificati client, possiamo utilizzare lo script <code>certs-manager.sh</code>, già impiegato per generare il certificato della CA e quello del server. Ricordiamo che lo script si trova nel percorso <code>src/main/shell/certs-manager</code>, mentre i certificati generati finora sono conservati nella directory <code>src/main/resources/certs</code>.</p>



<p>Andremo a generare un set di certificati client con le seguenti caratteristiche:</p>



<ol class="wp-block-list">
<li>un certificato client senza estensioni personalizzate;</li>



<li>un certificato client con l'estensione personalizzata <code>DeviceId</code> e il valore <code>1234567890</code>;</li>



<li>un certificato client con l'estensione personalizzata <code>DeviceId</code> con il corretto valore generato dall'algoritmo descritto nel capitolo <em>Algoritmo per la generazione del DeviceId</em> e l'estensione personalizzata <code>Roles</code> e il valore <code>123User</code>;</li>



<li>un certificato client con l'estensione personalizzata <code>DeviceId</code> con il corretto valore generato dall'algoritmo descritto nel capitolo <em>Algoritmo per la generazione del DeviceId</em> e l'estensione personalizzata <code>Roles</code> e il valore <code>ProjectManager</code>;</li>



<li>un certificato client con l'estensione personalizzata <code>DeviceId</code> con il corretto valore generato dall'algoritmo descritto nel capitolo <em>Algoritmo per la generazione del DeviceId</em> e l'estensione personalizzata <code>Roles</code> e il valore <code>User,Administrator</code>.</li>
</ol>



<p>Ricordiamo che i certificati client generati saranno firmati dalla Certificate Authority (CA) che abbiamo creato in precedenza. Il certificato di CA è stato inoltre importato nel truststore dell'applicazione Quarkus per poter verificare la validità dei certificati client attraverso la proprietà <code>quarkus.tls.https.trust-store.pem.certs</code> valorizzata con il valore <code>certs/ca_cert.pem</code>.</p>



<p>Procediamo quindi con la generazione dei certificati client eseguendo lo script <code>certs-manager.sh</code> come indicato a seguire.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# Generate a client certificate without custom extensions
./src/main/shell/certs-manager/certs_manager.sh generate-client --working-dir src/main/resources/certs \
    --private-key-file client_without_custom_ext_key.pem \
    --csr-file client_without_custom_ext_csr.pem \
    --client-cert-file client_without_custom_ext_cert.pem \
    --validity-days 365 \
    --ca-cert-file ca_cert.pem \
    --ca-key-file ca_private_key.pem \
    --ca-key-password &quot;$(cat src/main/resources/certs/ca_private_key.pem.password)&quot; \
    --country IT \
    --state Italy \
    --locality Rome \
    --organization &quot;Mario Rossi Corporation&quot; \
    --organizational-unit &quot;Community &amp; News&quot; \
    --common-name &quot;D54FF113-A0C4-4A67-A6DE-B8DEE24A5095&quot; \
    --extensions-file src/main/shell/certs-manager/ssl_extensions_without_custom.cnf \
    --output-p12-file client_without_custom_ext_cert.p12" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88"># Generate a client certificate without custom extensions</span></span>
<span class="line"><span style="color: #88C0D0">./src/main/shell/certs-manager/certs_manager.sh</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">generate-client</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">--working-dir</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">src/main/resources/certs</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--private-key-file</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">client_without_custom_ext_key.pem</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--csr-file</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">client_without_custom_ext_csr.pem</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--client-cert-file</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">client_without_custom_ext_cert.pem</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--validity-days</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">365</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--ca-cert-file</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ca_cert.pem</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--ca-key-file</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ca_private_key.pem</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--ca-key-password</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;$(</span><span style="color: #88C0D0">cat</span><span style="color: #A3BE8C"> src/main/resources/certs/ca_private_key.pem.password</span><span style="color: #ECEFF4">)&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--country</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">IT</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--state</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Italy</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--locality</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Rome</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--organization</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Mario Rossi Corporation</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--organizational-unit</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Community &amp; News</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--common-name</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">D54FF113-A0C4-4A67-A6DE-B8DEE24A5095</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--extensions-file</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">src/main/shell/certs-manager/ssl_extensions_without_custom.cnf</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--output-p12-file</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">client_without_custom_ext_cert.p12</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Bash</span></div>



<p>Console 13 - Generazione di un certificato client senza estensioni personalizzate</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# Generate a client certificate with custom extension DeviceId and value 1234567890
./src/main/shell/certs-manager/certs_manager.sh generate-client --working-dir src/main/resources/certs \
    --private-key-file client_with_bad_device_id_key.pem \
    --csr-file client_with_bad_device_id_csr.pem \
    --client-cert-file client_with_bad_device_id_cert.pem \
    --validity-days 365 \
    --ca-cert-file ca_cert.pem \
    --ca-key-file ca_private_key.pem \
    --ca-key-password &quot;$(cat src/main/resources/certs/ca_private_key.pem.password)&quot; \
    --country IT \
    --state Italy \
    --locality Rome \
    --organization &quot;Antonella Bianchi Corporation&quot; \
    --organizational-unit &quot;Community &amp; News&quot; \
    --common-name &quot;438D4FFD-0082-4189-8659-012692868913&quot; \
    --extensions-file src/main/shell/certs-manager/ssl_extensions.cnf \
    --ext-cert-device-id 1234567890 \
    --output-p12-file client_with_bad_device_id_cert.p12" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88"># Generate a client certificate with custom extension DeviceId and value 1234567890</span></span>
<span class="line"><span style="color: #88C0D0">./src/main/shell/certs-manager/certs_manager.sh</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">generate-client</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">--working-dir</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">src/main/resources/certs</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--private-key-file</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">client_with_bad_device_id_key.pem</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--csr-file</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">client_with_bad_device_id_csr.pem</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--client-cert-file</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">client_with_bad_device_id_cert.pem</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--validity-days</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">365</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--ca-cert-file</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ca_cert.pem</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--ca-key-file</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ca_private_key.pem</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--ca-key-password</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;$(</span><span style="color: #88C0D0">cat</span><span style="color: #A3BE8C"> src/main/resources/certs/ca_private_key.pem.password</span><span style="color: #ECEFF4">)&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--country</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">IT</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--state</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Italy</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--locality</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Rome</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--organization</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Antonella Bianchi Corporation</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--organizational-unit</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Community &amp; News</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--common-name</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">438D4FFD-0082-4189-8659-012692868913</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--extensions-file</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">src/main/shell/certs-manager/ssl_extensions.cnf</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--ext-cert-device-id</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1234567890</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--output-p12-file</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">client_with_bad_device_id_cert.p12</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Bash</span></div>



<p>Console 14 - Generazione di un certificato client con estensione personalizzata <code>DeviceId</code> e valore <code>1234567890</code></p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# Generate a client certificate with custom extension DeviceId with the correct value generated by the algorithm described in the chapter &quot;Algorithm for generating the DeviceId&quot; and the custom extension Roles and the value 123User
./src/main/shell/certs-manager/certs_manager.sh generate-client --working-dir src/main/resources/certs \
    --private-key-file client_with_device_id_and_bad_roles_key.pem \
    --csr-file client_with_device_id_and_bad_roles_csr.pem \
    --client-cert-file client_with_device_id_and_bad_roles_cert.pem \
    --validity-days 365 \
    --ca-cert-file ca_cert.pem \
    --ca-key-file ca_private_key.pem \
    --ca-key-password &quot;$(cat src/main/resources/certs/ca_private_key.pem.password)&quot; \
    --country IT \
    --state Italy \
    --locality Rome \
    --organization &quot;Andrea Valdasso Corporation&quot; \
    --organizational-unit &quot;Community &amp; News&quot; \
    --common-name &quot;B7422CD0-DDCC-435F-843C-11649C987256&quot; \
    --extensions-file src/main/shell/certs-manager/ssl_extensions.cnf \
    --ext-cert-role 123User \
    --ext-cert-device-id &quot;$(./src/main/shell/certs-manager/generate_device_id.sh generate true)&quot; \
    --output-p12-file client_with_bad_device_id_and_bad_roles_cert.p12" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88"># Generate a client certificate with custom extension DeviceId with the correct value generated by the algorithm described in the chapter &quot;Algorithm for generating the DeviceId&quot; and the custom extension Roles and the value 123User</span></span>
<span class="line"><span style="color: #88C0D0">./src/main/shell/certs-manager/certs_manager.sh</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">generate-client</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">--working-dir</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">src/main/resources/certs</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--private-key-file</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">client_with_device_id_and_bad_roles_key.pem</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--csr-file</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">client_with_device_id_and_bad_roles_csr.pem</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--client-cert-file</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">client_with_device_id_and_bad_roles_cert.pem</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--validity-days</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">365</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--ca-cert-file</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ca_cert.pem</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--ca-key-file</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ca_private_key.pem</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--ca-key-password</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;$(</span><span style="color: #88C0D0">cat</span><span style="color: #A3BE8C"> src/main/resources/certs/ca_private_key.pem.password</span><span style="color: #ECEFF4">)&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--country</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">IT</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--state</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Italy</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--locality</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Rome</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--organization</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Andrea Valdasso Corporation</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--organizational-unit</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Community &amp; News</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--common-name</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">B7422CD0-DDCC-435F-843C-11649C987256</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--extensions-file</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">src/main/shell/certs-manager/ssl_extensions.cnf</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--ext-cert-role</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">123</span><span style="color: #A3BE8C">User</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--ext-cert-device-id</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;$(</span><span style="color: #88C0D0">./src/main/shell/certs-manager/generate_device_id.sh</span><span style="color: #A3BE8C"> generate </span><span style="color: #81A1C1">true</span><span style="color: #ECEFF4">)&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--output-p12-file</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">client_with_bad_device_id_and_bad_roles_cert.p12</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Bash</span></div>



<p>Console 15 - Generazione di un certificato client con estensione personalizzata <code>DeviceId</code> con il corretto valore ed estensione personalizzata <code>Roles</code> e valore <code>123User</code></p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# Generate a client certificate with custom extension DeviceId with the correct value generated by the algorithm described in the chapter &quot;Algorithm for generating the DeviceId&quot; and the custom extension Roles and the value ProjectManager
./src/main/shell/certs-manager/certs_manager.sh generate-client --working-dir src/main/resources/certs \
    --private-key-file client_with_device_id_and_roles_key.pem \
    --csr-file client_with_device_id_and_roles_csr.pem \
    --client-cert-file client_with_device_id_and_roles_cert.pem \
    --validity-days 365 \
    --ca-cert-file ca_cert.pem \
    --ca-key-file ca_private_key.pem \
    --ca-key-password &quot;$(cat src/main/resources/certs/ca_private_key.pem.password)&quot; \
    --country IT \
    --state Italy \
    --locality Rome \
    --organization &quot;Marco Visco Corporation&quot; \
    --organizational-unit &quot;Community &amp; News&quot; \
    --common-name &quot;3C266B12-8400-40DC-891B-CB52BB84CD86&quot; \
    --extensions-file src/main/shell/certs-manager/ssl_extensions.cnf \
    --ext-cert-role ProjectManager \
    --ext-cert-device-id &quot;$(./src/main/shell/certs-manager/generate_device_id.sh generate true)&quot; \
    --output-p12-file client_with_device_id_and_roles_cert.p12" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88"># Generate a client certificate with custom extension DeviceId with the correct value generated by the algorithm described in the chapter &quot;Algorithm for generating the DeviceId&quot; and the custom extension Roles and the value ProjectManager</span></span>
<span class="line"><span style="color: #88C0D0">./src/main/shell/certs-manager/certs_manager.sh</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">generate-client</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">--working-dir</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">src/main/resources/certs</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--private-key-file</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">client_with_device_id_and_roles_key.pem</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--csr-file</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">client_with_device_id_and_roles_csr.pem</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--client-cert-file</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">client_with_device_id_and_roles_cert.pem</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--validity-days</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">365</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--ca-cert-file</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ca_cert.pem</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--ca-key-file</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ca_private_key.pem</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--ca-key-password</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;$(</span><span style="color: #88C0D0">cat</span><span style="color: #A3BE8C"> src/main/resources/certs/ca_private_key.pem.password</span><span style="color: #ECEFF4">)&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--country</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">IT</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--state</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Italy</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--locality</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Rome</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--organization</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Marco Visco Corporation</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--organizational-unit</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Community &amp; News</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--common-name</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">3C266B12-8400-40DC-891B-CB52BB84CD86</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--extensions-file</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">src/main/shell/certs-manager/ssl_extensions.cnf</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--ext-cert-role</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ProjectManager</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--ext-cert-device-id</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;$(</span><span style="color: #88C0D0">./src/main/shell/certs-manager/generate_device_id.sh</span><span style="color: #A3BE8C"> generate </span><span style="color: #81A1C1">true</span><span style="color: #ECEFF4">)&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--output-p12-file</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">client_with_device_id_and_roles_cert.p12</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Bash</span></div>



<p>Console 16 - Generazione di un certificato client con estensione personalizzata <code>DeviceId</code> con il corretto valore ed estensione personalizzata <code>Roles</code> e valore <code>ProjectManager</code></p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# Generate a client certificate with custom extension DeviceId with the correct value generated by the algorithm described in the chapter &quot;Algorithm for generating the DeviceId&quot; and the custom extension Roles and the value User,Administrator
./src/main/shell/certs-manager/certs_manager.sh generate-client --working-dir src/main/resources/certs \
    --private-key-file client_with_device_id_and_roles_1_key.pem \
    --csr-file client_with_device_id_and_roles_1_csr.pem \
    --client-cert-file client_with_device_id_and_roles_1_cert.pem \
    --validity-days 365 \
    --ca-cert-file ca_cert.pem \
    --ca-key-file ca_private_key.pem \
    --ca-key-password &quot;$(cat src/main/resources/certs/ca_private_key.pem.password)&quot; \
    --country IT \
    --state Italy \
    --locality Rome \
    --organization &quot;Massimo Visco Corporation&quot; \
    --organizational-unit &quot;Community &amp; News&quot; \
    --common-name &quot;7BF80D48-B92C-45EB-80F0-363D1CCA6E4C&quot; \
    --extensions-file src/main/shell/certs-manager/ssl_extensions.cnf \
    --ext-cert-role User,Administrator \
    --ext-cert-device-id &quot;$(./src/main/shell/certs-manager/generate_device_id.sh generate true)&quot; \
    --output-p12-file client_with_device_id_and_roles_1_cert.p12" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88"># Generate a client certificate with custom extension DeviceId with the correct value generated by the algorithm described in the chapter &quot;Algorithm for generating the DeviceId&quot; and the custom extension Roles and the value User,Administrator</span></span>
<span class="line"><span style="color: #88C0D0">./src/main/shell/certs-manager/certs_manager.sh</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">generate-client</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">--working-dir</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">src/main/resources/certs</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--private-key-file</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">client_with_device_id_and_roles_1_key.pem</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--csr-file</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">client_with_device_id_and_roles_1_csr.pem</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--client-cert-file</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">client_with_device_id_and_roles_1_cert.pem</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--validity-days</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">365</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--ca-cert-file</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ca_cert.pem</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--ca-key-file</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ca_private_key.pem</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--ca-key-password</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;$(</span><span style="color: #88C0D0">cat</span><span style="color: #A3BE8C"> src/main/resources/certs/ca_private_key.pem.password</span><span style="color: #ECEFF4">)&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--country</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">IT</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--state</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Italy</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--locality</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Rome</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--organization</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Massimo Visco Corporation</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--organizational-unit</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Community &amp; News</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--common-name</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">7BF80D48-B92C-45EB-80F0-363D1CCA6E4C</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--extensions-file</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">src/main/shell/certs-manager/ssl_extensions.cnf</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--ext-cert-role</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">User,Administrator</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--ext-cert-device-id</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;$(</span><span style="color: #88C0D0">./src/main/shell/certs-manager/generate_device_id.sh</span><span style="color: #A3BE8C"> generate </span><span style="color: #81A1C1">true</span><span style="color: #ECEFF4">)&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--output-p12-file</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">client_with_device_id_and_roles_1_cert.p12</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Bash</span></div>



<p>Console 17 - Generazione di un certificato client con estensione personalizzata <code>DeviceId</code> con il corretto valore ed estensione personalizzata <code>Roles</code> e valore <code>User,Administrator</code></p>



<p>Come possiamo vedere dagli script sopra riportati, abbiamo generato cinque certificati client con le caratteristiche descritte in precedenza. I certificati client generati sono stati salvati all'interno della directory <code>src/main/resources/certs</code> e la tabella 3 mostra un riepilogo dei certificati client generati.</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>ID</th><th>Subject</th><th>Issuer</th><th>DeviceId</th><th>Roles</th><th>File p12</th><th>Password .p12</th><th>Password private key (PEM)</th></tr></thead><tbody><tr><td>1</td><td>C=IT, ST=Italy, L=Rome, O=Mario Rossi Corporation, OU=Community &amp; News, CN=D54FF113-A0C4-4A67-A6DE-B8DEE24A5095</td><td>Dontesta CA</td><td></td><td></td><td>client_without_custom_ext_cert.p12</td><td>5byk65SNHEIwfv3s</td><td>K3K8onVbmB2ACXdu</td></tr><tr><td>2</td><td>C=IT, ST=Italy, L=Rome, O=Antonella Bianchi Corporation, OU=Community &amp; News, CN=438D4FFD-0082-4189-8659-012692868913</td><td>Dontesta CA</td><td>1234567890</td><td></td><td>client_with_bad_device_id_cert.p12</td><td>HQeQYfBkq2cf8AjL</td><td>DDSO642Dq2o+U1cF</td></tr><tr><td>3</td><td>C=IT, ST=Italy, L=Rome, O=Andrea Valdasso Corporation, OU=Community &amp; News, CN=B7422CD0-DDCC-435F-843C-11649C987256</td><td>Dontesta CA</td><td></td><td>123User</td><td>client_with_device_id_and_bad_roles_cert.p12</td><td>7Rb1laR7WOdqcZk+</td><td>1JKARpPJ7wCnX4Ju</td></tr><tr><td>4</td><td>C=IT, ST=Italy, L=Rome, O=Marco Visco Corporation, OU=Community &amp; News, CN=3C266B12-8400-40DC-891B-CB52BB84CD86</td><td>Dontesta CA</td><td></td><td>ProjectManager</td><td>client_with_device_id_and_roles_cert.p12</td><td>HA5b7g0Cy3bI/+1/</td><td>AeqFJRRA2wqnG0Nf</td></tr><tr><td>5</td><td>C=IT, ST=Italy, L=Rome, O=Massimo Visco Corporation, OU=Community &amp; News, CN=7BF80D48-B92C-45EB-80F0-363D1CCA6E4C</td><td>Dontesta CA</td><td></td><td>User<br>Administrator</td><td>client_with_device_id_and_roles_1_cert.p12</td><td>uWTNwBluEXGszPYv</td><td>55MoxEiH1B/r5Muz</td></tr></tbody></table></figure>



<p>Tabella 3 - Certificati client generati per i test di accesso</p>



<p>Il valore del DeviceId è stato generato utilizzando lo script <code>generate_device_id.sh</code> e il valore è stato codificato in Base64. Il valore del DeviceId è stato inserito nel certificato client come estensione personalizzata <code>DeviceId</code>. A seguire un esempio dell'output dello script <code>generate_device_id.sh</code>.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# Generate a DeviceId
./src/main/shell/certs-manager/generate_device_id.sh generate true

# Output
MTcyNjM1NTMzNTQyMzYxNzAwMCMyYzBlMzY4ZS1lMDU5LTQ5OWQtYjFjNS0zNGU4MjdiYmE0MTIjYW11c2FycmEtbWFjYm9vay1wcm8ubG9jYWwjNmNlZDI3YTI5ODUyMDJiNjhiOTA2YjQ3YTQzM2QyOGNkYTFmN2JkMjMxNzMzNTUxNmIzNmVlYTViMTc0MTdlOA==" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88"># Generate a DeviceId</span></span>
<span class="line"><span style="color: #88C0D0">./src/main/shell/certs-manager/generate_device_id.sh</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">generate</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">true</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Output</span></span>
<span class="line"><span style="color: #D8DEE9">MTcyNjM1NTMzNTQyMzYxNzAwMCMyYzBlMzY4ZS1lMDU5LTQ5OWQtYjFjNS0zNGU4MjdiYmE0MTIjYW11c2FycmEtbWFjYm9vay1wcm8ubG9jYWwjNmNlZDI3YTI5ODUyMDJiNjhiOTA2YjQ3YTQzM2QyOGNkYTFmN2JkMjMxNzMzNTUxNmIzNmVlYTViMTc0MTdlOA</span><span style="color: #81A1C1">=</span><span style="color: #A3BE8C">=</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Bash</span></div>



<p>Console 18 - Esempio di output dello script <code>generate_device_id.sh</code> per la generazione del DeviceId</p>



<h3 class="wp-block-heading" id="step-11---test-della-configurazione-mtls">Step 11 - Test della configurazione mTLS</h3>



<p>Il tag di riferimento per questo step è <a href="https://github.com/amusarra/quarkus-mtls-auth-tutorial/tree/tutorial-step-11-test-config-mtls/src/main/resources/certs">tutorial-step-11-test-mtls-config</a>.</p>



<p>Adesso che abbiamo generato i certificati client, possiamo procedere con il test dell'applicazione Quarkus per verificare che l'autenticazione mTLS funzioni correttamente e che le policy di accesso ai servizi REST siano rispettate.</p>



<p>Prima di proseguire con la serie di test, dobbiamo applicare una configurazione obbligatoria, ovvero, la secret key necessaria per la decodifica e verifica del DeviceId. La proprietà da aggiungere al file di configurazione <code>application.properties</code> è indicata a seguire.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# Setting the secret key for verifying the device ID extracted from the client certificate.
# The secret key is stored in the `application.properties` file. In a production environment,
# it is recommended to use a secure password storage mechanism.
client.cert.device.id.secret-key=my_secret_key_for_generate_device_id" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88"># Setting the secret key for verifying the device ID extracted from the client certificate.</span></span>
<span class="line"><span style="color: #616E88"># The secret key is stored in the `application.properties` file. In a production environment,</span></span>
<span class="line"><span style="color: #616E88"># it is recommended to use a secure password storage mechanism.</span></span>
<span class="line"><span style="color: #88C0D0">client.cert.device.id.secret-key</span><span style="color: #D8DEE9FF">=my_secret_key_for_generate_device_id</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Bash</span></div>



<p>Application Properties 4 - Configurazione della secret key per la verifica del DeviceId</p>



<p>La verifica del DeviceId è un passaggio obbligatorio per l’autenticazione mTLS. Il DeviceId è un identificativo univoco generato e inserito nel certificato client durante la sua creazione. Questo valore viene prodotto tramite un algoritmo specifico e successivamente decodificato e verificato dall’applicazione Quarkus per garantire l’autenticazione mTLS.</p>



<p>La verifica è implementata all'interno della classe <code>DeviceIdUtil</code> attraverso il metodo <code>verifyDeviceId</code> e l'algoritmo per la generazione del DeviceId è descritto nel capitolo <em>Algoritmo per la generazione del DeviceId</em>.</p>



<p>Durante la fase di test, potrebbe risultare utile avere il log di debug dei componenti di <code>SecurityAugmentor</code> per verificare che l'autenticazione mTLS funzioni correttamente. Per fare ciò, possiamo aggiungere le seguenti proprietà al file di configurazione <code>application.properties</code>.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# Logging configuration
quarkus.log.category.&quot;it.dontesta.quarkus.tls.auth.ws.security.identity.RolesAugmentor&quot;.level=DEBUG
quarkus.log.category.&quot;it.dontesta.quarkus.tls.auth.ws.security.identity.AttributesAugmentor&quot;.level=DEBUG
quarkus.log.category.&quot;it.dontesta.quarkus.tls.auth.ws.security.identity.OidSecurityIdentityAugmentor&quot;.level=DEBUG" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88"># Logging configuration</span></span>
<span class="line"><span style="color: #88C0D0">quarkus.log.category.</span><span style="color: #88C0D0">&quot;it.dontesta.quarkus.tls.auth.ws.security.identity.RolesAugmentor&quot;</span><span style="color: #88C0D0">.level</span><span style="color: #D8DEE9FF">=DEBUG</span></span>
<span class="line"><span style="color: #88C0D0">quarkus.log.category.</span><span style="color: #88C0D0">&quot;it.dontesta.quarkus.tls.auth.ws.security.identity.AttributesAugmentor&quot;</span><span style="color: #88C0D0">.level</span><span style="color: #D8DEE9FF">=DEBUG</span></span>
<span class="line"><span style="color: #88C0D0">quarkus.log.category.</span><span style="color: #88C0D0">&quot;it.dontesta.quarkus.tls.auth.ws.security.identity.OidSecurityIdentityAugmentor&quot;</span><span style="color: #88C0D0">.level</span><span style="color: #D8DEE9FF">=DEBUG</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Bash</span></div>



<p>Application Properties 5 - Configurazione del log di debug</p>



<p>Adesso possiamo procedere con il test dell'applicazione Quarkus. Per fare ciò, eseguiremo i seguenti passaggi:</p>



<ol class="wp-block-list">
<li>avviare l'applicazione Quarkus;</li>



<li>eseguire i test di accesso ai servizi REST utilizzando i certificati client generati verificando che l'autenticazione mTLS funzioni correttamente, che le policy di accesso ai servizi REST siano rispettate e che le risposte dei servizi REST siano conformi agli schemi JSON definiti nel capitolo <em>Struttura JSON di risposta dei servizi Rest</em>.</li>
</ol>



<p>Per avviare l'applicazione basta eseguire il comando <code>quarkus:dev</code> e se non ci sono errori, l'applicazione Quarkus sarà pronta per i test e dovremmo vedere un output simile a quello riportato di seguito.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="
          ,--------.,--.    ,---.             ,---.
,--,--,--.'--.  .--'|  |   '   .-'  ,-----.  /  O  \  ,---.  ,---.
|        |   |  |   |  |   `.  `-.  '-----' |  .-.  || .-. || .-. |
|  |  |  |   |  |   |  '--..-'    |         |  | |  || '-' '| '-' '
`--`--`--'   `--'   `-----'`-----'          `--' `--'|  |-' |  |-'
                                                     `--'   `--'
Developed by: Antonio Musarra
Blog: https://www.dontesta.it
GitHub: https://github.com/amusarra
LinkedIn: https://www.linkedin.com/in/amusarra
Twitter: https://twitter.com/antonio_musarra

                                          Powered by Quarkus 3.14.3
2024-09-13 16:18:54,102 INFO  [io.quarkus] (Quarkus Main Thread) tls-mutual-auth 1.0.0-SNAPSHOT on JVM (powered by Quarkus 3.14.3) started in 1.436s. Listening on: https://localhost:8443

2024-09-13 16:18:54,103 INFO  [io.quarkus] (Quarkus Main Thread) Profile dev activated. Live Coding activated.
2024-09-13 16:18:54,104 INFO  [io.quarkus] (Quarkus Main Thread) Installed features: [cdi, rest, rest-jackson, security, smallrye-context-propagation, vertx]

--
Tests paused
Press [e] to edit command line args (currently ''), [r] to resume testing, [o] Toggle test output,  for the terminal, [h] for more options&gt;" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #88C0D0">,--------.,--.</span><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">,---.</span><span style="color: #D8DEE9FF">             </span><span style="color: #A3BE8C">,---.</span></span>
<span class="line"><span style="color: #88C0D0">,--,--,--.</span><span style="color: #88C0D0">&#39;--.  .--&#39;</span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF">   </span><span style="color: #88C0D0">&#39;   .-&#39;</span><span style="color: #D8DEE9FF">  </span><span style="color: #A3BE8C">,-----.</span><span style="color: #D8DEE9FF">  </span><span style="color: #A3BE8C">/</span><span style="color: #D8DEE9FF">  </span><span style="color: #A3BE8C">O</span><span style="color: #D8DEE9FF">  </span><span style="color: #EBCB8B">\ </span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">,---.</span><span style="color: #D8DEE9FF">  </span><span style="color: #A3BE8C">,---.</span></span>
<span class="line"><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF">   </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF">   </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF">   </span><span style="color: #ECEFF4">`</span><span style="color: #88C0D0">.</span><span style="color: #A3BE8C">  </span><span style="color: #ECEFF4">`</span><span style="color: #88C0D0">-.</span><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">-----</span><span style="color: #ECEFF4">&#39;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">.</span><span style="color: #D8DEE9FF">-</span><span style="color: #88C0D0">.</span><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">||</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">.</span><span style="color: #D8DEE9FF">-</span><span style="color: #88C0D0">.</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">||</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">.</span><span style="color: #D8DEE9FF">-</span><span style="color: #88C0D0">.</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">|</span></span>
<span class="line"><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF">   </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF">   </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">&#39;--..-&#39;</span><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF">         </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">||</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">&#39;-&#39;</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">| </span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">-</span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C"> </span><span style="color: #ECEFF4">&#39;</span></span>
<span class="line"><span style="color: #ECEFF4">`</span><span style="color: #88C0D0">--</span><span style="color: #ECEFF4">`</span><span style="color: #88C0D0">--</span><span style="color: #ECEFF4">`</span><span style="color: #88C0D0">--&#39;   `--&#39;</span><span style="color: #A3BE8C">   </span><span style="color: #ECEFF4">`</span><span style="color: #88C0D0">-----</span><span style="color: #88C0D0">&#39;`-----&#39;</span><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">`</span><span style="color: #88C0D0">--&#39; `--&#39;</span><span style="color: #81A1C1">|</span><span style="color: #A3BE8C">  </span><span style="color: #81A1C1">|</span><span style="color: #88C0D0">-&#39; |  |-&#39;</span></span>
<span class="line"><span style="color: #A3BE8C">                                                     </span><span style="color: #ECEFF4">`</span><span style="color: #88C0D0">--</span><span style="color: #88C0D0">&#39;   `--&#39;</span></span>
<span class="line"><span style="color: #88C0D0">Developed</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">by:</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Antonio</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Musarra</span></span>
<span class="line"><span style="color: #88C0D0">Blog:</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">https://www.dontesta.it</span></span>
<span class="line"><span style="color: #88C0D0">GitHub:</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">https://github.com/amusarra</span></span>
<span class="line"><span style="color: #88C0D0">LinkedIn:</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">https://www.linkedin.com/in/amusarra</span></span>
<span class="line"><span style="color: #88C0D0">Twitter:</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">https://twitter.com/antonio_musarra</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">                                          </span><span style="color: #88C0D0">Powered</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">by</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Quarkus</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">3.14</span><span style="color: #A3BE8C">.3</span></span>
<span class="line"><span style="color: #88C0D0">2024-09-13</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">16</span><span style="color: #A3BE8C">:18:54,102</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">INFO</span><span style="color: #D8DEE9FF">  [io.quarkus] </span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">Quarkus</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Main</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Thread</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> tls-mutual-auth 1.0.0-SNAPSHOT on JVM </span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">powered</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">by</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Quarkus</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">3.14</span><span style="color: #A3BE8C">.3</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> started </span><span style="color: #81A1C1">in</span><span style="color: #D8DEE9FF"> 1.436s. Listening on: https://localhost:8443</span></span>
<span class="line"></span>
<span class="line"><span style="color: #88C0D0">2024-09-13</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">16</span><span style="color: #A3BE8C">:18:54,103</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">INFO</span><span style="color: #D8DEE9FF">  [io.quarkus] </span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">Quarkus</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Main</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Thread</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> Profile dev activated. Live Coding activated.</span></span>
<span class="line"><span style="color: #88C0D0">2024-09-13</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">16</span><span style="color: #A3BE8C">:18:54,104</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">INFO</span><span style="color: #D8DEE9FF">  [io.quarkus] </span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">Quarkus</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Main</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Thread</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> Installed features: </span><span style="color: #ECEFF4">[</span><span style="color: #D8DEE9FF">cdi, rest, rest-jackson, security, smallrye-context-propagation, vertx</span><span style="color: #ECEFF4">]</span></span>
<span class="line"></span>
<span class="line"><span style="color: #88C0D0">--</span></span>
<span class="line"><span style="color: #88C0D0">Tests</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">paused</span></span>
<span class="line"><span style="color: #88C0D0">Press</span><span style="color: #D8DEE9FF"> [e] to edit command line args </span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">currently</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&#39;&#39;</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF">, </span><span style="color: #ECEFF4">[</span><span style="color: #D8DEE9FF">r</span><span style="color: #ECEFF4">]</span><span style="color: #D8DEE9FF"> to resume testing, </span><span style="color: #ECEFF4">[</span><span style="color: #D8DEE9FF">o</span><span style="color: #ECEFF4">]</span><span style="color: #D8DEE9FF"> Toggle test output,  </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> the terminal, </span><span style="color: #ECEFF4">[</span><span style="color: #D8DEE9FF">h</span><span style="color: #ECEFF4">]</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> more options</span><span style="color: #81A1C1">&gt;</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Bash</span></div>



<p>Console 18 - Avvio dell'applicazione Quarkus</p>



<p>Avviata l'applicazione, possiamo preparare un set di richieste HTTP verso i due endpoint REST che abbiamo implementato. Per fare ciò, possiamo utilizzare un tool come <code>curl</code> o <code>Postman</code>. In questo esempio, utilizzeremo <code>curl</code> per inviare le richieste HTTP. In pipe (|) al comando <code>curl</code> è stato incluso l'utilizzo del tool <code>jq</code> che ci permette di ottenere un output più leggibile (in formato JSON) dei risultati delle richieste HTTP. Non è obbligatorio, ma è consigliabile <a href="https://jqlang.github.io/jq/">installare il tool</a> <code>jq</code> per poter leggere meglio l'output dei comandi.</p>



<p>Tenendo davanti a noi la tabella 2 con i certificati client generati (in formato PKCS#12), potremo procedere con i test di accesso ai servizi REST, verificando che l'output sia quello atteso. Ricordiamo che l'output dipenderà dal certificato client utilizzato per l'accesso ai servizi REST.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# Execute the request to the /api/v1/connection-info/info endpoint using the client certificate without custom extensions
curl -s \
    --cert src/main/resources/certs/client_without_custom_ext_cert.p12:5byk65SNHEIwfv3s \
    --cert-type P12 \
    --cacert src/main/resources/certs/ca_cert.pem \
    https://localhost:8443/api/v1/connection-info/info | jq
    
# Output
{
  &quot;statusCode&quot;: 401,
  &quot;message&quot;: &quot;Invalid certificate OID { 1.3.6.1.4.1.99999.2 } missing for DeviceId.&quot;
}
    
# Execute the request to the /api/v1/connection-info/user-identity endpoint using the client certificate without custom extensions
curl -s \
    --cert src/main/resources/certs/client_without_custom_ext_cert.p12:5byk65SNHEIwfv3s \
    --cert-type P12 \
    --cacert src/main/resources/certs/ca_cert.pem \
    https://localhost:8443/api/v1/connection-info/user-identity | jq

# Output
{
  &quot;statusCode&quot;: 401,
  &quot;message&quot;: &quot;Invalid certificate OID { 1.3.6.1.4.1.99999.2 } missing for DeviceId.&quot;
}" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88"># Execute the request to the /api/v1/connection-info/info endpoint using the client certificate without custom extensions</span></span>
<span class="line"><span style="color: #88C0D0">curl</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-s</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--cert</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">src/main/resources/certs/client_without_custom_ext_cert.p12:5byk65SNHEIwfv3s</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--cert-type</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">P12</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--cacert</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">src/main/resources/certs/ca_cert.pem</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">https://localhost:8443/api/v1/connection-info/info</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">jq</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span></span>
<span class="line"><span style="color: #616E88"># Output</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">&quot;statusCode&quot;</span><span style="color: #88C0D0">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">401</span><span style="color: #A3BE8C">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">&quot;message&quot;</span><span style="color: #88C0D0">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Invalid certificate OID { 1.3.6.1.4.1.99999.2 } missing for DeviceId.</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span></span>
<span class="line"><span style="color: #616E88"># Execute the request to the /api/v1/connection-info/user-identity endpoint using the client certificate without custom extensions</span></span>
<span class="line"><span style="color: #88C0D0">curl</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-s</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--cert</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">src/main/resources/certs/client_without_custom_ext_cert.p12:5byk65SNHEIwfv3s</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--cert-type</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">P12</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--cacert</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">src/main/resources/certs/ca_cert.pem</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">https://localhost:8443/api/v1/connection-info/user-identity</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">jq</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Output</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">&quot;statusCode&quot;</span><span style="color: #88C0D0">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">401</span><span style="color: #A3BE8C">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">&quot;message&quot;</span><span style="color: #88C0D0">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Invalid certificate OID { 1.3.6.1.4.1.99999.2 } missing for DeviceId.</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Bash</span></div>



<p>Console 19 - Esecuzione del test di accesso ai servizi REST con il certificato client senza estensioni personalizzate</p>



<p>L'output dei test di accesso ai servizi REST con il certificato client senza estensioni personalizzate mostra che l'autenticazione mTLS è fallita così come ci aspettavamo, in virtù del fatto che il certificato client non contiene l'estensione personalizzata <code>DeviceId</code> necessaria per l'autenticazione mTLS. In questo caso è intervenuta è la classe <code>OidSecurityIdentityAugmentor</code> che ha la priorità più alta rispetto alle altre e che ha lanciato l'eccezione <code>SecurityException</code> perché l'OID del DeviceId non è stato trovato.</p>



<p>Proseguiamo il test con il certificato client con l'estensione personalizzata <code>DeviceId</code> e il valore <code>1234567890</code>.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# Execute the request to the /api/v1/connection-info/info endpoint using the client certificate with custom extension DeviceId and value 1234567890
curl -s \
    --cert src/main/resources/certs/client_with_bad_device_id_cert.p12:HQeQYfBkq2cf8AjL \
    --cert-type P12 \
    --cacert src/main/resources/certs/ca_cert.pem \
    https://localhost:8443/api/v1/connection-info/info | jq

# Output
{
  &quot;statusCode&quot;: 401,
  &quot;message&quot;: &quot;Invalid certificate OID value { 1234567890 } or OID { 1.3.6.1.4.1.99999.2 } missing for DeviceId.&quot;
}

# Execute the request to the /api/v1/connection-info/user-identity endpoint using the client certificate with custom extension DeviceId and value 1234567890
curl -s \
    --cert src/main/resources/certs/client_with_bad_device_id_cert.p12:HQeQYfBkq2cf8AjL \
    --cert-type P12 \
    --cacert src/main/resources/certs/ca_cert.pem \
    https://localhost:8443/api/v1/connection-info/user-identity | jq

# Output
{
  &quot;statusCode&quot;: 401,
  &quot;message&quot;: &quot;Invalid certificate OID value { 1234567890 } or OID { 1.3.6.1.4.1.99999.2 } missing for DeviceId.&quot;
}" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88"># Execute the request to the /api/v1/connection-info/info endpoint using the client certificate with custom extension DeviceId and value 1234567890</span></span>
<span class="line"><span style="color: #88C0D0">curl</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-s</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--cert</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">src/main/resources/certs/client_with_bad_device_id_cert.p12:HQeQYfBkq2cf8AjL</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--cert-type</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">P12</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--cacert</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">src/main/resources/certs/ca_cert.pem</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">https://localhost:8443/api/v1/connection-info/info</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">jq</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Output</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">&quot;statusCode&quot;</span><span style="color: #88C0D0">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">401</span><span style="color: #A3BE8C">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">&quot;message&quot;</span><span style="color: #88C0D0">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Invalid certificate OID value { 1234567890 } or OID { 1.3.6.1.4.1.99999.2 } missing for DeviceId.</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Execute the request to the /api/v1/connection-info/user-identity endpoint using the client certificate with custom extension DeviceId and value 1234567890</span></span>
<span class="line"><span style="color: #88C0D0">curl</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-s</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--cert</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">src/main/resources/certs/client_with_bad_device_id_cert.p12:HQeQYfBkq2cf8AjL</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--cert-type</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">P12</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--cacert</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">src/main/resources/certs/ca_cert.pem</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">https://localhost:8443/api/v1/connection-info/user-identity</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">jq</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Output</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">&quot;statusCode&quot;</span><span style="color: #88C0D0">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">401</span><span style="color: #A3BE8C">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">&quot;message&quot;</span><span style="color: #88C0D0">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Invalid certificate OID value { 1234567890 } or OID { 1.3.6.1.4.1.99999.2 } missing for DeviceId.</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Bash</span></div>



<p>Console 20 - Esecuzione del test di accesso ai servizi REST con il certificato client con estensione personalizzata <code>DeviceId</code> e valore <code>1234567890</code></p>



<p>Anche in questo caso l'esito del test è quello atteso, con la differenza che il messaggio di errore è leggermente diverso: <code>l'OID del DeviceId è stato trovato ma il valore non è valido</code>. In questo caso il blocco di codice che ha lanciato l'eccezione è quello che verifica il valore del DeviceId, cosi come mostrato a seguire (dalla classe <code>OidSecurityIdentityAugmentor</code>).</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="      if (!DeviceIdUtil.verifyDeviceId(oidValue)) {
        throw new SecurityException(
            &quot;Invalid certificate OID value { %s } or OID { %s } missing for DeviceId.&quot;.formatted(
                oidValue, AttributesAugmentor.OID_DEVICE_ID));
      }" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">(</span><span style="color: #81A1C1">!</span><span style="color: #D8DEE9">DeviceIdUtil</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">verifyDeviceId</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">oidValue</span><span style="color: #ECEFF4">))</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">throw</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">new</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">SecurityException</span><span style="color: #ECEFF4">(</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Invalid certificate OID value { %s } or OID { %s } missing for DeviceId.</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">formatted</span><span style="color: #ECEFF4">(</span></span>
<span class="line"><span style="color: #D8DEE9FF">                oidValue</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">AttributesAugmentor</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">OID_DEVICE_ID</span><span style="color: #ECEFF4">))</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">}</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Java</span></div>



<p>Source Code 6 - Blocco di codice che verifica il valore del DeviceId</p>



<p>Continuiamo il test con il certificato client con l'estensione personalizzata <code>DeviceId</code> che ha il corretto valore generato dall'algoritmo descritto nel capitolo <em>Algoritmo per la generazione del DeviceId</em> e l'estensione personalizzata <code>Roles</code> con il valore <code>123User</code>.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# Execute the request to the /api/v1/connection-info/info endpoint using the client certificate with custom extension DeviceId with the correct value generated by the algorithm and the custom extension Roles and the value 123User
curl -s \
    --cert src/main/resources/certs/client_with_device_id_and_bad_roles_cert.p12:7Rb1laR7WOdqcZk+ \
    --cert-type P12 \
    --cacert src/main/resources/certs/ca_cert.pem \
    https://localhost:8443/api/v1/connection-info/info | jq

# Output
{
  &quot;statusCode&quot;: 401,
  &quot;message&quot;: &quot;Decoded roles do not match the expected pattern: Role=123User&quot;
}

# Execute the request to the /api/v1/connection-info/user-identity endpoint using the client certificate with custom extension DeviceId with the correct value generated by the algorithm and the custom extension Roles and the value 123User
curl -s \
    --cert src/main/resources/certs/client_with_device_id_and_bad_roles_cert.p12:7Rb1laR7WOdqcZk+ \
    --cert-type P12 \
    --cacert src/main/resources/certs/ca_cert.pem \
    https://localhost:8443/api/v1/connection-info/user-identity | jq

# Output
{
  &quot;statusCode&quot;: 401,
  &quot;message&quot;: &quot;Decoded roles do not match the expected pattern: Role=123User&quot;
}" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88"># Execute the request to the /api/v1/connection-info/info endpoint using the client certificate with custom extension DeviceId with the correct value generated by the algorithm and the custom extension Roles and the value 123User</span></span>
<span class="line"><span style="color: #88C0D0">curl</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-s</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--cert</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">src/main/resources/certs/client_with_device_id_and_bad_roles_cert.p12:7Rb1laR7WOdqcZk+</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--cert-type</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">P12</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--cacert</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">src/main/resources/certs/ca_cert.pem</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">https://localhost:8443/api/v1/connection-info/info</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">jq</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Output</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">&quot;statusCode&quot;</span><span style="color: #88C0D0">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">401</span><span style="color: #A3BE8C">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">&quot;message&quot;</span><span style="color: #88C0D0">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Decoded roles do not match the expected pattern: Role=123User</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Execute the request to the /api/v1/connection-info/user-identity endpoint using the client certificate with custom extension DeviceId with the correct value generated by the algorithm and the custom extension Roles and the value 123User</span></span>
<span class="line"><span style="color: #88C0D0">curl</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-s</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--cert</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">src/main/resources/certs/client_with_device_id_and_bad_roles_cert.p12:7Rb1laR7WOdqcZk+</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--cert-type</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">P12</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--cacert</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">src/main/resources/certs/ca_cert.pem</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">https://localhost:8443/api/v1/connection-info/user-identity</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">jq</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Output</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">&quot;statusCode&quot;</span><span style="color: #88C0D0">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">401</span><span style="color: #A3BE8C">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">&quot;message&quot;</span><span style="color: #88C0D0">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Decoded roles do not match the expected pattern: Role=123User</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Bash</span></div>



<p>Console 21 - Esecuzione del test di accesso ai servizi REST con il certificato client con estensione personalizzata <code>DeviceId</code> con il corretto valore ed estensione personalizzata <code>Roles</code> e valore <code>123User</code></p>



<p>Anche in questo caso l'esito del test è quello atteso, con la differenza che il messaggio di errore è leggermente diverso: <code>Decoded roles do not match the expected pattern: Role=123User</code>. In questo caso il blocco di codice che ha lanciato l'eccezione è quello che verifica il pattern dei ruoli, cosi come mostrato a seguire (dalla classe <code>RolesAugmentor</code>).</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="        if (decodedRoles != null) {
          log.debug(&quot;Decoded roles from certificate: %s&quot;.formatted(decodedRoles));

          // Verify that decodedRoles matches the expected pattern
          if (decodedRoles.matches(&quot;^Role=([A-Za-z]+(?:,[A-Za-z]+)*+)$&quot;)) {
            // Add the roles to the set
            roles.addAll(Arrays.stream(decodedRoles.split(&quot;=&quot;)[1].split(&quot;,&quot;))
                .map(String::trim)
                .collect(Collectors.toSet()));
          } else {
            log.warn(&quot;Decoded roles do not match the expected pattern: %s&quot;.formatted(decodedRoles));

            throw new SecurityException(
                &quot;Decoded roles do not match the expected pattern: %s&quot;.formatted(decodedRoles));
          }
        }" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">decodedRoles </span><span style="color: #81A1C1">!=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">null</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #D8DEE9">log</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">debug</span><span style="color: #ECEFF4">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Decoded roles from certificate: %s</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">formatted</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">decodedRoles</span><span style="color: #ECEFF4">))</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ECEFF4">          </span><span style="color: #616E88">// Verify that decodedRoles matches the expected pattern</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9">decodedRoles</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">matches</span><span style="color: #ECEFF4">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">^Role=([A-Za-z]+(?:,[A-Za-z]+)*+)$</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">))</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #ECEFF4">            </span><span style="color: #616E88">// Add the roles to the set</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #D8DEE9">roles</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">addAll</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9">Arrays</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">stream</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9">decodedRoles</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">split</span><span style="color: #ECEFF4">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">=</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">)[</span><span style="color: #B48EAD">1</span><span style="color: #ECEFF4">].</span><span style="color: #88C0D0">split</span><span style="color: #ECEFF4">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">,</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">))</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">map</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">String</span><span style="color: #81A1C1">::</span><span style="color: #D8DEE9FF">trim</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">collect</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9">Collectors</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">toSet</span><span style="color: #ECEFF4">()))</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">else</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #D8DEE9">log</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">warn</span><span style="color: #ECEFF4">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Decoded roles do not match the expected pattern: %s</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">formatted</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">decodedRoles</span><span style="color: #ECEFF4">))</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #81A1C1">throw</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">new</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">SecurityException</span><span style="color: #ECEFF4">(</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Decoded roles do not match the expected pattern: %s</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">formatted</span><span style="color: #ECEFF4">(</span><span style="color: #D8DEE9FF">decodedRoles</span><span style="color: #ECEFF4">))</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">          </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">}</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Java</span></div>



<p>Source Code 7 - Blocco di codice che verifica il pattern dei ruoli</p>



<p>Sulla console di Quarkus dovremmo vedere un output simile a quello riportato di seguito.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="2024-09-13 17:07:57,107 DEBUG [it.don.qua.tls.aut.ws.sec.ide.RolesAugmentor] (vert.x-eventloop-thread-0) Augmenting SecurityIdentity with roles extracted from certificate with OID: 1.3.6.1.4.1.99999.1
2024-09-13 17:07:57,109 DEBUG [it.don.qua.tls.aut.ws.sec.ide.RolesAugmentor] (vert.x-eventloop-thread-0) Decoded roles from certificate: Role=123User
2024-09-13 17:07:57,109 WARN  [it.don.qua.tls.aut.ws.sec.ide.RolesAugmentor] (vert.x-eventloop-thread-0) Decoded roles do not match the expected pattern: Role=123User
2024-09-13 17:07:57,109 ERROR [it.don.qua.tls.aut.ws.sec.ide.RolesAugmentor] (vert.x-eventloop-thread-0) Occurred an error during roles extraction from certificate" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #d8dee9ff">2024-09-13 17:07:57,107 DEBUG [it.don.qua.tls.aut.ws.sec.ide.RolesAugmentor] (vert.x-eventloop-thread-0) Augmenting SecurityIdentity with roles extracted from certificate with OID: 1.3.6.1.4.1.99999.1</span></span>
<span class="line"><span style="color: #d8dee9ff">2024-09-13 17:07:57,109 DEBUG [it.don.qua.tls.aut.ws.sec.ide.RolesAugmentor] (vert.x-eventloop-thread-0) Decoded roles from certificate: Role=123User</span></span>
<span class="line"><span style="color: #d8dee9ff">2024-09-13 17:07:57,109 WARN  [it.don.qua.tls.aut.ws.sec.ide.RolesAugmentor] (vert.x-eventloop-thread-0) Decoded roles do not match the expected pattern: Role=123User</span></span>
<span class="line"><span style="color: #d8dee9ff">2024-09-13 17:07:57,109 ERROR [it.don.qua.tls.aut.ws.sec.ide.RolesAugmentor] (vert.x-eventloop-thread-0) Occurred an error during roles extraction from certificate</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Plaintext</span></div>



<p>Console 22 - Log di debug per la verifica del pattern dei ruoli</p>



<p>Andiamo avanti con il test utilizzando il certificato client con l'estensione personalizzata <code>DeviceId</code> che ha il corretto valore generato dall'algoritmo descritto nel capitolo <em>Algoritmo per la generazione del DeviceId</em> e l'estensione personalizzata <code>Roles</code> con il valore <code>ProjectManager</code>.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# Execute the request to the /api/v1/connection-info/info endpoint using the client certificate with custom extension DeviceId with the correct value generated by the algorithm and the custom extension Roles and the value ProjectManager
curl -i \
    --cert src/main/resources/certs/client_with_device_id_and_roles_cert.p12:HA5b7g0Cy3bI/+1/ \
    --cert-type P12 \
    --cacert src/main/resources/certs/ca_cert.pem \
    https://localhost:8443/api/v1/connection-info/info

# Output
HTTP/2 403
content-length: 0

# Execute the request to the /api/v1/connection-info/user-identity endpoint using the client certificate with custom extension DeviceId with the correct value generated by the algorithm and the custom extension Roles and the value ProjectManager
curl -i \
    --cert src/main/resources/certs/client_with_device_id_and_roles_cert.p12:HA5b7g0Cy3bI/+1/ \
    --cert-type P12 \
    --cacert src/main/resources/certs/ca_cert.pem \
    https://localhost:8443/api/v1/connection-info/user-identity

# Output
HTTP/2 403
content-length: 0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88"># Execute the request to the /api/v1/connection-info/info endpoint using the client certificate with custom extension DeviceId with the correct value generated by the algorithm and the custom extension Roles and the value ProjectManager</span></span>
<span class="line"><span style="color: #88C0D0">curl</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-i</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--cert</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">src/main/resources/certs/client_with_device_id_and_roles_cert.p12:HA5b7g0Cy3bI/+1/</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--cert-type</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">P12</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--cacert</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">src/main/resources/certs/ca_cert.pem</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">https://localhost:8443/api/v1/connection-info/info</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Output</span></span>
<span class="line"><span style="color: #88C0D0">HTTP/2</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">403</span></span>
<span class="line"><span style="color: #88C0D0">content-length:</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Execute the request to the /api/v1/connection-info/user-identity endpoint using the client certificate with custom extension DeviceId with the correct value generated by the algorithm and the custom extension Roles and the value ProjectManager</span></span>
<span class="line"><span style="color: #88C0D0">curl</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-i</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--cert</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">src/main/resources/certs/client_with_device_id_and_roles_cert.p12:HA5b7g0Cy3bI/+1/</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--cert-type</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">P12</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--cacert</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">src/main/resources/certs/ca_cert.pem</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">https://localhost:8443/api/v1/connection-info/user-identity</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Output</span></span>
<span class="line"><span style="color: #88C0D0">HTTP/2</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">403</span></span>
<span class="line"><span style="color: #88C0D0">content-length:</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Bash</span></div>



<p>Console 22 - Esecuzione del test di accesso ai servizi REST con il certificato client con estensione personalizzata <code>DeviceId</code> con il corretto valore ed estensione personalizzata <code>Roles</code> e valore <code>ProjectManager</code></p>



<p>Anche in questo caso l'esito del test è quello atteso. L'accesso ai servizi REST è stato negato in quanto il ruolo <code>ProjectManager</code> non è presente tra i ruoli consentiti, infatti la policy di accesso che abbiamo definito sulla proprietà <code>quarkus.http.auth.policy.role-policy-cert.roles-allowed</code> prevede solo i ruoli <code>User</code> e <code>Administrator</code>.</p>



<p>Infine, proseguiamo il test con il certificato client che possiede l'estensione personalizzata <code>DeviceId</code> che ha il corretto valore generato dall'algoritmo descritto nel capitolo <em>Algoritmo per la generazione del DeviceId</em> e l'estensione personalizzata <code>Roles</code> con il valore <code>User,Administrator</code>.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# Execute the request to the /api/v1/connection-info/info endpoint using the client certificate with custom extension DeviceId with the correct value generated by the algorithm and the custom extension Roles and the value User,Administrator
curl -s \
    --cert src/main/resources/certs/client_with_device_id_and_roles_1_cert.p12:uWTNwBluEXGszPYv \
    --cert-type P12 \
    --cacert src/main/resources/certs/ca_cert.pem \
    https://localhost:8443/api/v1/connection-info/info | jq

# Output
{
  &quot;httpRequestHeaders&quot;: {
    &quot;user-agent&quot;: &quot;curl/8.7.1&quot;,
    &quot;accept&quot;: &quot;*/*&quot;
  },
  &quot;server&quot;: {
    &quot;notAfter&quot;: &quot;Fri Sep 12 18:13:44 CEST 2025&quot;,
    &quot;keyAlgorithm&quot;: &quot;RSA&quot;,
    &quot;keySize&quot;: 2048,
    &quot;certCommonName&quot;: &quot;rd.quarkus.dontesta.it&quot;,
    &quot;certIssuer&quot;: &quot;CN=Dontesta CA,OU=IT Labs,O=Dontesta,L=Bronte,ST=Catania,C=IT&quot;,
    &quot;subjectAlternativeNames&quot;: [
      [
        2,
        &quot;admin.quarkus.dontesta.it&quot;
      ],
      [
        2,
        &quot;blog.quarkus.dontesta.it&quot;
      ],
      [
        2,
        &quot;localhost&quot;
      ]
    ],
    &quot;certSubject&quot;: &quot;CN=rd.quarkus.dontesta.it,OU=IT Labs,O=Dontesta,L=Bronte (CT),ST=Italy,C=IT&quot;,
    &quot;certSerialNumber&quot;: &quot;376693016274162034819659983838224914643739644606&quot;,
    &quot;certPEM&quot;: &quot;&lt;removed&gt;&quot;,
    &quot;customExtensions&quot;: {},
    &quot;notBefore&quot;: &quot;Thu Sep 12 18:13:44 CEST 2024&quot;
  },
  &quot;protocol&quot;: &quot;TLSv1.3&quot;,
  &quot;httpProtocol&quot;: &quot;HTTP_2&quot;,
  &quot;clientPort&quot;: 64218,
  &quot;isSecure&quot;: true,
  &quot;client&quot;: {
    &quot;notAfter&quot;: &quot;Sat Sep 13 15:03:16 CEST 2025&quot;,
    &quot;keyAlgorithm&quot;: &quot;RSA&quot;,
    &quot;keySize&quot;: 2048,
    &quot;certCommonName&quot;: &quot;7BF80D48-B92C-45EB-80F0-363D1CCA6E4C&quot;,
    &quot;certIssuer&quot;: &quot;CN=Dontesta CA,OU=IT Labs,O=Dontesta,L=Bronte,ST=Catania,C=IT&quot;,
    &quot;subjectAlternativeNames&quot;: null,
    &quot;certSubject&quot;: &quot;CN=7BF80D48-B92C-45EB-80F0-363D1CCA6E4C,OU=Community &amp; News,O=Massimo Visco Corporation,L=Rome,ST=Italy,C=IT&quot;,
    &quot;certSerialNumber&quot;: &quot;376693016274162034819659983838224914643739644614&quot;,
    &quot;certPEM&quot;: &quot;&lt;removed&gt;&quot;,
    &quot;customExtensions&quot;: {
      &quot;role&quot;: &quot;Role=User,Administrator&quot;,
      &quot;deviceId&quot;: &quot;DeviceId=MTcyNjIzMjU5Njc5NTk2NjAwMCNmMjEwNTM2Ni02MTEyLTQyYTctOGI5OC00Njg3NmRkYWU0MmYjYW11c2FycmEtbWFjYm9vay1wcm8ubG9jYWwjNWZlMGUxMTNkMGJjMDIzZTQ3YTY0OTAzM2Q1NmM2MmEwN2EzMDk0MzVkYzdiOWIyMjIxZjkxNDcwNDVkZTdjNg==&quot;
    },
    &quot;notBefore&quot;: &quot;Fri Sep 13 15:03:16 CEST 2024&quot;
  },
  &quot;userAgent&quot;: &quot;curl/8.7.1&quot;,
  &quot;cipherSuite&quot;: &quot;TLS_AES_256_GCM_SHA384&quot;,
  &quot;clientAddress&quot;: &quot;127.0.0.1:64218&quot;
}

# Execute the request to the /api/v1/connection-info/user-identity endpoint using the client certificate with custom extension DeviceId with the correct value generated by the algorithm and the custom extension Roles and the value User,Administrator
curl -s \
    --cert src/main/resources/certs/client_with_device_id_and_roles_1_cert.p12:uWTNwBluEXGszPYv \
    --cert-type P12 \
    --cacert src/main/resources/certs/ca_cert.pem \
    https://localhost:8443/api/v1/connection-info/user-identity | jq

# Output
{
  &quot;principal&quot;: &quot;CN=7BF80D48-B92C-45EB-80F0-363D1CCA6E4C,OU=Community &amp; News,O=Massimo Visco Corporation,L=Rome,ST=Italy,C=IT&quot;,
  &quot;roles&quot;: [
    &quot;User&quot;,
    &quot;Administrator&quot;
  ],
  &quot;attributes&quot;: {
    &quot;deviceId&quot;: &quot;MTcyNjIzMjU5Njc5NTk2NjAwMCNmMjEwNTM2Ni02MTEyLTQyYTctOGI5OC00Njg3NmRkYWU0MmYjYW11c2FycmEtbWFjYm9vay1wcm8ubG9jYWwjNWZlMGUxMTNkMGJjMDIzZTQ3YTY0OTAzM2Q1NmM2MmEwN2EzMDk0MzVkYzdiOWIyMjIxZjkxNDcwNDVkZTdjNg==&quot;
  },
  &quot;userCN&quot;: &quot;7BF80D48-B92C-45EB-80F0-363D1CCA6E4C&quot;
}" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88"># Execute the request to the /api/v1/connection-info/info endpoint using the client certificate with custom extension DeviceId with the correct value generated by the algorithm and the custom extension Roles and the value User,Administrator</span></span>
<span class="line"><span style="color: #88C0D0">curl</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-s</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--cert</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">src/main/resources/certs/client_with_device_id_and_roles_1_cert.p12:uWTNwBluEXGszPYv</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--cert-type</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">P12</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--cacert</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">src/main/resources/certs/ca_cert.pem</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">https://localhost:8443/api/v1/connection-info/info</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">jq</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Output</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">&quot;httpRequestHeaders&quot;</span><span style="color: #88C0D0">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">&quot;user-agent&quot;</span><span style="color: #88C0D0">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">curl/8.7.1</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">&quot;accept&quot;</span><span style="color: #88C0D0">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">*/*</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">&quot;server&quot;</span><span style="color: #88C0D0">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">&quot;notAfter&quot;</span><span style="color: #88C0D0">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Fri Sep 12 18:13:44 CEST 2025</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">&quot;keyAlgorithm&quot;</span><span style="color: #88C0D0">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">RSA</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">&quot;keySize&quot;</span><span style="color: #88C0D0">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">2048</span><span style="color: #A3BE8C">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">&quot;certCommonName&quot;</span><span style="color: #88C0D0">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">rd.quarkus.dontesta.it</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">&quot;certIssuer&quot;</span><span style="color: #88C0D0">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">CN=Dontesta CA,OU=IT Labs,O=Dontesta,L=Bronte,ST=Catania,C=IT</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">&quot;subjectAlternativeNames&quot;</span><span style="color: #88C0D0">:</span><span style="color: #D8DEE9FF"> [</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">[</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #B48EAD">2</span><span style="color: #D8DEE9FF">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">admin.quarkus.dontesta.it</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">]</span><span style="color: #88C0D0">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">[</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #B48EAD">2</span><span style="color: #D8DEE9FF">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">blog.quarkus.dontesta.it</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">]</span><span style="color: #88C0D0">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">[</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #B48EAD">2</span><span style="color: #D8DEE9FF">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">localhost</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #ECEFF4">]</span></span>
<span class="line"><span style="color: #D8DEE9FF">    ],</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">&quot;certSubject&quot;</span><span style="color: #88C0D0">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">CN=rd.quarkus.dontesta.it,OU=IT Labs,O=Dontesta,L=Bronte (CT),ST=Italy,C=IT</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">&quot;certSerialNumber&quot;</span><span style="color: #88C0D0">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">376693016274162034819659983838224914643739644606</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">&quot;certPEM&quot;</span><span style="color: #88C0D0">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">&lt;removed&gt;</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">&quot;customExtensions&quot;</span><span style="color: #88C0D0">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">{},</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">&quot;notBefore&quot;</span><span style="color: #88C0D0">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Thu Sep 12 18:13:44 CEST 2024</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  },</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">&quot;protocol&quot;</span><span style="color: #88C0D0">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">TLSv1.3</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">&quot;httpProtocol&quot;</span><span style="color: #88C0D0">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">HTTP_2</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">&quot;clientPort&quot;</span><span style="color: #88C0D0">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">64218</span><span style="color: #A3BE8C">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">&quot;isSecure&quot;</span><span style="color: #88C0D0">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">true</span><span style="color: #A3BE8C">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">&quot;client&quot;</span><span style="color: #88C0D0">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">&quot;notAfter&quot;</span><span style="color: #88C0D0">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Sat Sep 13 15:03:16 CEST 2025</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">&quot;keyAlgorithm&quot;</span><span style="color: #88C0D0">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">RSA</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">&quot;keySize&quot;</span><span style="color: #88C0D0">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">2048</span><span style="color: #A3BE8C">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">&quot;certCommonName&quot;</span><span style="color: #88C0D0">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">7BF80D48-B92C-45EB-80F0-363D1CCA6E4C</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">&quot;certIssuer&quot;</span><span style="color: #88C0D0">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">CN=Dontesta CA,OU=IT Labs,O=Dontesta,L=Bronte,ST=Catania,C=IT</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">&quot;subjectAlternativeNames&quot;</span><span style="color: #88C0D0">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">null,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">&quot;certSubject&quot;</span><span style="color: #88C0D0">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">CN=7BF80D48-B92C-45EB-80F0-363D1CCA6E4C,OU=Community &amp; News,O=Massimo Visco Corporation,L=Rome,ST=Italy,C=IT</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">&quot;certSerialNumber&quot;</span><span style="color: #88C0D0">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">376693016274162034819659983838224914643739644614</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">&quot;certPEM&quot;</span><span style="color: #88C0D0">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">&lt;removed&gt;</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">&quot;customExtensions&quot;</span><span style="color: #88C0D0">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #88C0D0">&quot;role&quot;</span><span style="color: #88C0D0">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Role=User,Administrator</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #88C0D0">&quot;deviceId&quot;</span><span style="color: #88C0D0">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">DeviceId=MTcyNjIzMjU5Njc5NTk2NjAwMCNmMjEwNTM2Ni02MTEyLTQyYTctOGI5OC00Njg3NmRkYWU0MmYjYW11c2FycmEtbWFjYm9vay1wcm8ubG9jYWwjNWZlMGUxMTNkMGJjMDIzZTQ3YTY0OTAzM2Q1NmM2MmEwN2EzMDk0MzVkYzdiOWIyMjIxZjkxNDcwNDVkZTdjNg==</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    },</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">&quot;notBefore&quot;</span><span style="color: #88C0D0">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Fri Sep 13 15:03:16 CEST 2024</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  },</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">&quot;userAgent&quot;</span><span style="color: #88C0D0">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">curl/8.7.1</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">&quot;cipherSuite&quot;</span><span style="color: #88C0D0">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">TLS_AES_256_GCM_SHA384</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">&quot;clientAddress&quot;</span><span style="color: #88C0D0">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">127.0.0.1:64218</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Execute the request to the /api/v1/connection-info/user-identity endpoint using the client certificate with custom extension DeviceId with the correct value generated by the algorithm and the custom extension Roles and the value User,Administrator</span></span>
<span class="line"><span style="color: #88C0D0">curl</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-s</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--cert</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">src/main/resources/certs/client_with_device_id_and_roles_1_cert.p12:uWTNwBluEXGszPYv</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--cert-type</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">P12</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">--cacert</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">src/main/resources/certs/ca_cert.pem</span><span style="color: #D8DEE9FF"> </span><span style="color: #EBCB8B">\</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #A3BE8C">https://localhost:8443/api/v1/connection-info/user-identity</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">jq</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Output</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">&quot;principal&quot;</span><span style="color: #88C0D0">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">CN=7BF80D48-B92C-45EB-80F0-363D1CCA6E4C,OU=Community &amp; News,O=Massimo Visco Corporation,L=Rome,ST=Italy,C=IT</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">&quot;roles&quot;</span><span style="color: #88C0D0">:</span><span style="color: #D8DEE9FF"> [</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">&quot;User&quot;</span><span style="color: #88C0D0">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">&quot;Administrator&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  ],</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">&quot;attributes&quot;</span><span style="color: #88C0D0">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">&quot;deviceId&quot;</span><span style="color: #88C0D0">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">MTcyNjIzMjU5Njc5NTk2NjAwMCNmMjEwNTM2Ni02MTEyLTQyYTctOGI5OC00Njg3NmRkYWU0MmYjYW11c2FycmEtbWFjYm9vay1wcm8ubG9jYWwjNWZlMGUxMTNkMGJjMDIzZTQ3YTY0OTAzM2Q1NmM2MmEwN2EzMDk0MzVkYzdiOWIyMjIxZjkxNDcwNDVkZTdjNg==</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">&quot;userCN&quot;</span><span style="color: #88C0D0">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">7BF80D48-B92C-45EB-80F0-363D1CCA6E4C</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">}</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Bash</span></div>



<p>Console 23 - Esecuzione del test di accesso ai servizi REST con il certificato client con estensione personalizzata <code>DeviceId</code> con il corretto valore ed estensione personalizzata <code>Roles</code> e valore <code>User,Administrator</code></p>



<p>L'output dei test di accesso ai servizi REST con il certificato client con l'estensione personalizzata <code>DeviceId</code> con il corretto valore generato dall'algoritmo descritto nel capitolo <em>Algoritmo per la generazione del DeviceId</em> e l'estensione personalizzata <code>Roles</code> con il valore <code>User,Administrator</code> mostra che l'autenticazione mTLS è avvenuta con successo e che l'accesso ai servizi REST è stato consentito. Inoltre, l'output dei servizi REST è conforme agli schemi JSON definiti nel capitolo <em>Struttura JSON di risposta dei servizi Rest</em>.</p>



<p>Con questo ultimo test abbiamo completato la serie di verifiche dell’accesso ai servizi REST utilizzando i certificati client generati. Abbiamo confermato che l’autenticazione mTLS ha funzionato correttamente e che le policy di accesso ai servizi REST sono state applicate in modo adeguato.</p>



<h2 class="wp-block-heading" id="cosè-il-trusted-service-list-tsl-e-come-integrarlo">Cos'è il Trusted Service List (TSL) e come integrarlo</h2>



<p>Il <strong>TSL</strong> (Trusted Service List) è un documento elettronico standardizzato che contiene informazioni sui <strong>servizi fiduciari</strong> di uno Stato membro dell’Unione Europea o di un altro paese riconosciuto. I servizi fiduciari includono quelli che offrono servizi di firma digitale, autenticazione, sigilli elettronici, certificati SSL/TLS e altri meccanismi di sicurezza legati all’identità digitale.</p>



<p>La <strong>mindmap</strong> seguente suddivide il TSL nei seguenti rami principali.</p>



<ul class="wp-block-list">
<li><strong>Definizione</strong>: contiene la definizione del TSL e il documento elettronico standard che lo rappresenta.</li>



<li><strong>Componenti Principali</strong>: elenca i principali componenti del TSL, come i fornitori di servizi fiduciari (TSP), i certificati digitali e i servizi fiduciari qualificati.</li>



<li><strong>Normative</strong>: descrive le normative che regolano il TSL, come il regolamento eIDAS nell’UE e l’interoperabilità tra paesi.</li>



<li><strong>Utilizzo</strong>: spiega come utilizzare il TSL per verificare i certificati, garantire la conformità normativa, firmare documenti digitali e proteggere i siti web con certificati SSL/TLS.</li>



<li><strong>Aggiornamenti</strong>: discute la validità e l’aggiornamento periodico del TSL, nonché la revoca dei fornitori non conformi.</li>
</ul>



<figure class="wp-block-image size-large"><img width="1024" height="407" decoding="async" loading="lazy" src="https://www.dontesta.it/wp-content/uploads/2024/09/mindmap-tsl-1024x407.png" alt="" class="wp-image-5770" srcset="https://www.dontesta.it/wp-content/uploads/2024/09/mindmap-tsl-1024x407.png 1024w, https://www.dontesta.it/wp-content/uploads/2024/09/mindmap-tsl-300x119.png 300w, https://www.dontesta.it/wp-content/uploads/2024/09/mindmap-tsl-768x306.png 768w, https://www.dontesta.it/wp-content/uploads/2024/09/mindmap-tsl-1536x611.png 1536w, https://www.dontesta.it/wp-content/uploads/2024/09/mindmap-tsl-2048x815.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">Figura 11 - Mindmap del Trusted Service List (TSL)</figcaption></figure>



<p></p>



<p>Gli Stati membri dell'Unione Europea e dello Spazio Economico Europeo pubblicano elenchi attendibili di fornitori di servizi fiduciari qualificati in conformità al Regolamento eIDAS. La Commissione Europea pubblica questi elenchi di fiducia in un formato elettronico standardizzato chiamato Trusted List (TL) che è possibile consultare sulla <a href="https://eidas.ec.europa.eu/efda/tl-browser/#/screen/home">eIDAS Dashboard</a>.</p>



<h3 class="wp-block-heading" id="la-soluzione-dellintegrazione-del-tsl-in-quarkus">La soluzione dell'integrazione del TSL in Quarkus</h3>



<p>Il tag di riferimento per questo step è <a href="https://github.com/amusarra/quarkus-mtls-auth-tutorial/tree/tutorial-bonus-integrate-tsl">tutorial-bonus-integrate-tsl</a>.</p>



<p>Per integrare il TSL in un'applicazione Quarkus, potremmo utilizzare la libreria <strong><a href="https://ec.europa.eu/digital-building-blocks/sites/display/DIGITAL/Digital+Signature+Service+-++DSS">DSS : Digital Signature Service</a></strong> che fornisce un'implementazione Java per la gestione delle Trusted Lists (TL) più decine di altre cose all'interno dell'ecosistema DSS. La libreria DSS è stata sviluppata dalla Commissione Europea e fa parte dei <a href="https://ec.europa.eu/digital-building-blocks/sites/display/DIGITAL/">Digital Building Blocks (DBB)</a> per la creazione di servizi digitali sicuri e interoperabili. In questo esempio d'integrazione, faremo una nostra implementazione che richiede davvero poco sforzo e sfrutteremo in questo modo delle caratteristiche di Quarkus.</p>



<p>L'<a href="https://github.com/amusarra/quarkus-mtls-auth-tutorial">applicazione Quarkus</a>, fino a questo momento è stata configurata per l'autenticazione mTLS e l'accesso ai servizi REST è stato limitato in base ai ruoli definiti e attributi presenti nel certificato client. L'integrazione del TSL potrebbe essere utile per verificare i certificati digitali dei fornitori di servizi fiduciari qualificati e garantire la conformità normativa.</p>



<p>Restando nel territorio Italiano e volendo fare un esempio pratico, potremmo utilizzare il TSL Italiano pubblicato dall'<a href="https://www.agid.gov.it/it">Agenzia per l'Italia Digitale (AgID)</a> e integrarlo nell'applicazione Quarkus. L'AgID pubblica il TSL Italiano in un formato elettronico standardizzato che può essere consultato sulla <a href="https://eidas.ec.europa.eu/efda/tl-browser/#/screen/tl/IT">eIDAS Dashboard</a>.</p>



<p>Integrando il TSL Italiano sulla nostra applicazione Quarkus, potremo consentire l'accesso ai servizi REST per i possessori di certificati digitali rilasciati da fornitori di servizi fiduciari qualificati. Qual è il primo certificato digitale che quasi tutti i cittadini Italiani posseggono? La <strong><a href="https://www.cartaidentita.interno.gov.it/">Carta d'Identità Elettronica (CIE)</a></strong> rilasciata dal Ministero dell'Interno e prodotta dal Poligrafico e Zecca dello Stato, è un esempio di certificato digitale che può essere verificato tramite il TSL Italiano.</p>



<p>Quali sono i macro passaggi per integrare il TSL Italiano nell'applicazione Quarkus?</p>



<ol class="wp-block-list">
<li>Scaricare il file XML del TSL Italiano da eIDAS (<a href="https://eidas.agid.gov.it/TL/TSL-IT.xml">https://eidas.agid.gov.it/TL/TSL-IT.xml</a>).</li>



<li>Eseguire il parsing del file XML.</li>



<li>Estrarre i certificati X509 delle CA dei fornitori di servizi fiduciari qualificati.</li>



<li>Verificare i certificati digitali in ingresso.</li>



<li>Configurare il TLS in Quarkus con i certificati digitali validati.</li>
</ol>



<p>Questi macro passaggi possono essere implementati all'interno di un <strong><a href="https://quarkus.io/guides/scheduler">Periodic Task</a></strong> di Quarkus che eseguirà gli step indicati in precedenza, così come mostrato nel diagramma di flusso a seguire.</p>



<div class="wp-block-wp-mermaid-block mermaid">
flowchart TD
   UpdateTSL>Periodic Task \nGov Certificate Updater] --> SA
   subgraph SA [TSL Update Process]
      Start([Start]) --> A[Download the TSL-IT.xml]
      A --> B[Parse the XML file]
      B --> C[Extract certificates and TSP]
      C --> D{Valid certificates?}
      D -->|Yes| E[Validate incoming certificates]
      D -->|No| F[Generate invalid certificate error]
      E --> G[Configure TLS in Quarkus]
      F --> End
      G --> End([End])
   end
</div>



<p>Figura 12 - Diagramma di flusso per l'integrazione del TSL in Quarkus</p>



<h4 class="wp-block-heading" id="implementazione-del-parser-xml-del-tsl-e-del-task-periodico-di-aggiornamento">Implementazione del parser XML del TSL e del task periodico di aggiornamento</h4>



<p>Per quanto riguarda il parser XML del TSL, andremo a scrivere un componente che chiameremo <code>GovCertificateParser</code> che avrà le seguenti responsabilità:</p>



<ol class="wp-block-list">
<li>eseguire il parser del file XML estraendo solo i certificati X509 che sono identificati dall'elemento <code>ServiceTypeIdentifier</code> con il valore <code>http://uri.etsi.org/TrstSvc/Svctype/IdV</code>;</li>



<li>verificare che i certificati X509 siano validi;</li>



<li>salvare i certificati X509 validi in formato PEM;</li>



<li>creare un bundle di certificati PEM che sarà poi utilizzato per configurare il TLS in Quarkus.</li>
</ol>



<p>Per quanto riguarda il task periodico di aggiornamento, andremo a scrivere un componente che chiameremo <code>GovCertificateUpdater</code> che avrà le seguenti responsabilità:</p>



<ol class="wp-block-list">
<li>eseguire il task periodico di aggiornamento del TSL con una frequenza che sia configurabile attraverso una proprietà applicativa sul file <code>application.properties</code>;</li>



<li>scaricare il file XML del TSL Italiano;</li>



<li>chiamare il componente <code>GovCertificateParser</code> che esegue il parsing del file XML e salva i certificati X509 all'interno di un bundle di certificati PEM;</li>
</ol>



<p>Qui non riporterò il codice sorgente completo, che potete sempre visionare qui <a href="https://github.com/amusarra/quarkus-mtls-auth-tutorial/tree/tutorial-bonus-integrate-tsl">tutorial-bonus-integrate-tsl</a> ma vi mostrerò il codice sorgente del componente <a href="https://github.com/amusarra/quarkus-mtls-auth-tutorial/blob/tutorial-bonus-integrate-tsl/src/main/java/it/dontesta/quarkus/tls/auth/certificate/etsi/gov/GovCertificateUpdater.java">GovCertificateUpdater</a> che si occupa di scaricare il file XML del TSL Italiano e di chiamare il componente <a href="https://github.com/amusarra/quarkus-mtls-auth-tutorial/blob/tutorial-bonus-integrate-tsl/src/main/java/it/dontesta/quarkus/tls/auth/certificate/etsi/gov/GovCertificateParser.java">GovCertificateParser</a> per eseguire il parsing del file XML e salvare i certificati X509 all'interno di un bundle di certificati PEM.</p>



<div class="wp-block-wp-mermaid-block mermaid">
sequenceDiagram
   participant Scheduler
   participant GovCertificateUpdater
   participant HttpClient
   participant GovCertificateParser
   Scheduler->>GovCertificateUpdater: updateCertificates()
   activate GovCertificateUpdater
   GovCertificateUpdater->>HttpClient: download TSL-IT.xml
   activate HttpClient
   HttpClient-->>GovCertificateUpdater: TSL-IT.xml content
   deactivate HttpClient
   GovCertificateUpdater->>GovCertificateParser: parseAndSaveCerts(xmlContent)
   activate GovCertificateParser
   GovCertificateParser->>GovCertificateParser: cleanOutputPath()
   GovCertificateParser->>GovCertificateParser: apply(Node node)
   GovCertificateParser->>GovCertificateParser: saveCertificatesAsPem(inputDirectory, outputPath)
   deactivate GovCertificateParser
   deactivate GovCertificateUpdater
</div>



<p>Figura 13 - Diagramma di sequenza per l'aggiornamento del TSL in Quarkus</p>



<p>Le configurazioni applicative introdotte per l'integrazione del TSL sono mostrate di seguito.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# Setting the URL of the Trust Service List (TSL) for the Italian government.
gov.trust.certs.url=https://eidas.agid.gov.it/TL/TSL-IT.xml

# Setting the path where the TSL certificates are stored.
gov.trust.certs.pem.bundle.output.path=/tmp/tsl-it

# Setting the name of the TSL certificates bundle file.
gov.trust.certs.pem.bundle.file.name=tsl-it_bundle.pem

# Setting the period for updating the TSL certificates
# The value can be expressed in milliseconds (ms), seconds (s), minutes (m), hours (h), or days (d).
# The configuration used by GovCertificateUpdater.
gov.trust.certs.tsl.update.period=2m

# Setting the initial delay for updating the TSL certificates
gov.trust.certs.tsl.update.initial.delay=60s" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88"># Setting the URL of the Trust Service List (TSL) for the Italian government.</span></span>
<span class="line"><span style="color: #88C0D0">gov.trust.certs.url</span><span style="color: #D8DEE9FF">=https://eidas.agid.gov.it/TL/TSL-IT.xml</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Setting the path where the TSL certificates are stored.</span></span>
<span class="line"><span style="color: #88C0D0">gov.trust.certs.pem.bundle.output.path</span><span style="color: #D8DEE9FF">=/tmp/tsl-it</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Setting the name of the TSL certificates bundle file.</span></span>
<span class="line"><span style="color: #88C0D0">gov.trust.certs.pem.bundle.file.name</span><span style="color: #D8DEE9FF">=tsl-it_bundle.pem</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Setting the period for updating the TSL certificates</span></span>
<span class="line"><span style="color: #616E88"># The value can be expressed in milliseconds (ms), seconds (s), minutes (m), hours (h), or days (d).</span></span>
<span class="line"><span style="color: #616E88"># The configuration used by GovCertificateUpdater.</span></span>
<span class="line"><span style="color: #88C0D0">gov.trust.certs.tsl.update.period</span><span style="color: #D8DEE9FF">=2m</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Setting the initial delay for updating the TSL certificates</span></span>
<span class="line"><span style="color: #88C0D0">gov.trust.certs.tsl.update.initial.delay</span><span style="color: #D8DEE9FF">=60s</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Bash</span></div>



<p>Application Properties 6 - Configurazioni applicative per l'integrazione del TSL</p>



<p>Oltre a introdurre queste nuove configurazioni applicative, affinché il TLS Registry di Quarkus sia in grado di caricare sul truststore i certificati estratti dal TSL Italiano, dobbiamo configurare il truststore di Quarkus con il bundle di certificati PEM e abilitare il meccanismo di refresh dei certificati. Per fare ciò, dobbiamo modificare la proprietà <code>quarkus.tls.https.trust-store.pem.certs</code> per aggiungere anche il bundle PEM delle CA del TSL e aggiungere la proprietà <code>quarkus.tls.https.reload-period</code>. A seguire le modifiche apportate al file <code>application.properties</code>.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# Setting the trust-store path.
# The trust-store file is located in the `certs` directory
# inside the resources directory.
quarkus.tls.https.trust-store.pem.certs=certs/ca_cert.pem,/tmp/tsl-it/tsl-it_bundle.pem

# Setting the reload period for the TLS configuration to 125 seconds.
quarkus.tls.https.reload-period=125s" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88"># Setting the trust-store path.</span></span>
<span class="line"><span style="color: #616E88"># The trust-store file is located in the `certs` directory</span></span>
<span class="line"><span style="color: #616E88"># inside the resources directory.</span></span>
<span class="line"><span style="color: #88C0D0">quarkus.tls.https.trust-store.pem.certs</span><span style="color: #D8DEE9FF">=certs/ca_cert.pem,/tmp/tsl-it/tsl-it_bundle.pem</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Setting the reload period for the TLS configuration to 125 seconds.</span></span>
<span class="line"><span style="color: #88C0D0">quarkus.tls.https.reload-period</span><span style="color: #D8DEE9FF">=125s</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Bash</span></div>



<p>Application Properties 7 - Configurazioni del TLS Registry per l'integrazione del TSL</p>



<p>L'attuale implementazione del TLS Registry di Quarkus, prevede che il caricamento iniziale dei certificati e successivo reload, possa avvenire solo attraverso filesystem, questo implica che il file <code>tsl-it_bundle.pem</code> (vedi configurazione) debba essere presente sul filesystem e valido; per esempio non può essere un file vuoto. Se queste condizioni non sono rispettate, il TLS Registry di Quarkus non sarà capace di caricare i certificati e il server non verrà avviato. Per maggiori informazioni consultare la documentazione ufficiale <a href="https://quarkus.io/guides/tls-registry-reference#startup-checks">6. Startup checks</a>.</p>



<p><strong>Come risolvere questo problema?</strong> Per gli ambienti superiori a sviluppo non è un problema perché in genere sono adottate soluzioni basate sulle <a href="https://kubernetes.io/docs/concepts/configuration/secret/">kubernetes secrets</a> o <a href="https://cert-manager.io/">cert-manager</a> (vedi <a href="https://quarkus.io/guides/tls-registry-reference#using-kubernetes-secrets-or-cert-manager">8. Using Kubernetes secrets or cert-manager</a>) che inietteranno i certificati direttamente nel filesystem locale del pod, e questo garantirà che il bundle PEM sia presente e valido. Quanto mostrato in console è un esempio di quando l'applicazione Quarkus non riesce ad avviarsi a causa di un file PEM non valido.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="2024-09-17 17:30:20,018 ERROR [io.qua.run.Application] (Quarkus Main Thread) Failed to start application: java.lang.RuntimeException: Failed to start quarkus
        at io.quarkus.runner.ApplicationImpl.doStart(Unknown Source)
        at io.quarkus.runtime.Application.start(Application.java:101)
        at io.quarkus.runtime.ApplicationLifecycleManager.run(ApplicationLifecycleManager.java:119)
        at io.quarkus.runtime.Quarkus.run(Quarkus.java:71)
        at io.quarkus.runtime.Quarkus.run(Quarkus.java:44)
        at io.quarkus.runtime.Quarkus.run(Quarkus.java:124)
        at io.quarkus.runner.GeneratedMain.main(Unknown Source)
        at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
        at java.base/java.lang.reflect.Method.invoke(Method.java:580)
        at io.quarkus.runner.bootstrap.StartupActionImpl$1.run(StartupActionImpl.java:116)
        at java.base/java.lang.Thread.run(Thread.java:1583)
Caused by: java.lang.IllegalStateException: Invalid PEM trusted certificates configuration for certificate 'https' - cannot read the PEM certificate files
        at io.quarkus.tls.runtime.keystores.PemKeyStores.verifyPEMTrustStoreStore(PemKeyStores.java:49)" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #d8dee9ff">2024-09-17 17:30:20,018 ERROR [io.qua.run.Application] (Quarkus Main Thread) Failed to start application: java.lang.RuntimeException: Failed to start quarkus</span></span>
<span class="line"><span style="color: #d8dee9ff">        at io.quarkus.runner.ApplicationImpl.doStart(Unknown Source)</span></span>
<span class="line"><span style="color: #d8dee9ff">        at io.quarkus.runtime.Application.start(Application.java:101)</span></span>
<span class="line"><span style="color: #d8dee9ff">        at io.quarkus.runtime.ApplicationLifecycleManager.run(ApplicationLifecycleManager.java:119)</span></span>
<span class="line"><span style="color: #d8dee9ff">        at io.quarkus.runtime.Quarkus.run(Quarkus.java:71)</span></span>
<span class="line"><span style="color: #d8dee9ff">        at io.quarkus.runtime.Quarkus.run(Quarkus.java:44)</span></span>
<span class="line"><span style="color: #d8dee9ff">        at io.quarkus.runtime.Quarkus.run(Quarkus.java:124)</span></span>
<span class="line"><span style="color: #d8dee9ff">        at io.quarkus.runner.GeneratedMain.main(Unknown Source)</span></span>
<span class="line"><span style="color: #d8dee9ff">        at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)</span></span>
<span class="line"><span style="color: #d8dee9ff">        at java.base/java.lang.reflect.Method.invoke(Method.java:580)</span></span>
<span class="line"><span style="color: #d8dee9ff">        at io.quarkus.runner.bootstrap.StartupActionImpl$1.run(StartupActionImpl.java:116)</span></span>
<span class="line"><span style="color: #d8dee9ff">        at java.base/java.lang.Thread.run(Thread.java:1583)</span></span>
<span class="line"><span style="color: #d8dee9ff">Caused by: java.lang.IllegalStateException: Invalid PEM trusted certificates configuration for certificate &#39;https&#39; - cannot read the PEM certificate files</span></span>
<span class="line"><span style="color: #d8dee9ff">        at io.quarkus.tls.runtime.keystores.PemKeyStores.verifyPEMTrustStoreStore(PemKeyStores.java:49)</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Plaintext</span></div>



<p>Console 24 - Errore di avvio dell'applicazione Quarkus a causa di un file PEM non valido</p>



<p>Per riuscire a far partire l'applicazione Quarkus sul nostro ambiente di sviluppo, le strade sono due:</p>



<ol class="wp-block-list">
<li>creare un file PEM (<code>tsl-it_bundle.pem</code>) con almeno un certificato valido all'interno della directory <code>/tmp/tsl-it</code> prima di avviare l'applicazione Quarkus;</li>



<li>creare il file <code>tsl-it_bundle.pem</code> contenente i certificati validi estratti dal TSL Italiano all'interno della directory <code>/tmp/tsl-it</code> prima di avviare l'applicazione Quarkus.</li>
</ol>



<p>Indubbiamente la prima strada è la più semplice e veloce da percorrere, mentre la seconda richiede più di lavoro.</p>



<p>Seguendo la prima strada dovremmo attendere l'esecuzione del task finché porti a compimento l'aggiornamento del TSL per ottenere il bundle PEM con i certificati validi, per poi attendere il reload del TLS Registry di Quarkus (vedi <code>quarkus.tls.https.reload-period</code>). Il vantaggio della seconda strada è che all'avvio dell'applicazione Quarkus avremo già il bundle PEM con i certificati validi estratti dal TSL Italiano e il TLS sarà configurato correttamente.</p>



<p>In ogni caso, una volta che l'applicazione Quarkus sarà partita, il task periodico di aggiornamento del TSL si occuperà di aggiornare il file PEM con i certificati validi estratti dal TSL Italiano. Direi di seguire entrambe le strade e verificare così la differenza di comportamento.</p>



<p>La prima strada prevede di creare un file PEM con almeno un certificato di CA. Eseguendo dalla home del progetto lo script shell <code>./src/main/shell/certs-manager/download_tsl_it_certs.sh --fake</code>, genereremo un file PEM con un certificato di CA fake. A seguire l'output dello script shell.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="&#x1f680; Starting certificate update process
&#x1f510; Generating fake CA certificate
.+.....+.+...+...+..+++++++++++++++++++++++++++++++++++++++*.+.....................+..+..........+..+............+...............+...+...+....+......+..+......+++++++++++++++++++++++++++++++++++++++*...+....+...+...........+....+......+..+.............+..+...+....+.....+.+...............+....................+.+..................+..+....+.....+.........+.+..+.........+...+...+...+....+...........+....+......+.....+.........+.......+...+...+.........+......+.....+...+......+...+.+......+...+..+...+...............+.............+...+.....+.+...........+....+........+............+......+...+....+.................+...+.+......+...+...+........+....+...+..............+....+.....+.+...............+.....+....+..............+............+......+.......+......+...........+.........+............+....+.....+.+.....+...+......+......+...+.........+.+.....................+...+.....+.......+.....+.+..+.............+..+............+......+....+.........++++++
...+..+.+.........+........+.+.........+++++++++++++++++++++++++++++++++++++++*.........+.+..+...+......+.+...+++++++++++++++++++++++++++++++++++++++*...++++++
&#x2705; Generated fake CA certificate at /tmp/tsl-it/fake_ca.pem
&#x2705; Added fake CA certificate to PEM bundle" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">&#x1f680;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Starting</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">certificate</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">update</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">process</span></span>
<span class="line"><span style="color: #88C0D0">&#x1f510;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Generating</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">fake</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">CA</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">certificate</span></span>
<span class="line"><span style="color: #88C0D0">.</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.....</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">...</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">...</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">..</span><span style="color: #D8DEE9FF">+++++++++++++++++++++++++++++++++++++++*</span><span style="color: #88C0D0">.</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.....................</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">..</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">..........</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">..</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">............</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">...............</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">...</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">...</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">....</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">......</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">..</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">......</span><span style="color: #D8DEE9FF">+++++++++++++++++++++++++++++++++++++++*</span><span style="color: #88C0D0">...</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">....</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">...</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">...........</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">....</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">......</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">..</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.............</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">..</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">...</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">....</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.....</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">...............</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">....................</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">..................</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">..</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">....</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.....</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.........</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">..</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.........</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">...</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">...</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">...</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">....</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">...........</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">....</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">......</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.....</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.........</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.......</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">...</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">...</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.........</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">......</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.....</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">...</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">......</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">...</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">......</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">...</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">..</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">...</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">...............</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.............</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">...</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.....</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">...........</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">....</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">........</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">............</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">......</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">...</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">....</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.................</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">...</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">......</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">...</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">...</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">........</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">....</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">...</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">..............</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">....</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.....</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">...............</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.....</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">....</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">..............</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">............</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">......</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.......</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">......</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">...........</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.........</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">............</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">....</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.....</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.....</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">...</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">......</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">......</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">...</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.........</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.....................</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">...</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.....</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.......</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.....</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">..</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.............</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">..</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">............</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">......</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">....</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.........</span><span style="color: #D8DEE9FF">++++++</span></span>
<span class="line"><span style="color: #88C0D0">...</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">..</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.........</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">........</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.........</span><span style="color: #D8DEE9FF">+++++++++++++++++++++++++++++++++++++++*</span><span style="color: #88C0D0">.........</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">..</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">...</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">......</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">.</span><span style="color: #D8DEE9FF">+</span><span style="color: #88C0D0">...</span><span style="color: #D8DEE9FF">+++++++++++++++++++++++++++++++++++++++*</span><span style="color: #88C0D0">...</span><span style="color: #D8DEE9FF">++++++</span></span>
<span class="line"><span style="color: #88C0D0">&#x2705;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Generated</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">fake</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">CA</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">certificate</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">at</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/tmp/tsl-it/fake_ca.pem</span></span>
<span class="line"><span style="color: #88C0D0">&#x2705;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Added</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">fake</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">CA</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">certificate</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">to</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">PEM</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">bundle</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Bash</span></div>



<p>Console 25 - Esecuzione dello script shell per la generazione di un file PEM con un certificato di CA fake</p>



<p>Una volta ottenuto il file <code>/tmp/tsl-it/fake_ca.pem</code> lo rinominiamo in <code>tsl-it_bundle.pem</code> e avviamo l'applicazione Quarkus con il comando <code>quarkus dev</code>. L'applicazione Quarkus dovrebbe partire senza problemi, ed eseguendo il comando <code>openssl s_client -connect localhost:8443 -showcerts</code>, dovremmo vedere nella lista degli <strong>Acceptable client certificate CA names</strong> il certificato di CA fake (con subject <code>C=US, ST=California, L=San Francisco, O=Fake Identity Corp, OU=IT Department, CN=Faked Identity Corp Root CA</code>) che abbiamo generato, così come mostrato di seguito da un estratto dell'output del comando.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="Connecting to 127.0.0.1
CONNECTED(00000005)
Can't use SSL_get_servername
depth=0 C=IT, ST=Catania, L=Bronte, O=Dontesta, OU=IT Labs, CN=rd.quarkus.dontesta.it
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 C=IT, ST=Catania, L=Bronte, O=Dontesta, OU=IT Labs, CN=rd.quarkus.dontesta.it
verify error:num=21:unable to verify the first certificate
verify return:1
depth=0 C=IT, ST=Catania, L=Bronte, O=Dontesta, OU=IT Labs, CN=rd.quarkus.dontesta.it
verify return:1

Server certificate
subject=C=IT, ST=Catania, L=Bronte, O=Dontesta, OU=IT Labs, CN=rd.quarkus.dontesta.it
issuer=C=IT, ST=Catania, L=Bronte, O=Dontesta, OU=IT Labs, CN=Dontesta CA

Certificate chain
 0 s:C=IT, ST=Catania, L=Bronte, O=Dontesta, OU=IT Labs, CN=rd.quarkus.dontesta.it
   i:C=IT, ST=Catania, L=Bronte, O=Dontesta, OU=IT Labs, CN=Dontesta CA
   a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA256
   v:NotBefore: Sep  6 22:16:21 2024 GMT; NotAfter: Sep  6 22:16:21 2025 GMT

Acceptable client certificate CA names
C=IT, O=Actalis S.p.A., OU=Servizi di Certificazione, CN=Regione Molise - CA Cittadini 2020
C=IT, O=Telecom Italia Trust Technologies S.r.l., OU=Servizi di certificazione, CN=TI Trust Technologies per il Ministero dell'Interno CA
C=IT, O=InfoCert S.p.A., OU=Servizi di Certificazione, CN=Regione Basilicata - CA Cittadini
C=IT, O=InfoCert S.p.A., OU=Trust Service Provider, organizationIdentifier=VATIT-07945211006, CN=InfoCert Certification Services CA 3
C=IT, O=Poste Italiane S.p.A., OU=Servizi di Certificazione, CN=Regione Siciliana - CA Cittadini
C=IT, O=Actalis S.p.A., OU=Servizi di Certificazione, CN=Regione Umbria - CA Cittadini
C=IT, O=InfoCert S.p.A., OU=Servizi di Certificazione, CN=Regione Marche - CA Cittadini
C=IT, L=Ponte San Pietro, O=ArubaPEC S.p.A., organizationIdentifier=VATIT-01879020517, OU=Trust Service Provider, CN=ArubaPEC EU Authentication Certificates CA G1" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #d8dee9ff">Connecting to 127.0.0.1</span></span>
<span class="line"><span style="color: #d8dee9ff">CONNECTED(00000005)</span></span>
<span class="line"><span style="color: #d8dee9ff">Can&#39;t use SSL_get_servername</span></span>
<span class="line"><span style="color: #d8dee9ff">depth=0 C=IT, ST=Catania, L=Bronte, O=Dontesta, OU=IT Labs, CN=rd.quarkus.dontesta.it</span></span>
<span class="line"><span style="color: #d8dee9ff">verify error:num=20:unable to get local issuer certificate</span></span>
<span class="line"><span style="color: #d8dee9ff">verify return:1</span></span>
<span class="line"><span style="color: #d8dee9ff">depth=0 C=IT, ST=Catania, L=Bronte, O=Dontesta, OU=IT Labs, CN=rd.quarkus.dontesta.it</span></span>
<span class="line"><span style="color: #d8dee9ff">verify error:num=21:unable to verify the first certificate</span></span>
<span class="line"><span style="color: #d8dee9ff">verify return:1</span></span>
<span class="line"><span style="color: #d8dee9ff">depth=0 C=IT, ST=Catania, L=Bronte, O=Dontesta, OU=IT Labs, CN=rd.quarkus.dontesta.it</span></span>
<span class="line"><span style="color: #d8dee9ff">verify return:1</span></span>
<span class="line"><span style="color: #d8dee9ff"></span></span>
<span class="line"><span style="color: #d8dee9ff">Server certificate</span></span>
<span class="line"><span style="color: #d8dee9ff">subject=C=IT, ST=Catania, L=Bronte, O=Dontesta, OU=IT Labs, CN=rd.quarkus.dontesta.it</span></span>
<span class="line"><span style="color: #d8dee9ff">issuer=C=IT, ST=Catania, L=Bronte, O=Dontesta, OU=IT Labs, CN=Dontesta CA</span></span>
<span class="line"><span style="color: #d8dee9ff"></span></span>
<span class="line"><span style="color: #d8dee9ff">Certificate chain</span></span>
<span class="line"><span style="color: #d8dee9ff"> 0 s:C=IT, ST=Catania, L=Bronte, O=Dontesta, OU=IT Labs, CN=rd.quarkus.dontesta.it</span></span>
<span class="line"><span style="color: #d8dee9ff">   i:C=IT, ST=Catania, L=Bronte, O=Dontesta, OU=IT Labs, CN=Dontesta CA</span></span>
<span class="line"><span style="color: #d8dee9ff">   a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA256</span></span>
<span class="line"><span style="color: #d8dee9ff">   v:NotBefore: Sep  6 22:16:21 2024 GMT; NotAfter: Sep  6 22:16:21 2025 GMT</span></span>
<span class="line"><span style="color: #d8dee9ff"></span></span>
<span class="line"><span style="color: #d8dee9ff">Acceptable client certificate CA names</span></span>
<span class="line"><span style="color: #d8dee9ff">C=IT, O=Actalis S.p.A., OU=Servizi di Certificazione, CN=Regione Molise - CA Cittadini 2020</span></span>
<span class="line"><span style="color: #d8dee9ff">C=IT, O=Telecom Italia Trust Technologies S.r.l., OU=Servizi di certificazione, CN=TI Trust Technologies per il Ministero dell&#39;Interno CA</span></span>
<span class="line"><span style="color: #d8dee9ff">C=IT, O=InfoCert S.p.A., OU=Servizi di Certificazione, CN=Regione Basilicata - CA Cittadini</span></span>
<span class="line"><span style="color: #d8dee9ff">C=IT, O=InfoCert S.p.A., OU=Trust Service Provider, organizationIdentifier=VATIT-07945211006, CN=InfoCert Certification Services CA 3</span></span>
<span class="line"><span style="color: #d8dee9ff">C=IT, O=Poste Italiane S.p.A., OU=Servizi di Certificazione, CN=Regione Siciliana - CA Cittadini</span></span>
<span class="line"><span style="color: #d8dee9ff">C=IT, O=Actalis S.p.A., OU=Servizi di Certificazione, CN=Regione Umbria - CA Cittadini</span></span>
<span class="line"><span style="color: #d8dee9ff">C=IT, O=InfoCert S.p.A., OU=Servizi di Certificazione, CN=Regione Marche - CA Cittadini</span></span>
<span class="line"><span style="color: #d8dee9ff">C=IT, L=Ponte San Pietro, O=ArubaPEC S.p.A., organizationIdentifier=VATIT-01879020517, OU=Trust Service Provider, CN=ArubaPEC EU Authentication Certificates CA G1</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Plaintext</span></div>



<p>Console 27 - Output del comando <code>openssl s_client -connect localhost:8443 -showcerts</code></p>



<p>Seguendo la prima strada del certificato di CA fake, abbiamo avuto modo di appurare come la nostra implementazione dell'integrazione del TSL e la configurazione del TLS Registry di Quarkus funzionino correttamente e come atteso. Ora possiamo passare alla seconda strada, ovvero, quella di creare il file <code>tsl-it_bundle.pem</code> con i certificati validi estratti dal TSL prima di avviare l'applicazione Quarkus.</p>



<p>Per generare quindi il file <code>tsl-it_bundle.pem</code> con i certificati validi estratti dal TSL, eseguiremo lo script shell <code>./src/main/shell/certs-manager/download_tsl_it_certs.sh</code> che si occuperà di scaricare il file XML del TSL, estrarre i certificati validi e salvarli in formato PEM (bundle) all'interno della directory <code>/tmp/tsl-it</code>. Prima di eseguire lo script, dovreste accertare che l'applicazione Quarkus non sia attiva. A seguire un estratto di esecuzione dello script shell.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="&#x1f680; Starting certificate update process
&#x2705; Downloaded XML content
&#x1f4be; Saving XML content to file: /tmp/tsl-it.xml
&#x2705; Saved XML content to /tmp/tsl-it.xml
&#x1f50d; Parsing and saving certificates
&#x1f9f9; Cleaning output path: /tmp/tsl-it
&#x2705; Cleaned output path: /tmp/tsl-it
**** Retrieving: /tmp/tsl-it.xml ****
**** Processing: /tmp/tsl-it.xml ****
&#x1f4be; Saving certificate as PEM
Certificate will not expire
&#x2705; Saved certificate to /tmp/tsl-it/b43852d091d7d0ecd4bd473286dc82e5ba1f24f9d82ac2b6d0fae39e5c38637f.pem
&#x1f50d; Certificate subject: subject=C=IT, O=INFOCERT SPA, OU=Ente Certificatore, serialNumber=07945211006, CN=InfoCert Servizi di Certificazione 2
&#x1f4be; Saving certificate as PEM
Certificate will not expire
&#x2705; Saved certificate to /tmp/tsl-it/1b944bedf3d946bb0f8b889b6fa5130a152668e1d73ea253c334d8ea392c773b.pem
&#x1f50d; Certificate subject: subject=C=IT, O=InfoCert S.p.A., OU=Servizi di Certificazione, CN=Provincia Autonoma di Bolzano - CA Cittadini
&#x1f4be; Saving certificate as PEM
Certificate will not expire
Certificate will expire
&#x274c; Certificate subject=C=IT, O=Postecom S.p.A., OU=Servizi di Certificazione, CN=Regione Marche - CA Cittadini is expired or not yet valid. Removing /tmp/tsl-it/b70ad3ec6f408fb3e3f42f22c0e0e654893204fa0401052e96932b5f192539d8.pem
&#x1f3c1; Processed 138 certificates
&#x1f3c1; Expired certificates: 31
&#x1f4e6; Creating PEM bundle
&#x2705; Created PEM bundle at /tmp/tsl-it/tsl-it_bundle.pem
&#x1f3c1; Certificate update process completed" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">&#x1f680;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Starting</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">certificate</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">update</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">process</span></span>
<span class="line"><span style="color: #88C0D0">&#x2705;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Downloaded</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">XML</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">content</span></span>
<span class="line"><span style="color: #88C0D0">&#x1f4be;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Saving</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">XML</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">content</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">to</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">file:</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/tmp/tsl-it.xml</span></span>
<span class="line"><span style="color: #88C0D0">&#x2705;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Saved</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">XML</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">content</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">to</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/tmp/tsl-it.xml</span></span>
<span class="line"><span style="color: #88C0D0">&#x1f50d;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Parsing</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">and</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">saving</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">certificates</span></span>
<span class="line"><span style="color: #88C0D0">&#x1f9f9;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Cleaning</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">output</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">path:</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/tmp/tsl-it</span></span>
<span class="line"><span style="color: #88C0D0">&#x2705;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Cleaned</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">output</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">path:</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/tmp/tsl-it</span></span>
<span class="line"><span style="color: #81A1C1">****</span><span style="color: #D8DEE9FF"> Retrieving: /tmp/tsl-it.xml </span><span style="color: #81A1C1">****</span></span>
<span class="line"><span style="color: #81A1C1">****</span><span style="color: #D8DEE9FF"> Processing: /tmp/tsl-it.xml </span><span style="color: #81A1C1">****</span></span>
<span class="line"><span style="color: #88C0D0">&#x1f4be;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Saving</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">certificate</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">as</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">PEM</span></span>
<span class="line"><span style="color: #88C0D0">Certificate</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">will</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">not</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">expire</span></span>
<span class="line"><span style="color: #88C0D0">&#x2705;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Saved</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">certificate</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">to</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/tmp/tsl-it/b43852d091d7d0ecd4bd473286dc82e5ba1f24f9d82ac2b6d0fae39e5c38637f.pem</span></span>
<span class="line"><span style="color: #88C0D0">&#x1f50d;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Certificate</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">subject:</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">subject=C=IT,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">O=INFOCERT</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">SPA,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">OU=Ente</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Certificatore,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">serialNumber=</span><span style="color: #B48EAD">07945211006</span><span style="color: #A3BE8C">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">CN=InfoCert</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Servizi</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">di</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Certificazione</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">2</span></span>
<span class="line"><span style="color: #88C0D0">&#x1f4be;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Saving</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">certificate</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">as</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">PEM</span></span>
<span class="line"><span style="color: #88C0D0">Certificate</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">will</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">not</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">expire</span></span>
<span class="line"><span style="color: #88C0D0">&#x2705;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Saved</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">certificate</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">to</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/tmp/tsl-it/1b944bedf3d946bb0f8b889b6fa5130a152668e1d73ea253c334d8ea392c773b.pem</span></span>
<span class="line"><span style="color: #88C0D0">&#x1f50d;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Certificate</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">subject:</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">subject=C=IT,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">O=InfoCert</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">S.p.A.,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">OU=Servizi</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">di</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Certificazione,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">CN=Provincia</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Autonoma</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">di</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Bolzano</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">CA</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Cittadini</span></span>
<span class="line"><span style="color: #88C0D0">&#x1f4be;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Saving</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">certificate</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">as</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">PEM</span></span>
<span class="line"><span style="color: #88C0D0">Certificate</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">will</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">not</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">expire</span></span>
<span class="line"><span style="color: #88C0D0">Certificate</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">will</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">expire</span></span>
<span class="line"><span style="color: #88C0D0">&#x274c;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Certificate</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">subject=C=IT,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">O=Postecom</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">S.p.A.,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">OU=Servizi</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">di</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Certificazione,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">CN=Regione</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Marche</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">CA</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Cittadini</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">is</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">expired</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">or</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">not</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">yet</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">valid.</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Removing</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/tmp/tsl-it/b70ad3ec6f408fb3e3f42f22c0e0e654893204fa0401052e96932b5f192539d8.pem</span></span>
<span class="line"><span style="color: #88C0D0">&#x1f3c1;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Processed</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">138</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">certificates</span></span>
<span class="line"><span style="color: #88C0D0">&#x1f3c1;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Expired</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">certificates:</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">31</span></span>
<span class="line"><span style="color: #88C0D0">&#x1f4e6;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Creating</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">PEM</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">bundle</span></span>
<span class="line"><span style="color: #88C0D0">&#x2705;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Created</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">PEM</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">bundle</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">at</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/tmp/tsl-it/tsl-it_bundle.pem</span></span>
<span class="line"><span style="color: #88C0D0">&#x1f3c1;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Certificate</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">update</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">process</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">completed</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative">Bash</span></div>



<p>Console 25 - Esecuzione dello script shell per l'aggiornamento del file <code>tsl-it_bundle.pem</code></p>



<p>Ottimo! Abbiamo generato il file <code>tsl-it_bundle.pem</code> con i certificati validi estratti dal TSL. Ora possiamo avviare l'applicazione Quarkus con il comando <code>quarkus dev</code> e verificare che il TLS Registry di Quarkus sia stato ricaricato con i certificati validi estratti dal TSL. Eseguendo il comando <code>openssl s_client -connect localhost:8443 -showcerts</code>, dovreste vedere nella lista degli <strong>Acceptable client certificate CA names</strong> i certificati validi estratti dal TSL, così come atteso.</p>



<p>Adesso la nostra applicazione Quarkus è potenzialmente pronta per accettare client che si vogliano per esempio autenticare tramite CIE o CNS. Potenzialmente, perché l'attuale implementazione andrebbe estesa per garantire l'accesso ai servizi REST ma questo è un esercizio che lascio a voi.</p>



<h3 class="wp-block-heading" id="test-di-accesso-con-la-ts-cns">Test di accesso con la TS-CNS</h3>



<p>Adesso che abbiamo integrato il TSL nel nostro progetto Quarkus, dovremmo essere nelle condizioni di poter accedere alla Dev Console di Quarkus utilizzando per esempio la TS-CNS. Questo test ci permetterà di verificare che il TLS sia configurato correttamente e che il server sia in grado di autenticare il client.</p>



<p>Il comportamento atteso è che l'accesso alla Dev Console di Quarkus avvenga senza alcun problema dopo avere inserito il PIN della TS-CNS mentre l'accesso ai servizi REST dovrebbe fallire perché il certificato client della TS-CNS non rispetta i requisiti che abbiamo imposto per i certificati client (vedi tabella sui requisiti dei certificati client).</p>



<p>Per eseguire il test diamo per scontato che la macchina su cui eseguirete il test abbia installato e configurato correttamente un lettore di smart card compatibile con la vostra TS-CNS e che il browser utilizzato sia compatibile e configurato per l'uso della smart card.</p>



<p>Il test può essere eseguito in due modi, uno semplice e uno più avanzato.</p>



<ol class="wp-block-list">
<li>dopo aver collegato il lettore di smart card e inserita la TS-CNS, puntando il browser sull'indirizzo <code>https://localhost:8443/q/dev/</code>, il comportamento atteso è che sia visualizzato il pop-up per l'inserimento del PIN, successivamente visulizzato il pop-up per la selezione e conferma del certificato client e infine la Dev Console di Quarkus;</li>



<li>utilizzando cURL avendo cura di istruire il comando curl a utilizzare il certificato client presente all'interno della TS-CNS. Per questo test vi rimando al video <a href="https://www.youtube.com/watch?v=N-IJeuN1oyE">Autenticazione con la TS-CNS: come usarla in modalità batch</a>.</li>
</ol>



<p>A seguire le immagine del pop-up per l'inserimento del PIN della TS-CNS, del pop-up per la selezione del certificato client e della Dev Console di Quarkus.</p>


<div class="wp-block-image">
<figure class="aligncenter size-large is-resized"><img width="940" height="940" decoding="async" loading="lazy" src="https://www.dontesta.it/wp-content/uploads/2024/09/request-smart-card-ts-cns-pin-edited.png" alt="" class="wp-image-5777" style="width:1212px;height:auto" srcset="https://www.dontesta.it/wp-content/uploads/2024/09/request-smart-card-ts-cns-pin-edited.png 940w, https://www.dontesta.it/wp-content/uploads/2024/09/request-smart-card-ts-cns-pin-edited-300x300.png 300w, https://www.dontesta.it/wp-content/uploads/2024/09/request-smart-card-ts-cns-pin-edited-150x150.png 150w, https://www.dontesta.it/wp-content/uploads/2024/09/request-smart-card-ts-cns-pin-edited-768x768.png 768w, https://www.dontesta.it/wp-content/uploads/2024/09/request-smart-card-ts-cns-pin-edited-80x80.png 80w, https://www.dontesta.it/wp-content/uploads/2024/09/request-smart-card-ts-cns-pin-edited-320x320.png 320w, https://www.dontesta.it/wp-content/uploads/2024/09/request-smart-card-ts-cns-pin-edited-65x65.png 65w" sizes="auto, (max-width: 940px) 100vw, 940px" /><figcaption class="wp-element-caption">Figura 14 - Pop-up per l'inserimento del PIN della TS-CNS</figcaption></figure>
</div>


<p></p>


<div class="wp-block-image">
<figure class="aligncenter size-large"><img width="1024" height="644" decoding="async" loading="lazy" src="https://www.dontesta.it/wp-content/uploads/2024/09/request-smart-card-ts-cns-select-certificate-1024x644.png" alt="" class="wp-image-5773" srcset="https://www.dontesta.it/wp-content/uploads/2024/09/request-smart-card-ts-cns-select-certificate-1024x644.png 1024w, https://www.dontesta.it/wp-content/uploads/2024/09/request-smart-card-ts-cns-select-certificate-300x189.png 300w, https://www.dontesta.it/wp-content/uploads/2024/09/request-smart-card-ts-cns-select-certificate-768x483.png 768w, https://www.dontesta.it/wp-content/uploads/2024/09/request-smart-card-ts-cns-select-certificate-1536x967.png 1536w, https://www.dontesta.it/wp-content/uploads/2024/09/request-smart-card-ts-cns-select-certificate.png 1948w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">Figura 15 - Pop-up per la selezione del certificato client</figcaption></figure>
</div>


<p></p>


<div class="wp-block-image">
<figure class="aligncenter size-large"><img width="1024" height="812" decoding="async" loading="lazy" src="https://www.dontesta.it/wp-content/uploads/2024/09/quarkus-dev-console-1024x812.png" alt="" class="wp-image-5774" srcset="https://www.dontesta.it/wp-content/uploads/2024/09/quarkus-dev-console-1024x812.png 1024w, https://www.dontesta.it/wp-content/uploads/2024/09/quarkus-dev-console-300x238.png 300w, https://www.dontesta.it/wp-content/uploads/2024/09/quarkus-dev-console-768x609.png 768w, https://www.dontesta.it/wp-content/uploads/2024/09/quarkus-dev-console-1536x1218.png 1536w, https://www.dontesta.it/wp-content/uploads/2024/09/quarkus-dev-console-2048x1625.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">Figura 16 - Dev Console di Quarkus</figcaption></figure>
</div>


<p></p>



<p>Ottimo! Abbiamo ottenuto il risultato atteso.
Accedendo al servizio REST <a href="https://localhost:8443/api/v1/connection-info/user-identity">https://localhost:8443/api/v1/connection-info/user-identity</a> dovremmo ottenere l'accesso negato al servizio in virtù del fatto che il certificato della TS-CNS non rispetta i requisiti imposti dalla nostra implementazione.</p>


<div class="wp-block-image">
<figure class="aligncenter size-large"><img width="1024" height="92" decoding="async" loading="lazy" src="https://www.dontesta.it/wp-content/uploads/2024/09/errore-accesso-servizio-rest-via-ts-cns-1024x92.png" alt="" class="wp-image-5775" srcset="https://www.dontesta.it/wp-content/uploads/2024/09/errore-accesso-servizio-rest-via-ts-cns-1024x92.png 1024w, https://www.dontesta.it/wp-content/uploads/2024/09/errore-accesso-servizio-rest-via-ts-cns-300x27.png 300w, https://www.dontesta.it/wp-content/uploads/2024/09/errore-accesso-servizio-rest-via-ts-cns-768x69.png 768w, https://www.dontesta.it/wp-content/uploads/2024/09/errore-accesso-servizio-rest-via-ts-cns-1536x138.png 1536w, https://www.dontesta.it/wp-content/uploads/2024/09/errore-accesso-servizio-rest-via-ts-cns-2048x184.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">Figura 17 - Accesso negato al servizio REST</figcaption></figure>
</div>


<p></p>



<p>Come ho scritto in precedenza, l'estensione dell'implementazione per supportare i certificati digitali della TS-CNS o CIE è un esercizio che lascio a voi.</p>



<h2 class="wp-block-heading" id="risorse">Risorse</h2>



<ul class="wp-block-list">
<li>[1] <a href="https://www.dontesta.it/2020/02/25/liferay-7-2-esempio-di-two-way-ssl-tls-mutual-authentication-client/">Antonio Musarra's Blog - Liferay 7.2: Esempio di Two-Way SSL/TLS Mutual Authentication Client</a></li>



<li>[2] <a href="https://www.dontesta.it/2020/02/04/docker-image-apache-ssl-tls-mutual-authentication-on-azure-cloud/">Antonio Musarra's Blog - Docker Image Apache SSL/TLS Mutual Authentication on Azure Cloud</a></li>



<li>[3] <a href="https://www.dontesta.it/2020/01/26/cose-il-progetto-cie-cns-apache-docker/">Antonio Musarra's Blog - Cos’è il progetto CIE/CNS Apache Docker</a></li>



<li>[4] <a href="https://theredcode.it/devops/differenze-tra-keystore-e-truststore/">theRedCode - Differenze tra keystore e truststore</a></li>



<li>[5] <a href="https://theredcode.it/devops/self-signed-certificati-openssl/">theRedCode - Certificati Self-Signed e OpenSSL</a></li>



<li>[4] <a href="https://github.com/italia/cie-cns-apache-docker">GitHub - CIE/CNS Apache Docker</a></li>



<li>[5] <a href="https://github.com/amusarra/docker-apache-ssl-tls-mutual-authentication">GitHub - Docker Apache SSL/TLS Mutual Authentication</a></li>



<li>[6] <a href="https://github.com/smclab/cie-cns-auth-token-sso">GitHub - CIE/CNS Auth Token SSO</a></li>



<li>[7] <a href="https://www.youtube.com/watch?v=N-IJeuN1oyE">Video - Autenticazione con la TS-CNS: come usarla in modalità batch</a></li>



<li>[8] <a href="https://www.youtube.com/watch?v=TcAzn1POhsM">Video - Cos'è il progetto CIE/CNS Apache Docker - Developers Italia</a></li>



<li>[9] <a href="https://www.slideshare.net/slideshow/liferay-ssltls-security-come-configurare-il-bundle-liferay-per-funzionare-in-modalit-sicura-tramite-il-protocollo-ssltls/151608797">eBook - Liferay SSL/TLS Security. Come configurare il bundle Liferay per abilitare il protocollo SSL/TLS</a></li>



<li>[10] <a href="https://amzn.to/47uFKOg">Book - Implementing SSL/TLS</a></li>



<li>[11] <a href="https://amzn.to/3zoGSGE">Book - Network Security with OpenSSL</a></li>
</ul>



<h2 class="wp-block-heading" id="considerazioni-finali">Considerazioni finali</h2>



<p>Wow! Abbiamo fatto un bel percorso.</p>



<p>L’implementazione di TLS Mutual Authentication (mTLS) utilizzando il framework Quarkus rappresenta un passo cruciale per garantire comunicazioni sicure e affidabili tra client e server. Il protocollo TLS, che cifra i dati trasmessi, viene potenziato con l’introduzione di mTLS, permettendo la doppia autenticazione tramite l’uso di certificati sia da parte del client che del server.</p>



<p>Un elemento fondamentale per la corretta gestione dei certificati e della fiducia tra le parti è la Trusted Service List (TSL), che fornisce un elenco di servizi e certificati fidati approvati da autorità di certificazione riconosciute. Nel contesto dell’implementazione di mTLS, l’uso di una TSL permette di garantire che solo i certificati verificati e conformi agli standard di sicurezza possano essere utilizzati, migliorando ulteriormente l’affidabilità del sistema.</p>



<p>Quarkus, con la sua capacità di integrarsi facilmente con mTLS e la gestione di certificati validati tramite TSL, fornisce una piattaforma sicura e scalabile per applicazioni cloud-native. Questo approccio consente di proteggere le comunicazioni, stabilire fiducia reciproca tra client e server e mantenere elevati livelli di sicurezza per le applicazioni distribuite.</p>



<p>In conclusione, l’integrazione di TLS, mTLS e TSL rappresenta una soluzione completa per chi desidera implementare elevati standard di sicurezza nelle proprie applicazioni. Con Quarkus, con una manciata di configurazioni e poche righe di codice, è possibile raggiungere questi obiettivi in maniera efficiente, bilanciando prestazioni e sicurezza.</p>
<p>L'articolo <a href="https://www.dontesta.it/2024/09/19/implementazione-tls-mutual-authentication-mtls-con-quarkus/">Implementazione di TLS Mutual Authentication (mTLS) con Quarkus</a> sembra essere il primo su <a href="https://www.dontesta.it">Antonio Musarra&#039;s Blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.dontesta.it/2024/09/19/implementazione-tls-mutual-authentication-mtls-con-quarkus/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Cosa sono i modelli di licenza multipli nel software?</title>
		<link>https://www.dontesta.it/2024/08/21/cosa-sono-i-modelli-di-licenza-multipli-nel-software/</link>
					<comments>https://www.dontesta.it/2024/08/21/cosa-sono-i-modelli-di-licenza-multipli-nel-software/#respond</comments>
		
		<dc:creator><![CDATA[Antonio Musarra]]></dc:creator>
		<pubDate>Wed, 21 Aug 2024 07:15:48 +0000</pubDate>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Editoria]]></category>
		<category><![CDATA[Open Source]]></category>
		<guid isPermaLink="false">https://www.dontesta.it/?p=5726</guid>

					<description><![CDATA[<p>Nel mondo del software, la scelta di una licenza rappresenta un passaggio cruciale nello sviluppo e nella distribuzione di un prodotto. Tuttavia, in alcuni casi, gli sviluppatori decidono di adottare un approccio più flessibile,&#46;&#46;&#46;</p>
<p>L'articolo <a href="https://www.dontesta.it/2024/08/21/cosa-sono-i-modelli-di-licenza-multipli-nel-software/">Cosa sono i modelli di licenza multipli nel software?</a> sembra essere il primo su <a href="https://www.dontesta.it">Antonio Musarra&#039;s Blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="p1">Nel mondo del software, la scelta di una licenza rappresenta un passaggio cruciale nello sviluppo e nella distribuzione di un prodotto. Tuttavia, in alcuni casi, gli sviluppatori decidono di adottare un approccio più flessibile, optando per modelli di licenza multipli. Questa strategia permette al software di essere distribuito sotto diverse licenze, a seconda delle esigenze dell’utente o del contesto di utilizzo. </p>



<p>A settembre del 2023 ho deciso di archiviare il progetto <a href="https://github.com/amusarra/liferay-portal-database-all-in-one-support">liferay-portal-database-all-in-one-support</a> e uno dei motivi principali che ha spinto questa mia azione riguardava proprio l'adozione dei modelli di licenza multipli da parte del progetto <a href="https://github.com/liferay/liferay-portal">Liferay Portal</a>.</p>



<p class="p1">In questo articolo esploreremo quali sono gli aspetti essenziali dei modelli di licenza multipli, il loro funzionamento, i vantaggi e gli svantaggi, nonché alcuni casi d’uso reali.</p>



<p></p>



<h2 class="wp-block-heading">Cosa sono?</h2>



<p class="wp-block-heading"><br>I modelli di licenza multipli si riferiscono alla pratica di rilasciare un software sotto più di una licenza. Questo significa che gli utenti o le aziende possono scegliere tra diverse licenze, ognuna delle quali offre diritti e restrizioni diversi. Le ragioni per adottare un approccio del genere sono molteplici e spesso includono la volontà di massimizzare la diffusione del software, soddisfare le esigenze di diversi mercati, o rispondere a differenti contesti normativi e commerciali. </p>



<h2 class="wp-block-heading">Tipi di modelli di licenza multipli</h2>



<p>Esistono diverse configurazioni per i modelli di licenza multipli.</p>



<p>1. <strong>Dual Licensing</strong>: Questa è la forma più comune di licenza multipla. In un modello di licenza duale, il software viene rilasciato sotto due licenze distinte, una delle quali è spesso una licenza open-source, come la <a href="https://it.wikipedia.org/wiki/GNU_General_Public_License">GPL (General Public License)</a>, e l’altra è una licenza commerciale. Gli utenti possono scegliere di utilizzare il software secondo i termini della licenza open-source o di acquistare una licenza commerciale che offre vantaggi aggiuntivi, come l’assistenza tecnica o il diritto di creare software proprietario basato sul codice.</p>



<p>2. <strong>Licenza con Eccezione</strong>: Alcuni sviluppatori rilasciano il software sotto una licenza principale open-source, con delle eccezioni che permettono un utilizzo più ampio del codice. Ad esempio, un software potrebbe essere rilasciato sotto la GPL con un’eccezione che permette l’integrazione con software proprietari senza imporre la stessa licenza a quest’ultimo.</p>



<p>3. <strong>Licenza Tripla o Multipla</strong>: In questo modello, il software è rilasciato sotto tre o più licenze, offrendo una maggiore flessibilità. Ad esempio, un progetto potrebbe essere disponibile sotto la GPL, la <a href="https://it.wikipedia.org/wiki/GNU_Lesser_General_Public_License">LGPL (Lesser General Public License)</a> e una licenza commerciale, permettendo agli utenti di scegliere quella che meglio si adatta alle loro necessità.</p>



<h2 class="wp-block-heading">Vantaggi dei modelli di licenza multipli</h2>



<p>I modelli di licenza multipli offrono una serie di vantaggi sia per gli sviluppatori che per gli utenti.</p>



<p>1. <strong>Flessibilità</strong>: Gli sviluppatori possono soddisfare le esigenze di diversi utenti o mercati, aumentando il potenziale di adozione del software.</p>



<p>2. <strong>Monetizzazione</strong>: La combinazione di licenze open-source e commerciali permette agli sviluppatori di attrarre una vasta base di utenti, pur mantenendo la possibilità di monetizzare attraverso licenze commerciali.</p>



<p>3. <strong>Adozione da Parte delle Aziende</strong>: Molte aziende preferiscono utilizzare software con licenze commerciali per motivi di supporto e conformità legale. Offrire un’opzione commerciale può facilitare l’adozione da parte di queste aziende.</p>



<p>4. <strong>Contributo alla Comunità</strong>: L’uso di una licenza open-source consente alla comunità di contribuire al progetto, migliorando il software e beneficiando al contempo di un feedback più ampio.</p>



<h2 class="wp-block-heading">Svantaggi</h2>



<p class="wp-block-heading"> Nonostante i numerosi vantaggi, i modelli di licenza multipli non sono privi di critiche.</p>



<p>1. <strong>Confusione</strong>: L’esistenza di più licenze può creare confusione tra gli utenti, specialmente se non sono esperti in materia legale.</p>



<p>2. <strong>Complessità Legale</strong>: Gestire più licenze può comportare una maggiore complessità legale, sia per gli sviluppatori che per gli utenti, che devono assicurarsi di rispettare i termini di tutte le licenze applicabili.</p>



<p>3. <strong>Rischio di Forking</strong>: In alcuni casi, i modelli di licenza multipli possono incentivare la creazione di fork del software, in particolare se una parte della comunità non è d’accordo con le condizioni delle licenze commerciali.</p>



<p class="p1">I punti sopra indicati evidenziano come i modelli di licenza multipli, pur offrendo flessibilità e opportunità, possano anche introdurre sfide significative nella gestione e nell’adozione del software.</p>



<h2 class="wp-block-heading">Esempi di applicazione e note pratica</h2>



<p class="wp-block-heading">Alcuni dei più noti software che utilizzano modelli di licenza multipli includono:</p>



<p>• <strong>MySQL</strong>: Questo celebre sistema di gestione di database è stato rilasciato sotto la GPL, ma è disponibile anche con una licenza commerciale per coloro che desiderano incorporare il database in applicazioni proprietarie senza rilasciare il codice sorgente.</p>



<p>• <strong>Qt</strong>: La libreria Qt, utilizzata per lo sviluppo di interfacce grafiche, è disponibile sotto diverse licenze, inclusa una licenza GPL, LGPL, e una licenza commerciale.</p>



<p>• <strong>Mozilla Firefox</strong>: Anche se principalmente rilasciato sotto la <a href="https://www.mozilla.org/en-US/MPL/">MPL (Mozilla Public License)</a>, Firefox offre componenti disponibili sotto altre licenze, come la GPL e la LGPL, per favorire l’integrazione e l’utilizzo in vari contesti.</p>



<p>Prendendo in considerazione il progetto <a href="https://github.com/liferay/liferay-portal">Liferay Portal</a>, anch'esso fa uso dell'approccio dual-licensing di cui riporto un breve estratto dal file <a href="https://github.com/liferay/liferay-portal/blob/master/LICENSING.markdown" class="broken_link">LICENSING.markdown</a>.</p>



<p></p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="This software is available to you under a dual-licensing approach, whereby you may choose under any of the following options:

- **FOSS [GNU Lesser General Public License v2.1 or later][lgpl-2.1-or-later]** – this means anyone may use it under either LGPL-2.1 or any later version of LGPL. Currently the only newer version is LGPL-3.0, but should the [FSF][fsf] in the future adopt a newer version, you will be able to choose that as well;
- **proprietary [EULA: Liferay Digital Experience Platform And Certain Applications (2002306_GL)][dxp_eula]**, available through _[Liferay Enterprise Services Agreement][esa]_ – this additional option is intended for Liferay's subscription customers. Should you wish to become a subscription customer, contact Liferay at &lt;https://www.liferay.com/contact-sales&gt;.

In addition, you should be aware that even if you opt to use the code under the LGPL-2.1 license (instead of LGPL-3.0), Liferay is a signatory of the [GPL Cooperation Commitment][gplcc]. Meaning that in case you, by chance, violated the LGPL-2.1, we would apply the much more friendly grace period and automatic license reinstatement from the GPL-3.0. For more info, see [our public commitment][gplcc_liferay] and this [blog post][gplcc_blog].

## SPDX and REUSE standards

The above licensing situation is expressed in [SPDX language][spdx_id] with the following unambiguous identifier, which you can find in every source code file that is released to you under these licenses:

`SPDX-License-Identifier: (LGPL-2.1-or-later OR LicenseRef-Liferay-DXP-EULA-2.0.0-2023-06)`

You can find the texts of both licenses in the `LICENSES/` folder in the root of this repository/package, with the SPDX ID of each license as the files base name, specifically in:

- [LICENSES/LGPL-2.1-or-later.txt](LICENSES/LGPL-2.1-or-later.txt)
- [LICENSES/LicenseRef-Liferay-DXP-EULA-2.0.0-2023-06.txt](LICENSES/LicenseRef-Liferay-DXP-EULA-2.0.0-2023-06.txt)

This is in line with the [REUSE Software 3.0 specification][reuse] of community best practices regarding standardised declaring of copyright and licensing information for software projects." style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">This software is available to you under a dual-licensing approach, whereby you may choose under any of the following options:</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ECEFF4">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4; font-weight: bold">**</span><span style="color: #D8DEE9FF; font-weight: bold">FOSS </span><span style="color: #ECEFF4; font-weight: bold">[</span><span style="color: #88C0D0; font-weight: bold">GNU Lesser General Public License v2.1 or later</span><span style="color: #ECEFF4; font-weight: bold">]</span><span style="color: #81A1C1; font-weight: bold">[</span><span style="color: #88C0D0; font-weight: bold">lgpl-2.1-or-later</span><span style="color: #81A1C1; font-weight: bold">]</span><span style="color: #ECEFF4; font-weight: bold">**</span><span style="color: #D8DEE9FF"> – this means anyone may use it under either LGPL-2.1 or any later version of LGPL. Currently the only newer version is LGPL-3.0, but should the </span><span style="color: #ECEFF4">[</span><span style="color: #88C0D0">FSF</span><span style="color: #ECEFF4">]</span><span style="color: #81A1C1">[</span><span style="color: #88C0D0">fsf</span><span style="color: #81A1C1">]</span><span style="color: #D8DEE9FF"> in the future adopt a newer version, you will be able to choose that as well;</span></span>
<span class="line"><span style="color: #ECEFF4">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4; font-weight: bold">**</span><span style="color: #D8DEE9FF; font-weight: bold">proprietary </span><span style="color: #ECEFF4; font-weight: bold">[</span><span style="color: #88C0D0; font-weight: bold">EULA: Liferay Digital Experience Platform And Certain Applications (2002306_GL)</span><span style="color: #ECEFF4; font-weight: bold">]</span><span style="color: #81A1C1; font-weight: bold">[</span><span style="color: #88C0D0; font-weight: bold">dxp_eula</span><span style="color: #81A1C1; font-weight: bold">]</span><span style="color: #ECEFF4; font-weight: bold">**</span><span style="color: #D8DEE9FF">, available through </span><span style="color: #ECEFF4; font-style: italic">_[</span><span style="color: #88C0D0; font-style: italic">Liferay Enterprise Services Agreement</span><span style="color: #ECEFF4; font-style: italic">]</span><span style="color: #81A1C1; font-style: italic">[</span><span style="color: #88C0D0; font-style: italic">esa</span><span style="color: #81A1C1; font-style: italic">]</span><span style="color: #ECEFF4; font-style: italic">_</span><span style="color: #D8DEE9FF"> – this additional option is intended for Liferay&#39;s subscription customers. Should you wish to become a subscription customer, contact Liferay at </span><span style="color: #ECEFF4">&lt;</span><span style="color: #D8DEE9FF; text-decoration: underline">https://www.liferay.com/contact-sales</span><span style="color: #ECEFF4">&gt;</span><span style="color: #D8DEE9FF">.</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">In addition, you should be aware that even if you opt to use the code under the LGPL-2.1 license (instead of LGPL-3.0), Liferay is a signatory of the </span><span style="color: #ECEFF4">[</span><span style="color: #88C0D0">GPL Cooperation Commitment</span><span style="color: #ECEFF4">]</span><span style="color: #81A1C1">[</span><span style="color: #88C0D0">gplcc</span><span style="color: #81A1C1">]</span><span style="color: #D8DEE9FF">. Meaning that in case you, by chance, violated the LGPL-2.1, we would apply the much more friendly grace period and automatic license reinstatement from the GPL-3.0. For more info, see </span><span style="color: #ECEFF4">[</span><span style="color: #88C0D0">our public commitment</span><span style="color: #ECEFF4">]</span><span style="color: #81A1C1">[</span><span style="color: #88C0D0">gplcc_liferay</span><span style="color: #81A1C1">]</span><span style="color: #D8DEE9FF"> and this </span><span style="color: #ECEFF4">[</span><span style="color: #88C0D0">blog post</span><span style="color: #ECEFF4">]</span><span style="color: #81A1C1">[</span><span style="color: #88C0D0">gplcc_blog</span><span style="color: #81A1C1">]</span><span style="color: #D8DEE9FF">.</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">##</span><span style="color: #88C0D0"> SPDX and REUSE standards</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">The above licensing situation is expressed in </span><span style="color: #ECEFF4">[</span><span style="color: #88C0D0">SPDX language</span><span style="color: #ECEFF4">]</span><span style="color: #81A1C1">[</span><span style="color: #88C0D0">spdx_id</span><span style="color: #81A1C1">]</span><span style="color: #D8DEE9FF"> with the following unambiguous identifier, which you can find in every source code file that is released to you under these licenses:</span></span>
<span class="line"></span>
<span class="line"><span style="color: #8FBCBB">`SPDX-License-Identifier: (LGPL-2.1-or-later OR LicenseRef-Liferay-DXP-EULA-2.0.0-2023-06)`</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">You can find the texts of both licenses in the </span><span style="color: #8FBCBB">`LICENSES/`</span><span style="color: #D8DEE9FF"> folder in the root of this repository/package, with the SPDX ID of each license as the files base name, specifically in:</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ECEFF4">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">[</span><span style="color: #88C0D0">LICENSES/LGPL-2.1-or-later.txt</span><span style="color: #ECEFF4">](</span><span style="color: #D8DEE9FF; text-decoration: underline">LICENSES/LGPL-2.1-or-later.txt</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #ECEFF4">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">[</span><span style="color: #88C0D0">LICENSES/LicenseRef-Liferay-DXP-EULA-2.0.0-2023-06.txt</span><span style="color: #ECEFF4">](</span><span style="color: #D8DEE9FF; text-decoration: underline">LICENSES/LicenseRef-Liferay-DXP-EULA-2.0.0-2023-06.txt</span><span style="color: #ECEFF4">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">This is in line with the </span><span style="color: #ECEFF4">[</span><span style="color: #88C0D0">REUSE Software 3.0 specification</span><span style="color: #ECEFF4">]</span><span style="color: #81A1C1">[</span><span style="color: #88C0D0">reuse</span><span style="color: #81A1C1">]</span><span style="color: #D8DEE9FF"> of community best practices regarding standardised declaring of copyright and licensing information for software projects.</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative"><a class="cbp-footer-link broken_link" href="https://github.com/liferay/liferay-portal/blob/master/LICENSING.markdown" style="color:#c8d0e0;text-decoration:none;font-weight:normal;border:none;background:none;border-radius:0;padding:0;margin:0">Licensing.markdown</a></span></div>



<p>L'intestazione dei file sorgenti (indicata a seguire) riporta le due license mostrate nell'estratto precedente. Le licenze sono espresse in formato <a href="https://spdx.org/ids">SPDX language</a> come illustrato enll'esempio seguente per il file sorgente <a href="https://github.com/liferay/liferay-portal/blob/master/modules/dxp/apps/portal/portal-dao-db/src/main/java/com/liferay/portal/dao/db/OracleDB.java">OracleDB.java</a>.</p>



<p></p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="/**
* SPDX-FileCopyrightText: (c) 2000 Liferay, Inc. https://liferay.com
* SPDX-License-Identifier: LGPL-2.1-or-later OR LicenseRef-Liferay-DXP-EULA-2.0.0-2023-06
*/ " style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88">/**</span></span>
<span class="line"><span style="color: #616E88">* SPDX-FileCopyrightText: (c) 2000 Liferay, Inc. https://liferay.com</span></span>
<span class="line"><span style="color: #616E88">* SPDX-License-Identifier: LGPL-2.1-or-later OR LicenseRef-Liferay-DXP-EULA-2.0.0-2023-06</span></span>
<span class="line"><span style="color: #616E88">*/</span><span style="color: #D8DEE9FF"> </span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-start;background-color:#2e3440ff;color:#c8d0e0;font-size:12px;line-height:1;position:relative"><a class="cbp-footer-link" href="https://github.com/liferay/liferay-portal/blob/master/modules/dxp/apps/portal/portal-dao-db/src/main/java/com/liferay/portal/dao/db/OracleDB.java" style="color:#c8d0e0;text-decoration:none;font-weight:normal;border:none;background:none;border-radius:0;padding:0;margin:0">OracleDB.java</a></span></div>



<p>Se notate, le due licenze sono indicate con la chiave “<strong>OR</strong>”, significa che il codice sorgente è rilasciato sotto una licenza duale, e chi utilizza il codice ha la possibilità di scegliere quale delle due licenze adottare. L’utente potrà quindi scegliere se rispettare i termini della licenza LGPL-2.1-or-later oppure quelli della licenza <a href="https://web.liferay.com/legal/doc/eula/dxp/2002306_GL">LicenseRef-Liferay-DXP-EULA-2.0.0-2023-06</a>. Ogni licenza ha le proprie condizioni e obblighi, quindi la scelta dell’utente può dipendere da quale licenza è più adatta al loro uso specifico.</p>



<p class="p1">Oltre alla chiave “OR”, esistono altre chiavi o combinazioni che possono essere utilizzate per indicare diverse modalità di licenza del codice sorgente, anche se sono meno comuni. Ecco una panoramica delle opzioni:</p>



<p class="p3"><b><strong>1. AND:</strong></b></p>



<ul class="wp-block-list">
<li><b><strong>Significato</strong></b>: Se le licenze sono indicate con la chiave “AND” (esempio: “GPL-3.0 AND <a href="https://opensource.org/license/mit">MIT</a>”), significa che chi utilizza il codice deve rispettare <b>entrambe</b> le licenze contemporaneamente.</li>
</ul>



<ul class="wp-block-list">
<li><b><strong>Implicazioni</strong></b>: Questo scenario richiede che l’utente soddisfi i requisiti di tutte le licenze applicabili. Questo può essere complicato, soprattutto se le licenze hanno condizioni che potrebbero essere difficili da conciliare.</li>
</ul>



<p class="p1"><b>Esempio</b>:</p>



<ul class="wp-block-list">
<li><b>GPL-3.0 AND MIT</b>: L’utente deve rispettare i termini della GPL-3.0, che impone il rilascio del codice derivato sotto la stessa licenza, e anche i termini della licenza MIT, che potrebbe essere più permissiva. Di fatto, la GPL-3.0 è la licenza più restrittiva e quindi le sue condizioni prevalgono, ma bisogna comunque rispettare entrambe.</li>
</ul>



<p class="p3"><b><strong>2. WITH</strong>:</b></p>



<ul class="wp-block-list">
<li><b><strong>Significato</strong></b>: La chiave “WITH” viene utilizzata in combinazione con clausole aggiuntive o eccezioni.</li>
</ul>



<ul class="wp-block-list">
<li><b><strong>Implicazioni</strong></b>: Questa chiave indica che il codice è licenziato sotto una licenza principale, ma con alcune modifiche o eccezioni specifiche.</li>
</ul>



<p class="p1"><b>Esempio</b>:</p>



<ul class="wp-block-list">
<li><b>GPL-3.0 WITH Classpath Exception</b>: Questa combinazione indica che il codice è rilasciato sotto la GPL-3.0, ma con un’eccezione specifica (la Classpath Exception) che consente un utilizzo più flessibile del codice in alcuni contesti, come il linking con software proprietario.</li>
</ul>



<p class="p3"><b><strong>3. Dual/Multi-Licensing (senza chiavi specifiche)</strong>:</b></p>



<ul class="wp-block-list">
<li><b>Descrizione</b>: Alcuni progetti possono essere rilasciati con più licenze, ma senza usare chiavi specifiche come “OR” o “AND”. In questi casi, le modalità di scelta o combinazione delle licenze vengono spiegate in dettaglio nella documentazione del progetto.</li>
</ul>



<ul class="wp-block-list">
<li><b>Implicazioni</b>: La chiarezza delle condizioni di licenza dipende fortemente dalla documentazione fornita.</li>
</ul>



<p class="p3"><b><strong>4. Composite Licensing</strong>:</b></p>



<ul class="wp-block-list">
<li><b>Descrizione</b>: In alcuni casi complessi, il codice potrebbe essere soggetto a una combinazione di licenze per diverse parti del progetto. Ad esempio, una parte del codice potrebbe essere rilasciata sotto una licenza e un’altra parte sotto un’altra.</li>
</ul>



<ul class="wp-block-list">
<li><b>Implicazioni</b>: Gli utenti devono fare attenzione a rispettare le licenze specifiche applicabili a ciascuna parte del codice.</li>
</ul>



<p class="p1">È essenziale per chi utilizza il codice comprendere queste combinazioni per garantire la conformità alle condizioni legali richieste.</p>



<h2 class="wp-block-heading">Conclusioni</h2>



<p>I modelli di licenza multipli rappresentano una strategia versatile che permette di combinare i vantaggi del software open-source con le opportunità commerciali. L’uso di chiavi come “OR”, “AND” e “WITH” permette di definire con precisione come devono essere applicate le licenze in un progetto di software. </p>



<p>L'adozione di modelli multipli, sebbene possano presentare alcune sfide, offrono un mezzo efficace per adattarsi a diversi mercati e contesti normativi. Per gli sviluppatori, la chiave del successo con questo modello risiede nella trasparenza e nella chiarezza nella comunicazione delle condizioni di licenza, assicurando che gli utenti comprendano appieno le opzioni a loro disposizione.</p>



<h2 class="wp-block-heading">Risorse</h2>



<p class="p1"><span class="s1"> 1. </span><b>Open Source Initiative (OSI)</b> - <a href="https://opensource.org">opensource.org</a></p>



<ul class="wp-block-list">
<li>L’OSI è l’organizzazione di riferimento per la certificazione delle licenze open-source. Il sito contiene risorse educative, articoli e documenti su varie licenze, comprese quelle multiple.</li>
</ul>



<p class="p1"><span class="s1"> 2. </span><b>Free Software Foundation (FSF)</b> - <a href="https://www.fsf.org">fsf.org</a></p>



<ul class="wp-block-list">
<li>La FSF offre risorse approfondite sulle licenze software libere, inclusa la GPL, e sulle modalità di rilascio del software sotto licenze multiple.</li>
</ul>



<p>3. <strong>Understanding Open Source and Free Software Licensing</strong> di <a href="https://www.amazon.it/Andrew-M-St-Laurent/e/B001IQXSBI/ref=dp_byline_cont_book_1">Andrew M St Laurent</a> (Autore)</p>



<ul class="wp-block-list">
<li>Un testo essenziale per chiunque voglia capire le differenze tra le licenze open-source e free software. Include esempi pratici di licenze multiple e casi d’uso reali.</li>
</ul>



<p>4. <strong>The Cathedral &amp; the Bazaar – Musings on Linux &amp; Open Source by an Accidental Revolutionary</strong> di <a href="https://www.amazon.it/Eric-Raymond/e/B000APZT1U/ref=dp_byline_cont_book_1" class="broken_link">Eric Raymond</a> (Autore)</p>



<ul class="wp-block-list">
<li>Anche se non specificamente focalizzato sulle licenze multiple, questo libro esplora la filosofia open-source e le implicazioni pratiche del rilascio di software con licenze aperte, toccando anche le dinamiche legate alla scelta delle licenze.</li>
</ul>



<p class="wp-block-heading">&nbsp;</p>



<p>&nbsp;</p>
<p>L'articolo <a href="https://www.dontesta.it/2024/08/21/cosa-sono-i-modelli-di-licenza-multipli-nel-software/">Cosa sono i modelli di licenza multipli nel software?</a> sembra essere il primo su <a href="https://www.dontesta.it">Antonio Musarra&#039;s Blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.dontesta.it/2024/08/21/cosa-sono-i-modelli-di-licenza-multipli-nel-software/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Cos&#8217;è l&#8217;approccio Document as Code (doc-as-code)</title>
		<link>https://www.dontesta.it/2024/06/25/approccio-document-as-code/</link>
					<comments>https://www.dontesta.it/2024/06/25/approccio-document-as-code/#respond</comments>
		
		<dc:creator><![CDATA[Antonio Musarra]]></dc:creator>
		<pubDate>Mon, 24 Jun 2024 22:35:00 +0000</pubDate>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Framework]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tools]]></category>
		<guid isPermaLink="false">https://www.dontesta.it/?p=5622</guid>

					<description><![CDATA[<p>Negli ultimi anni, l’approccio Document as Code (Doc-as-Code) ha guadagnato popolarità tra i team di sviluppo software e le organizzazioni che si occupano di documentazione tecnica. Questa metodologia trasferisce i principi dello sviluppo software&#46;&#46;&#46;</p>
<p>L'articolo <a href="https://www.dontesta.it/2024/06/25/approccio-document-as-code/">Cos&#8217;è l&#8217;approccio Document as Code (doc-as-code)</a> sembra essere il primo su <a href="https://www.dontesta.it">Antonio Musarra&#039;s Blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p></p>



<p>Negli ultimi anni, l’approccio <strong>Document as Code</strong> (Doc-as-Code) ha guadagnato popolarità tra i team di sviluppo software e le organizzazioni che si occupano di documentazione tecnica. Questa metodologia trasferisce i principi dello sviluppo software alla creazione e gestione della documentazione, portando con sé numerosi vantaggi in termini di efficienza, qualità e collaborazione. Ma cosa significa esattamente Document as Code?</p>



<p>Cercherò di spiegare questo approccio nel modo più chiaro e sintetico possibile per poi lasciarvi il bonus, ovvero, un progetto completo (out-of-the-box) di questo tipo di approccio.</p>



<h2 class="wp-block-heading">1. Definizione e Principi Fondamentali</h2>



<p>L’approccio Doc-as-Code prevede la gestione della documentazione tecnica nello stesso modo in cui si gestisce il codice sorgente. Ciò implica che i documenti siano scritti in formati testuali, abbiano una versione applicata tramite sistemi di controllo del codice sorgente come Git, e sottoposti a revisione e test automatizzati. I principi cardine di questo approccio sono indicati e descritti a seguire.</p>



<ol class="wp-block-list">
<li><strong>Tracciabilità e Versionamento</strong>: Utilizzando sistemi di controllo del codice sorgente, è possibile tracciare ogni modifica apportata alla documentazione. Questo consente di mantenere una cronologia completa delle versioni, facilitando il ritorno a una versione precedente in caso di necessità.</li>



<li><strong>Collaborazione e Revisione</strong>: La documentazione può essere revisionata e migliorata attraverso <strong>pull request</strong> e <strong>code review</strong>, proprio come avviene per il codice sorgente. Questo processo incrementa la qualità e la precisione del contenuto.</li>



<li><strong>Automazione</strong>: Strumenti di integrazione continua (<strong>CI</strong>) possono essere utilizzati per automatizzare la generazione, la validazione e la pubblicazione della documentazione. Questo riduce gli errori manuali e accelera il processo di aggiornamento.</li>



<li><strong>Uniformità</strong>: Utilizzando linguaggi di markup (tra i più noti) come <a href="https://www.markdownguide.org/" target="_blank" rel="noopener">Markdown</a>, <a href="https://asciidoc.org/" target="_blank" rel="noopener">AsciiDoc</a> e <a href="https://docutils.sourceforge.io/rst.html" target="_blank" rel="noopener">reStructuredText</a>, è possibile mantenere uno stile coerente e facilmente leggibile. Inoltre, i generatori di documentazione come <a href="https://www.sphinx-doc.org/en/master/" target="_blank" rel="noopener">Sphinx</a> o <a href="https://www.mkdocs.org/" target="_blank" rel="noopener">MkDocs</a> possono essere utilizzati per creare documenti HTML, PDF e altro ancora da sorgenti testuali.</li>
</ol>



<h2 class="wp-block-heading">2. Vantaggi dell'Approccio Doc-as-Code</h2>



<ol class="wp-block-list">
<li><strong>Miglioramento della Qualità</strong>: La revisione paritaria e i test automatici assicurano che la documentazione sia accurata e aggiornata, riducendo il rischio di errori.</li>



<li><strong>Efficienza</strong>: L’automazione delle operazioni di generazione e pubblicazione consente di risparmiare tempo prezioso, permettendo agli autori di concentrarsi sui contenuti piuttosto che sui dettagli tecnici.</li>



<li><strong>Collaborazione</strong>: L’uso di strumenti comuni tra sviluppatori e scrittori tecnici facilita una collaborazione più stretta e una migliore integrazione tra codice e documentazione.</li>



<li><strong>Flessibilità</strong>: La documentazione può essere aggiornata e distribuita rapidamente, adattandosi facilmente ai cambiamenti del software e alle esigenze degli utenti.</li>



<li><strong>Manutenibilità</strong>: La struttura modularizzata e versionata dei documenti semplifica la gestione e l’aggiornamento continuo del materiale di documentazione.</li>
</ol>



<h2 class="wp-block-heading">3. Strumenti e Tecnologie</h2>



<p>L’approccio Doc-as-Code si avvale di una serie di strumenti e tecnologie che facilitano la creazione, gestione e pubblicazione della documentazione.</p>



<ul class="wp-block-list">
<li><strong>Sistemi di Controllo del Codice Sorgente</strong>: Git è il più utilizzato, permettendo di versionare la documentazione e gestire le collaborazioni.</li>



<li><strong>Linguaggi di Markup</strong>: Markdown, AsciiDoc e reStructuredText sono i più comuni, grazie alla loro semplicità e leggibilità.</li>



<li><strong>Generatori di Documentazione</strong>: Strumenti come Sphinx, MkDocs, <a href="https://jekyllrb.com/" target="_blank" rel="noopener">Jekyll</a> e <a href="https://gohugo.io/" target="_blank" rel="noopener">Hugo</a> trasformano i file di markup in documenti formattati e navigabili.</li>



<li><strong>CI/CD</strong>: Piattaforme come Jenkins, Travis CI e GitHub Actions possono automatizzare la generazione e la pubblicazione della documentazione.</li>



<li><strong>Editor di Testo</strong>: Visual Studio Code, Intellj IDEA e altri editor moderni supportano estensioni che migliorano la scrittura e la formattazione della documentazione.</li>
</ul>



<h2 class="wp-block-heading">4. Il bonus: un progetto Doc-as-Code</h2>



<p>Ogni promessa va onorata, per cui è arrivato il momento di presentarvi il bonus, un progetto doc-as-code completo.</p>



<p>L'articolo <a href="https://theredcode.it/devops/deploy-quarkus-openshift-facile" target="_blank" rel="noopener">Deploy di un'applicazione Quarkus su OpenShift</a> pubblicato su <a href="https://www.theredcode.it/" target="_blank" rel="noopener">TheRedCode.it</a>, è il primo di quattro articoli che spiegano parte del progetto <a href="https://github.com/amusarra/eventbus-logging-filter-jaxrs" target="_blank" rel="noopener">Quarkus Event Bus Logging Filter JAX-RS</a> e la documentazione di quest'ultimo è stata realizzata con l'approccio doc-as-code e in particolare:</p>



<ol class="wp-block-list">
<li>questo <a href="https://github.com/amusarra/eventbus-logging-filter-jaxrs-docs/" target="_blank" rel="noopener">Documentazione Quarkus Event Bus Logging Filter JAX-RS</a> è il link al repository GitHub del progetto doc-as-code;</li>



<li>questo <a href="https://amusarra.github.io/eventbus-logging-filter-jaxrs-docs/" target="_blank" rel="noopener">https://amusarra.github.io/eventbus-logging-filter-jaxrs-docs/</a> è il link alle GitHub Pages dov'è stata pubblicata la documentazione in formato HTML;</li>



<li>cliccando qui <a href="https://github.com/amusarra/eventbus-logging-filter-jaxrs-docs/releases/download/v1.0.0/eventbus-logging-filter-jaxrs-docs-1.0.0.pdf" target="_blank" rel="noopener">Quarkus Event - Come sfruttarlo al massimo, utilizzi e vantaggi</a> otterrete la documentazione in formato PDF;</li>



<li>il linguaggio di markup utilizzato è AsciiDoc;</li>



<li>AsciiDoctor è il processore di testo che supporta la sintassi AsciiDoc e produce HTML5, DocBook, PDF e altri formati;</li>



<li>per ulteriori dettagli sul progetto, fare riferimento al <a href="https://github.com/amusarra/eventbus-logging-filter-jaxrs-docs/blob/main/README.md" target="_blank" rel="noopener">README</a>.</li>
</ol>



<p>Vi lascio altro bonus. Conoscete <a href="https://mia-platform.eu/it/platform/" target="_blank" rel="noreferrer noopener">Mia-Platform</a>? La documentazione è realizzata usando l'approccio doc-as-code e qui <a href="https://mia-platform.eu/it/blog/docs-as-code-migliora-developer-experience/" target="_blank" rel="noreferrer noopener">Come abbiamo implementato l’approccio Docs as Code in Mia‑Platform</a> puoi leggere tutti i dettagli.</p>



<p>Con questo bonus spero che apprezziate ancora di più l'approccio doc-as-code e che in qualche modo possa servire come buon punto d'inizio per i vostri progetti doc-as-code.</p>



<h2 class="wp-block-heading">Conclusioni</h2>



<p>L’approccio Document as Code rappresenta un’evoluzione significativa nella gestione della documentazione tecnica. Adottando pratiche di sviluppo software per la creazione di documenti, le organizzazioni possono migliorare la qualità, l’efficienza e la collaborazione, offrendo agli utenti finali documentazione sempre aggiornata e accurata. In un mondo in cui il software è in continua evoluzione, <strong>avere una documentazione che può tenere il passo è essenziale per il successo di qualsiasi progetto</strong>.</p>



<p></p>
<p>L'articolo <a href="https://www.dontesta.it/2024/06/25/approccio-document-as-code/">Cos&#8217;è l&#8217;approccio Document as Code (doc-as-code)</a> sembra essere il primo su <a href="https://www.dontesta.it">Antonio Musarra&#039;s Blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.dontesta.it/2024/06/25/approccio-document-as-code/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
