<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Antonio Musarra</title>
    <description>The latest articles on DEV Community by Antonio Musarra (@amusarra).</description>
    <link>https://dev.to/amusarra</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F351777%2F0658db37-171f-4ede-8447-1d8187fe6714.jpg</url>
      <title>DEV Community: Antonio Musarra</title>
      <link>https://dev.to/amusarra</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/amusarra"/>
    <language>en</language>
    <item>
      <title>Approfondimento sullo standard PKCS#11 e utilizzo con Smart Card</title>
      <dc:creator>Antonio Musarra</dc:creator>
      <pubDate>Sun, 22 Sep 2024 16:27:18 +0000</pubDate>
      <link>https://dev.to/amusarra/approfondimento-sullo-standard-pkcs11-e-utilizzo-con-smart-card-468</link>
      <guid>https://dev.to/amusarra/approfondimento-sullo-standard-pkcs11-e-utilizzo-con-smart-card-468</guid>
      <description>&lt;h2&gt;
  
  
  Introduzione a PKCS#11
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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" &lt;a href="https://sistemats1.sanita.finanze.it/portale/tessera-sanitaria" rel="noopener noreferrer"&gt;TS-CNS (Tessera Sanitaria - Carta Nazionale Servizi)&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  PKCS#11 e le Smart Card
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h3&gt;
  
  
  Vantaggi dell'uso delle Smart Card con PKCS#11
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Sicurezza Hardware&lt;/strong&gt; : le Smart Card sono dotate di un chip che esegue tutte le operazioni crittografiche, proteggendo le chiavi private dall’essere esposte al sistema host.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Portabilità&lt;/strong&gt; : 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.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Indipendenza dalla piattaforma&lt;/strong&gt; : 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.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Architettura e concetti chiave di PKCS#11
&lt;/h2&gt;

&lt;p&gt;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:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Slot e Token&lt;/strong&gt; : 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).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sessioni e Oggetti&lt;/strong&gt; : 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.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Meccanismi Crittografici&lt;/strong&gt; : PKCS#11 supporta diversi meccanismi crittografici, inclusi RSA, ECC, AES, e SHA, rendendolo flessibile per diverse applicazioni.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chiavi e Certificati&lt;/strong&gt; : 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.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Crittografia a chiave asimmetrica: il classico esempio di Alice e Bob
&lt;/h2&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Chiave Pubblica&lt;/strong&gt; : può essere condivisa pubblicamente con chiunque. Serve per cifrare i messaggi che solo il proprietario della corrispondente chiave privata può decifrare.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chiave Privata&lt;/strong&gt; : deve essere mantenuta segreta. Viene usata per decifrare i messaggi cifrati con la chiave pubblica e per firmare digitalmente i dati.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Scambio delle Chiavi:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Alice invia un messaggio cifrato a Bob:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Bob invia un messaggio firmato ad Alice:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;sequenceDiagram participant Alice participant Bob Alice-&amp;gt;&amp;gt;Bob: Richiesta chiave pubblica Bob--&amp;gt;&amp;gt;Alice: Invia chiave pubblica Alice-&amp;gt;&amp;gt;Alice: Cifra il messaggio con la chiave pubblica di Bob Alice-&amp;gt;&amp;gt;Bob: Invia messaggio cifrato Bob-&amp;gt;&amp;gt;Bob: Decifra il messaggio con la sua chiave privata Bob-&amp;gt;&amp;gt;Alice: Richiesta chiave pubblica Alice--&amp;gt;&amp;gt;Bob: Invia chiave pubblica Bob-&amp;gt;&amp;gt;Bob: Firma il messaggio con la chiave privata Bob-&amp;gt;&amp;gt;Alice: Invia messaggio firmato Alice-&amp;gt;&amp;gt;Alice: Verifica la firma con la chiave pubblica di Bob&lt;/p&gt;

&lt;p&gt;Figura 1 - Sequence Diagram di come Alice e Bob si scambiano un messaggio cifrato e firmato utilizzando le chiavi asimmetriche.&lt;/p&gt;

&lt;p&gt;Ora, cerchiamo di capire una differenza importante, ovvero, quella esistente tra &lt;strong&gt;cifrare un messaggio&lt;/strong&gt; e &lt;strong&gt;firmare un messaggio&lt;/strong&gt;.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Cifrare un Messaggio
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Obiettivo&lt;/strong&gt; : proteggere il contenuto del messaggio, mantenendolo segreto e accessibile solo al destinatario autorizzato.&lt;/p&gt;

&lt;p&gt;Come funziona:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Chiave pubblica del destinatario&lt;/strong&gt; : usata per cifrare il messaggio.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chiave privata del destinatario&lt;/strong&gt; : usata per decifrare il messaggio.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Usando l'approccio della cifratura asimmetrica:&lt;/p&gt;

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

&lt;p&gt;Questo garantisce che &lt;strong&gt;nessun altro&lt;/strong&gt; possa leggere il messaggio, mantenendo la &lt;strong&gt;riservatezza&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Esempio:&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h3&gt;
  
  
  Firmare un Messaggio
&lt;/h3&gt;

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

&lt;p&gt;Come funziona:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Chiave privata del mittente&lt;/strong&gt; : usata per firmare digitalmente il messaggio.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chiave pubblica del mittente&lt;/strong&gt; : usata dal destinatario per verificare la firma.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Usando l'approccio della firma asimmetrica:&lt;/p&gt;

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

&lt;p&gt;Esempio:&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;La tabella a seguire mostra in modo schematico le differenze tra la cifratura e la firma digitale.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Aspetto&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Cifratura&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Firma Digitale&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Scopo&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Proteggere la riservatezza del messaggio&lt;/td&gt;
&lt;td&gt;Garantire l'autenticità e l'integrità del messaggio&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Chiave usata&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Chiave pubblica del destinatario per cifrare&lt;/td&gt;
&lt;td&gt;Chiave privata del mittente per firmare&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Chiave per verificare&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Chiave privata del destinatario per decifrare&lt;/td&gt;
&lt;td&gt;Chiave pubblica del mittente per verificare&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Risultato&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Solo il destinatario può leggere il messaggio&lt;/td&gt;
&lt;td&gt;Il destinatario può verificare la provenienza e l'integrità del messaggio&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Tabella 1 - Differenza tra cifratura e firma digitale&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Per fare un riepilogo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;cifrare&lt;/strong&gt; serve a &lt;strong&gt;proteggere i dati&lt;/strong&gt; , garantendo che solo il destinatario previsto possa leggere il messaggio.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;firmare&lt;/strong&gt; serve a &lt;strong&gt;garantire autenticità e integrità&lt;/strong&gt; , confermando che il messaggio proviene dal mittente e non è stato modificato.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;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à.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Esempio pratico con PKCS#11 e Smart Card
&lt;/h2&gt;

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

&lt;h3&gt;
  
  
  Requisiti
&lt;/h3&gt;

&lt;p&gt;Per portare a termine questo esempio, avremo bisogno degli elementi a seguire.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Una Smart Card compatibile con PKCS#11.&lt;/li&gt;
&lt;li&gt;Un certificato digitale per la tua Smart Card.&lt;/li&gt;
&lt;li&gt;Un PIN per accedere alla Smart Card.&lt;/li&gt;
&lt;li&gt;Un lettore di Smart Card.&lt;/li&gt;
&lt;li&gt;Un driver PKCS#11 per la tua Smart Card.&lt;/li&gt;
&lt;li&gt;Un ambiente di sviluppo per il linguaggio di programmazione che desideri utilizzare.&lt;/li&gt;
&lt;li&gt;Un'API PKCS#11 per il tuo linguaggio di programmazione.&lt;/li&gt;
&lt;li&gt;Un'applicazione che utilizzi PKCS#11 per accedere alla Smart Card.&lt;/li&gt;
&lt;li&gt;Un ambiente di test per eseguire l'applicazione.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;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 &lt;strong&gt;TS-CNS (Tessera Sanitaria - Carta Nazionale Servizi)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nota&lt;/strong&gt; : prima di poter usare il nostro certificato digitale della TS-CNS, è necessario provvedere alla sua attivazione. &lt;a href="https://sistemats1.sanita.finanze.it/portale/modalita-di-accesso-con-ts_cns" rel="noopener noreferrer"&gt;Sul portale STS (Sistema Tessera Sanitaria)&lt;/a&gt; è 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 &lt;a href="https://www.salutelazio.it/tessera-sanitaria-elettronica" rel="noopener noreferrer"&gt;sito ufficiale della Regione Lazio&lt;/a&gt; nella sezione &lt;em&gt;Come attivate la Carta Nazionale dei Servizi&lt;/em&gt;.&lt;/p&gt;

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

&lt;p&gt;Per quanto riguarda il driver PKCS#11, è possibile utilizzare quello fornito dal produttore della Smart Card o utilizzare un driver open source come &lt;a href="https://github.com/OpenSC/OpenSC" rel="noopener noreferrer"&gt;OpenSC&lt;/a&gt;. 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 &lt;code&gt;opensc-tool -c '?'&lt;/code&gt;per ottenere la lista dei driver tra cui è presente anche itacns - Italian CNS). Da non dimenticare che OpenSC è disponibile per diverse piattaforme, tra cui &lt;a href="https://github.com/OpenSC/OpenSC/releases/tag/0.26.0-rc1" rel="noopener noreferrer"&gt;Linux, macOS e Windows&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

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

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementazione dell'applicazione
&lt;/h3&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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 &lt;a href="https://docs.oasis-open.org/pkcs11/pkcs11-base/v3.0/pkcs11-base-v3.0.html" rel="noopener noreferrer"&gt;documentazione ufficiale&lt;/a&gt; e la documentazione di &lt;a href="https://pkcs11wrap.sourceforge.io/api/" rel="noopener noreferrer"&gt;PyKCS11&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;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 &lt;code&gt;PyKCS11&lt;/code&gt; e creare un oggetto &lt;code&gt;PyKCS11.PyKCS11Lib&lt;/code&gt; con il percorso del driver PKCS#11 della nostra Smart Card.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

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"Libreria PKCS#11 non trovata. Specifica il percorso manualmente. Percorso attuale: {pkcs11_lib_path}")

# Carica la libreria PKCS#11
pkcs11 = PyKCS11.PyKCS11Lib()
pkcs11.load(pkcs11_lib_path)


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Python&lt;/p&gt;

&lt;p&gt;Source Code 1 - Inizializzazione dell'API PKCS#11 e caricamento della libreria PKCS#11&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

    # Ottieni la lista degli slot con token presenti
    slots = pkcs11.getSlotList(tokenPresent=True)

    if len(slots) == 0:
        raise NoSmartCardInserted("Nessuna Smart Card inserita")

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

    # Apri una sessione con la Smart Card
    session = pkcs11.openSession(slot)
    session.login(args.pin)


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Python&lt;/p&gt;

&lt;p&gt;Source Code 2 - Ottenimento dello slot e del token della Smart Card e apertura di una sessione con la Smart Card&lt;/p&gt;

&lt;p&gt;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 &lt;code&gt;PyKCS11.CKO_PRIVATE_KEY&lt;/code&gt;, &lt;code&gt;PyKCS11.CKO_CERTIFICATE&lt;/code&gt; e &lt;code&gt;PyKCS11.CKA_VALUE&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;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 &lt;code&gt;[0]&lt;/code&gt; troveremo i nostri oggetti.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

    # 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()


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Python&lt;/p&gt;

&lt;p&gt;Source Code 3 - Caricamento della chiave privata e pubblica dalla Smart Card&lt;/p&gt;

&lt;p&gt;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 &lt;code&gt;PyKCS11.CKM_SHA256_RSA_PKCS&lt;/code&gt;.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

    # 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)


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Python&lt;/p&gt;

&lt;p&gt;Source Code 4 - Codifica del messaggio e firma del messaggio&lt;/p&gt;

&lt;p&gt;A questo punto abbiamo ottenuto la firma del messaggio (&lt;code&gt;signature = bytes(signature)&lt;/code&gt;) 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.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

   # Verifica la firma usando la chiave pubblica
   try:
      public_key.verify(
         signature,
         data,
         padding.PKCS1v15(),
         hashes.SHA256()
      )
      print(f"{Fore.GREEN}✅ Firma verificata correttamente!")
   except Exception as e:
      print(f"{Fore.RED}❌ Verifica della firma fallita: {e}")

   # Logout dalla sessione
   session.logout()


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Python&lt;/p&gt;

&lt;p&gt;Source Code 5 - Verifica della firma del messaggio&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;sequenceDiagram participant Bob participant SmartCard participant Alice Bob-&amp;gt;&amp;gt;SmartCard: Inserisce la Smart Card Bob-&amp;gt;&amp;gt;SmartCard: Inserisce il PIN SmartCard--&amp;gt;&amp;gt;Bob: Autenticazione riuscita Bob-&amp;gt;&amp;gt;SmartCard: Firma il messaggio SmartCard--&amp;gt;&amp;gt;Bob: Restituisce la firma Bob-&amp;gt;&amp;gt;Alice: Invia messaggio e firma Alice-&amp;gt;&amp;gt;Bob: Chiede a Bob la chiave pubblica Bob--&amp;gt;&amp;gt;Alice: Restituisce la chiave pubblica Alice-&amp;gt;&amp;gt;Alice: Verifica la firma con la chiave pubblica Alice--&amp;gt;&amp;gt;Alice: Firma verificata correttamente&lt;/p&gt;

&lt;p&gt;Figura 2 - Sequence Diagram di come Alice e Bob si scambiano un messaggio cifrato e firmato utilizzando le chiavi asimmetriche.&lt;/p&gt;

&lt;p&gt;Conclusa la fase d'implementazione, passeremo alla fase di test.&lt;/p&gt;

&lt;h3&gt;
  
  
  Test dell'applicazione di firma digitale
&lt;/h3&gt;

&lt;p&gt;L'applicazione finale è disponibile su GitHub 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:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

# Installazione dei requirements
pip install -r requirements.txt

# Esegui l'applicazione per firmare un messaggio
./sign-via-ts-cns.py --pin 123456 --message "Prima firma di un messaggio tramite la mia TS-CNS"


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;Console 1 - Esempio di esecuzione dell'applicazione di firma digitale&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

🔍 Dati da firmare: b'Prima firma di un messaggio tramite la mia TS-CNS'
✅ Firma generata (in esadecimale): b'99be876fb527dbd8e36e9d76f69357e6ef006c737e535b48ed45acd28ebb3b2a14cc7a08cc4902d92194b18b2cc8b61cc2a23747119b6c473fe4757e12ac66c6ce9488354a9fbbb95b003b643295e428b18383328192953c645afe0f9b00e9bf405981da4a52b40f288275023d8aa06e81f88a066888dc29e88a1b6280b5e7c2f26b1e8d5bc469839dcf07128b3e525ad88c9190b76811def76530131246e201a4428b74f65757957e67190ce284b0c8ee89f422b3cf960899467fd1bb66ded6a97999ccf3a2407b07f49af697590b0dac28585c5c3e8b0ca3b3aa1bc47eb1aab2d67a0b0fc1c8cf9bde51512acb9ebed80bf514f6cfe7e9900d2d3541df1f39'
✅ Firma verificata correttamente!


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Plaintext&lt;/p&gt;

&lt;p&gt;Console 2 - Esempio di output dell'applicazione di firma digitale&lt;/p&gt;

&lt;p&gt;Quando l'applicazione termina con successo, questa genera tre file:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;message_&amp;lt;uuid4&amp;gt;txt&lt;/code&gt;: il messaggio originale.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;signature_&amp;lt;uuid4&amp;gt;.txt&lt;/code&gt;: la firma generata.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;public_cert.pem&lt;/code&gt;: la chiave pubblica.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;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.&lt;/p&gt;

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



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

# Verifica la firma del messaggio tramite openssl.
openssl dgst -sha256 -verify &amp;lt;(openssl x509 -in public_cert.pem -pubkey -noout) -signature signature_e032b4fe6213486eb9830fe0dacf9f3b.bin message_9789a64270b1443da672a5d1776d6664.txt


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;Console 3 - Verifica della firma del messaggio tramite OpenSSL&lt;/p&gt;

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

&lt;p&gt;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.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

# Altera il messaggio originale
echo "Messaggio alterato" &amp;gt; message_9789a64270b1443da672a5d1776d6664.txt

# Verifica la firma del messaggio tramite openssl.
openssl dgst -sha256 -verify &amp;lt;(openssl x509 -in public_cert.pem -pubkey -noout) -signature signature_e032b4fe6213486eb9830fe0dacf9f3b.bin message_9789a64270b1443da672a5d1776d6664.txt



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;Console 4 - Verifica della firma del messaggio tramite OpenSSL con messaggio alterato&lt;/p&gt;

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

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



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

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



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;Console 5 - Help dell'applicazione di firma digitale&lt;/p&gt;

&lt;p&gt;L'opzione che mi sento di consigliare è &lt;code&gt;--debug&lt;/code&gt; 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 &lt;code&gt;--pkcs11-lib&lt;/code&gt; e i file in cui salvare la firma e il messaggio con le opzioni &lt;code&gt;--signature-file&lt;/code&gt; e &lt;code&gt;--message-file&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

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

&lt;p&gt;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&lt;/p&gt;

&lt;h2&gt;
  
  
  Utilizzo in applicazioni reali
&lt;/h2&gt;

&lt;p&gt;Le Smart Card e lo standard PKCS#11 sono utilizzati in molti scenari di sicurezza crittografica.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Firma Digitale&lt;/strong&gt; : le firme digitali eseguite tramite chiavi private su Smart Card sono molto comuni in applicazioni di governo elettronico (e-government) e nei sistemi finanziari.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Autenticazione Forte&lt;/strong&gt; : molte aziende e istituzioni richiedono un’autenticazione a due fattori (2FA) basata su Smart Card per l’accesso ai sistemi critici.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Crittografia e Decrittazione&lt;/strong&gt; : 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.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Infrastruttura PKI&lt;/strong&gt; : le Smart Card sono comunemente utilizzate in un’infrastruttura a chiave pubblica (PKI) per la gestione sicura delle identità digitali.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Risorse e Approfondimenti
&lt;/h2&gt;

&lt;p&gt;Il repository GitHub &lt;strong&gt;pkcs11-smart-card&lt;/strong&gt; con il codice completo dell'applicazione è disponibile al seguente &lt;a href="https://github.com/amusarra/pkcs11-smart-card" rel="noopener noreferrer"&gt;link&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;Per ulteriori informazioni su OpenSC, consiglio di consultare la documentazione ufficiale: &lt;a href="https://github.com/OpenSC/OpenSC/wiki" rel="noopener noreferrer"&gt;OpenSC&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;Per altri temi che riguardano Smart Card e sicurezza informatica, propongo qualche articolo pubblicato sul mio blog personale:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://www.dontesta.it/2022/03/11/raspberry-pi-smart-card-mifare-classic-1k-realizzare-sistema-accesso/" rel="noopener noreferrer"&gt;Raspberry Pi e Smart Card Mifare Classic 1K: Realizzare un sistema di accesso&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.dontesta.it/2024/09/19/implementazione-tls-mutual-authentication-mtls-con-quarkus/" rel="noopener noreferrer"&gt;Implementazione di TLS Mutual Authentication (mTLS) con Quarkus&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.dontesta.it/2020/07/17/raspberry-pi-esempio-applicazione-ts-cns-smartcard/" rel="noopener noreferrer"&gt;Raspberry Pi – Un esempio di applicazione della TS-CNS&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusioni
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;L'articolo &lt;a href="https://www.dontesta.it/2024/09/22/approfondimento-standard-pkcs11-smart-card/" rel="noopener noreferrer"&gt;Approfondimento sullo standard PKCS#11 e utilizzo con Smart Card&lt;/a&gt; sembra essere il primo su &lt;a href="https://www.dontesta.it" rel="noopener noreferrer"&gt;Antonio Musarra's Blog&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>blog</category>
      <category>security</category>
      <category>pkcs11</category>
      <category>smartcard</category>
    </item>
    <item>
      <title>Implementazione di TLS Mutual Authentication (mTLS) con Quarkus</title>
      <dc:creator>Antonio Musarra</dc:creator>
      <pubDate>Wed, 18 Sep 2024 23:21:53 +0000</pubDate>
      <link>https://dev.to/amusarra/implementazione-di-tls-mutual-authentication-mtls-con-quarkus-2i63</link>
      <guid>https://dev.to/amusarra/implementazione-di-tls-mutual-authentication-mtls-con-quarkus-2i63</guid>
      <description>&lt;h1&gt;
  
  
  Implementazione di TLS Mutual Authentication (mTLS) con Quarkus
&lt;/h1&gt;

&lt;p&gt;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’&lt;strong&gt;autenticazione reciproca TLS (mTLS)&lt;/strong&gt; 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 &lt;strong&gt;&lt;a href="https://quarkus.io" rel="noopener noreferrer"&gt;Quarkus&lt;/a&gt;&lt;/strong&gt;, un framework Java ottimizzato per il cloud.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cos’è l’autenticazione reciproca TLS (mTLS)?
&lt;/h2&gt;

&lt;p&gt;L’autenticazione reciproca TLS (o mutual TLS o mTLS) è un’estensione del protocollo &lt;a href="https://it.wikipedia.org/wiki/Transport_Layer_Security" rel="noopener noreferrer"&gt;TLS&lt;/a&gt; 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. &lt;strong&gt;Con mTLS, anche il client deve presentare un certificato valido, garantendo così che entrambe le parti siano autentiche&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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).&lt;/p&gt;

&lt;p&gt;sequenceDiagram autonumber participant Client participant Server Client-&amp;gt;&amp;gt;Server: Client Hello (Supported ciphersuites, Random number) Server--&amp;gt;&amp;gt;Client: Server Hello (Chosen ciphersuite, Random number, Request client certificate) Server--&amp;gt;&amp;gt;Client: Certificate (Server's certificate) Client--&amp;gt;&amp;gt;Client: Verify Server Certificate Client-&amp;gt;&amp;gt;Server: Client Certificate (Client's certificate) Server--&amp;gt;&amp;gt;Server: Verify Client Certificate Client-&amp;gt;&amp;gt;Server: Client Key Exchange (Premaster secret encrypted with server public key) Client-&amp;gt;&amp;gt;Server: Finished (Encrypted with session key) Server-&amp;gt;&amp;gt;Client: Finished (Encrypted with session key) Client-&amp;gt;&amp;gt;Server: Application Data Server-&amp;gt;&amp;gt;Client: Application Data&lt;/p&gt;

&lt;p&gt;Figura 1 - Sequence diagramm del processo di autenticazione reciproca TLS (mTLS)&lt;/p&gt;

&lt;p&gt;È 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.&lt;/p&gt;

&lt;p&gt;Vediamo di approfondire quali sono i passaggi chiave per la verifica dei certificati in un contesto mTLS.&lt;/p&gt;

&lt;h3&gt;
  
  
  Verifica del certificato del server da parte del client
&lt;/h3&gt;

&lt;p&gt;Quando il server invia il proprio certificato al client, quest’ultimo deve verificarlo attraverso i seguenti passaggi.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Catena di certificazione (Certificate Chain)&lt;/strong&gt;: 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.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Firma del certificato&lt;/strong&gt; : 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.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Validità temporale&lt;/strong&gt; : il client verifica che il certificato non sia scaduto, controllando le date di validità (notBefore e notAfter) contenute nel certificato.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Revoca del certificato&lt;/strong&gt; : il client può verificare se il certificato del server è stato revocato. Questo avviene tramite il controllo delle &lt;strong&gt;&lt;a href="https://en.wikipedia.org/wiki/Certificate_revocation_list" rel="noopener noreferrer"&gt;CRL (Certificate Revocation List)&lt;/a&gt;&lt;/strong&gt; o utilizzando il protocollo &lt;strong&gt;&lt;a href="https://en.wikipedia.org/wiki/Online_Certificate_Status_Protocol" rel="noopener noreferrer"&gt;OCSP (Online Certificate Status Protocol)&lt;/a&gt;&lt;/strong&gt; per interrogare in tempo reale lo stato del certificato.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hostname&lt;/strong&gt; : Il client verifica che l’hostname del server corrisponda a quello presente nel certificato (nel campo &lt;strong&gt;Subject&lt;/strong&gt; o nel campo &lt;strong&gt;&lt;a href="https://en.wikipedia.org/wiki/Public_key_certificate#Subject_Alternative_Name_certificate" rel="noopener noreferrer"&gt;Subject Alternative Name&lt;/a&gt;&lt;/strong&gt;). Questo assicura che il certificato sia effettivamente emesso per il server con cui il client sta tentando di comunicare.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Verifica del certificato del client da parte del server
&lt;/h3&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Catena di certificazione&lt;/strong&gt; : 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.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Firma del certificato&lt;/strong&gt; : 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.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Validità temporale&lt;/strong&gt; : il server controlla che il certificato del client non sia scaduto, verificando le date di inizio e fine validità.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Revoca del certificato&lt;/strong&gt; : 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.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Identità del client&lt;/strong&gt; : 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.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Crittografia e integrità dei certificati
&lt;/h3&gt;

&lt;p&gt;Durante l’handshake, la chiave pubblica contenuta nei certificati viene utilizzata per scambiare in modo sicuro il &lt;strong&gt;premaster secret&lt;/strong&gt; , 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.&lt;/p&gt;

&lt;h3&gt;
  
  
  I cassetti digitali
&lt;/h3&gt;

&lt;p&gt;Sì, i certificati utilizzati per l'autenticazione, sia lato client sia lato server, sono memorizzati in &lt;strong&gt;repository specifici&lt;/strong&gt; che fungono da &lt;strong&gt;"cassetti digitali"&lt;/strong&gt; 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.&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Truststore
&lt;/h4&gt;

&lt;p&gt;Il &lt;strong&gt;truststore&lt;/strong&gt; è 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.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Lato Client&lt;/strong&gt; : 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.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Lato Server&lt;/strong&gt; : analogamente, il server verifica il certificato del client confrontandolo con le CA presenti nel suo truststore.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Qualcuno si chiederà dove si trovi il truststore, questo dipende dal sistema operativo.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Sistemi operativi&lt;/strong&gt; : il truststore è integrato nel sistema operativo. Ad esempio, su:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Applicazioni&lt;/strong&gt; : 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.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  2. Keystore
&lt;/h4&gt;

&lt;p&gt;Il &lt;strong&gt;keystore&lt;/strong&gt; è 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.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Lato Server&lt;/strong&gt; : 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.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Lato Client&lt;/strong&gt; : 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.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Qui la posizione del keystore dipende dal tipo di applicazione e dal sistema operativo.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Java KeyStore (JKS)&lt;/strong&gt;: Java usa un formato keystore specifico chiamato &lt;strong&gt;&lt;a href="https://en.wikipedia.org/wiki/Java_KeyStore" rel="noopener noreferrer"&gt;JKS&lt;/a&gt;&lt;/strong&gt;. Questo file può contenere certificati e chiavi private ed è ampiamente usato in ambienti Java, come server applicativi (es. Tomcat, Spring Boot).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PKCS#12 (PFX o P12)&lt;/strong&gt;: è un &lt;a href="https://en.wikipedia.org/wiki/PKCS_12" rel="noopener noreferrer"&gt;formato standard&lt;/a&gt; per contenere certificati e chiavi private. Viene usato su diversi sistemi operativi e server. Ad esempio, i file &lt;code&gt;.pfx&lt;/code&gt; o &lt;code&gt;.p12&lt;/code&gt; possono essere caricati in un server come Apache o NGINX.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keychain (macOS)&lt;/strong&gt;: Su macOS, i certificati e le chiavi private possono essere memorizzati nel &lt;strong&gt;Keychain&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Il formato &lt;strong&gt;JKS&lt;/strong&gt; è ancora supportato ma sconsigliato l'uso in favore di &lt;strong&gt;PKCS#12&lt;/strong&gt; , soprattutto per nuove implementazioni, poiché offre una migliore sicurezza e compatibilità.&lt;/p&gt;

&lt;h4&gt;
  
  
  3. Verifica tramite CRL o OCSP
&lt;/h4&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;CRL (Certificate Revocation List)&lt;/strong&gt;: è 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.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OCSP (Online Certificate Status Protocol)&lt;/strong&gt;: invece di scaricare un'intera lista, il sistema può interrogare un server OCSP per verificare in tempo reale se un certificato è stato revocato.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Volendo fare un riassunto, ecco un elenco dei principali componenti coinvolti nella gestione dei certificati e nella verifica durante l'handshake TLS/mTLS.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Truststore&lt;/strong&gt; : contiene i certificati delle CA radice fidate e viene usato per verificare i certificati ricevuti da client o server.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keystore&lt;/strong&gt; : contiene il certificato dell'entità (client o server) e la relativa chiave privata. Viene usato per l'autenticazione.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CRL/OCSP&lt;/strong&gt; : utilizzati per controllare la revoca dei certificati.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;Vi posso consigliare di esplorare il progetto su GitHub &lt;a href="https://github.com/amusarra/docker-apache-ssl-tls-mutual-authentication" rel="noopener noreferrer"&gt;docker-apache-ssl-tls-mutual-authentication&lt;/a&gt; e il relativo articolo &lt;a href="http://bit.ly/2Sm5dU7" rel="noopener noreferrer"&gt;Docker Image Apache SSL/TLS Mutual Authentication on Azure Cloud&lt;/a&gt; per avere un'idea pratica di come implementare mTLS con Apache.&lt;/p&gt;

&lt;h2&gt;
  
  
  Perché gestire mTLS direttamente sull'applicazione?
&lt;/h2&gt;

&lt;p&gt;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?&lt;/p&gt;

&lt;p&gt;È 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.&lt;/p&gt;

&lt;h3&gt;
  
  
  Vantaggi di configurare mTLS direttamente sull’applicazione
&lt;/h3&gt;

&lt;p&gt;A seguire vedremo brevemente quali siano i vantaggi principali nell'adozione di questa scelta.&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Maggiore controllo e flessibilità
&lt;/h4&gt;

&lt;p&gt;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:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;quali endpoint richiedono mTLS e quali no;&lt;/li&gt;
&lt;li&gt;diversificare la gestione dei certificati a livello di servizio o microservizio in base alle esigenze di sicurezza specifiche.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Questo tipo di configurazione può essere particolarmente utile in ambienti &lt;strong&gt;multi-tenant&lt;/strong&gt; o con &lt;strong&gt;servizi sensibili&lt;/strong&gt; , dove i requisiti di sicurezza possono variare da un microservizio all’altro.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Difesa in profondità
&lt;/h4&gt;

&lt;p&gt;In sicurezza informatica, il principio di &lt;strong&gt;difesa in profondità&lt;/strong&gt; (vedi sezione &lt;a href="https://www.cybersecurity360.it/outlook/i-nuovi-standard-degli-iacs-che-cosa-sono-e-a-cosa-servono/" rel="noopener noreferrer"&gt;Importanti principi di protezione dell’ISA/IEC 62443&lt;/a&gt;) 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:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;se l’infrastruttura del gateway viene bypassata o compromessa, l’applicazione richiede comunque l’autenticazione reciproca per accedere.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h4&gt;
  
  
  3. Sicurezza end-to-end
&lt;/h4&gt;

&lt;p&gt;Gestendo mTLS a livello dell’applicazione, puoi garantire una &lt;strong&gt;sicurezza end-to-end&lt;/strong&gt; 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 &lt;strong&gt;fino all’applicazione stessa&lt;/strong&gt; , non solo fino al gateway.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I &lt;strong&gt;certificati del client&lt;/strong&gt; 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.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  4. Riduzione della complessità di infrastruttura
&lt;/h4&gt;

&lt;p&gt;In alcune architetture moderne, come quelle &lt;strong&gt;serverless&lt;/strong&gt; o &lt;strong&gt;microservizi in ambienti containerizzati&lt;/strong&gt; , 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:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;in ambienti dinamici, dove i microservizi si scalano rapidamente, l’uso di &lt;strong&gt;service mesh&lt;/strong&gt; (ad esempio &lt;a href="https://istio.io/" rel="noopener noreferrer"&gt;Istio&lt;/a&gt;) o configurazioni centralizzate a livello di applicazione può risultare più gestibile rispetto a delegare tutto ai dispositivi di front-end.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  5. Ambienti multi-cloud o ibridi
&lt;/h4&gt;

&lt;p&gt;In contesti &lt;strong&gt;multi-cloud&lt;/strong&gt; o &lt;strong&gt;ibridi&lt;/strong&gt; , 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.&lt;/p&gt;

&lt;h4&gt;
  
  
  6. Indipendenza dai dispositivi di rete
&lt;/h4&gt;

&lt;p&gt;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 &lt;strong&gt;portabilità&lt;/strong&gt; tra ambienti diversi (ad esempio, passare da un cloud provider all’altro senza dover riconfigurare l’infrastruttura di sicurezza a monte).&lt;/p&gt;

&lt;h4&gt;
  
  
  7. Testing e sviluppo più sicuri
&lt;/h4&gt;

&lt;p&gt;Configurare mTLS direttamente nell’applicazione permette di simulare e testare scenari di sicurezza anche in ambienti di &lt;strong&gt;sviluppo&lt;/strong&gt; o &lt;strong&gt;pre-produzione&lt;/strong&gt; , senza dover riprodurre l’intera infrastruttura di produzione. In questo modo, i team di sviluppo possono:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;testare con maggiore precisione le configurazioni di sicurezza che verranno utilizzate in produzione;&lt;/li&gt;
&lt;li&gt;implementare flussi di &lt;strong&gt;&lt;a href="https://it.wikipedia.org/wiki/DevOps" rel="noopener noreferrer"&gt;DevSecOps&lt;/a&gt;&lt;/strong&gt; più fluidi, dove la sicurezza viene verificata in ogni fase del ciclo di vita del software.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  8. Personalizzazione della logica di autenticazione
&lt;/h4&gt;

&lt;p&gt;In alcuni casi, potrebbe essere necessario &lt;strong&gt;personalizzare la logica di autenticazione&lt;/strong&gt; in base alle esigenze specifiche dell’applicazione. Configurare mTLS direttamente nel codice o nelle configurazioni dell’applicazione permette di introdurre logiche personalizzate come:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;validazioni aggiuntive sui certificati;&lt;/li&gt;
&lt;li&gt;limitare l’accesso a specifici client in base a metadati contenuti nei certificati.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Quando usare dispositivi dedicati per la gestione di mTLS?
&lt;/h3&gt;

&lt;p&gt;Nonostante i vantaggi della configurazione di mTLS direttamente nell’applicazione, ci sono contesti in cui l’uso di dispositivi dedicati rimane una scelta preferibile.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scalabilità centralizzata&lt;/strong&gt; : 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.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance e ottimizzazione&lt;/strong&gt; : 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.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Amministrazione centralizzata&lt;/strong&gt; : 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.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  In conclusione
&lt;/h3&gt;

&lt;p&gt;Configurare &lt;strong&gt;mTLS direttamente sull’applicazione&lt;/strong&gt; 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 &lt;strong&gt;difesa in profondità&lt;/strong&gt; è un requisito fondamentale.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quale scenario andremo a implementare
&lt;/h2&gt;

&lt;p&gt;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:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;il &lt;strong&gt;Client&lt;/strong&gt; inizia la connessione TLS con l’applicazione &lt;strong&gt;Quarkus&lt;/strong&gt; ;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Quarkus&lt;/strong&gt; richiede il certificato del client come parte della procedura di autenticazione reciproca mTLS;&lt;/li&gt;
&lt;li&gt;il &lt;strong&gt;Client&lt;/strong&gt; invia il proprio certificato;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Quarkus&lt;/strong&gt; verifica il certificato del client

&lt;ol&gt;
&lt;li&gt;se il certificato è valido, &lt;strong&gt;Quarkus&lt;/strong&gt; elabora la richiesta di accesso alla risorsa e restituisce i dati della risorsa;&lt;/li&gt;
&lt;li&gt;se il certificato non è valido, &lt;strong&gt;Quarkus&lt;/strong&gt; restituisce un errore, negando l’accesso alla risorsa.&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;/ol&gt;

&lt;p&gt;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 &lt;em&gt;Cos’è l’autenticazione reciproca TLS (mTLS)&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;sequenceDiagram participant Client participant QuarkusApp as Quarkus Application %% TLS Handshake Note over Client, QuarkusApp: TLS Handshake Starts Client-&amp;gt;&amp;gt;QuarkusApp: Initiate TLS handshake QuarkusApp-&amp;gt;&amp;gt;Client: Request Client Certificate Client-&amp;gt;&amp;gt;QuarkusApp: Send Client Certificate Note over Client, QuarkusApp: TLS Handshake Complete QuarkusApp-&amp;gt;&amp;gt;QuarkusApp: Verify Client Certificate via mTLS %% Resource Request alt Valid Client Certificate Client-&amp;gt;&amp;gt;QuarkusApp: Request access to /resource QuarkusApp-&amp;gt;&amp;gt;QuarkusApp: Process the request QuarkusApp-&amp;gt;&amp;gt;Client: Return /resource data else Invalid Client Certificate QuarkusApp-&amp;gt;&amp;gt;Client: Error: Invalid Client Certificate end&lt;/p&gt;

&lt;p&gt;Figura 2 - Sequence diagramm della soluzione di mTLS da implementare tramite Quarkus&lt;/p&gt;

&lt;p&gt;Per realizzare la soluzione mostrata nel diagramma precedente, avremo bisogno dei seguenti strumenti software.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Java 21&lt;/li&gt;
&lt;li&gt;Maven (per la gestione del progetto)&lt;/li&gt;
&lt;li&gt;Quarks CLI (per l'installazione fare riferimento &lt;a href="https://quarkus.io/guides/cli-tooling" rel="noopener noreferrer"&gt;Building Quarkus apps with Quarkus Command Line Interface (CLI)&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Certificati TLS per il client e il server&lt;/li&gt;
&lt;li&gt;OpenSSL per gestire la generazione dei certificati&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nel corso dell'implementazione andremo a utilizzare diversi componenti di Quarkus che rientrano nel panorama dell' &lt;strong&gt;architettura di sicurezza&lt;/strong&gt; di Quarkus e per cui invito a leggere le seguenti risorse.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://quarkus.io/guides/security-architecture" rel="noopener noreferrer"&gt;Quarkus Security architecture&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://quarkus.io/guides/security-overview" rel="noopener noreferrer"&gt;Quarkus Security overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://quarkus.io/guides/security-authentication-mechanisms#built-in-authentication-mechanisms" rel="noopener noreferrer"&gt;Built-in authentication mechanisms&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://quarkus.io/guides/security-authorize-web-endpoints-reference" rel="noopener noreferrer"&gt;Authorization of web endpoints&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://quarkus.io/guides/tls-registry-reference" rel="noopener noreferrer"&gt;TLS registry reference&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;La figura 3 mostra l'architettura di sicurezza di Quarkus, dove ho volutamente evidenziare lo strato che riguarda il componente &lt;strong&gt;&lt;a href="https://quarkus.io/guides/security-architecture#securityidentityaugmentor" rel="noopener noreferrer"&gt;SecurityIdentityAugmentor&lt;/a&gt;&lt;/strong&gt; perché nel corso dell'articolo vedremo a cosa serve questo componente e come implementare una personalizzazione utile per i nostri scopi.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F65v4ohti1x18qzvque1i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F65v4ohti1x18qzvque1i.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figura 3 - Quarkus Security Architecture e flow del processo di autenticazione e autorizzazione (fonte Quarkus.io)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Tra l'elenco delle risorse ho menzionato il &lt;strong&gt;TLS Registry&lt;/strong&gt; che utilizzeremo per portare a termine con successo l'implementazione della soluzione.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cos’è il TLS Registry di Quarkus?&lt;/strong&gt; È 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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Requisiti dell'applicazione Quarkus
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;ID&lt;/th&gt;
&lt;th&gt;Requisito&lt;/th&gt;
&lt;th&gt;Descrizione&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Autenticazione mTLS&lt;/td&gt;
&lt;td&gt;È richiesto che l'applicazione supporti mTLS come meccanismo di autenticazione utilizzando certificati in formato PEM e PKCS#12.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Private end-point REST&lt;/td&gt;
&lt;td&gt;È 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 &lt;em&gt;Generazione dei certificati&lt;/em&gt;).&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Il primo end-point deve essere definito con la URI &lt;code&gt;/v1/connection-info/info&lt;/code&gt; con metodo &lt;code&gt;GET&lt;/code&gt; e produrre un JSON avente la struttura mostrata al capitolo &lt;em&gt;Struttura JSON di risposta dei servizi REST&lt;/em&gt;. La risposta del servizio conterrà un set d'informazioni che riguardano la connessione instaurata.  &lt;/p&gt;

&lt;p&gt;Il secondo end-point deve essere definito con la URI &lt;code&gt;/v1/connection-info/user-identity&lt;/code&gt; con metodo &lt;code&gt;GET&lt;/code&gt; e produrre un JSON avente la struttura mostrata al capitolo &lt;em&gt;Struttura JSON di risposta dei servizi REST&lt;/em&gt;. La risposta del servizio conterrà un set d'informazioni che riguardano l'indentità del client che ha richiesto l'accesso alla risorsa. |&lt;br&gt;
| 3 | Mapping automatico dei ruoli | È richiesto che l'applicazione sia capace di mappare attributi specifici del certificato client sui &lt;strong&gt;ruoli&lt;/strong&gt; gestisti da Quarkus (vedi &lt;a href="https://quarkus.io/guides/security-authorize-web-endpoints-reference" rel="noopener noreferrer"&gt;Authorization of web endpoints&lt;/a&gt;). Per i dettagli sulla struttura del certificato client fare riferimento al capitolo &lt;em&gt;Generazione dei certificati&lt;/em&gt;. |&lt;br&gt;
| 4 | Mapping automatico degli attributi d'identità | È richiesto che l'applicazione sia capace di mappare attributi specifici del certificato client sugli &lt;strong&gt;Identity Attributes&lt;/strong&gt; del client che ha richiesto l'accesso alla risorsa. Per i dettagli sulla struttura del certificato client fare riferimento al capitolo &lt;em&gt;Generazione dei certificati&lt;/em&gt;. |&lt;br&gt;
| 5 | Definizione delle policy di accesso ai servizi Rest | È richiesto che l'applicazione definisca una policy chiamata per esempio &lt;code&gt;role-policy-cert&lt;/code&gt; che definisca i ruoli &lt;em&gt;User&lt;/em&gt; e &lt;em&gt;Administrator&lt;/em&gt; come abilitati per l'accesso alle due risorse REST descritte sul requisito numero 1. |&lt;br&gt;
| 6_BONUS | Integrazione Trusted Service List (TSL) | È richiesto che l'applicazione sia integrata con il &lt;strong&gt;Trusted Service List (TSL)&lt;/strong&gt; 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. |&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Tabella 1 - Requisiti che l'applicazione Quarkus deve implementare.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Generazione dei certificati
&lt;/h3&gt;

&lt;p&gt;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 &lt;a href="https://en.wikipedia.org/wiki/X.509#Certificates" rel="noopener noreferrer"&gt;X.509&lt;/a&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;un certificato di &lt;a href="https://it.wikipedia.org/wiki/Certificate_authority" rel="noopener noreferrer"&gt;Certificate Authority (CA)&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;un certificato server per il servizio HTTPS, quest'ultimo basato su &lt;a href="https://vertx.io/docs/vertx-core/java/" rel="noopener noreferrer"&gt;Vert.x Core&lt;/a&gt; integrato all'interno di Quarkus;&lt;/li&gt;
&lt;li&gt;un set di &lt;a href="https://en.wikipedia.org/wiki/Client_certificate" rel="noopener noreferrer"&gt;certificati client&lt;/a&gt; che devono avere specifiche caratteristiche per accedere ai servizi (vedi requisiti tre, quattro e sei).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tipo&lt;/th&gt;
&lt;th&gt;CN&lt;/th&gt;
&lt;th&gt;SAN&lt;/th&gt;
&lt;th&gt;O&lt;/th&gt;
&lt;th&gt;OU&lt;/th&gt;
&lt;th&gt;L&lt;/th&gt;
&lt;th&gt;ST&lt;/th&gt;
&lt;th&gt;C&lt;/th&gt;
&lt;th&gt;Valitità&lt;/th&gt;
&lt;th&gt;Issuer&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;CA&lt;/td&gt;
&lt;td&gt;Dontesta CA&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Dontesta&lt;/td&gt;
&lt;td&gt;IT Labs&lt;/td&gt;
&lt;td&gt;Bronte&lt;/td&gt;
&lt;td&gt;Catania&lt;/td&gt;
&lt;td&gt;IT&lt;/td&gt;
&lt;td&gt;5 anni&lt;/td&gt;
&lt;td&gt;self&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Server&lt;/td&gt;
&lt;td&gt;rd.quarkus.dontesta.it&lt;/td&gt;
&lt;td&gt;admin.quarkus.dontesta.it, blog.quarkus.dontesta.it, localhost&lt;/td&gt;
&lt;td&gt;Dontesta&lt;/td&gt;
&lt;td&gt;IT Labs&lt;/td&gt;
&lt;td&gt;Bronte&lt;/td&gt;
&lt;td&gt;Catania&lt;/td&gt;
&lt;td&gt;IT&lt;/td&gt;
&lt;td&gt;1 anno&lt;/td&gt;
&lt;td&gt;Dontesta CA, Dontesta&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Client&lt;/td&gt;
&lt;td&gt;#client-id (può essere un qualunque tipo di identificatore)&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;#Organization&lt;/td&gt;
&lt;td&gt;#OrganizationUnit&lt;/td&gt;
&lt;td&gt;#Locality&lt;/td&gt;
&lt;td&gt;#State&lt;/td&gt;
&lt;td&gt;#Country&lt;/td&gt;
&lt;td&gt;#Validity&lt;/td&gt;
&lt;td&gt;#Issuer&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Tabella 2 - Caratteristiche dei certificati da generare&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nota&lt;/strong&gt; : gli FQDN (Fully Qualified Domain Name) usati nei certificati sono puramente di esempio e andranno poi sostituiti con quelli reali.&lt;/p&gt;

&lt;p&gt;Per soddisfare il requisito tre e quattro, il certificato client deve essere creato con le seguenti caratteristiche:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;clientAuth in extendedKeyUsage&lt;/strong&gt; : l’extendedKeyUsage con il valore &lt;strong&gt;clientAuth&lt;/strong&gt; 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’**&lt;a href="https://en.wikipedia.org/wiki/Object_identifier" rel="noopener noreferrer"&gt;Object Identifier (OID)&lt;/a&gt;** 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;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;estensione personalizzate&lt;/strong&gt; : per gestire i ruoli e attributi, i certificati client dovranno avere le seguenti estensioni personalizzate:

&lt;ol&gt;
&lt;li&gt;1.3.6.1.4.1.99999.1 = ASN1:UTF8String:Role=${ext_cert_role}&lt;/li&gt;
&lt;li&gt;1.3.6.1.4.1.99999.2 = ASN1:UTF8String:DeviceId=${ext_cert_device_id}&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;/ol&gt;

&lt;p&gt;Le due estensioni personalizzate che sono identificate con OID della classe privata &lt;code&gt;1.3.6.1.4.1&lt;/code&gt; dove &lt;code&gt;99999&lt;/code&gt; rappresenta un numero riservato per un’ipotetica organizzazione, sono usate rispettivamente per indicare &lt;strong&gt;ruoli&lt;/strong&gt; e il &lt;strong&gt;deviceId&lt;/strong&gt;. I placeholder &lt;code&gt;${ext_cert_role}&lt;/code&gt; e &lt;code&gt;${ext_cert_device_id}&lt;/code&gt; conterranno i rispettivi valori per Role e DeviceId.&lt;/p&gt;

&lt;p&gt;L'estensione personalizzata avente OID &lt;code&gt;1.3.6.1.4.1.99999.1&lt;/code&gt; deve contenere uno più ruoli attraverso una stringa che dovrà rispettare il pattern &lt;code&gt;^Role=([A-Za-z]+(?:,[A-Za-z]+)*+)$&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;L'estensione personalizzata avente OID &lt;code&gt;1.3.6.1.4.1.99999.2&lt;/code&gt; deve contenere l'identificativo di un ipotetico deviceId il cui valore deve essere calcolato secondo un regola ben definita e che vedremo successivamente.&lt;/p&gt;

&lt;p&gt;In termini di configurazione OpenSSL, a seguire è mostrato un esempio di configurazione da usare per la generazione dei certificati client usando OpenSSL.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[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}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;INI&lt;/p&gt;

&lt;p&gt;Configurazione 1 - Configurazione di OpenSSL per la generazione dei certificati client&lt;/p&gt;

&lt;p&gt;L'extendedKeyUsage clientAuth ha il flag a &lt;strong&gt;critical&lt;/strong&gt; 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).&lt;/p&gt;

&lt;p&gt;A seguire è mostrato un estratto della chiave pubblica di un certificato client generato secondo le specifiche discusse in precendenza. La sezione &lt;strong&gt;X509v3 extensions&lt;/strong&gt; mostra appunto le estensioni usate, sia quelle standard, sia quelle personalizzate.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;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;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:...

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Plaintext&lt;/p&gt;

&lt;p&gt;Configurazione 2 - Estratto della chiave pubblica di un certificato client generato secondo le specifiche.&lt;/p&gt;

&lt;h4&gt;
  
  
  Algoritmo per la generazione del DeviceId
&lt;/h4&gt;

&lt;p&gt;La generazione del DeviceId dovrà avvenire nel modo seguente:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;combina il timestamp corrente, un &lt;a href="https://it.wikipedia.org/wiki/Universally_unique_identifier" rel="noopener noreferrer"&gt;UUID (Universally Unique Identifier)&lt;/a&gt; generato e l’hostname del dispositivo per creare una stringa unica. Le singole informazioni devono essere separate dal carattere # (hash o diesis);&lt;/li&gt;
&lt;li&gt;genera un &lt;a href="https://it.wikipedia.org/wiki/HMAC" rel="noopener noreferrer"&gt;HMAC (Hash-based Message Authentication Code)&lt;/a&gt; usando SHA-256 e una chiave segreta;&lt;/li&gt;
&lt;li&gt;combina queste informazioni e codifica il risultato in Base64.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Il processo di verifica, è praticamente l'inverso:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;decodifica un DeviceId codificato in Base64;&lt;/li&gt;
&lt;li&gt;separa la stringa combinata e l’HMAC fornito;&lt;/li&gt;
&lt;li&gt;rigenera l’HMAC basandosi sulla stringa originale.&lt;/li&gt;
&lt;li&gt;confronta l’HMAC calcolato con quello fornito per verificare la validità dell’ID.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A seguire è mostrato il flow di quanto descritto in precedenza per generare e verificare il DeviceId.&lt;/p&gt;

&lt;p&gt;graph TD A((Start)) --&amp;gt; B{Command?} B --&amp;gt; |Generate| C[Collect timestamp, UUID, and hostname] C --&amp;gt; D[Create combined string] D --&amp;gt; E[Generate HMAC SHA-256 with secret key] E --&amp;gt; F[Combine with HMAC and encode in Base64] F --&amp;gt; G[Return Base64 Device ID] B --&amp;gt; |Verify| H[Decode Base64 Device ID] H --&amp;gt; I[Extract combined string and provided HMAC] I --&amp;gt; J[Recalculate HMAC using secret key] J --&amp;gt; K{Compare HMACs} K --&amp;gt; |Match| L[Device ID verified] K --&amp;gt; |Mismatch| M[Verification failed] G --&amp;gt; N((End)) L --&amp;gt; N M --&amp;gt; N&lt;/p&gt;

&lt;p&gt;Figura 4 - Flow per la generazione e verifica del DeviceId.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# 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="${timestamp}#${uuid}#${hostname}"
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 "$combined_string" | openssl dgst -sha256 -hmac "$DEVICE_ID_SECRET_KEY" | awk '{print $2}')
a7d2ff42462b0fcada335b007ca7a8a6975d66e6a70877c53733efbf380d1d97

# Combine the device ID with the HMAC
# device_id="${combined_string}#${hmac}"
1726134463113076000#41bf4014-e41e-49ae-a582-652b0a335e17#amusarra-macbook-pro.local#a7d2ff42462b0fcada335b007ca7a8a6975d66e6a70877c53733efbf380d1d97

# DeviceId in Base64
# Encode the result using Base64
# encoded_device_id=$(echo -n "$device_id" | base64)
MTcyNjEzNDQ2MzExMzA3NjAwMCM0MWJmNDAxNC1lNDFlLTQ5YWUtYTU4Mi02NTJiMGEzMzVlMTcjYW11c2FycmEtbWFjYm9vay1wcm8ubG9jYWwjYTdkMmZmNDI0NjJiMGZjYWRhMzM1YjAwN2NhN2E4YTY5NzVkNjZlNmE3MDg3N2M1MzczM2VmYmYzODBkMWQ5Nw==

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;Source Code 1 - Pseudo codice che mostra la generazione del DeviceId&lt;/p&gt;

&lt;p&gt;Volendo implementare uno script per la generazione e verifica del DeviceId, quello a seguire è il sequence diagram.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmozxprfee6c1fssncwht.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmozxprfee6c1fssncwht.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figura 5 - Sequence Diagram che mostra il funzionamento di un ipotetico script di generazione e verifica del DeviceId.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Struttura JSON di risposta dei servizi REST
&lt;/h3&gt;

&lt;p&gt;A seguire lo schema del JSON di risposta per il servizio &lt;code&gt;/api/v1/connection-info/user-identity&lt;/code&gt; e un esempio dell'istanza.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "type": "object",
  "properties": {
    "principal": {
      "type": "string",
      "description": "A distinguished name (DN) representing the principal."
    },
    "roles": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "An array of roles assigned to the principal."
    },
    "attributes": {
      "type": "object",
      "properties": {
        "deviceId": {
          "type": "string",
          "description": "An identifier for the device associated with the principal."
        }
      },
      "required": ["deviceId"],
      "description": "Additional attributes related to the principal."
    },
    "userCN": {
      "type": "string",
      "description": "The common name (CN) of the user."
    }
  },
  "required": ["principal", "roles", "attributes", "userCN"],
  "description": "Schema for representing a user principal with roles and attributes."
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;JSON&lt;/p&gt;

&lt;p&gt;Source Code 2 - Schema del JSON di risposta per il servizio &lt;code&gt;/api/v1/connection-info/user-identity&lt;/code&gt;&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "principal": "CN=24A5CCC7-EE36-4449-9025-54CED3011920,OU=Community &amp;amp; News,O=Bad Corporation,L=Rome,ST=Italy,C=IT",
  "roles": [
    "User",
    "CommunityManager"
  ],
  "attributes": {
    "deviceId": "MTcyNjEzNDQ2MzExMzA3NjAwMCM0MWJmNDAxNC1lNDFlLTQ5YWUtYTU4Mi02NTJiMGEzMzVlMTcjYW11c2FycmEtbWFjYm9vay1wcm8ubG9jYWwjYTdkMmZmNDI0NjJiMGZjYWRhMzM1YjAwN2NhN2E4YTY5NzVkNjZlNmE3MDg3N2M1MzczM2VmYmYzODBkMWQ5Nw=="
  },
  "userCN": "24A5CCC7-EE36-4449-9025-54CED3011920"
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;JSON&lt;/p&gt;

&lt;p&gt;Source Code 3 - Esempio di risposta JSON del servizio &lt;code&gt;/api/v1/connection-info/user-identity&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;A seguire lo schema del JSON di risposta per il servizio &lt;code&gt;/api/v1/connection-info/info&lt;/code&gt; e un esempio dell'istanza.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "type": "object",
  "properties": {
    "httpRequestHeaders": {
      "type": "object",
      "properties": {
        "user-agent": {
          "type": "string",
          "description": "User agent string of the HTTP request."
        },
        "accept": {
          "type": "string",
          "description": "Accept header of the HTTP request."
        }
      },
      "required": ["user-agent", "accept"],
      "description": "Headers of the HTTP request."
    },
    "server": {
      "type": "object",
      "properties": {
        "notAfter": {
          "type": "string",
          "description": "Expiration date of the server's certificate."
        },
        "keyAlgorithm": {
          "type": "string",
          "description": "Algorithm used for the server's key."
        },
        "keySize": {
          "type": "integer",
          "description": "Size of the server's key in bits."
        },
        "certCommonName": {
          "type": "string",
          "description": "Common name of the server's certificate."
        },
        "certIssuer": {
          "type": "string",
          "description": "Issuer of the server's certificate."
        },
        "subjectAlternativeNames": {
          "type": "array",
          "items": {
            "type": "array",
            "items": [
              { "type": "integer" },
              { "type": "string" }
            ]
          },
          "description": "Subject alternative names in the server's certificate."
        },
        "certSubject": {
          "type": "string",
          "description": "Subject of the server's certificate."
        },
        "certSerialNumber": {
          "type": "string",
          "description": "Serial number of the server's certificate."
        },
        "certPEM": {
          "type": "string",
          "description": "PEM encoded server certificate."
        },
        "customExtensions": {
          "type": "object",
          "description": "Custom extensions for the server's certificate."
        },
        "notBefore": {
          "type": "string",
          "description": "Start date of validity for the server's certificate."
        }
      },
      "required": [
        "notAfter",
        "keyAlgorithm",
        "keySize",
        "certCommonName",
        "certIssuer",
        "subjectAlternativeNames",
        "certSubject",
        "certSerialNumber",
        "certPEM",
        "notBefore"
      ],
      "description": "Details about the server's certificate and key."
    },
    "protocol": {
      "type": "string",
      "description": "Protocol used for the connection (e.g., TLS version)."
    },
    "httpProtocol": {
      "type": "string",
      "description": "HTTP protocol version (e.g., HTTP/2)."
    },
    "clientPort": {
      "type": "integer",
      "description": "Port number used by the client."
    },
    "isSecure": {
      "type": "boolean",
      "description": "Indicates if the connection is secure."
    },
    "client": {
      "type": "object",
      "properties": {
        "notAfter": {
          "type": "string",
          "description": "Expiration date of the client's certificate."
        },
        "keyAlgorithm": {
          "type": "string",
          "description": "Algorithm used for the client's key."
        },
        "keySize": {
          "type": "integer",
          "description": "Size of the client's key in bits."
        },
        "certCommonName": {
          "type": "string",
          "description": "Common name of the client's certificate."
        },
        "certIssuer": {
          "type": "string",
          "description": "Issuer of the client's certificate."
        },
        "subjectAlternativeNames": {
          "type": "null",
          "description": "Subject alternative names in the client's certificate, if any."
        },
        "certSubject": {
          "type": "string",
          "description": "Subject of the client's certificate."
        },
        "certSerialNumber": {
          "type": "string",
          "description": "Serial number of the client's certificate."
        },
        "certPEM": {
          "type": "string",
          "description": "PEM encoded client certificate."
        },
        "customExtensions": {
          "type": "object",
          "properties": {
            "role": {
              "type": "string",
              "description": "Custom role information in the client's certificate."
            },
            "deviceId": {
              "type": "string",
              "description": "Custom device ID information in the client's certificate."
            }
          },
          "description": "Custom extensions for the client's certificate."
        },
        "notBefore": {
          "type": "string",
          "description": "Start date of validity for the client's certificate."
        }
      },
      "required": [
        "notAfter",
        "keyAlgorithm",
        "keySize",
        "certCommonName",
        "certIssuer",
        "certSubject",
        "certSerialNumber",
        "certPEM",
        "notBefore"
      ],
      "description": "Details about the client's certificate and key."
    },
    "userAgent": {
      "type": "string",
      "description": "User agent string used by the client."
    },
    "cipherSuite": {
      "type": "string",
      "description": "Cipher suite used for the connection."
    },
    "clientAddress": {
      "type": "string",
      "description": "Address and port of the client."
    }
  },
  "required": [
    "httpRequestHeaders",
    "server",
    "protocol",
    "httpProtocol",
    "clientPort",
    "isSecure",
    "client",
    "userAgent",
    "cipherSuite",
    "clientAddress"
  ],
  "description": "Schema representing a network connection including server and client details, protocols, and certificates."
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;JSON&lt;/p&gt;

&lt;p&gt;Source Code 4 - Schema del JSON di risposta per il servizio &lt;code&gt;/api/v1/connection-info/info&lt;/code&gt;&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "httpRequestHeaders": {
    "user-agent": "curl/8.7.1",
    "accept": "*/*"
  },
  "server": {
    "notAfter": "Sun Sep 07 00:16:21 CEST 2025",
    "keyAlgorithm": "RSA",
    "keySize": 2048,
    "certCommonName": "rd.quarkus.dontesta.it",
    "certIssuer": "CN=Dontesta CA,OU=IT Labs,O=Dontesta,L=Bronte,ST=Catania,C=IT",
    "subjectAlternativeNames": [
      [
        2,
        "admin.quarkus.dontesta.it"
      ],
      [
        2,
        "blog.quarkus.dontesta.it"
      ],
      [
        2,
        "localhost"
      ]
    ],
    "certSubject": "CN=rd.quarkus.dontesta.it,OU=IT Labs,O=Dontesta,L=Bronte,ST=Catania,C=IT",
    "certSerialNumber": "581958667903693191343101950434363490497173665817",
    "certPEM": "&amp;lt;certPEM&amp;gt;",
    "customExtensions": {},
    "notBefore": "Sat Sep 07 00:16:21 CEST 2024"
  },
  "protocol": "TLSv1.3",
  "httpProtocol": "HTTP_2",
  "clientPort": 54845,
  "isSecure": true,
  "client": {
    "notAfter": "Fri Sep 12 11:47:43 CEST 2025",
    "keyAlgorithm": "RSA",
    "keySize": 2048,
    "certCommonName": "24A5CCC7-EE36-4449-9025-54CED3011920",
    "certIssuer": "CN=Dontesta CA,OU=IT Labs,O=Dontesta,L=Bronte,ST=Catania,C=IT",
    "subjectAlternativeNames": null,
    "certSubject": "CN=24A5CCC7-EE36-4449-9025-54CED3011920,OU=Community &amp;amp; News,O=Bad Corporation,L=Rome,ST=Italy,C=IT",
    "certSerialNumber": "581958667903693191343101950434363490497173665825",
    "certPEM": "&amp;lt;certPEM&amp;gt;",
    "customExtensions": {
      "role": "Role=User,CommunityManager",
      "deviceId": "DeviceId=MTcyNjEzNDQ2MzExMzA3NjAwMCM0MWJmNDAxNC1lNDFlLTQ5YWUtYTU4Mi02NTJiMGEzMzVlMTcjYW11c2FycmEtbWFjYm9vay1wcm8ubG9jYWwjYTdkMmZmNDI0NjJiMGZjYWRhMzM1YjAwN2NhN2E4YTY5NzVkNjZlNmE3MDg3N2M1MzczM2VmYmYzODBkMWQ5Nw=="
    },
    "notBefore": "Thu Sep 12 11:47:43 CEST 2024"
  },
  "userAgent": "curl/8.7.1",
  "cipherSuite": "TLS_AES_256_GCM_SHA384",
  "clientAddress": "127.0.0.1:54845"
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;JSON&lt;/p&gt;

&lt;p&gt;Source Code 5 - Esempio di risposta JSON del servizio &lt;code&gt;/api/v1/connection-info/info&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Requisiti software
&lt;/h2&gt;

&lt;p&gt;Per sviluppare la nostra soluzione mTLS, abbiamo necessità di un set di strumenti software che potremmo dividere in due categorie.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Sviluppo&lt;/strong&gt;

&lt;ol&gt;
&lt;li&gt;Java 21&lt;/li&gt;
&lt;li&gt;Maven 3.9.x&lt;/li&gt;
&lt;li&gt;Quarkus 3.14.x&lt;/li&gt;
&lt;li&gt;Quarkus CLI (opzionale ma consigliato)&lt;/li&gt;
&lt;li&gt;Git (opzionale ma consigliato)&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Gestione certificati TLS&lt;/strong&gt; (opzionali ma consigliato)

&lt;ol&gt;
&lt;li&gt;bash 5.2.x | zsh 5.x | GitBash 2.46&lt;/li&gt;
&lt;li&gt;OpenSSL 3.x&lt;/li&gt;
&lt;li&gt;Curl 8.x&lt;/li&gt;
&lt;li&gt;Java KeyTool (in genere installato con la JDK)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/benibela/xidel" rel="noopener noreferrer"&gt;Xidel&lt;/a&gt; è uno strumento da riga di comando e una libreria che consente di estrarre dati da documenti XML, HTML e JSON usando XPath, XQuery o CSS Selectors&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;/ol&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;La &lt;a href="https://quarkus.io/get-started/" rel="noopener noreferrer"&gt;Quarkus CLI&lt;/a&gt; è 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.&lt;/p&gt;

&lt;p&gt;Git è opzionale ma consigliato se volete seguire gli step di questo articolo e clonare il repository del progetto completo.&lt;/p&gt;

&lt;p&gt;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).&lt;/p&gt;

&lt;p&gt;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 &lt;a href="https://quarkus.io/guides/tls-registry-reference#quarkus-cli-commands-and-development-ca-certificate-authority" rel="noopener noreferrer"&gt;Quarkus CLI commands and development CA (Certificate Authority)&lt;/a&gt; e &lt;a href="https://quarkus.io/guides/tls-registry-reference#lets-encrypt" rel="noopener noreferrer"&gt;Automatic certificate management with Let’s Encrypt&lt;/a&gt; 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.&lt;/p&gt;

&lt;p&gt;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 &lt;em&gt;Requisiti dell'applicazione Quarkus&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementazione della soluzione
&lt;/h2&gt;

&lt;p&gt;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 &lt;em&gt;Requisiti dell'applicazione Quarkus&lt;/em&gt;. 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.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Creazione dell'applicazione Quarkus tramite CLI specificando le estensioni necessarie.&lt;/li&gt;
&lt;li&gt;Generazione del certificato di Certification Authority.&lt;/li&gt;
&lt;li&gt;Generazione del certificato Server rilasciato dalla CA (creata alla step precedente).&lt;/li&gt;
&lt;li&gt;Configurazione di Quarkus per l'attivazione di HTTPS.&lt;/li&gt;
&lt;li&gt;Test della configurazione HTTPS/TLS.&lt;/li&gt;
&lt;li&gt;Abilitazione del mTLS.&lt;/li&gt;
&lt;li&gt;Implementazione dei componenti &lt;a href="https://quarkus.io/guides/security-architecture#securityidentityaugmentor" rel="noopener noreferrer"&gt;SecurityIdentityAugmentor&lt;/a&gt; per il mapping dei ruoli e attributi.&lt;/li&gt;
&lt;li&gt;Implementazione dei servizi REST.&lt;/li&gt;
&lt;li&gt;Configurazione delle policy di accesso ai servizi REST.&lt;/li&gt;
&lt;li&gt;Generazione di un set di certificati client per eseguire dei test di accesso (positivi e negativi).&lt;/li&gt;
&lt;li&gt;Test della configurazione mTLS.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Durante l'esecuzione degli step faremo riferimento al repository GitHub &lt;a href="https://github.com/amusarra/quarkus-mtls-auth-tutorial" rel="noopener noreferrer"&gt;quarkus-mtls-auth-tutorial&lt;/a&gt; attraverso l'uso di tag per identificare gli step, per cui basta effettuare il clone in questo modo: &lt;code&gt;git clone -b &amp;lt;nome-tag&amp;gt; https://github.com/amusarra/quarkus-mtls-auth-tutorial.git&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Tra il repository dedicato al tutorial e quello contenente il progetto completo della soluzione (disponibile sul repository GitHub &lt;a href="https://github.com/amusarra/quarkus-mtls-auth" rel="noopener noreferrer"&gt;Quarkus mTLS Auth&lt;/a&gt;), potreste notare delle differenze come per esempio la presenza degli unit-test ma i livello di funzionalità sono gli stessi.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1 - Creazione dell'applicazione Quarkus via CLI
&lt;/h3&gt;

&lt;p&gt;Il tag di riferimento per questo step è &lt;a href="https://github.com/amusarra/quarkus-mtls-auth-tutorial/tree/tutorial-step-1-create-project" rel="noopener noreferrer"&gt;tutorial-step-1-create-project&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Le estensioni Quarkus di cui abbiamo bisogno sono:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;io.quarkus:quarkus-vertx&lt;/li&gt;
&lt;li&gt;io.quarkus:quarkus-arc&lt;/li&gt;
&lt;li&gt;io.quarkus:quarkus-rest&lt;/li&gt;
&lt;li&gt;io.quarkus:quarkus-rest-jackson&lt;/li&gt;
&lt;li&gt;io.quarkus:quarkus-security&lt;/li&gt;
&lt;li&gt;io.quarkus:quarkus-elytron-security-common&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;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 &lt;code&gt;quarkus-mtls-auth-tutorial&lt;/code&gt; con il tag di riferimento per questo step).&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# 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

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;Console 1 - Creazione del progetto Quarkus con le estensioni necessarie&lt;/p&gt;

&lt;p&gt;Al termine dell'esecuzione del comando di creazione dell'applicazione Quarkus, dovremmo avere la directory &lt;code&gt;tls-mutual-auth&lt;/code&gt; avente la struttura a mostrata a seguire.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;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

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;Console 2 - Struttura del progetto Quarkus creato tramite la CLI&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2 - Generazione del certificato di Certification Authority
&lt;/h3&gt;

&lt;p&gt;Il tag di riferimento per questo step è &lt;a href="https://github.com/amusarra/quarkus-mtls-auth-tutorial/tree/tutorial-step-2-gen-cert-ca" rel="noopener noreferrer"&gt;tutorial-step-2-generate-ca&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Per generare il certificato della &lt;strong&gt;Certification Authority&lt;/strong&gt; secondo quanto indicato in tabella 2, procederemo utilizzando lo script &lt;code&gt;certs_manager.sh&lt;/code&gt;. Questo script è stato creato appositamente per questo tutorial e si trova all'interno del progetto Quarkus.&lt;/p&gt;

&lt;p&gt;Per eseguire lo script sulla propria macchina di sviluppo, è necessario che i requisiti software per &lt;em&gt;Gestione certificati TLS&lt;/em&gt; (vedi capitolo &lt;em&gt;Requisiti software&lt;/em&gt;) siano soddisfatti.&lt;/p&gt;

&lt;p&gt;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 &lt;code&gt;src/main/shell/certs-manager/certs_manager.sh&lt;/code&gt;), creerà all'interno della directory &lt;code&gt;src/main/resources/certs&lt;/code&gt; i seguenti file:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;ca_private_key.pem: chiave privata del certificato in formato &lt;a href="https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail" rel="noopener noreferrer"&gt;PEM (Privacy-Enhanced Mail)&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;ca_private_key.pem.password: file contenente la password della chiave private;&lt;/li&gt;
&lt;li&gt;ca_cert.pem: chiave certificato in formato PEM;&lt;/li&gt;
&lt;li&gt;ca_cert.p12: formato PKCS#12 del certificato.&lt;/li&gt;
&lt;/ol&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# 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 "Bronte" \
    --organization Dontesta \
    --organizational-unit "IT Labs" \
    --common-name "Dontesta CA" \
    --output-p12-file ca_cert.p12

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;Console 3 - Generazione della CA&lt;/p&gt;

&lt;p&gt;L'esecuzione del comando precedente, dovrebbe produrre un output simile a quello mostrato a seguire. Ricordate di prendere nota della password del file &lt;code&gt;ca_cert.p12&lt;/code&gt; che dovremo poi impostare sulla configurazione dell'applicazione Quarkus.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;✅ OpenSSL version 3.3.2 is suitable.
🔑 Generating the private key...
..+.+...............+...........+...+++++++++++++++++++++++++++++++++++++++*..+.....+....+.........+.....+......+...+.+..+.......+..+...+.+...............+..+.........+.+..+.............+........+.+...+++++++++++++++++++++++++++++++++++++++*......+....+...+......+.+........................+...+...++++++
Private key password: 57t4Qb1IaGDSZSdv
📜 Generating the CA certificate...
✅ CA certificate generated successfully!
🔍 Verifying the Certificate Issuer...
✅ Certificate Issuer: issuer=C=IT, ST=Catania, L=Bronte, O=Dontesta, OU=IT Labs, CN=Dontesta CA
🔍 Verifying the Certificate Serial...
✅ Certificate Serial (hex): serial=79FE005459C8FD77ABD0038B1383431380D97BD3
🔍 Verifying the Certificate Subject...
✅ Certificate Subject: subject=C=IT, ST=Catania, L=Bronte, O=Dontesta, OU=IT Labs, CN=Dontesta CA
🔒 Generating the p12 file...
✅ p12 file generated successfully!
p12 file: src/main/resources/certs/ca_cert.p12
p12 password: bdo6zkObhUDsa3aL
All files generated in: src/main/resources/certs

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;Console 4 - Output del comando che ha generato il certificato della CA.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3 - Generazione del certificato Server rilasciato dalla CA
&lt;/h3&gt;

&lt;p&gt;Per generare il certificato server firmato dalla CA appena creata, utilizzeremo sempre lo stesso script &lt;code&gt;cert-manager.sh&lt;/code&gt; ma con parametri diversi. Il comando da eseguire è indicato a seguire. L'esecuzione del comando indicato, creerà all'interno della directory &lt;code&gt;src/main/resources/certs&lt;/code&gt; i seguenti file:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;server_private_key.pem: chiave privata del certificato in formato PEM;&lt;/li&gt;
&lt;li&gt;server_csr.pem: &lt;a href="https://it.wikipedia.org/wiki/Certificate_Signing_Request" rel="noopener noreferrer"&gt;Certificate Signing Request (CSR)&lt;/a&gt; del certificato in formato PEM;&lt;/li&gt;
&lt;li&gt;server_cert.pem: certificato del server in formato PEM;&lt;/li&gt;
&lt;li&gt;server_cert.p12: formato PKCS#12 del certificato.&lt;/li&gt;
&lt;/ol&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# 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 "$(cat src/main/resources/certs/ca_private_key.pem.password)" \
    --validity-days 365 \
    --country IT \
    --state Italy \
    --locality "Bronte (CT)" \
    --organization Dontesta \
    --organizational-unit "IT Labs" \
    --common-name "rd.quarkus.dontesta.it" \
    --san-domains "DNS:admin.quarkus.dontesta.it,DNS:blog.quarkus.dontesta.it,DNS:localhost" \
    --output-p12-file server_cert.p12

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;Console 5 - Generazione del certificato server firmato dalla CA&lt;/p&gt;

&lt;p&gt;L'esecuzione del comando precedente, dovrebbe produrre un output simile a quello mostrato a seguire. Ricordate di prendere nota della password del file &lt;code&gt;server_cert.p12&lt;/code&gt; che dovremo poi impostare sulla configurazione dell'applicazione Quarkus.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;✅ OpenSSL version 3.3.2 is suitable.
🔑 Generating the private key...
....+++++++++++++++++++++++++++++++++++++++*.......+.....+.+.....+..........+..+.+..............+.......+........+..........+...+..+.+...........+...+.+......+...+............+...+........+..+..............++++++
Private key password: k/6lEQi/Abxm6lLu
📝 Creating OpenSSL config file for SAN...
✅ OpenSSL config file created for SAN.
📑 Generating the CSR...
🔏 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
🔍 Verifying the Certificate Issuer...
✅ Certificate Issuer: issuer=C=IT, ST=Catania, L=Bronte, O=Dontesta, OU=IT Labs, CN=Dontesta CA
🔍 Verifying the Certificate Serial...
✅ Certificate Serial (hex): serial=41FB7FC18FABB3A846893339E25D3CAD399A92BE
🔍 Verifying the Certificate Subject...
✅ Certificate Subject: subject=C=IT, ST=Italy, L=Bronte (CT), O=Dontesta, OU=IT Labs, CN=rd.quarkus.dontesta.it
🔒 Generating the p12 file...
✅ p12 file generated successfully!
p12 file: src/main/resources/certs/server_cert.p12
p12 password: NWiOJRmJ26D8RTYD
All files generated in: src/main/resources/certs

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;Console 6 - Output del comando che ha generato il certificato del server firmato dalla CA.&lt;/p&gt;

&lt;p&gt;Per maggiori informazioni sullo script &lt;code&gt;certs_manager.sh&lt;/code&gt;, eseguire il comando &lt;code&gt;./src/main/shell/certs-manager/certs_manager.sh&lt;/code&gt; per ottenere la lista dei parametri che gestisce e la loro descrizione.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4 - Configurazione di Quarkus per l'attivazione di HTTPS
&lt;/h3&gt;

&lt;p&gt;Il tag di riferimento per questo step è &lt;a href="https://github.com/amusarra/quarkus-mtls-auth-tutorial/tree/tutorial-step-4-config-tls-1/src/main/resources" rel="noopener noreferrer"&gt;tutorial-step-4-configure-https&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;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 &lt;code&gt;src/main/resources/application.properties&lt;/code&gt; aggiungendo le proprietà necessarie affinché:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;l'applicazione Quarkus utilizzi il certificato PKCS#12 del server;&lt;/li&gt;
&lt;li&gt;l'applicazione Quarkus utilizzi il certificato PEM della CA per essere aggiunto al truststore;&lt;/li&gt;
&lt;li&gt;l'applicazione Quarkus accetti solo richieste HTTPS;&lt;/li&gt;
&lt;li&gt;l'applicazione Quarkus utilizzi solo il protocollo &lt;a href="https://en.wikipedia.org/wiki/Transport_Layer_Security" rel="noopener noreferrer"&gt;TLSv1.3&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;l'applicazione Quarkus utilizzi la configurazione TLS denominata &lt;code&gt;https&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#
# 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

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;Application Properties 1 - Configurazione di Quarkus per l'attivazione di HTTPS&lt;/p&gt;

&lt;p&gt;In questa configurazione sono state utilizzate le proprietà che fanno parte del componente Quarkus TLS Registry e in particolare la caratteristica delle &lt;strong&gt;named configuration&lt;/strong&gt; che nel nostro caso si chiama &lt;code&gt;https&lt;/code&gt; , definita dalla proprietà &lt;code&gt;quarkus.http.tls-configuration-name&lt;/code&gt; nel file &lt;code&gt;application.properties&lt;/code&gt;. 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 &lt;a href="https://quarkus.io/guides/tls-registry-reference" rel="noopener noreferrer"&gt;documentazione ufficiale&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Adesso che abbiamo configurato l'applicazione Quarkus per l'attivazione del protocollo HTTPS, potremo procedere con il test della configurazione HTTPS/TLS.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5 - Test della configurazione HTTPS/TLS
&lt;/h3&gt;

&lt;p&gt;Per testare la configurazione HTTPS/TLS, possiamo eseguire il comando &lt;code&gt;quarkus:dev&lt;/code&gt; e verificare che l'applicazione Quarkus sia in esecuzione e che accetti solo richieste HTTPS.&lt;/p&gt;

&lt;p&gt;Dall'output del comando &lt;code&gt;quarkus:dev&lt;/code&gt;, dovremmo notare che l'applicazione Quarkus è in esecuzione e accetti solo richieste HTTPS sulla porta 8443. L'output del comando &lt;code&gt;quarkus:dev&lt;/code&gt; dovrebbe essere simile a quello mostrato a seguire.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;______  _______  _____  __________
 --/ __\/ / / / _ | / _ \/ //_/ / / /__ /
 -/ /_/ / /_/ / __ |/ , _/ ,&amp;lt; / /_/ /\ \
--\ ___\_\____ /_/ |_/_/|_/_/|_|\ ____/___ /
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]

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;Console 7 - Output del comando &lt;code&gt;quarkus:dev&lt;/code&gt; che mostra l'applicazione Quarkus in esecuzione&lt;/p&gt;

&lt;p&gt;Se l’applicazione Quarkus è in esecuzione e accetta solo richieste HTTPS, il comando &lt;code&gt;curl&lt;/code&gt; 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.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# 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

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;Console 8 - Test della configurazione HTTPS/TLS&lt;/p&gt;

&lt;p&gt;Verifichiamo ora che l’applicazione Quarkus accetti richieste HTTPS. A tal fine, possiamo utilizzare il comando &lt;code&gt;curl&lt;/code&gt; per inviare una richiesta HTTPS. Il comando dovrebbe restituire una risposta dall’applicazione.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# 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

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;Console 9 - Test della configurazione HTTPS/TLS&lt;/p&gt;

&lt;p&gt;L'output del comando &lt;code&gt;curl&lt;/code&gt; dovrebbe essere simile a quello mostrato a seguire.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;* 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: */*]
&amp;gt; GET / HTTP/2
&amp;gt; Host: localhost:8443
&amp;gt; User-Agent: curl/8.7.1
&amp;gt; Accept: */*
&amp;gt;
* Request completely sent off
&amp;lt; HTTP/2 302
&amp;lt; location: /q/dev-ui/welcome
&amp;lt; content-length: 0
&amp;lt;
* Connection #0 to host localhost left intact

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Plaintext&lt;/p&gt;

&lt;p&gt;Console 10 - Output del comando &lt;code&gt;curl&lt;/code&gt; che ha testato la configurazione HTTPS/TLS&lt;/p&gt;

&lt;p&gt;I più attenti avranno notato dall'output del comando precedente le seguenti informazioni:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;la connessione TLS è stata stabilita con successo utilizzando il protocollo TLSv1.3;&lt;/li&gt;
&lt;li&gt;grazie a &lt;strong&gt;&lt;a href="https://en.wikipedia.org/wiki/Application-Layer_Protocol_Negotiation" rel="noopener noreferrer"&gt;ALPN&lt;/a&gt;&lt;/strong&gt;, il server ha accettato il protocollo HTTP/2. Su Quarkus il protocollo HTTP/2 è abilitato di default;&lt;/li&gt;
&lt;li&gt;il server ha risposto con il certificato del server creato in precedenza e firmato dalla CA sempre creata in precedenza.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;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.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# 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
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;Console 11 - Test della configurazione HTTPS/TLS&lt;/p&gt;

&lt;p&gt;In questo caso il comando &lt;code&gt;openssl&lt;/code&gt; dovrebbe restituire un messaggio di errore che indica che la connessione è stata rifiutata e in particolare &lt;code&gt;tlsv1 alert protocol version:ssl/record/rec_layer_s3.c:907:SSL alert number 70&lt;/code&gt;. Questo è il comportamento atteso poiché l'applicazione Quarkus accetta solo richieste HTTPS con il protocollo TLSv1.3.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 6 - Abilitazione del mTLS
&lt;/h3&gt;

&lt;p&gt;Il tag di riferimento per questo step è &lt;a href="https://github.com/amusarra/quarkus-mtls-auth-tutorial/tree/tutorial-step-6-config-tls-2/src/main/resources" rel="noopener noreferrer"&gt;tutorial-step-6-enable-mtls&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;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 &lt;code&gt;src/main/resources/application.properties&lt;/code&gt; aggiungendo le proprietà necessarie affinché l'applicazione Quarkus sia configurata per il supporto di mTLS.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#
# 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
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;Application Properties 2 - Abilitazione del mTLS&lt;/p&gt;

&lt;p&gt;Per impostazione predefinita l'applicazione Quarkus è configurata per non richiedere l'autenticazione del client. Per abilitare l'autenticazione del client, dobbiamo impostare la proprietà &lt;code&gt;quarkus.http.ssl.client-auth&lt;/code&gt; su &lt;code&gt;REQUEST&lt;/code&gt; o &lt;code&gt;REQUIRED&lt;/code&gt;. In questo caso, impostiamo la proprietà su &lt;code&gt;REQUIRED&lt;/code&gt; alfine di richiedere l'autenticazione del client.&lt;/p&gt;

&lt;p&gt;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 &lt;code&gt;curl&lt;/code&gt; come indicato a seguire.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Verify that the application only accepts HTTPS requests with the TLSv1.3 protocol and requires client authentication.
curl -k -v https://localhost:8443
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;Console 12 - Test della configurazione mTLS&lt;/p&gt;

&lt;p&gt;L'output del comando &lt;code&gt;curl&lt;/code&gt; dovrebbe essere simile a quello mostrato a seguire che indica che la connessione è stata rifiutata.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;* 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: */*]
&amp;gt; GET / HTTP/2
&amp;gt; Host: localhost:8443
&amp;gt; User-Agent: curl/8.7.1
&amp;gt; Accept: */*
&amp;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
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Plaintext&lt;/p&gt;

&lt;p&gt;Console 13 - Output del comando &lt;code&gt;curl&lt;/code&gt; che ha testato la configurazione mTLS&lt;/p&gt;

&lt;p&gt;Dall'output del comando è possibile notare la richiesta del certificato client da parte del server (&lt;code&gt;(304) (IN), TLS handshake, Request CERT (13)&lt;/code&gt;). 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.&lt;/p&gt;

&lt;p&gt;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 &lt;code&gt;SecurityIdentityAugmentor&lt;/code&gt; per il mapping dei ruoli e attributi.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 7 - Implementazione dei componenti SecurityIdentityAugmentor
&lt;/h3&gt;

&lt;p&gt;Il tag di riferimento per questo step è &lt;a href="https://github.com/amusarra/quarkus-mtls-auth-tutorial/tree/tutorial-step-7-impl-security-identity-augmentor/src/main/resources" rel="noopener noreferrer"&gt;tutorial-step-7-impl-security-identity-augmentor&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;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 &lt;code&gt;SecurityIdentityAugmentor&lt;/code&gt; per il mapping di ruoli e attributi.&lt;/p&gt;

&lt;p&gt;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 è &lt;code&gt;1.3.6.1.4.1.99999.1&lt;/code&gt;, mentre &lt;code&gt;1.3.6.1.4.1.99999.2&lt;/code&gt; identifica l'attributo DeviceId.&lt;/p&gt;

&lt;p&gt;I componenti &lt;code&gt;SecurityIdentityAugmentor&lt;/code&gt; che implementeremo dovranno verificare che i valori degli OID siano presenti nel certificato del client e, in caso affermativo, estrarli e aggiungerli all’oggetto &lt;code&gt;SecurityIdentity&lt;/code&gt; di Quarkus. Qualora i valori degli OID non rispettino le regole di validazione (vedi pattern per l’OID dei ruoli, capitolo &lt;em&gt;Generazione dei certificati&lt;/em&gt; e capitolo &lt;em&gt;Algoritmo per la generazione del DeviceId&lt;/em&gt;), il componente &lt;code&gt;SecurityIdentityAugmentor&lt;/code&gt; dovrà rifiutare la richiesta di autenticazione.&lt;/p&gt;

&lt;p&gt;Per raggiungere l'obiettivo andremo a implementare tre classi.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;AttributesAugmentor&lt;/strong&gt; : classe che implementa l'interfaccia &lt;code&gt;io.quarkus.security.identity.SecurityIdentityAugmentor&lt;/code&gt; e sovrascrive il metodo &lt;code&gt;augment&lt;/code&gt; per estrarre il valore dell'OID &lt;code&gt;1.3.6.1.4.1.99999.2&lt;/code&gt; (DeviceId) e renderlo disponibile sull'oggetto &lt;code&gt;io.quarkus.security.identity.SecurityIdentity&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RolesAugmentor&lt;/strong&gt; : classe che implementa l'interfaccia &lt;code&gt;io.quarkus.security.identity.SecurityIdentityAugmentor&lt;/code&gt; e sovrascrive il metodo &lt;code&gt;augment&lt;/code&gt; per estrarre il valore dell'OID &lt;code&gt;1.3.6.1.4.1.99999.1&lt;/code&gt; (ruoli) e renderlo disponibile sull'oggetto &lt;code&gt;io.quarkus.security.identity.SecurityIdentity&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OidSecurityIdentityAugmentor&lt;/strong&gt; : classe che implementa l'interfaccia &lt;code&gt;io.quarkus.security.identity.SecurityIdentityAugmentor&lt;/code&gt; e sovrascrive il metodo &lt;code&gt;augment&lt;/code&gt; per verificare che il valore dell'OID che identifica il DeviceId sia presente e valido secondo l'algoritmo descritto nel capitolo &lt;em&gt;Algoritmo per la generazione del DeviceId&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Le classi &lt;code&gt;AttributesAugmentor&lt;/code&gt;, &lt;code&gt;RolesAugmentor&lt;/code&gt; e &lt;code&gt;OidSecurityIdentityAugmentor&lt;/code&gt; fanno parte del package &lt;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" rel="noopener noreferrer"&gt;it.dontesta.quarkus.tls.auth.ws.security.identity&lt;/a&gt;. A seguire i sequence diagram che illustrano il flusso di esecuzione delle classi implementate.&lt;/p&gt;

&lt;p&gt;Il primo sequence diagram per &lt;code&gt;AttributesAugmentor.augment()&lt;/code&gt; prevede i seguenti attori.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Client&lt;/strong&gt; : il sistema o servizio che invoca la classe per l’operazione di autenticazione.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AttributesAugmentor&lt;/strong&gt; : la classe principale che manipola il &lt;code&gt;SecurityIdentity&lt;/code&gt; e ne arricchisce gli attributi con informazioni dal certificato.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CertificateCredential&lt;/strong&gt; : un oggetto che contiene il certificato X.509 dal quale vengono estratti gli attributi.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SecurityIdentity&lt;/strong&gt; : l’identità di sicurezza che viene aumentata con nuovi attributi.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;QuarkusSecurityIdentity.Builder&lt;/strong&gt; : il costruttore utilizzato per modificare e creare una nuova istanza di &lt;code&gt;SecurityIdentity&lt;/code&gt; arricchita.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CertificateUtil&lt;/strong&gt; : utility che decodifica il valore del certificato.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;X509Certificate&lt;/strong&gt; : il certificato dal quale viene estratto l’ID del dispositivo.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;sequenceDiagram participant Client participant AttributesAugmentor participant SecurityIdentity participant CertificateCredential participant X509Certificate participant CertificateUtil participant QuarkusSecurityIdentityBuilder as QuarkusSecurityIdentity.Builder Client-&amp;gt;&amp;gt;AttributesAugmentor: augment(identity, context) AttributesAugmentor-&amp;gt;&amp;gt;SecurityIdentity: getCredential(CertificateCredential) SecurityIdentity--&amp;gt;&amp;gt;AttributesAugmentor: CertificateCredential AttributesAugmentor-&amp;gt;&amp;gt;CertificateCredential: getCertificate() CertificateCredential--&amp;gt;&amp;gt;AttributesAugmentor: X509Certificate alt Certificate is null AttributesAugmentor--&amp;gt;&amp;gt;Client: SecurityIdentity (no augmentation) else Certificate is present AttributesAugmentor-&amp;gt;&amp;gt;AttributesAugmentor: extractAttributesFromCertificate(X509Certificate) AttributesAugmentor-&amp;gt;&amp;gt;X509Certificate: getExtensionValue(OID_DEVICE_ID) alt OID not found AttributesAugmentor--&amp;gt;&amp;gt;Client: SecurityIdentity (no augmentation) else OID found X509Certificate--&amp;gt;&amp;gt;AttributesAugmentor: byte[] AttributesAugmentor-&amp;gt;&amp;gt;CertificateUtil: decodeExtensionValue(byte[]) CertificateUtil--&amp;gt;&amp;gt;AttributesAugmentor: deviceId alt deviceId is null AttributesAugmentor--&amp;gt;&amp;gt;Client: SecurityIdentity (no augmentation) else deviceId is valid AttributesAugmentor-&amp;gt;&amp;gt;QuarkusSecurityIdentityBuilder: addAttribute("deviceId", deviceId) end end AttributesAugmentor-&amp;gt;&amp;gt;QuarkusSecurityIdentityBuilder: build() QuarkusSecurityIdentityBuilder--&amp;gt;&amp;gt;AttributesAugmentor: SecurityIdentity AttributesAugmentor--&amp;gt;&amp;gt;Client: SecurityIdentity end opt Error during extraction AttributesAugmentor-&amp;gt;&amp;gt;AttributesAugmentor: throw SecurityException AttributesAugmentor--&amp;gt;&amp;gt;Client: SecurityException end&lt;/p&gt;

&lt;p&gt;Figura 6 - Sequence Diagram del flusso di esecuzione di &lt;code&gt;AttributesAugmentor.augment()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Il secondo sequence diagram per &lt;code&gt;RolesAugmentor.augment()&lt;/code&gt; prevede gli stessi attori del diagramma precedente con &lt;code&gt;RolesAugmentor&lt;/code&gt; al posto di &lt;code&gt;AttributesAugmentor&lt;/code&gt; che manipola il &lt;code&gt;SecurityIdentity&lt;/code&gt; e ne arricchisce i ruoli con informazioni dal certificato.&lt;/p&gt;

&lt;p&gt;sequenceDiagram participant Client participant RolesAugmentor participant SecurityIdentity participant CertificateCredential participant X509Certificate participant CertificateUtil participant QuarkusSecurityIdentityBuilder as QuarkusSecurityIdentity.Builder Client-&amp;gt;&amp;gt;RolesAugmentor: augment(identity, context) RolesAugmentor-&amp;gt;&amp;gt;SecurityIdentity: getCredential(CertificateCredential) SecurityIdentity--&amp;gt;&amp;gt;RolesAugmentor: CertificateCredential RolesAugmentor-&amp;gt;&amp;gt;CertificateCredential: getCertificate() CertificateCredential--&amp;gt;&amp;gt;RolesAugmentor: X509Certificate alt Certificate is null RolesAugmentor--&amp;gt;&amp;gt;Client: SecurityIdentity (no augmentation) else Certificate is present RolesAugmentor-&amp;gt;&amp;gt;RolesAugmentor: extractRolesFromCertificate(X509Certificate) RolesAugmentor-&amp;gt;&amp;gt;X509Certificate: getExtensionValue(OID_ROLES) alt OID not found RolesAugmentor--&amp;gt;&amp;gt;Client: SecurityIdentity (no augmentation) else OID found X509Certificate--&amp;gt;&amp;gt;RolesAugmentor: byte[] RolesAugmentor-&amp;gt;&amp;gt;CertificateUtil: decodeExtensionValue(byte[]) CertificateUtil--&amp;gt;&amp;gt;RolesAugmentor: decodedRoles alt decodedRoles is null RolesAugmentor--&amp;gt;&amp;gt;Client: SecurityIdentity (no augmentation) else decodedRoles matches pattern RolesAugmentor-&amp;gt;&amp;gt;RolesAugmentor: Add roles to set RolesAugmentor-&amp;gt;&amp;gt;QuarkusSecurityIdentityBuilder: addRoles(extracted roles) else decodedRoles does not match pattern RolesAugmentor-&amp;gt;&amp;gt;RolesAugmentor: throw SecurityException RolesAugmentor--&amp;gt;&amp;gt;Client: SecurityException end end RolesAugmentor-&amp;gt;&amp;gt;QuarkusSecurityIdentityBuilder: build() QuarkusSecurityIdentityBuilder--&amp;gt;&amp;gt;RolesAugmentor: SecurityIdentity RolesAugmentor--&amp;gt;&amp;gt;Client: SecurityIdentity end opt Error during extraction RolesAugmentor-&amp;gt;&amp;gt;RolesAugmentor: throw SecurityException RolesAugmentor--&amp;gt;&amp;gt;Client: SecurityException end&lt;/p&gt;

&lt;p&gt;Figura 7 - Sequence Diagrama del flusso di esecuzione di &lt;code&gt;RolesAugmentor.augment()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Il terzo diagramma di sequenza relativo a &lt;code&gt;OidSecurityIdentityAugmentor.augment()&lt;/code&gt; evidenzia che, in questo caso, il componente non agisce direttamente su &lt;code&gt;SecurityIdentity&lt;/code&gt;, ma si limita a verificare che il valore dell’OID che identifica il DeviceId sia presente e valido secondo l’algoritmo descritto nel capitolo &lt;em&gt;Algoritmo per la generazione del DeviceId&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;sequenceDiagram participant Client participant OidSecurityIdentityAugmentor participant SecurityIdentity participant CertificateCredential participant X509Certificate participant CertificateUtil participant DeviceIdUtil Client-&amp;gt;&amp;gt;OidSecurityIdentityAugmentor: augment(identity, context) OidSecurityIdentityAugmentor-&amp;gt;&amp;gt;SecurityIdentity: getCredential(CertificateCredential) SecurityIdentity--&amp;gt;&amp;gt;OidSecurityIdentityAugmentor: CertificateCredential alt CertificateCredential is null OidSecurityIdentityAugmentor--&amp;gt;&amp;gt;Client: throw SecurityException("Client certificate not found") else CertificateCredential is present OidSecurityIdentityAugmentor-&amp;gt;&amp;gt;CertificateCredential: getCertificate() CertificateCredential--&amp;gt;&amp;gt;OidSecurityIdentityAugmentor: X509Certificate OidSecurityIdentityAugmentor-&amp;gt;&amp;gt;X509Certificate: getExtensionValue(AttributesAugmentor.OID_DEVICE_ID) alt OID is null OidSecurityIdentityAugmentor--&amp;gt;&amp;gt;Client: throw SecurityException("Invalid certificate OID missing for DeviceId") else OID is present X509Certificate--&amp;gt;&amp;gt;OidSecurityIdentityAugmentor: oidValueFromCert OidSecurityIdentityAugmentor-&amp;gt;&amp;gt;CertificateUtil: decodeExtensionValue(oidValueFromCert) CertificateUtil--&amp;gt;&amp;gt;OidSecurityIdentityAugmentor: decoded OID value OidSecurityIdentityAugmentor-&amp;gt;&amp;gt;OidSecurityIdentityAugmentor: remove OID prefix and trim value OidSecurityIdentityAugmentor-&amp;gt;&amp;gt;DeviceIdUtil: verifyDeviceId(oidValue) alt DeviceId is not valid DeviceIdUtil--&amp;gt;&amp;gt;OidSecurityIdentityAugmentor: false OidSecurityIdentityAugmentor--&amp;gt;&amp;gt;Client: throw SecurityException("Invalid certificate OID value") else DeviceId is valid DeviceIdUtil--&amp;gt;&amp;gt;OidSecurityIdentityAugmentor: true OidSecurityIdentityAugmentor--&amp;gt;&amp;gt;Client: return identity end end end&lt;/p&gt;

&lt;p&gt;Figura 8 - Sequence Diagram del flusso di esecuzione di &lt;code&gt;OidSecurityIdentityAugmentor.augment()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Nel nostro caso, abbiamo registrato più di una &lt;code&gt;SecurityIdentityAugmentor&lt;/code&gt; personalizzata nell’applicazione Quarkus. Queste saranno considerate paritetiche e invocate in ordine casuale. Tuttavia, è possibile imporre un ordine implementando il metodo &lt;code&gt;SecurityIdentityAugmentor#priority&lt;/code&gt;. Gli Augmentor con priorità più alta saranno invocati per primi.&lt;/p&gt;

&lt;p&gt;Nella classe &lt;code&gt;OidSecurityIdentityAugmentor&lt;/code&gt; 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 &lt;code&gt;SecurityException&lt;/code&gt; e l’autenticazione fallirà (vedi sequence diagram di figura 8).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nota&lt;/strong&gt; : i &lt;code&gt;SecurityIdentityAugmentor&lt;/code&gt; 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.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 8 - Implementazione dei servizi REST
&lt;/h3&gt;

&lt;p&gt;Il tag di riferimento per questo step è &lt;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" rel="noopener noreferrer"&gt;tutorial-step-8-impl-rest-services&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;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 &lt;em&gt;Requisiti dell’applicazione Quarkus&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I servizi REST che andremo a realizzare troveranno spazio all'interno del package &lt;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" rel="noopener noreferrer"&gt;it.dontesta.quarkus.tls.auth.ws.resources.endpoint.v1&lt;/a&gt; e saranno implementati dalla classe &lt;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" rel="noopener noreferrer"&gt;ConnectionInfoResourceEndPoint&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;La classe &lt;code&gt;ConnectionInfoResourceEndPoint&lt;/code&gt; implementerà i seguenti metodi:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;@GET /v1/connection-info/info&lt;/code&gt;: metodo che restituirà le informazioni di connessione del client;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@GET /v1/connection-info/user-identity&lt;/code&gt;: metodo che restituirà le informazioni circa l'identità del client che ha effettuato la richiesta.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Le risposte dei metodi saranno in formato JSON e conterranno le informazioni richieste e conformi agli schemi JSON definiti nel capitolo &lt;em&gt;Struttura JSON di risposta dei servizi Rest&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Il sequence diagram mostra il flusso di esecuzione del metodo &lt;code&gt;ConnectionInfoResourceEndPoint.getConnectionInfo()&lt;/code&gt;. Gli attori coinvolti nel diagramma sono:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Client&lt;/strong&gt; : il sistema o servizio che invoca il metodo &lt;code&gt;getConnectionInfo()&lt;/code&gt; sull'endpoint &lt;code&gt;ConnectionInfoResourceEndPoint&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ConnectionInfoResourceEndPoint&lt;/strong&gt; : la classe che gestisce la richiesta del client e costruisce l'oggetto &lt;code&gt;connectionInfo&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RoutingContext&lt;/strong&gt; : contesto di routing che fornisce informazioni sulla richiesta HTTP.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HttpServerRequest&lt;/strong&gt; : rappresenta la richiesta HTTP ricevuta dal server.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SSLSession&lt;/strong&gt; : rappresenta la sessione TLS/SSL, utilizzata per ottenere informazioni di sicurezza aggiuntive se la connessione è sicura.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Questi attori collaborano per ottenere e restituire le informazioni di connessione in risposta alla richiesta del client.&lt;/p&gt;

&lt;p&gt;sequenceDiagram participant Client participant ConnectionInfoResourceEndPoint participant RoutingContext participant HttpServerRequest participant SSLSession Client-&amp;gt;&amp;gt;ConnectionInfoResourceEndPoint: GET /v1/connection-info/info ConnectionInfoResourceEndPoint-&amp;gt;&amp;gt;RoutingContext: &lt;a class="mentioned-user" href="https://dev.to/context"&gt;@context&lt;/a&gt; RoutingContext RoutingContext--&amp;gt;&amp;gt;ConnectionInfoResourceEndPoint: routingContext ConnectionInfoResourceEndPoint-&amp;gt;&amp;gt;HttpServerRequest: request() HttpServerRequest--&amp;gt;&amp;gt;ConnectionInfoResourceEndPoint: HttpServerRequest ConnectionInfoResourceEndPoint-&amp;gt;&amp;gt;ConnectionInfoResourceEndPoint: Create connectionInfo map ConnectionInfoResourceEndPoint-&amp;gt;&amp;gt;ConnectionInfoResourceEndPoint: Add basic connection details ConnectionInfoResourceEndPoint-&amp;gt;&amp;gt;ConnectionInfoResourceEndPoint: Add client address and port information alt request.isSSL() is true ConnectionInfoResourceEndPoint-&amp;gt;&amp;gt;HttpServerRequest: sslSession() HttpServerRequest--&amp;gt;&amp;gt;ConnectionInfoResourceEndPoint: SSLSession alt sslSession is not null ConnectionInfoResourceEndPoint-&amp;gt;&amp;gt;ConnectionInfoResourceEndPoint: Add SSL-specific details ConnectionInfoResourceEndPoint-&amp;gt;&amp;gt;SSLSession: getProtocol() SSLSession--&amp;gt;&amp;gt;ConnectionInfoResourceEndPoint: protocol ConnectionInfoResourceEndPoint-&amp;gt;&amp;gt;SSLSession: getCipherSuite() SSLSession--&amp;gt;&amp;gt;ConnectionInfoResourceEndPoint: cipherSuite ConnectionInfoResourceEndPoint-&amp;gt;&amp;gt;SSLSession: getLocalCertificates() SSLSession--&amp;gt;&amp;gt;ConnectionInfoResourceEndPoint: serverCerts ConnectionInfoResourceEndPoint-&amp;gt;&amp;gt;SSLSession: getPeerCertificates() SSLSession--&amp;gt;&amp;gt;ConnectionInfoResourceEndPoint: clientCerts end end ConnectionInfoResourceEndPoint--&amp;gt;&amp;gt;Client: Response.ok(connectionInfo).build()&lt;/p&gt;

&lt;p&gt;Figura 9 - Sequence Diagram del flusso di esecuzione di &lt;code&gt;ConnectionInfoResourceEndPoint.info()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Il sequence diagram mostra il flusso di esecuzione del metodo &lt;code&gt;ConnectionInfoResourceEndPoint.getUserIdentity()&lt;/code&gt;. Gli attori coinvolti nel diagramma sono:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Client&lt;/strong&gt; : il sistema o servizio che invoca il metodo &lt;code&gt;getUserIdentity()&lt;/code&gt; sull'endpoint &lt;code&gt;ConnectionInfoResourceEndPoint&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ConnectionInfoResourceEndPoint&lt;/strong&gt; : la classe che gestisce la richiesta del client e costruisce l'oggetto &lt;code&gt;securityIdentityInfo&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SecurityIdentity&lt;/strong&gt; : l'identità di sicurezza che contiene le informazioni dell'utente autenticato.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CertificateCredential&lt;/strong&gt; : un oggetto che contiene il certificato X.509 dal quale vengono estratti gli attributi.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;X509Certificate&lt;/strong&gt; : il certificato dal quale vengono estratti gli attributi.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Questi attori collaborano per ottenere e restituire le informazioni di identità dell'utente in risposta alla richiesta del client.&lt;/p&gt;

&lt;p&gt;sequenceDiagram participant Client participant ConnectionInfoResourceEndPoint participant SecurityIdentity participant CertificateCredential participant X509Certificate Client-&amp;gt;&amp;gt;ConnectionInfoResourceEndPoint: GET /v1/connection-info/user-identity ConnectionInfoResourceEndPoint-&amp;gt;&amp;gt;SecurityIdentity: &lt;a class="mentioned-user" href="https://dev.to/context"&gt;@context&lt;/a&gt; SecurityIdentity SecurityIdentity--&amp;gt;&amp;gt;ConnectionInfoResourceEndPoint: securityIdentity ConnectionInfoResourceEndPoint-&amp;gt;&amp;gt;ConnectionInfoResourceEndPoint: Create securityIdentityInfo map ConnectionInfoResourceEndPoint-&amp;gt;&amp;gt;ConnectionInfoResourceEndPoint: Add principal, roles, and attributes ConnectionInfoResourceEndPoint-&amp;gt;&amp;gt;SecurityIdentity: getCredential(CertificateCredential.class) SecurityIdentity--&amp;gt;&amp;gt;ConnectionInfoResourceEndPoint: CertificateCredential ConnectionInfoResourceEndPoint-&amp;gt;&amp;gt;CertificateCredential: getCertificate() CertificateCredential--&amp;gt;&amp;gt;ConnectionInfoResourceEndPoint: X509Certificate ConnectionInfoResourceEndPoint-&amp;gt;&amp;gt;X509Certificate: getCommonName() X509Certificate--&amp;gt;&amp;gt;ConnectionInfoResourceEndPoint: userCN ConnectionInfoResourceEndPoint-&amp;gt;&amp;gt;ConnectionInfoResourceEndPoint: Add userCN to securityIdentityInfo ConnectionInfoResourceEndPoint--&amp;gt;&amp;gt;Client: Response.ok(securityIdentityInfo).build()&lt;/p&gt;

&lt;p&gt;Figura 10 - Sequence Diagram del flusso di esecuzione di &lt;code&gt;ConnectionInfoResourceEndPoint.getUserIdentity()&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 9 - Configurazione delle policy di accesso ai servizi REST
&lt;/h3&gt;

&lt;p&gt;Il tag di riferimento per questo step è &lt;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" rel="noopener noreferrer"&gt;tutorial-step-9-config-rest-services&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;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 &lt;em&gt;Requisiti dell’applicazione Quarkus&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Configurare le policy di accesso significa definire quali ruoli possono accedere ai servizi REST. Nel nostro caso, i ruoli sono due: &lt;code&gt;Administartor&lt;/code&gt; e &lt;code&gt;User&lt;/code&gt;. Questa configurazione può essere effettuata modificando il file &lt;code&gt;application.properties&lt;/code&gt; aggiungendo le proprietà indicate di seguito.&lt;/p&gt;

&lt;p&gt;Tramite la configurazione abbiamo definito:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;un set di permessi &lt;code&gt;certauthenticated&lt;/code&gt; che

&lt;ol&gt;
&lt;li&gt;si applicano alle risorse REST di tipo JAX-RS;&lt;/li&gt;
&lt;li&gt;si applicano ai metodi &lt;code&gt;GET&lt;/code&gt; e &lt;code&gt;POST&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;si applicano ai servizi REST &lt;code&gt;/api/v1/connection-info/*&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;utilizzano la policy &lt;code&gt;role-policy-cert&lt;/code&gt; per il controllo degli accessi;&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;li&gt;la policy &lt;code&gt;role-policy-cert&lt;/code&gt; che

&lt;ol&gt;
&lt;li&gt;definisce i ruoli &lt;code&gt;User&lt;/code&gt; e &lt;code&gt;Administrator&lt;/code&gt; che possono accedere ai servizi REST.&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;/ol&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#
# 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
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;Application Properties 3 - Configurazione delle policy di accesso ai servizi REST&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 10 - Generazione di un set di certificati client per eseguire dei test di accesso
&lt;/h3&gt;

&lt;p&gt;Il tag di riferimento per questo step è &lt;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" rel="noopener noreferrer"&gt;tutorial-step-10-generate-client-certificates&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;Per generare i certificati client, possiamo utilizzare lo script &lt;code&gt;certs-manager.sh&lt;/code&gt;, già impiegato per generare il certificato della CA e quello del server. Ricordiamo che lo script si trova nel percorso &lt;code&gt;src/main/shell/certs-manager&lt;/code&gt;, mentre i certificati generati finora sono conservati nella directory &lt;code&gt;src/main/resources/certs&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Andremo a generare un set di certificati client con le seguenti caratteristiche:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;un certificato client senza estensioni personalizzate;&lt;/li&gt;
&lt;li&gt;un certificato client con l'estensione personalizzata &lt;code&gt;DeviceId&lt;/code&gt; e il valore &lt;code&gt;1234567890&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;un certificato client con l'estensione personalizzata &lt;code&gt;DeviceId&lt;/code&gt; con il corretto valore generato dall'algoritmo descritto nel capitolo &lt;em&gt;Algoritmo per la generazione del DeviceId&lt;/em&gt; e l'estensione personalizzata &lt;code&gt;Roles&lt;/code&gt; e il valore &lt;code&gt;123User&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;un certificato client con l'estensione personalizzata &lt;code&gt;DeviceId&lt;/code&gt; con il corretto valore generato dall'algoritmo descritto nel capitolo &lt;em&gt;Algoritmo per la generazione del DeviceId&lt;/em&gt; e l'estensione personalizzata &lt;code&gt;Roles&lt;/code&gt; e il valore &lt;code&gt;ProjectManager&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;un certificato client con l'estensione personalizzata &lt;code&gt;DeviceId&lt;/code&gt; con il corretto valore generato dall'algoritmo descritto nel capitolo &lt;em&gt;Algoritmo per la generazione del DeviceId&lt;/em&gt; e l'estensione personalizzata &lt;code&gt;Roles&lt;/code&gt; e il valore &lt;code&gt;User,Administrator&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;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à &lt;code&gt;quarkus.tls.https.trust-store.pem.certs&lt;/code&gt; valorizzata con il valore &lt;code&gt;certs/ca_cert.pem&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Procediamo quindi con la generazione dei certificati client eseguendo lo script &lt;code&gt;certs-manager.sh&lt;/code&gt; come indicato a seguire.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# 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 "$(cat src/main/resources/certs/ca_private_key.pem.password)" \
    --country IT \
    --state Italy \
    --locality Rome \
    --organization "Mario Rossi Corporation" \
    --organizational-unit "Community &amp;amp; News" \
    --common-name "D54FF113-A0C4-4A67-A6DE-B8DEE24A5095" \
    --extensions-file src/main/shell/certs-manager/ssl_extensions_without_custom.cnf \
    --output-p12-file client_without_custom_ext_cert.p12
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;Console 13 - Generazione di un certificato client senza estensioni personalizzate&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# 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 "$(cat src/main/resources/certs/ca_private_key.pem.password)" \
    --country IT \
    --state Italy \
    --locality Rome \
    --organization "Antonella Bianchi Corporation" \
    --organizational-unit "Community &amp;amp; News" \
    --common-name "438D4FFD-0082-4189-8659-012692868913" \
    --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
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;Console 14 - Generazione di un certificato client con estensione personalizzata &lt;code&gt;DeviceId&lt;/code&gt; e valore &lt;code&gt;1234567890&lt;/code&gt;&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Generate a client certificate with custom extension DeviceId with the correct value generated by the algorithm described in the chapter "Algorithm for generating the DeviceId" 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 "$(cat src/main/resources/certs/ca_private_key.pem.password)" \
    --country IT \
    --state Italy \
    --locality Rome \
    --organization "Andrea Valdasso Corporation" \
    --organizational-unit "Community &amp;amp; News" \
    --common-name "B7422CD0-DDCC-435F-843C-11649C987256" \
    --extensions-file src/main/shell/certs-manager/ssl_extensions.cnf \
    --ext-cert-role 123User \
    --ext-cert-device-id "$(./src/main/shell/certs-manager/generate_device_id.sh generate true)" \
    --output-p12-file client_with_bad_device_id_and_bad_roles_cert.p12
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;Console 15 - Generazione di un certificato client con estensione personalizzata &lt;code&gt;DeviceId&lt;/code&gt; con il corretto valore ed estensione personalizzata &lt;code&gt;Roles&lt;/code&gt; e valore &lt;code&gt;123User&lt;/code&gt;&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Generate a client certificate with custom extension DeviceId with the correct value generated by the algorithm described in the chapter "Algorithm for generating the DeviceId" 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 "$(cat src/main/resources/certs/ca_private_key.pem.password)" \
    --country IT \
    --state Italy \
    --locality Rome \
    --organization "Marco Visco Corporation" \
    --organizational-unit "Community &amp;amp; News" \
    --common-name "3C266B12-8400-40DC-891B-CB52BB84CD86" \
    --extensions-file src/main/shell/certs-manager/ssl_extensions.cnf \
    --ext-cert-role ProjectManager \
    --ext-cert-device-id "$(./src/main/shell/certs-manager/generate_device_id.sh generate true)" \
    --output-p12-file client_with_device_id_and_roles_cert.p12
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;Console 16 - Generazione di un certificato client con estensione personalizzata &lt;code&gt;DeviceId&lt;/code&gt; con il corretto valore ed estensione personalizzata &lt;code&gt;Roles&lt;/code&gt; e valore &lt;code&gt;ProjectManager&lt;/code&gt;&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Generate a client certificate with custom extension DeviceId with the correct value generated by the algorithm described in the chapter "Algorithm for generating the DeviceId" 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 "$(cat src/main/resources/certs/ca_private_key.pem.password)" \
    --country IT \
    --state Italy \
    --locality Rome \
    --organization "Massimo Visco Corporation" \
    --organizational-unit "Community &amp;amp; News" \
    --common-name "7BF80D48-B92C-45EB-80F0-363D1CCA6E4C" \
    --extensions-file src/main/shell/certs-manager/ssl_extensions.cnf \
    --ext-cert-role User,Administrator \
    --ext-cert-device-id "$(./src/main/shell/certs-manager/generate_device_id.sh generate true)" \
    --output-p12-file client_with_device_id_and_roles_1_cert.p12
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;Console 17 - Generazione di un certificato client con estensione personalizzata &lt;code&gt;DeviceId&lt;/code&gt; con il corretto valore ed estensione personalizzata &lt;code&gt;Roles&lt;/code&gt; e valore &lt;code&gt;User,Administrator&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;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 &lt;code&gt;src/main/resources/certs&lt;/code&gt; e la tabella 3 mostra un riepilogo dei certificati client generati.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;ID&lt;/th&gt;
&lt;th&gt;Subject&lt;/th&gt;
&lt;th&gt;Issuer&lt;/th&gt;
&lt;th&gt;DeviceId&lt;/th&gt;
&lt;th&gt;Roles&lt;/th&gt;
&lt;th&gt;File p12&lt;/th&gt;
&lt;th&gt;Password .p12&lt;/th&gt;
&lt;th&gt;Password private key (PEM)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;C=IT, ST=Italy, L=Rome, O=Mario Rossi Corporation, OU=Community &amp;amp; News, CN=D54FF113-A0C4-4A67-A6DE-B8DEE24A5095&lt;/td&gt;
&lt;td&gt;Dontesta CA&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;client_without_custom_ext_cert.p12&lt;/td&gt;
&lt;td&gt;5byk65SNHEIwfv3s&lt;/td&gt;
&lt;td&gt;K3K8onVbmB2ACXdu&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;C=IT, ST=Italy, L=Rome, O=Antonella Bianchi Corporation, OU=Community &amp;amp; News, CN=438D4FFD-0082-4189-8659-012692868913&lt;/td&gt;
&lt;td&gt;Dontesta CA&lt;/td&gt;
&lt;td&gt;1234567890&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;client_with_bad_device_id_cert.p12&lt;/td&gt;
&lt;td&gt;HQeQYfBkq2cf8AjL&lt;/td&gt;
&lt;td&gt;DDSO642Dq2o+U1cF&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;C=IT, ST=Italy, L=Rome, O=Andrea Valdasso Corporation, OU=Community &amp;amp; News, CN=B7422CD0-DDCC-435F-843C-11649C987256&lt;/td&gt;
&lt;td&gt;Dontesta CA&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;123User&lt;/td&gt;
&lt;td&gt;client_with_device_id_and_bad_roles_cert.p12&lt;/td&gt;
&lt;td&gt;7Rb1laR7WOdqcZk+&lt;/td&gt;
&lt;td&gt;1JKARpPJ7wCnX4Ju&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;C=IT, ST=Italy, L=Rome, O=Marco Visco Corporation, OU=Community &amp;amp; News, CN=3C266B12-8400-40DC-891B-CB52BB84CD86&lt;/td&gt;
&lt;td&gt;Dontesta CA&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;ProjectManager&lt;/td&gt;
&lt;td&gt;client_with_device_id_and_roles_cert.p12&lt;/td&gt;
&lt;td&gt;HA5b7g0Cy3bI/+1/&lt;/td&gt;
&lt;td&gt;AeqFJRRA2wqnG0Nf&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;C=IT, ST=Italy, L=Rome, O=Massimo Visco Corporation, OU=Community &amp;amp; News, CN=7BF80D48-B92C-45EB-80F0-363D1CCA6E4C&lt;/td&gt;
&lt;td&gt;Dontesta CA&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;User&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Administrator&lt;/td&gt;
&lt;td&gt;client_with_device_id_and_roles_1_cert.p12&lt;/td&gt;
&lt;td&gt;uWTNwBluEXGszPYv&lt;/td&gt;
&lt;td&gt;55MoxEiH1B/r5Muz&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Tabella 3 - Certificati client generati per i test di accesso&lt;/p&gt;

&lt;p&gt;Il valore del DeviceId è stato generato utilizzando lo script &lt;code&gt;generate_device_id.sh&lt;/code&gt; e il valore è stato codificato in Base64. Il valore del DeviceId è stato inserito nel certificato client come estensione personalizzata &lt;code&gt;DeviceId&lt;/code&gt;. A seguire un esempio dell'output dello script &lt;code&gt;generate_device_id.sh&lt;/code&gt;.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Generate a DeviceId
./src/main/shell/certs-manager/generate_device_id.sh generate true

# Output
MTcyNjM1NTMzNTQyMzYxNzAwMCMyYzBlMzY4ZS1lMDU5LTQ5OWQtYjFjNS0zNGU4MjdiYmE0MTIjYW11c2FycmEtbWFjYm9vay1wcm8ubG9jYWwjNmNlZDI3YTI5ODUyMDJiNjhiOTA2YjQ3YTQzM2QyOGNkYTFmN2JkMjMxNzMzNTUxNmIzNmVlYTViMTc0MTdlOA==
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;Console 18 - Esempio di output dello script &lt;code&gt;generate_device_id.sh&lt;/code&gt; per la generazione del DeviceId&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 11 - Test della configurazione mTLS
&lt;/h3&gt;

&lt;p&gt;Il tag di riferimento per questo step è &lt;a href="https://github.com/amusarra/quarkus-mtls-auth-tutorial/tree/tutorial-step-11-test-config-mtls/src/main/resources/certs" rel="noopener noreferrer"&gt;tutorial-step-11-test-mtls-config&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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 &lt;code&gt;application.properties&lt;/code&gt; è indicata a seguire.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# 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
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;Application Properties 4 - Configurazione della secret key per la verifica del DeviceId&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;La verifica è implementata all'interno della classe &lt;code&gt;DeviceIdUtil&lt;/code&gt; attraverso il metodo &lt;code&gt;verifyDeviceId&lt;/code&gt; e l'algoritmo per la generazione del DeviceId è descritto nel capitolo &lt;em&gt;Algoritmo per la generazione del DeviceId&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Durante la fase di test, potrebbe risultare utile avere il log di debug dei componenti di &lt;code&gt;SecurityAugmentor&lt;/code&gt; per verificare che l'autenticazione mTLS funzioni correttamente. Per fare ciò, possiamo aggiungere le seguenti proprietà al file di configurazione &lt;code&gt;application.properties&lt;/code&gt;.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Logging configuration
quarkus.log.category."it.dontesta.quarkus.tls.auth.ws.security.identity.RolesAugmentor".level=DEBUG
quarkus.log.category."it.dontesta.quarkus.tls.auth.ws.security.identity.AttributesAugmentor".level=DEBUG
quarkus.log.category."it.dontesta.quarkus.tls.auth.ws.security.identity.OidSecurityIdentityAugmentor".level=DEBUG
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;Application Properties 5 - Configurazione del log di debug&lt;/p&gt;

&lt;p&gt;Adesso possiamo procedere con il test dell'applicazione Quarkus. Per fare ciò, eseguiremo i seguenti passaggi:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;avviare l'applicazione Quarkus;&lt;/li&gt;
&lt;li&gt;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 &lt;em&gt;Struttura JSON di risposta dei servizi Rest&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Per avviare l'applicazione basta eseguire il comando &lt;code&gt;quarkus:dev&lt;/code&gt; 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.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
          ,--------.,--. ,---. ,---.
,--,--,--.'--. .--'| | ' .-' ,-----. / 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&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;Console 18 - Avvio dell'applicazione Quarkus&lt;/p&gt;

&lt;p&gt;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 &lt;code&gt;curl&lt;/code&gt; o &lt;code&gt;Postman&lt;/code&gt;. In questo esempio, utilizzeremo &lt;code&gt;curl&lt;/code&gt; per inviare le richieste HTTP. In pipe (|) al comando &lt;code&gt;curl&lt;/code&gt; è stato incluso l'utilizzo del tool &lt;code&gt;jq&lt;/code&gt; che ci permette di ottenere un output più leggibile (in formato JSON) dei risultati delle richieste HTTP. Non è obbligatorio, ma è consigliabile &lt;a href="https://jqlang.github.io/jq/" rel="noopener noreferrer"&gt;installare il tool&lt;/a&gt; &lt;code&gt;jq&lt;/code&gt; per poter leggere meglio l'output dei comandi.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# 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
{
  "statusCode": 401,
  "message": "Invalid certificate OID { 1.3.6.1.4.1.99999.2 } missing for DeviceId."
}

# 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
{
  "statusCode": 401,
  "message": "Invalid certificate OID { 1.3.6.1.4.1.99999.2 } missing for DeviceId."
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;Console 19 - Esecuzione del test di accesso ai servizi REST con il certificato client senza estensioni personalizzate&lt;/p&gt;

&lt;p&gt;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 &lt;code&gt;DeviceId&lt;/code&gt; necessaria per l'autenticazione mTLS. In questo caso è intervenuta è la classe &lt;code&gt;OidSecurityIdentityAugmentor&lt;/code&gt; che ha la priorità più alta rispetto alle altre e che ha lanciato l'eccezione &lt;code&gt;SecurityException&lt;/code&gt; perché l'OID del DeviceId non è stato trovato.&lt;/p&gt;

&lt;p&gt;Proseguiamo il test con il certificato client con l'estensione personalizzata &lt;code&gt;DeviceId&lt;/code&gt; e il valore &lt;code&gt;1234567890&lt;/code&gt;.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# 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
{
  "statusCode": 401,
  "message": "Invalid certificate OID value { 1234567890 } or OID { 1.3.6.1.4.1.99999.2 } missing for DeviceId."
}

# 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
{
  "statusCode": 401,
  "message": "Invalid certificate OID value { 1234567890 } or OID { 1.3.6.1.4.1.99999.2 } missing for DeviceId."
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;Console 20 - Esecuzione del test di accesso ai servizi REST con il certificato client con estensione personalizzata &lt;code&gt;DeviceId&lt;/code&gt; e valore &lt;code&gt;1234567890&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Anche in questo caso l'esito del test è quello atteso, con la differenza che il messaggio di errore è leggermente diverso: &lt;code&gt;l'OID del DeviceId è stato trovato ma il valore non è valido&lt;/code&gt;. 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 &lt;code&gt;OidSecurityIdentityAugmentor&lt;/code&gt;).&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;      if (!DeviceIdUtil.verifyDeviceId(oidValue)) {
        throw new SecurityException(
            "Invalid certificate OID value { %s } or OID { %s } missing for DeviceId.".formatted(
                oidValue, AttributesAugmentor.OID_DEVICE_ID));
      }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Java&lt;/p&gt;

&lt;p&gt;Source Code 6 - Blocco di codice che verifica il valore del DeviceId&lt;/p&gt;

&lt;p&gt;Continuiamo il test con il certificato client con l'estensione personalizzata &lt;code&gt;DeviceId&lt;/code&gt; che ha il corretto valore generato dall'algoritmo descritto nel capitolo &lt;em&gt;Algoritmo per la generazione del DeviceId&lt;/em&gt; e l'estensione personalizzata &lt;code&gt;Roles&lt;/code&gt; con il valore &lt;code&gt;123User&lt;/code&gt;.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# 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
{
  "statusCode": 401,
  "message": "Decoded roles do not match the expected pattern: Role=123User"
}

# 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
{
  "statusCode": 401,
  "message": "Decoded roles do not match the expected pattern: Role=123User"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;Console 21 - Esecuzione del test di accesso ai servizi REST con il certificato client con estensione personalizzata &lt;code&gt;DeviceId&lt;/code&gt; con il corretto valore ed estensione personalizzata &lt;code&gt;Roles&lt;/code&gt; e valore &lt;code&gt;123User&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Anche in questo caso l'esito del test è quello atteso, con la differenza che il messaggio di errore è leggermente diverso: &lt;code&gt;Decoded roles do not match the expected pattern: Role=123User&lt;/code&gt;. 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 &lt;code&gt;RolesAugmentor&lt;/code&gt;).&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;        if (decodedRoles != null) {
          log.debug("Decoded roles from certificate: %s".formatted(decodedRoles));

          // Verify that decodedRoles matches the expected pattern
          if (decodedRoles.matches("^Role=([A-Za-z]+(?:,[A-Za-z]+)*+)$")) {
            // Add the roles to the set
            roles.addAll(Arrays.stream(decodedRoles.split("=")[1].split(","))
                .map(String::trim)
                .collect(Collectors.toSet()));
          } else {
            log.warn("Decoded roles do not match the expected pattern: %s".formatted(decodedRoles));

            throw new SecurityException(
                "Decoded roles do not match the expected pattern: %s".formatted(decodedRoles));
          }
        }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Java&lt;/p&gt;

&lt;p&gt;Source Code 7 - Blocco di codice che verifica il pattern dei ruoli&lt;/p&gt;

&lt;p&gt;Sulla console di Quarkus dovremmo vedere un output simile a quello riportato di seguito.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;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
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Plaintext&lt;/p&gt;

&lt;p&gt;Console 22 - Log di debug per la verifica del pattern dei ruoli&lt;/p&gt;

&lt;p&gt;Andiamo avanti con il test utilizzando il certificato client con l'estensione personalizzata &lt;code&gt;DeviceId&lt;/code&gt; che ha il corretto valore generato dall'algoritmo descritto nel capitolo &lt;em&gt;Algoritmo per la generazione del DeviceId&lt;/em&gt; e l'estensione personalizzata &lt;code&gt;Roles&lt;/code&gt; con il valore &lt;code&gt;ProjectManager&lt;/code&gt;.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# 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
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;Console 22 - Esecuzione del test di accesso ai servizi REST con il certificato client con estensione personalizzata &lt;code&gt;DeviceId&lt;/code&gt; con il corretto valore ed estensione personalizzata &lt;code&gt;Roles&lt;/code&gt; e valore &lt;code&gt;ProjectManager&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Anche in questo caso l'esito del test è quello atteso. L'accesso ai servizi REST è stato negato in quanto il ruolo &lt;code&gt;ProjectManager&lt;/code&gt; non è presente tra i ruoli consentiti, infatti la policy di accesso che abbiamo definito sulla proprietà &lt;code&gt;quarkus.http.auth.policy.role-policy-cert.roles-allowed&lt;/code&gt; prevede solo i ruoli &lt;code&gt;User&lt;/code&gt; e &lt;code&gt;Administrator&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Infine, proseguiamo il test con il certificato client che possiede l'estensione personalizzata &lt;code&gt;DeviceId&lt;/code&gt; che ha il corretto valore generato dall'algoritmo descritto nel capitolo &lt;em&gt;Algoritmo per la generazione del DeviceId&lt;/em&gt; e l'estensione personalizzata &lt;code&gt;Roles&lt;/code&gt; con il valore &lt;code&gt;User,Administrator&lt;/code&gt;.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# 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
{
  "httpRequestHeaders": {
    "user-agent": "curl/8.7.1",
    "accept": "*/*"
  },
  "server": {
    "notAfter": "Fri Sep 12 18:13:44 CEST 2025",
    "keyAlgorithm": "RSA",
    "keySize": 2048,
    "certCommonName": "rd.quarkus.dontesta.it",
    "certIssuer": "CN=Dontesta CA,OU=IT Labs,O=Dontesta,L=Bronte,ST=Catania,C=IT",
    "subjectAlternativeNames": [
      [
        2,
        "admin.quarkus.dontesta.it"
      ],
      [
        2,
        "blog.quarkus.dontesta.it"
      ],
      [
        2,
        "localhost"
      ]
    ],
    "certSubject": "CN=rd.quarkus.dontesta.it,OU=IT Labs,O=Dontesta,L=Bronte (CT),ST=Italy,C=IT",
    "certSerialNumber": "376693016274162034819659983838224914643739644606",
    "certPEM": "&amp;lt;removed&amp;gt;",
    "customExtensions": {},
    "notBefore": "Thu Sep 12 18:13:44 CEST 2024"
  },
  "protocol": "TLSv1.3",
  "httpProtocol": "HTTP_2",
  "clientPort": 64218,
  "isSecure": true,
  "client": {
    "notAfter": "Sat Sep 13 15:03:16 CEST 2025",
    "keyAlgorithm": "RSA",
    "keySize": 2048,
    "certCommonName": "7BF80D48-B92C-45EB-80F0-363D1CCA6E4C",
    "certIssuer": "CN=Dontesta CA,OU=IT Labs,O=Dontesta,L=Bronte,ST=Catania,C=IT",
    "subjectAlternativeNames": null,
    "certSubject": "CN=7BF80D48-B92C-45EB-80F0-363D1CCA6E4C,OU=Community &amp;amp; News,O=Massimo Visco Corporation,L=Rome,ST=Italy,C=IT",
    "certSerialNumber": "376693016274162034819659983838224914643739644614",
    "certPEM": "&amp;lt;removed&amp;gt;",
    "customExtensions": {
      "role": "Role=User,Administrator",
      "deviceId": "DeviceId=MTcyNjIzMjU5Njc5NTk2NjAwMCNmMjEwNTM2Ni02MTEyLTQyYTctOGI5OC00Njg3NmRkYWU0MmYjYW11c2FycmEtbWFjYm9vay1wcm8ubG9jYWwjNWZlMGUxMTNkMGJjMDIzZTQ3YTY0OTAzM2Q1NmM2MmEwN2EzMDk0MzVkYzdiOWIyMjIxZjkxNDcwNDVkZTdjNg=="
    },
    "notBefore": "Fri Sep 13 15:03:16 CEST 2024"
  },
  "userAgent": "curl/8.7.1",
  "cipherSuite": "TLS_AES_256_GCM_SHA384",
  "clientAddress": "127.0.0.1:64218"
}

# 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
{
  "principal": "CN=7BF80D48-B92C-45EB-80F0-363D1CCA6E4C,OU=Community &amp;amp; News,O=Massimo Visco Corporation,L=Rome,ST=Italy,C=IT",
  "roles": [
    "User",
    "Administrator"
  ],
  "attributes": {
    "deviceId": "MTcyNjIzMjU5Njc5NTk2NjAwMCNmMjEwNTM2Ni02MTEyLTQyYTctOGI5OC00Njg3NmRkYWU0MmYjYW11c2FycmEtbWFjYm9vay1wcm8ubG9jYWwjNWZlMGUxMTNkMGJjMDIzZTQ3YTY0OTAzM2Q1NmM2MmEwN2EzMDk0MzVkYzdiOWIyMjIxZjkxNDcwNDVkZTdjNg=="
  },
  "userCN": "7BF80D48-B92C-45EB-80F0-363D1CCA6E4C"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;Console 23 - Esecuzione del test di accesso ai servizi REST con il certificato client con estensione personalizzata &lt;code&gt;DeviceId&lt;/code&gt; con il corretto valore ed estensione personalizzata &lt;code&gt;Roles&lt;/code&gt; e valore &lt;code&gt;User,Administrator&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;L'output dei test di accesso ai servizi REST con il certificato client con l'estensione personalizzata &lt;code&gt;DeviceId&lt;/code&gt; con il corretto valore generato dall'algoritmo descritto nel capitolo &lt;em&gt;Algoritmo per la generazione del DeviceId&lt;/em&gt; e l'estensione personalizzata &lt;code&gt;Roles&lt;/code&gt; con il valore &lt;code&gt;User,Administrator&lt;/code&gt; 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 &lt;em&gt;Struttura JSON di risposta dei servizi Rest&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cos'è il Trusted Service List (TSL) e come integrarlo
&lt;/h2&gt;

&lt;p&gt;Il &lt;strong&gt;TSL&lt;/strong&gt; (Trusted Service List) è un documento elettronico standardizzato che contiene informazioni sui &lt;strong&gt;servizi fiduciari&lt;/strong&gt; 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.&lt;/p&gt;

&lt;p&gt;La &lt;strong&gt;mindmap&lt;/strong&gt; seguente suddivide il TSL nei seguenti rami principali.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Definizione&lt;/strong&gt; : contiene la definizione del TSL e il documento elettronico standard che lo rappresenta.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Componenti Principali&lt;/strong&gt; : elenca i principali componenti del TSL, come i fornitori di servizi fiduciari (TSP), i certificati digitali e i servizi fiduciari qualificati.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Normative&lt;/strong&gt; : descrive le normative che regolano il TSL, come il regolamento eIDAS nell’UE e l’interoperabilità tra paesi.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Utilizzo&lt;/strong&gt; : 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.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Aggiornamenti&lt;/strong&gt; : discute la validità e l’aggiornamento periodico del TSL, nonché la revoca dei fornitori non conformi.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh36gt9v6u9nstgi5x37h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh36gt9v6u9nstgi5x37h.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figura 11 - Mindmap del Trusted Service List (TSL)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;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 &lt;a href="https://eidas.ec.europa.eu/efda/tl-browser/#/screen/home" rel="noopener noreferrer"&gt;eIDAS Dashboard&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  La soluzione dell'integrazione del TSL in Quarkus
&lt;/h3&gt;

&lt;p&gt;Il tag di riferimento per questo step è &lt;a href="https://github.com/amusarra/quarkus-mtls-auth-tutorial/tree/tutorial-bonus-integrate-tsl" rel="noopener noreferrer"&gt;tutorial-bonus-integrate-tsl&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Per integrare il TSL in un'applicazione Quarkus, potremmo utilizzare la libreria &lt;strong&gt;&lt;a href="https://ec.europa.eu/digital-building-blocks/sites/display/DIGITAL/Digital+Signature+Service+-++DSS" rel="noopener noreferrer"&gt;DSS : Digital Signature Service&lt;/a&gt;&lt;/strong&gt; 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 &lt;a href="https://ec.europa.eu/digital-building-blocks/sites/display/DIGITAL/" rel="noopener noreferrer"&gt;Digital Building Blocks (DBB)&lt;/a&gt; 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.&lt;/p&gt;

&lt;p&gt;L'&lt;a href="https://github.com/amusarra/quarkus-mtls-auth-tutorial" rel="noopener noreferrer"&gt;applicazione Quarkus&lt;/a&gt;, 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.&lt;/p&gt;

&lt;p&gt;Restando nel territorio Italiano e volendo fare un esempio pratico, potremmo utilizzare il TSL Italiano pubblicato dall'&lt;a href="https://www.agid.gov.it/it" rel="noopener noreferrer"&gt;Agenzia per l'Italia Digitale (AgID)&lt;/a&gt; e integrarlo nell'applicazione Quarkus. L'AgID pubblica il TSL Italiano in un formato elettronico standardizzato che può essere consultato sulla &lt;a href="https://eidas.ec.europa.eu/efda/tl-browser/#/screen/tl/IT" rel="noopener noreferrer"&gt;eIDAS Dashboard&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;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 &lt;strong&gt;&lt;a href="https://www.cartaidentita.interno.gov.it/" rel="noopener noreferrer"&gt;Carta d'Identità Elettronica (CIE)&lt;/a&gt;&lt;/strong&gt; 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.&lt;/p&gt;

&lt;p&gt;Quali sono i macro passaggi per integrare il TSL Italiano nell'applicazione Quarkus?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Scaricare il file XML del TSL Italiano da eIDAS (&lt;a href="https://eidas.agid.gov.it/TL/TSL-IT.xml" rel="noopener noreferrer"&gt;https://eidas.agid.gov.it/TL/TSL-IT.xml&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Eseguire il parsing del file XML.&lt;/li&gt;
&lt;li&gt;Estrarre i certificati X509 delle CA dei fornitori di servizi fiduciari qualificati.&lt;/li&gt;
&lt;li&gt;Verificare i certificati digitali in ingresso.&lt;/li&gt;
&lt;li&gt;Configurare il TLS in Quarkus con i certificati digitali validati.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Questi macro passaggi possono essere implementati all'interno di un &lt;strong&gt;&lt;a href="https://quarkus.io/guides/scheduler" rel="noopener noreferrer"&gt;Periodic Task&lt;/a&gt;&lt;/strong&gt; di Quarkus che eseguirà gli step indicati in precedenza, così come mostrato nel diagramma di flusso a seguire.&lt;/p&gt;

&lt;p&gt;flowchart TD UpdateTSL&amp;gt;Periodic Task \nGov Certificate Updater] --&amp;gt; SA subgraph SA [TSL Update Process] Start([Start]) --&amp;gt; A[Download the TSL-IT.xml] A --&amp;gt; B[Parse the XML file] B --&amp;gt; C[Extract certificates and TSP] C --&amp;gt; D{Valid certificates?} D --&amp;gt;|Yes| E[Validate incoming certificates] D --&amp;gt;|No| F[Generate invalid certificate error] E --&amp;gt; G[Configure TLS in Quarkus] F --&amp;gt; End G --&amp;gt; End([End]) end&lt;/p&gt;

&lt;p&gt;Figura 12 - Diagramma di flusso per l'integrazione del TSL in Quarkus&lt;/p&gt;

&lt;h4&gt;
  
  
  Implementazione del parser XML del TSL e del task periodico di aggiornamento
&lt;/h4&gt;

&lt;p&gt;Per quanto riguarda il parser XML del TSL, andremo a scrivere un componente che chiameremo &lt;code&gt;GovCertificateParser&lt;/code&gt; che avrà le seguenti responsabilità:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;eseguire il parser del file XML estraendo solo i certificati X509 che sono identificati dall'elemento &lt;code&gt;ServiceTypeIdentifier&lt;/code&gt; con il valore &lt;code&gt;http://uri.etsi.org/TrstSvc/Svctype/IdV&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;verificare che i certificati X509 siano validi;&lt;/li&gt;
&lt;li&gt;salvare i certificati X509 validi in formato PEM;&lt;/li&gt;
&lt;li&gt;creare un bundle di certificati PEM che sarà poi utilizzato per configurare il TLS in Quarkus.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Per quanto riguarda il task periodico di aggiornamento, andremo a scrivere un componente che chiameremo &lt;code&gt;GovCertificateUpdater&lt;/code&gt; che avrà le seguenti responsabilità:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;eseguire il task periodico di aggiornamento del TSL con una frequenza che sia configurabile attraverso una proprietà applicativa sul file &lt;code&gt;application.properties&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;scaricare il file XML del TSL Italiano;&lt;/li&gt;
&lt;li&gt;chiamare il componente &lt;code&gt;GovCertificateParser&lt;/code&gt; che esegue il parsing del file XML e salva i certificati X509 all'interno di un bundle di certificati PEM;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Qui non riporterò il codice sorgente completo, che potete sempre visionare qui &lt;a href="https://github.com/amusarra/quarkus-mtls-auth-tutorial/tree/tutorial-bonus-integrate-tsl" rel="noopener noreferrer"&gt;tutorial-bonus-integrate-tsl&lt;/a&gt; ma vi mostrerò il codice sorgente del componente &lt;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" rel="noopener noreferrer"&gt;GovCertificateUpdater&lt;/a&gt; che si occupa di scaricare il file XML del TSL Italiano e di chiamare il componente &lt;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" rel="noopener noreferrer"&gt;GovCertificateParser&lt;/a&gt; per eseguire il parsing del file XML e salvare i certificati X509 all'interno di un bundle di certificati PEM.&lt;/p&gt;

&lt;p&gt;sequenceDiagram participant Scheduler participant GovCertificateUpdater participant HttpClient participant GovCertificateParser Scheduler-&amp;gt;&amp;gt;GovCertificateUpdater: updateCertificates() activate GovCertificateUpdater GovCertificateUpdater-&amp;gt;&amp;gt;HttpClient: download TSL-IT.xml activate HttpClient HttpClient--&amp;gt;&amp;gt;GovCertificateUpdater: TSL-IT.xml content deactivate HttpClient GovCertificateUpdater-&amp;gt;&amp;gt;GovCertificateParser: parseAndSaveCerts(xmlContent) activate GovCertificateParser GovCertificateParser-&amp;gt;&amp;gt;GovCertificateParser: cleanOutputPath() GovCertificateParser-&amp;gt;&amp;gt;GovCertificateParser: apply(Node node) GovCertificateParser-&amp;gt;&amp;gt;GovCertificateParser: saveCertificatesAsPem(inputDirectory, outputPath) deactivate GovCertificateParser deactivate GovCertificateUpdater&lt;/p&gt;

&lt;p&gt;Figura 13 - Diagramma di sequenza per l'aggiornamento del TSL in Quarkus&lt;/p&gt;

&lt;p&gt;Le configurazioni applicative introdotte per l'integrazione del TSL sono mostrate di seguito.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# 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
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;Application Properties 6 - Configurazioni applicative per l'integrazione del TSL&lt;/p&gt;

&lt;p&gt;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à &lt;code&gt;quarkus.tls.https.trust-store.pem.certs&lt;/code&gt; per aggiungere anche il bundle PEM delle CA del TSL e aggiungere la proprietà &lt;code&gt;quarkus.tls.https.reload-period&lt;/code&gt;. A seguire le modifiche apportate al file &lt;code&gt;application.properties&lt;/code&gt;.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# 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
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;Application Properties 7 - Configurazioni del TLS Registry per l'integrazione del TSL&lt;/p&gt;

&lt;p&gt;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 &lt;code&gt;tsl-it_bundle.pem&lt;/code&gt; (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 &lt;a href="https://quarkus.io/guides/tls-registry-reference#startup-checks" rel="noopener noreferrer"&gt;6. Startup checks&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Come risolvere questo problema?&lt;/strong&gt; Per gli ambienti superiori a sviluppo non è un problema perché in genere sono adottate soluzioni basate sulle &lt;a href="https://kubernetes.io/docs/concepts/configuration/secret/" rel="noopener noreferrer"&gt;kubernetes secrets&lt;/a&gt; o &lt;a href="https://cert-manager.io/" rel="noopener noreferrer"&gt;cert-manager&lt;/a&gt; (vedi &lt;a href="https://quarkus.io/guides/tls-registry-reference#using-kubernetes-secrets-or-cert-manager" rel="noopener noreferrer"&gt;8. Using Kubernetes secrets or cert-manager&lt;/a&gt;) 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.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;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)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Plaintext&lt;/p&gt;

&lt;p&gt;Console 24 - Errore di avvio dell'applicazione Quarkus a causa di un file PEM non valido&lt;/p&gt;

&lt;p&gt;Per riuscire a far partire l'applicazione Quarkus sul nostro ambiente di sviluppo, le strade sono due:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;creare un file PEM (&lt;code&gt;tsl-it_bundle.pem&lt;/code&gt;) con almeno un certificato valido all'interno della directory &lt;code&gt;/tmp/tsl-it&lt;/code&gt; prima di avviare l'applicazione Quarkus;&lt;/li&gt;
&lt;li&gt;creare il file &lt;code&gt;tsl-it_bundle.pem&lt;/code&gt; contenente i certificati validi estratti dal TSL Italiano all'interno della directory &lt;code&gt;/tmp/tsl-it&lt;/code&gt; prima di avviare l'applicazione Quarkus.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Indubbiamente la prima strada è la più semplice e veloce da percorrere, mentre la seconda richiede più di lavoro.&lt;/p&gt;

&lt;p&gt;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 &lt;code&gt;quarkus.tls.https.reload-period&lt;/code&gt;). 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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;La prima strada prevede di creare un file PEM con almeno un certificato di CA. Eseguendo dalla home del progetto lo script shell &lt;code&gt;./src/main/shell/certs-manager/download_tsl_it_certs.sh --fake&lt;/code&gt;, genereremo un file PEM con un certificato di CA fake. A seguire l'output dello script shell.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;🚀 Starting certificate update process
🔐 Generating fake CA certificate
.+.....+.+...+...+..+++++++++++++++++++++++++++++++++++++++*.+.....................+..+..........+..+............+...............+...+...+....+......+..+......+++++++++++++++++++++++++++++++++++++++*...+....+...+...........+....+......+..+.............+..+...+....+.....+.+...............+....................+.+..................+..+....+.....+.........+.+..+.........+...+...+...+....+...........+....+......+.....+.........+.......+...+...+.........+......+.....+...+......+...+.+......+...+..+...+...............+.............+...+.....+.+...........+....+........+............+......+...+....+.................+...+.+......+...+...+........+....+...+..............+....+.....+.+...............+.....+....+..............+............+......+.......+......+...........+.........+............+....+.....+.+.....+...+......+......+...+.........+.+.....................+...+.....+.......+.....+.+..+.............+..+............+......+....+.........++++++
...+..+.+.........+........+.+.........+++++++++++++++++++++++++++++++++++++++*.........+.+..+...+......+.+...+++++++++++++++++++++++++++++++++++++++*...++++++
✅ Generated fake CA certificate at /tmp/tsl-it/fake_ca.pem
✅ Added fake CA certificate to PEM bundle
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;Console 25 - Esecuzione dello script shell per la generazione di un file PEM con un certificato di CA fake&lt;/p&gt;

&lt;p&gt;Una volta ottenuto il file &lt;code&gt;/tmp/tsl-it/fake_ca.pem&lt;/code&gt; lo rinominiamo in &lt;code&gt;tsl-it_bundle.pem&lt;/code&gt; e avviamo l'applicazione Quarkus con il comando &lt;code&gt;quarkus dev&lt;/code&gt;. L'applicazione Quarkus dovrebbe partire senza problemi, ed eseguendo il comando &lt;code&gt;openssl s_client -connect localhost:8443 -showcerts&lt;/code&gt;, dovremmo vedere nella lista degli &lt;strong&gt;Acceptable client certificate CA names&lt;/strong&gt; il certificato di CA fake (con subject &lt;code&gt;C=US, ST=California, L=San Francisco, O=Fake Identity Corp, OU=IT Department, CN=Faked Identity Corp Root CA&lt;/code&gt;) che abbiamo generato, così come mostrato di seguito da un estratto dell'output del comando.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;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
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Plaintext&lt;/p&gt;

&lt;p&gt;Console 27 - Output del comando &lt;code&gt;openssl s_client -connect localhost:8443 -showcerts&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;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 &lt;code&gt;tsl-it_bundle.pem&lt;/code&gt; con i certificati validi estratti dal TSL prima di avviare l'applicazione Quarkus.&lt;/p&gt;

&lt;p&gt;Per generare quindi il file &lt;code&gt;tsl-it_bundle.pem&lt;/code&gt; con i certificati validi estratti dal TSL, eseguiremo lo script shell &lt;code&gt;./src/main/shell/certs-manager/download_tsl_it_certs.sh&lt;/code&gt; che si occuperà di scaricare il file XML del TSL, estrarre i certificati validi e salvarli in formato PEM (bundle) all'interno della directory &lt;code&gt;/tmp/tsl-it&lt;/code&gt;. Prima di eseguire lo script, dovreste accertare che l'applicazione Quarkus non sia attiva. A seguire un estratto di esecuzione dello script shell.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;🚀 Starting certificate update process
✅ Downloaded XML content
💾 Saving XML content to file: /tmp/tsl-it.xml
✅ Saved XML content to /tmp/tsl-it.xml
🔍 Parsing and saving certificates
🧹 Cleaning output path: /tmp/tsl-it
✅ Cleaned output path: /tmp/tsl-it
****Retrieving: /tmp/tsl-it.xml****
 ****Processing: /tmp/tsl-it.xml****
💾 Saving certificate as PEM
Certificate will not expire
✅ Saved certificate to /tmp/tsl-it/b43852d091d7d0ecd4bd473286dc82e5ba1f24f9d82ac2b6d0fae39e5c38637f.pem
🔍 Certificate subject: subject=C=IT, O=INFOCERT SPA, OU=Ente Certificatore, serialNumber=07945211006, CN=InfoCert Servizi di Certificazione 2
💾 Saving certificate as PEM
Certificate will not expire
✅ Saved certificate to /tmp/tsl-it/1b944bedf3d946bb0f8b889b6fa5130a152668e1d73ea253c334d8ea392c773b.pem
🔍 Certificate subject: subject=C=IT, O=InfoCert S.p.A., OU=Servizi di Certificazione, CN=Provincia Autonoma di Bolzano - CA Cittadini
💾 Saving certificate as PEM
Certificate will not expire
Certificate will expire
❌ 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
🏁 Processed 138 certificates
🏁 Expired certificates: 31
📦 Creating PEM bundle
✅ Created PEM bundle at /tmp/tsl-it/tsl-it_bundle.pem
🏁 Certificate update process completed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;Console 25 - Esecuzione dello script shell per l'aggiornamento del file &lt;code&gt;tsl-it_bundle.pem&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Ottimo! Abbiamo generato il file &lt;code&gt;tsl-it_bundle.pem&lt;/code&gt; con i certificati validi estratti dal TSL. Ora possiamo avviare l'applicazione Quarkus con il comando &lt;code&gt;quarkus dev&lt;/code&gt; e verificare che il TLS Registry di Quarkus sia stato ricaricato con i certificati validi estratti dal TSL. Eseguendo il comando &lt;code&gt;openssl s_client -connect localhost:8443 -showcerts&lt;/code&gt;, dovreste vedere nella lista degli &lt;strong&gt;Acceptable client certificate CA names&lt;/strong&gt; i certificati validi estratti dal TSL, così come atteso.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h3&gt;
  
  
  Test di accesso con la TS-CNS
&lt;/h3&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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).&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;Il test può essere eseguito in due modi, uno semplice e uno più avanzato.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;dopo aver collegato il lettore di smart card e inserita la TS-CNS, puntando il browser sull'indirizzo &lt;code&gt;https://localhost:8443/q/dev/&lt;/code&gt;, 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;&lt;/li&gt;
&lt;li&gt;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 &lt;a href="https://www.youtube.com/watch?v=N-IJeuN1oyE" rel="noopener noreferrer"&gt;Autenticazione con la TS-CNS: come usarla in modalità batch&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5wpbw2d3h5xkb1x1r28y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5wpbw2d3h5xkb1x1r28y.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figura 14 - Pop-up per l'inserimento del PIN della TS-CNS&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq2qyp98b1l76a30twvly.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq2qyp98b1l76a30twvly.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figura 15 - Pop-up per la selezione del certificato client&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiom4aqepncwijhlvnnei.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiom4aqepncwijhlvnnei.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figura 16 - Dev Console di Quarkus&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Ottimo! Abbiamo ottenuto il risultato atteso. Accedendo al servizio REST &lt;a href="https://localhost:8443/api/v1/connection-info/user-identity" rel="noopener noreferrer"&gt;https://localhost:8443/api/v1/connection-info/user-identity&lt;/a&gt; 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.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr5ec2o61iqx1frhsqem7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr5ec2o61iqx1frhsqem7.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figura 17 - Accesso negato al servizio REST&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Risorse
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;[1] &lt;a href="https://www.dontesta.it/2020/02/25/liferay-7-2-esempio-di-two-way-ssl-tls-mutual-authentication-client/" rel="noopener noreferrer"&gt;Antonio Musarra's Blog - Liferay 7.2: Esempio di Two-Way SSL/TLS Mutual Authentication Client&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;[2] &lt;a href="https://www.dontesta.it/2020/02/04/docker-image-apache-ssl-tls-mutual-authentication-on-azure-cloud/" rel="noopener noreferrer"&gt;Antonio Musarra's Blog - Docker Image Apache SSL/TLS Mutual Authentication on Azure Cloud&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;[3] &lt;a href="https://www.dontesta.it/2020/01/26/cose-il-progetto-cie-cns-apache-docker/" rel="noopener noreferrer"&gt;Antonio Musarra's Blog - Cos’è il progetto CIE/CNS Apache Docker&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;[4] &lt;a href="https://theredcode.it/devops/differenze-tra-keystore-e-truststore/" rel="noopener noreferrer"&gt;theRedCode - Differenze tra keystore e truststore&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;[5] &lt;a href="https://theredcode.it/devops/self-signed-certificati-openssl/" rel="noopener noreferrer"&gt;theRedCode - Certificati Self-Signed e OpenSSL&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;[4] &lt;a href="https://github.com/italia/cie-cns-apache-docker" rel="noopener noreferrer"&gt;GitHub - CIE/CNS Apache Docker&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;[5] &lt;a href="https://github.com/amusarra/docker-apache-ssl-tls-mutual-authentication" rel="noopener noreferrer"&gt;GitHub - Docker Apache SSL/TLS Mutual Authentication&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;[6] &lt;a href="https://github.com/smclab/cie-cns-auth-token-sso" rel="noopener noreferrer"&gt;GitHub - CIE/CNS Auth Token SSO&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;[7] &lt;a href="https://www.youtube.com/watch?v=N-IJeuN1oyE" rel="noopener noreferrer"&gt;Video - Autenticazione con la TS-CNS: come usarla in modalità batch&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;[8] &lt;a href="https://www.youtube.com/watch?v=TcAzn1POhsM" rel="noopener noreferrer"&gt;Video - Cos'è il progetto CIE/CNS Apache Docker - Developers Italia&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;[9] &lt;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" rel="noopener noreferrer"&gt;eBook - Liferay SSL/TLS Security. Come configurare il bundle Liferay per abilitare il protocollo SSL/TLS&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;[10] &lt;a href="https://amzn.to/47uFKOg" rel="noopener noreferrer"&gt;Book - Implementing SSL/TLS&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;[11] &lt;a href="https://amzn.to/3zoGSGE" rel="noopener noreferrer"&gt;Book - Network Security with OpenSSL&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Considerazioni finali
&lt;/h2&gt;

&lt;p&gt;Wow! Abbiamo fatto un bel percorso.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;L'articolo &lt;a href="https://www.dontesta.it/2024/09/19/implementazione-tls-mutual-authentication-mtls-con-quarkus/" rel="noopener noreferrer"&gt;Implementazione di TLS Mutual Authentication (mTLS) con Quarkus&lt;/a&gt; sembra essere il primo su &lt;a href="https://www.dontesta.it" rel="noopener noreferrer"&gt;Antonio Musarra's Blog&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>blog</category>
      <category>security</category>
      <category>ssltls</category>
      <category>javasecurity</category>
    </item>
    <item>
      <title>Cosa sono i modelli di licenza multipli nel software?</title>
      <dc:creator>Antonio Musarra</dc:creator>
      <pubDate>Wed, 21 Aug 2024 07:15:48 +0000</pubDate>
      <link>https://dev.to/amusarra/cosa-sono-i-modelli-di-licenza-multipli-nel-software-398o</link>
      <guid>https://dev.to/amusarra/cosa-sono-i-modelli-di-licenza-multipli-nel-software-398o</guid>
      <description>&lt;p&gt;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.&lt;/p&gt;

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

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cosa sono?
&lt;/h2&gt;

&lt;p&gt;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. &lt;/p&gt;

&lt;h2&gt;
  
  
  Tipi di modelli di licenza multipli
&lt;/h2&gt;

&lt;p&gt;Esistono diverse configurazioni per i modelli di licenza multipli.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Dual Licensing&lt;/strong&gt; : 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 &lt;a href="https://it.wikipedia.org/wiki/GNU_General_Public_License" rel="noopener noreferrer"&gt;GPL (General Public License)&lt;/a&gt;, 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.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Licenza con Eccezione&lt;/strong&gt; : 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.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Licenza Tripla o Multipla&lt;/strong&gt; : 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 &lt;a href="https://it.wikipedia.org/wiki/GNU_Lesser_General_Public_License" rel="noopener noreferrer"&gt;LGPL (Lesser General Public License)&lt;/a&gt; e una licenza commerciale, permettendo agli utenti di scegliere quella che meglio si adatta alle loro necessità.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Vantaggi dei modelli di licenza multipli
&lt;/h2&gt;

&lt;p&gt;I modelli di licenza multipli offrono una serie di vantaggi sia per gli sviluppatori che per gli utenti.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Flessibilità&lt;/strong&gt; : Gli sviluppatori possono soddisfare le esigenze di diversi utenti o mercati, aumentando il potenziale di adozione del software.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Monetizzazione&lt;/strong&gt; : 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.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Adozione da Parte delle Aziende&lt;/strong&gt; : 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.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Contributo alla Comunità&lt;/strong&gt; : 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.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Svantaggi
&lt;/h2&gt;

&lt;p&gt;Nonostante i numerosi vantaggi, i modelli di licenza multipli non sono privi di critiche.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Confusione&lt;/strong&gt; : L’esistenza di più licenze può creare confusione tra gli utenti, specialmente se non sono esperti in materia legale.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Complessità Legale&lt;/strong&gt; : 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.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Rischio di Forking&lt;/strong&gt; : 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.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Esempi di applicazione e note pratica
&lt;/h2&gt;

&lt;p&gt;Alcuni dei più noti software che utilizzano modelli di licenza multipli includono:&lt;/p&gt;

&lt;p&gt;• &lt;strong&gt;MySQL&lt;/strong&gt; : 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.&lt;/p&gt;

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

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

&lt;p&gt;Prendendo in considerazione il progetto &lt;a href="https://github.com/liferay/liferay-portal" rel="noopener noreferrer"&gt;Liferay Portal&lt;/a&gt;, anch’esso fa uso dell’approccio dual-licensing di cui riporto un breve estratto dal file &lt;a href="https://github.com/liferay/liferay-portal/blob/master/LICENSING.markdown" rel="noopener noreferrer"&gt;LICENSING.markdown&lt;/a&gt;.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;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 &amp;lt;https://www.liferay.com/contact-sales&amp;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.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://github.com/liferay/liferay-portal/blob/master/LICENSING.markdown" rel="noopener noreferrer"&gt;Licensing.markdown&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;L’intestazione dei file sorgenti (indicata a seguire) riporta le due license mostrate nell’estratto precedente. Le licenze sono espresse in formato &lt;a href="https://spdx.org/ids" rel="noopener noreferrer"&gt;SPDX language&lt;/a&gt; come illustrato enll’esempio seguente per il file sorgente &lt;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" rel="noopener noreferrer"&gt;OracleDB.java&lt;/a&gt;.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/**
* 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
*/ 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;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" rel="noopener noreferrer"&gt;OracleDB.java&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Se notate, le due licenze sono indicate con la chiave “ &lt;strong&gt;OR&lt;/strong&gt; ”, 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 &lt;a href="https://web.liferay.com/legal/doc/eula/dxp/2002306_GL" rel="noopener noreferrer"&gt;LicenseRef-Liferay-DXP-EULA-2.0.0-2023-06&lt;/a&gt;. Ogni licenza ha le proprie condizioni e obblighi, quindi la scelta dell’utente può dipendere da quale licenza è più adatta al loro uso specifico.&lt;/p&gt;

&lt;p&gt;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:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. AND:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Significato&lt;/strong&gt; : Se le licenze sono indicate con la chiave “AND” (esempio: “GPL-3.0 AND &lt;a href="https://opensource.org/license/mit" rel="noopener noreferrer"&gt;MIT&lt;/a&gt;”), significa che chi utilizza il codice deve rispettare &lt;strong&gt;entrambe&lt;/strong&gt; le licenze contemporaneamente.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Implicazioni&lt;/strong&gt; : 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.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Esempio&lt;/strong&gt; :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GPL-3.0 AND MIT&lt;/strong&gt; : 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.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. WITH:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Significato&lt;/strong&gt; : La chiave “WITH” viene utilizzata in combinazione con clausole aggiuntive o eccezioni.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Implicazioni&lt;/strong&gt; : Questa chiave indica che il codice è licenziato sotto una licenza principale, ma con alcune modifiche o eccezioni specifiche.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Esempio&lt;/strong&gt; :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GPL-3.0 WITH Classpath Exception&lt;/strong&gt; : 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.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Dual/Multi-Licensing (senza chiavi specifiche):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Descrizione&lt;/strong&gt; : 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.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Implicazioni&lt;/strong&gt; : La chiarezza delle condizioni di licenza dipende fortemente dalla documentazione fornita.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;4. Composite Licensing:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Descrizione&lt;/strong&gt; : 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.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Implicazioni&lt;/strong&gt; : Gli utenti devono fare attenzione a rispettare le licenze specifiche applicabili a ciascuna parte del codice.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;È essenziale per chi utilizza il codice comprendere queste combinazioni per garantire la conformità alle condizioni legali richieste.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusioni
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Risorse
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Open Source Initiative (OSI)&lt;/strong&gt; – &lt;a href="https://opensource.org" rel="noopener noreferrer"&gt;opensource.org&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;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.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Free Software Foundation (FSF)&lt;/strong&gt; – &lt;a href="https://www.fsf.org" rel="noopener noreferrer"&gt;fsf.org&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;La FSF offre risorse approfondite sulle licenze software libere, inclusa la GPL, e sulle modalità di rilascio del software sotto licenze multiple.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Understanding Open Source and Free Software Licensing&lt;/strong&gt; di &lt;a href="https://www.amazon.it/Andrew-M-St-Laurent/e/B001IQXSBI/ref=dp_byline_cont_book_1" rel="noopener noreferrer"&gt;Andrew M St Laurent&lt;/a&gt; (Autore)&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;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.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The Cathedral &amp;amp; the Bazaar – Musings on Linux &amp;amp; Open Source by an Accidental Revolutionary&lt;/strong&gt; di &lt;a href="https://www.amazon.it/Eric-Raymond/e/B000APZT1U/ref=dp_byline_cont_book_1" rel="noopener noreferrer"&gt;Eric Raymond&lt;/a&gt; (Autore)&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;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.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;L'articolo &lt;a href="https://www.dontesta.it/2024/08/21/cosa-sono-i-modelli-di-licenza-multipli-nel-software/" rel="noopener noreferrer"&gt;Cosa sono i modelli di licenza multipli nel software?&lt;/a&gt; sembra essere il primo su &lt;a href="https://www.dontesta.it" rel="noopener noreferrer"&gt;Antonio Musarra's Blog&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>blog</category>
      <category>editoria</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Cos’è l’approccio Document as Code (doc-as-code)</title>
      <dc:creator>Antonio Musarra</dc:creator>
      <pubDate>Mon, 24 Jun 2024 22:35:00 +0000</pubDate>
      <link>https://dev.to/amusarra/cose-lapproccio-document-as-code-doc-as-code-2j4b</link>
      <guid>https://dev.to/amusarra/cose-lapproccio-document-as-code-doc-as-code-2j4b</guid>
      <description>&lt;p&gt;Negli ultimi anni, l’approccio &lt;strong&gt;Document as Code&lt;/strong&gt; (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?&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Definizione e Principi Fondamentali
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Tracciabilità e Versionamento&lt;/strong&gt; : 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à.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Collaborazione e Revisione&lt;/strong&gt; : La documentazione può essere revisionata e migliorata attraverso &lt;strong&gt;pull request&lt;/strong&gt; e &lt;strong&gt;code review&lt;/strong&gt; , proprio come avviene per il codice sorgente. Questo processo incrementa la qualità e la precisione del contenuto.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automazione&lt;/strong&gt; : Strumenti di integrazione continua ( &lt;strong&gt;CI&lt;/strong&gt; ) 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.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Uniformità&lt;/strong&gt; : Utilizzando linguaggi di markup (tra i più noti) come &lt;a href="https://www.markdownguide.org/" rel="noopener noreferrer"&gt;Markdown&lt;/a&gt;, &lt;a href="https://asciidoc.org/" rel="noopener noreferrer"&gt;AsciiDoc&lt;/a&gt; e &lt;a href="https://docutils.sourceforge.io/rst.html" rel="noopener noreferrer"&gt;reStructuredText&lt;/a&gt;, è possibile mantenere uno stile coerente e facilmente leggibile. Inoltre, i generatori di documentazione come &lt;a href="https://www.sphinx-doc.org/en/master/" rel="noopener noreferrer"&gt;Sphinx&lt;/a&gt; o &lt;a href="https://www.mkdocs.org/" rel="noopener noreferrer"&gt;MkDocs&lt;/a&gt; possono essere utilizzati per creare documenti HTML, PDF e altro ancora da sorgenti testuali.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  2. Vantaggi dell’Approccio Doc-as-Code
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Miglioramento della Qualità&lt;/strong&gt; : La revisione paritaria e i test automatici assicurano che la documentazione sia accurata e aggiornata, riducendo il rischio di errori.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Efficienza&lt;/strong&gt; : 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.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Collaborazione&lt;/strong&gt; : L’uso di strumenti comuni tra sviluppatori e scrittori tecnici facilita una collaborazione più stretta e una migliore integrazione tra codice e documentazione.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flessibilità&lt;/strong&gt; : La documentazione può essere aggiornata e distribuita rapidamente, adattandosi facilmente ai cambiamenti del software e alle esigenze degli utenti.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Manutenibilità&lt;/strong&gt; : La struttura modularizzata e versionata dei documenti semplifica la gestione e l’aggiornamento continuo del materiale di documentazione.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  3. Strumenti e Tecnologie
&lt;/h2&gt;

&lt;p&gt;L’approccio Doc-as-Code si avvale di una serie di strumenti e tecnologie che facilitano la creazione, gestione e pubblicazione della documentazione.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sistemi di Controllo del Codice Sorgente&lt;/strong&gt; : Git è il più utilizzato, permettendo di versionare la documentazione e gestire le collaborazioni.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Linguaggi di Markup&lt;/strong&gt; : Markdown, AsciiDoc e reStructuredText sono i più comuni, grazie alla loro semplicità e leggibilità.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Generatori di Documentazione&lt;/strong&gt; : Strumenti come Sphinx, MkDocs, &lt;a href="https://jekyllrb.com/" rel="noopener noreferrer"&gt;Jekyll&lt;/a&gt; e &lt;a href="https://gohugo.io/" rel="noopener noreferrer"&gt;Hugo&lt;/a&gt; trasformano i file di markup in documenti formattati e navigabili.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CI/CD&lt;/strong&gt; : Piattaforme come Jenkins, Travis CI e GitHub Actions possono automatizzare la generazione e la pubblicazione della documentazione.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Editor di Testo&lt;/strong&gt; : Visual Studio Code, Intellj IDEA e altri editor moderni supportano estensioni che migliorano la scrittura e la formattazione della documentazione.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  4. Il bonus: un progetto Doc-as-Code
&lt;/h2&gt;

&lt;p&gt;Ogni promessa va onorata, per cui è arrivato il momento di presentarvi il bonus, un progetto doc-as-code completo.&lt;/p&gt;

&lt;p&gt;L’articolo &lt;a href="https://theredcode.it/devops/deploy-quarkus-openshift-facile" rel="noopener noreferrer"&gt;Deploy di un’applicazione Quarkus su OpenShift&lt;/a&gt; pubblicato su &lt;a href="https://www.theredcode.it/" rel="noopener noreferrer"&gt;TheRedCode.it&lt;/a&gt;, è il primo di quattro articoli che spiegano parte del progetto &lt;a href="https://github.com/amusarra/eventbus-logging-filter-jaxrs" rel="noopener noreferrer"&gt;Quarkus Event Bus Logging Filter JAX-RS&lt;/a&gt; e la documentazione di quest’ultimo è stata realizzata con l’approccio doc-as-code e in particolare:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;questo &lt;a href="https://github.com/amusarra/eventbus-logging-filter-jaxrs-docs/" rel="noopener noreferrer"&gt;Documentazione Quarkus Event Bus Logging Filter JAX-RS&lt;/a&gt; è il link al repository GitHub del progetto doc-as-code;&lt;/li&gt;
&lt;li&gt;questo &lt;a href="https://amusarra.github.io/eventbus-logging-filter-jaxrs-docs/" rel="noopener noreferrer"&gt;https://amusarra.github.io/eventbus-logging-filter-jaxrs-docs/&lt;/a&gt; è il link alle GitHub Pages dov’è stata pubblicata la documentazione in formato HTML;&lt;/li&gt;
&lt;li&gt;cliccando qui &lt;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" rel="noopener noreferrer"&gt;Quarkus Event – Come sfruttarlo al massimo, utilizzi e vantaggi&lt;/a&gt; otterrete la documentazione in formato PDF;&lt;/li&gt;
&lt;li&gt;il linguaggio di markup utilizzato è AsciiDoc;&lt;/li&gt;
&lt;li&gt;AsciiDoctor è il processore di testo che supporta la sintassi AsciiDoc e produce HTML5, DocBook, PDF e altri formati;&lt;/li&gt;
&lt;li&gt;per ulteriori dettagli sul progetto, fare riferimento al &lt;a href="https://github.com/amusarra/eventbus-logging-filter-jaxrs-docs/blob/main/README.md" rel="noopener noreferrer"&gt;README&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusioni
&lt;/h2&gt;

&lt;p&gt;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, &lt;strong&gt;avere una documentazione che può tenere il passo è essenziale per il successo di qualsiasi progetto&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;L'articolo &lt;a href="https://www.dontesta.it/2024/06/25/approccio-document-as-code/" rel="noopener noreferrer"&gt;Cos’è l’approccio Document as Code (doc-as-code)&lt;/a&gt; sembra essere il primo su &lt;a href="https://www.dontesta.it" rel="noopener noreferrer"&gt;Antonio Musarra's Blog&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>blog</category>
      <category>framework</category>
      <category>programming</category>
      <category>tools</category>
    </item>
    <item>
      <title>Come usare Java JMX in ambienti container</title>
      <dc:creator>Antonio Musarra</dc:creator>
      <pubDate>Tue, 18 Jun 2024 22:05:43 +0000</pubDate>
      <link>https://dev.to/amusarra/come-usare-java-jmx-in-ambienti-container-5c67</link>
      <guid>https://dev.to/amusarra/come-usare-java-jmx-in-ambienti-container-5c67</guid>
      <description>&lt;p&gt;Con l’adozione crescente delle &lt;a href="https://martinfowler.com/articles/microservices.html" rel="noopener noreferrer"&gt;architetture a microservizi&lt;/a&gt; e dei container per la distribuzione delle applicazioni, il monitoraggio delle prestazioni e la gestione dei servizi diventano aspetti critici. &lt;a href="https://www.oracle.com/java/technologies/javase/javamanagement.html" rel="noopener noreferrer"&gt;&lt;strong&gt;Java Management Extensions (JMX)&lt;/strong&gt;&lt;/a&gt; è uno strumento potente che consente agli sviluppatori di monitorare e gestire le applicazioni Java. In ambienti containerizzati, come quelli orchestrati da &lt;a href="https://kubernetes.io/" rel="noopener noreferrer"&gt;Kubernetes&lt;/a&gt;, &lt;a href="https://www.docker.com/" rel="noopener noreferrer"&gt;Docker&lt;/a&gt;, &lt;a href="https://podman.io/" rel="noopener noreferrer"&gt;Podman&lt;/a&gt; o altro, l’utilizzo di JMX presenta alcune sfide e richiede configurazioni specifiche.&lt;/p&gt;

&lt;p&gt;Questo articolo fornirà una guida dettagliata su come usare Java JMX in ambienti container e in particolare su &lt;a href="https://www.redhat.com/en/technologies/cloud-computing/openshift" rel="noopener noreferrer"&gt;Red Hat OpenShift&lt;/a&gt;. Vedremo come configurare JMX in un’applicazione Java basata su &lt;a href="https://quarkus.io/" rel="noopener noreferrer"&gt;Quarkus&lt;/a&gt; e come connettersi a un server JMX utilizzando &lt;a href="https://www.oracle.com/java/technologies/jdk-mission-control.html" rel="noopener noreferrer"&gt;JDK Mission Control&lt;/a&gt; per monitorare le prestazioni, gestire le risorse, e cambiare il livello di log a runtime.&lt;/p&gt;

&lt;p&gt;Per l’esempio pratico faremo riferimento all’applicazione di esempio &lt;a href="https://github.com/amusarra/eventbus-logging-filter-jaxrs" rel="noopener noreferrer"&gt;Event Bus Logging Filter JAX-RS&lt;/a&gt; e come ambiente di deploy e runtime la &lt;a href="https://developers.redhat.com/developer-sandbox" rel="noopener noreferrer"&gt;Dev Sandbox di Red Hat OpenShift&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Qualcuno potrebbe domandarsi: &lt;strong&gt;JMX è ancora attuale?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;u&gt;&lt;span&gt;Sì, Java Management Extensions (JMX) è ancora attuale e rilevante nel contesto dello sviluppo e della gestione delle applicazioni Java.&lt;/span&gt;&lt;/u&gt; Anche se alcune tecnologie evolvono e nuovi strumenti emergono, JMX continua a essere una componente fondamentale per diverse ragioni.&lt;/p&gt;

&lt;h3&gt;
  
  
  Standardizzazione e Compatibilità
&lt;/h3&gt;

&lt;p&gt;JMX è una specifica standardizzata e parte integrante della piattaforma Java SE (Standard Edition). Questo garantisce la compatibilità con tutte le implementazioni di Java, rendendolo un’opzione affidabile per il monitoraggio e la gestione delle applicazioni.&lt;/p&gt;

&lt;h3&gt;
  
  
  Integrazione con Strumenti Moderni
&lt;/h3&gt;

&lt;p&gt;Molti strumenti di monitoraggio e gestione delle applicazioni Java, come &lt;a href="https://openjdk.org/tools/svc/jconsole/" rel="noopener noreferrer"&gt;JConsole&lt;/a&gt;, &lt;a href="https://visualvm.github.io/" rel="noopener noreferrer"&gt;VisualVM&lt;/a&gt;, e strumenti di terze parti come &lt;a href="https://prometheus.io/" rel="noopener noreferrer"&gt;Prometheus&lt;/a&gt; e &lt;a href="https://grafana.com/" rel="noopener noreferrer"&gt;Grafana&lt;/a&gt;, offrono integrazioni native o plugin per lavorare con JMX. Questo permette di utilizzare JMX come base per la raccolta di metriche e la gestione delle risorse, integrandolo con soluzioni più moderne per la visualizzazione e l’analisi dei dati.&lt;/p&gt;

&lt;h3&gt;
  
  
  Utilizzo in Architetture Distribuite
&lt;/h3&gt;

&lt;p&gt;Con l’aumento dell’adozione delle architetture a microservizi e dei container, JMX rimane utile per il monitoraggio delle applicazioni Java distribuite. Ad esempio, molti container orchestrator come Kubernetes possono essere configurati per raccogliere metriche esposte tramite JMX (&lt;a href="https://quarkus.io/extensions/io.quarkiverse.micrometer.registry/quarkus-micrometer-registry-jmx/" rel="noopener noreferrer"&gt;Quarkus&lt;/a&gt; e &lt;a href="https://docs.spring.io/spring-boot/reference/actuator/jmx.html" rel="noopener noreferrer"&gt;Spring Boot&lt;/a&gt; lo consentono), facilitando il monitoraggio centralizzato delle applicazioni distribuite.&lt;/p&gt;

&lt;h3&gt;
  
  
  Flessibilità ed Estensibilità
&lt;/h3&gt;

&lt;p&gt;JMX è altamente flessibile ed estendibile. Gli sviluppatori possono definire nuovi &lt;a href="https://docs.oracle.com/javase%2Ftutorial%2F/jmx/mbeans/index.html" rel="noopener noreferrer"&gt;MBean&lt;/a&gt; per esporre metriche specifiche o per aggiungere funzionalità di gestione personalizzate. Questa estensibilità lo rende adattabile a molteplici scenari, sia per applicazioni legacy che moderne.&lt;/p&gt;

&lt;p&gt;Anche se JMX rimane rilevante, &lt;u&gt;&lt;span&gt;è importante considerare che nuovi paradigmi di monitoraggio, come l’osservabilità completa (tracing, logging, e metriche combinate) con strumenti come &lt;/span&gt;&lt;span&gt;&lt;a href="https://opentelemetry.io/" rel="noopener noreferrer"&gt;&lt;span&gt;OpenTelemetry&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/u&gt;, stanno guadagnando popolarità. Tuttavia, questi strumenti spesso possono essere configurati per raccogliere dati da sorgenti JMX, mostrando come JMX continui a integrarsi con le tecnologie emergenti.&lt;/p&gt;

&lt;h2&gt;
  
  
  Perché JMX nei Container?
&lt;/h2&gt;

&lt;p&gt;L’utilizzo di JMX nei container permette di:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;monitorare le prestazioni e lo stato delle applicazioni Java;&lt;/li&gt;
&lt;li&gt;ottenere visibilità in tempo reale sulle risorse e sui thread dell’applicazione;&lt;/li&gt;
&lt;li&gt;gestire dinamicamente le configurazioni senza necessità di riavviare l’applicazione.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Inoltre, JMX nei container può essere integrato con strumenti di monitoraggio e gestione delle applicazioni, come Prometheus, Grafana, JConsole o strumenti di &lt;a href="https://en.wikipedia.org/wiki/Application_performance_management" rel="noopener noreferrer"&gt;APM (Application Performance Management)&lt;/a&gt;, per raccogliere e visualizzare metriche, analizzare i dati, e rispondere in modo pro attivo ai problemi di prestazioni.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configurazione di JMX in un’applicazione Java
&lt;/h2&gt;

&lt;p&gt;Per abilitare JMX in un’applicazione Java, è necessario configurare il server JMX per esporre le metriche e MBean. Questo può essere fatto tramite le opzioni di avvio della JVM, specificando le proprietà di sistema per abilitare il server JMX e definire la porta di ascolto. Ad esempio, è possibile utilizzare le seguenti opzioni di avvio.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=9091
-Dcom.sun.management.jmxremote.rmi.port=9091
-Djava.rmi.server.hostname=127.0.0.1
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.local.only=true


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Configurazione 1 – Opzioni di avvio per abilitare JMX&lt;/p&gt;

&lt;p&gt;Queste opzioni abilitano il server JMX sulla porta 9091, consentono la connessione da host remoti specificando l’indirizzo IP del server, disabilitano l’autenticazione e l’uso di SSL per semplificare la configurazione. È importante notare che queste opzioni sono solo un esempio e possono essere personalizzate in base alle esigenze specifiche dell’applicazione.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Se volessi abilitare JMX su di una applicazione Java basata su Quarkus e installata su Red Hat OpenShift, come dovrei fare?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Utilizzando gli strumenti messi a disposizione da Quarkus, tutto è molto semplice. Gli step sono i seguenti:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;abilitare l’estensione OpenShift per Quarkus (tramite il comando &lt;code&gt;quarkus add-extension io.quarkus:quarkus-openshift&lt;/code&gt;);&lt;/li&gt;
&lt;li&gt;configurare la variabile d’ambiente &lt;code&gt;JAVA_OPTS&lt;/code&gt; per il runtime di OpenShift per abilitare JMX;&lt;/li&gt;
&lt;li&gt;configurare i port mapping per esporre la porta JMX e consentire la connessione da host remoti.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Per aggiungere la variabile d’ambiente &lt;code&gt;JAVA_OPTS&lt;/code&gt; per abilitare JMX in Quarkus su OpenShift, è possibile utilizzare la seguente configurazione sul file &lt;code&gt;application.properties&lt;/code&gt;. Sono le stesse opzioni di avvio che abbiamo visto in precedenza ma configurate come variabile d’ambiente.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

quarkus.openshift.env.vars.java-opts=-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9091 -Dcom.sun.management.jmxremote.rmi.port=9091 -Djava.rmi.server.hostname=127.0.0.1 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.local.only=true


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Configurazione 2 – Variabile d’ambiente JAVA_OPTS per abilitare JMX in Quarkus su OpenShift&lt;/p&gt;

&lt;p&gt;Per soddisfare il terzo punto della precedente lista, occorre configurare il &lt;a href="https://kubernetes.io/docs/concepts/workloads/controllers/deployment/" rel="noopener noreferrer"&gt;Deployment&lt;/a&gt; e &lt;a href="https://kubernetes.io/docs/concepts/services-networking/service/" rel="noopener noreferrer"&gt;Service&lt;/a&gt; (oggetti K8s) per esporre la porta JMX e consentire quindi la connessione da host remoti. Questo può essere fatto utilizzando le seguenti configurazioni (sempre sul file di configurazione &lt;code&gt;application.properties&lt;/code&gt;).&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

# Define the ports that should be exposed by the container
# for the JMX monitoring
quarkus.openshift.ports.jmx.protocol=TCP
quarkus.openshift.ports.jmx.container-port=9091



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Configurazione 3 – Configurazione dei port mapping per JMX in Quarkus su OpenShift&lt;/p&gt;

&lt;p&gt;Le configurazioni mostrate in precedenza, faranno in modo che, in fase di build e deploy su OpenShift, siano creati i corretti oggetti K8s per esporre la porta JMX e consentire la connessione da host remoti; non ci dobbiamo preoccupare di creare manualmente i file di configurazione YAML per il Deployment e Service, di cui a seguire sono riportati gli estratti con le informazioni necessarie.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

apiVersion: apps/v1
kind: Deployment
metadata:
spec:
  replicas: 2
  selector:
    matchLabels:
  template:
    spec:
      containers:
        - env:
            - name: JAVA_OPTS
              value: -Dcom.sun.management.jmxremote
                -Dcom.sun.management.jmxremote.port=9091 -Dcom.sun.management.jmxremote.rmi.port=9091
                -Djava.rmi.server.hostname=127.0.0.1 -Dcom.sun.management.jmxremote.authenticate=false
                -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.local.only=true
            - name: JAVA_APP_JAR
              value: /deployments/quarkus-run.jar
          image: eventbus-logging-filter-jaxrs:1.2.7-SNAPSHOT
          imagePullPolicy: Always
          name: eventbus-logging-filter-jaxrs
          ports:
            - containerPort: 9091
              name: jmx
              protocol: TCP



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Configurazione 4 – Configurazione del Deployment per abilitare JMX in Quarkus su OpenShift&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; in realtà, la configurazione del Service per esporre la porta JMX non è strettamente necessaria, in quanto il Service viene creato automaticamente dal plugin OpenShift di Quarkus. Come vedremo in seguito, la connessione sarà instaurata direttamente con il pod che esegue l’applicazione Java.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

apiVersion: v1
kind: Service
metadata:
  name: eventbus-logging-filter-jaxrs
spec:
  ports:
    - name: jmx
      port: 9091
      protocol: TCP
      targetPort: 9091
  selector:
    app.kubernetes.io/name: eventbus-logging-filter-jaxrs
    app.kubernetes.io/version: 1.2.7-SNAPSHOT
  type: ClusterIP



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Configurazione 5 – Configurazione del Service per abilitare JMX in Quarkus su OpenShift&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; le configurazioni mostrate in precedenza sono generate automaticamente dal plugin OpenShift di Quarkus e disponibili all’interno del folder &lt;code&gt;target/kubernetes&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A questo punto è possibile procedere con build e il deploy dell’applicazione su OpenShift. Una volta completato il deploy, sarà possibile connettersi al server JMX esposto dall’applicazione Java e monitorare le prestazioni, le risorse e i MBean.&lt;/p&gt;

&lt;h2&gt;
  
  
  Verifica del deploy e preparazione connessione a JMX
&lt;/h2&gt;

&lt;p&gt;Per verificare che l’applicazione Java sia stata correttamente deployata su OpenShift e che il server JMX sia attivo, è possibile utilizzare il comando &lt;code&gt;oc&lt;/code&gt; per ottenere informazioni sul pod.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

# Get information about the pod
oc get pod

# Output
NAME READY STATUS RESTARTS AGE
activemq-artemis-675cf6d9-wpbrj 1/1 Running 0 3h26m
eventbus-logging-filter-jaxrs-66586f8dc4-5k7t4 1/1 Running 0 4m25s
eventbus-logging-filter-jaxrs-66586f8dc4-vx8sh 1/1 Running 0 4m36s
mongo-7d488b9474-vg8wq 1/1 Running 0 3h25m
postgresql-7fbdfbcd64-7b76h 1/1 Running 0 3h26m



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Console 1 – Output del comando oc get pod&lt;/p&gt;

&lt;p&gt;I pod (in questo caso due) dell’applicazione Java eventbus-logging-filter-jaxrs sono stati deployati correttamente e sono in stato Running. Adesso verifichiamo che la variabile di ambiente JAVA_OPTS sia stata correttamente configurata per abilitare JMX. Possiamo usare sempre il comando oc (in diverse forme) per ottenere informazioni sulle variabili d’ambiente del pod. A seguire sono mostrati due possibili modi.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

# Get environment variables for the pod
# 1. Using the get pod command with the -o json flag to get the JSON output
# To execute this command, you need to have the jq utility installed
oc get pod eventbus-logging-filter-jaxrs-66586f8dc4-5k7t4 -o json | jq '.spec.containers[].env'

# 2. Using the exc command to get the environment variables
oc exec eventbus-logging-filter-jaxrs-66586f8dc4-5k7t4 -- env | grep JAVA_OPTS



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Console 2 – Output dei comandi &lt;code&gt;oc&lt;/code&gt; per ottenere le variabili d’ambiente del pod&lt;/p&gt;

&lt;p&gt;A seguire l’output dei comandi oc per ottenere le variabili d’ambiente del pod e in particolare quella di nostro interesse JAVA_OPTS . Dall’output ottenuto, la variabile d’ambiente JAVA_OPTS è stata correttamente configurata e impostata per abilitare JMX.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

# Output of the oc get pod eventbus-logging-filter-jaxrs-66586f8dc4-5k7t4 -o json | jq '.spec.containers[].env'
[
{
"name": "JAVA_OPTS",
"value": "-Xms100M -Xmx500M -XX:+UseG1GC -XX:+UnlockExperimentalVMOptions -XX:MaxGCPauseMillis=200 -XX:InitiatingHeapOccupancyPercent=45 -XX:G1ReservePercent=10 -XX:ConcGCThreads=4 -XX:G1NewSizePercent=5 -XX:G1MaxNewSizePercent=60 -XX:ParallelGCThreads=4 -XX:+ExitOnOutOfMemoryError -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9091 -Dcom.sun.management.jmxremote.rmi.port=9091 -Djava.rmi.server.hostname=127.0.0.1 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.local.only=true"
},
{
"name": "JAVA_APP_JAR",
"value": "/deployments/quarkus-run.jar"
}
]

# Output of the oc exec eventbus-logging-filter-jaxrs-66586f8dc4-5k7t4 -- env | grep JAVA_OPTS
JAVA_OPTS=-Xms100M -Xmx500M -XX:+UseG1GC -XX:+UnlockExperimentalVMOptions -XX:MaxGCPauseMillis=200 -XX:InitiatingHeapOccupancyPercent=45 -XX:G1ReservePercent=10 -XX:ConcGCThreads=4 -XX:G1NewSizePercent=5 -XX:G1MaxNewSizePercent=60 -XX:ParallelGCThreads=4 -XX:+ExitOnOutOfMemoryError -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9091 -Dcom.sun.management.jmxremote.rmi.port=9091 -Djava.rmi.server.hostname=127.0.0.1 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.local.only=true


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Console 3 – Output dei comandi &lt;code&gt;oc&lt;/code&gt; per ottenere le variabili d’ambiente del pod (dettaglio)&lt;/p&gt;

&lt;p&gt;Affinchè dalla nostra macchina sia possibile eseguire la connessione JMX, è necessario creare un tunnel che reindirizza una porta del computer locale a una porta di un pod specifico; la porta di nostro interesse è la 9091. Questo tipo di operazione può essere fatta utilizzando il comando oc port-forward così come mostrato di seguito.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

# Enable port forwarding for the JMX port
oc port-forward pod/eventbus-logging-filter-jaxrs-66586f8dc4-5k7t4 9091:9091

# If the port forwarding is successful, you should see the following output
Forwarding from 127.0.0.1:9091 -&amp;gt; 9091
Forwarding from [::1]:9091 -&amp;gt; 9091



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Console 4 – Comando &lt;code&gt;oc port-forward&lt;/code&gt; per abilitare il forwarding della porta JMX&lt;/p&gt;

&lt;p&gt;A questo punto, l’applicazione Java è pronta per essere monitorata tramite JMX. Per connettersi al server JMX, è possibile utilizzare strumenti come JConsole, VisualVM, o qualsiasi altro client JMX compatibile. Nel nostro caso utilizzeremo JDK Mission Control.&lt;/p&gt;

&lt;h2&gt;
  
  
  Connessione a JMX tramite JDK Mission Control
&lt;/h2&gt;

&lt;p&gt;JDK Mission Control è uno strumento avanzato di monitoraggio e gestione delle applicazioni Java, incluso nella suite di strumenti &lt;a href="https://www.oracle.com/docs/tech/java/java-mission-control-technical-brief.pdf" rel="noopener noreferrer"&gt;Java Flight Recorder (JFR)&lt;/a&gt;. Per connettersi a un server JMX, è possibile utilizzare JDK Mission Control e specificare l’indirizzo IP e la porta del server JMX.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Avviare JDK Mission Control utilizzando il comando &lt;code&gt;jmc&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Dal menù &lt;code&gt;File&lt;/code&gt; selezionare la voce &lt;code&gt;Connect&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Selezionare la voce &lt;code&gt;Create a new connection&lt;/code&gt; per aggiungere una nuova connessione JMX.&lt;/li&gt;
&lt;li&gt;Specificare l’indirizzo IP e la porta del server JMX (es. &lt;code&gt;localhost:9091&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Specificare un nome per la connessione (es. &lt;code&gt;MyApp JMX Connection&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Fare clic su &lt;code&gt;Test Connection&lt;/code&gt; per verificare che la connessione vada a buon fine con i parametri specificati. Se la connessione avverrà con successo, sarà visualizzato un messaggio di conferma.&lt;/li&gt;
&lt;li&gt;Fare clic su &lt;code&gt;Finish&lt;/code&gt; per terminare la configurazione della connessione.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;La figura a seguire mostra la creazione di una nuova connessione JMX in JDK Mission Control e l’esito positivo del test di connessione.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2024/06/new_connection_jmx_2.jpg" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5uvphcm2bb35onedtkbr.jpg" alt="Figura 1 - Creazione di una nuova connessione JMX in JDK Mission Control" width="654" height="402"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figura 1 – Creazione di una nuova connessione JMX in JDK Mission Control&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Una volta definita la connessione JMX, è possibile visualizzare quali MBean sono esposti dall’applicazione Java, monitorare le prestazioni e le risorse, e gestire dinamicamente l’applicazione avviando la console JMX così come indicato dalla figura seguente.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2024/06/start_jmx_console_1.jpg" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwmo5knk590vszetarp06.jpg" alt="Figura 2 - Avvio della console JMX in JDK Mission Control" width="445" height="184"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figura 2 – Avvio della console JMX in JDK Mission Control&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Non appena connessi, dovreste vedere la dashboard di Mission Control con le metriche e i MBean esposti dall’applicazione Java. Da qui è possibile monitorare le prestazioni, analizzare i dati e gestire l’applicazione in tempo reale.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2024/06/jmc_dashboard_1.jpg" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjdawkqxgqmpx8zhhmb5n.jpg" alt="Figura 3 - Dashboard di JDK Mission Control con le metriche JMX" width="800" height="427"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figura 3 – Dashboard di JDK Mission Control con le metriche JMX&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Accedendo alla sezione &lt;code&gt;MBean Browser&lt;/code&gt; di JDK Mission Control, è possibile esplorare quali MBean sono esposti dall’applicazione Java e visualizzare le metriche e le operazioni disponibili per ciascun MBean. La figura seguente mostra per esempio le metriche che riguardano il connection pool e in particolare di &lt;a href="https://agroal.github.io/" rel="noopener noreferrer"&gt;Agroal&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2024/06/jmc_mbean_browser_1.jpg" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv49hn06k0l495dpqqsxr.jpg" alt="Figura 4 - Browser MBean di JDK Mission Control" width="800" height="660"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figura 4 – Browser MBean di JDK Mission Control&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Come cambiare il livello di log a runtime
&lt;/h2&gt;

&lt;p&gt;Quante volte vi è capitato di dover cambiare il livello di log di un’applicazione Java a runtime, senza dover riavviare l’applicazione stessa? Con JMX è possibile farlo in modo semplice e veloce.&lt;/p&gt;

&lt;p&gt;Una delle caratteristiche più potenti di JMX è la possibilità di gestire dinamicamente le risorse e le configurazioni dell’applicazione Java senza necessità di riavviare l’applicazione.&lt;/p&gt;

&lt;p&gt;Per farlo utilizzeremo JDK Mission Control e il MBean &lt;code&gt;java.util.logging:type=Logging&lt;/code&gt; per cambiare il livello di log a runtime. Questo MBean consente di modificare il livello di log per i logger specifici dell’applicazione Java, consentendo di aumentare o diminuire il livello di dettaglio dei log senza dover riavviare l’applicazione.&lt;/p&gt;

&lt;p&gt;Come primo step dobbiamo identificare il logger per cui desideriamo cambiare il livello di log. Questo può essere fatto esplorando i MBean esposti dall’applicazione Java e cercando il MBean &lt;code&gt;java.util.logging:type=Logging&lt;/code&gt; (vedi figura a seguire).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2024/06/jmc_mbean_browser_logger_1.jpg" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4jeqqlupsjkgwfe72lwy.jpg" alt="Figura 5 - MBean  raw `java.util.logging:type=Logging` endraw  in JDK Mission Control" width="800" height="243"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figura 5 – MBean &lt;code&gt;java.util.logging:type=Logging&lt;/code&gt; in JDK Mission Control&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Supponiamo di aver identificato il logger &lt;code&gt;it.dontesta.eventbus.consumers.events.handlers.Dispatcher&lt;/code&gt; per cui vogliamo cambiare il livello di log a &lt;code&gt;DEBUG&lt;/code&gt;. Prima di procedere con la modifica, verifichiamo il livello di log corrente (che dovrebbe essere &lt;code&gt;INFO&lt;/code&gt;) per il logger utilizzando il metodo &lt;code&gt;getLoggerLevel&lt;/code&gt; del MBean &lt;code&gt;java.util.logging:type=Logging&lt;/code&gt; (vedi figura a seguire) e successivamente cambieremo il livello di log utilizzando il metodo &lt;code&gt;setLoggerLevel&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Per accedere alle operazioni dello specifico MBean, fare clic sul nome del MBean e selezionare la voce &lt;code&gt;Operations&lt;/code&gt; per visualizzare i metodi disponibili.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2024/06/jmc_mbean_browser_logger_get_loglevel_1.jpg" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbi4k4dlf4v1a95lo40sv.jpg" alt="Figura 6 - Verifica del livello di log attuale per il logger it.dontesta.eventbus.consumers.events.handlers.Dispatcher" width="800" height="170"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figura 6 – Verifica del livello di log attuale per il logger it.dontesta.eventbus.consumers.events.handlers.Dispatcher&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Dal risultato visibile dalla precedente figura, il livello di log attuale per il logger &lt;code&gt;it.dontesta.eventbus.consumers.events.handlers.Dispatcher&lt;/code&gt; è &lt;code&gt;INFO&lt;/code&gt;. Per cambiarlo a &lt;code&gt;DEBUG&lt;/code&gt;, dobbiamo utilizzare il metodo &lt;code&gt;setLoggerLevel&lt;/code&gt; del MBean &lt;code&gt;java.util.logging:type=Logging&lt;/code&gt; specificando il nome del logger e il nuovo livello di log (vedi figura a seguire).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2024/06/jmc_mbean_browser_logger_set_loglevel_1.jpg" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5jxn07oy41map6yqf9jg.jpg" alt="Figura 7 - Cambio del livello di log a  raw `DEBUG` endraw  per il logger it.dontesta.eventbus.consumers.events.handlers.Dispatcher" width="800" height="155"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figura 7 – Cambio del livello di log a &lt;code&gt;DEBUG&lt;/code&gt; per il logger it.dontesta.eventbus.consumers.events.handlers.Dispatcher&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Una volta cambiato il livello di log, l’applicazione Java inizierà a registrare i log con il nuovo livello di dettaglio senza necessità di riavviare l’applicazione. Questo permette di gestire dinamicamente i log dell’applicazione Java in tempo reale, adattandoli alle esigenze di monitoraggio e debug. A seguire un esempio di log registrato dall’applicazione Java con il nuovo livello di log &lt;code&gt;DEBUG&lt;/code&gt;.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

# Log output with DEBUG level
oc logs -f eventbus-logging-filter-jaxrs-66586f8dc4-5k7t4

# Output
2024-06-09 14:23:38,806 DEBUG [it.don.eve.con.eve.han.Dispatcher] (vert.x-eventloop-thread-0) Sending event message to target virtual address: nosql-trace
2024-06-09 14:23:38,807 DEBUG [it.don.eve.con.eve.han.Dispatcher] (vert.x-eventloop-thread-0) Sending event message to target virtual address: queue-trace
2024-06-09 14:23:38,807 DEBUG [it.don.eve.con.eve.han.Dispatcher] (vert.x-eventloop-thread-0) Received response from target virtual address: nosql-trace with result: Documents inserted successfully with Id BsonObjectId{value=6665baea279ab051ec5bce3d}
2024-06-09 14:23:38,808 DEBUG [it.don.eve.con.eve.han.Dispatcher] (vert.x-eventloop-thread-0) Received response from target virtual address: queue-trace with result: Message sent to AMQP queue successfully!
2024-06-09 14:23:38,808 DEBUG [it.don.eve.con.eve.han.Dispatcher] (vert.x-eventloop-thread-0) Received response from target virtual address: nosql-trace with result: Documents inserted successfully with Id BsonObjectId{value=6665baea279ab051ec5bce3e}
2024-06-09 14:23:38,808 DEBUG [it.don.eve.con.eve.han.Dispatcher] (vert.x-eventloop-thread-0) Received response from target virtual address: queue-trace with result: Message sent to AMQP queue successfully!



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Console 5 – Output dei log con livello &lt;code&gt;DEBUG&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusioni
&lt;/h2&gt;

&lt;p&gt;In questo articolo abbiamo esplorato come utilizzare Java JMX in ambienti container, in particolare su Red Hat OpenShift. Abbiamo visto come configurare JMX in un’applicazione Java basata su Quarkus e come connettersi a un server JMX utilizzando JDK Mission Control per monitorare le prestazioni, gestire le risorse, e cambiare il livello di log a runtime.&lt;/p&gt;

&lt;p&gt;&lt;u&gt;&lt;span&gt;Vorrei sottolineare il fatto che JMX può essere configurato in modo indipendente dal framework o dalla piattaforma utilizzata, e può essere utilizzato per monitorare e gestire qualsiasi applicazione Java.&lt;/span&gt;&lt;/u&gt;&lt;/p&gt;

&lt;p&gt;La possibilità di utilizzare JMX risulta particolarmente utile quando per esempio siamo ancora in fase di sviluppo o in fase di test, (non abbiamo un strumento di APM completo) e dobbiamo monitorare le prestazioni e le risorse dell’applicazione Java, o quando dobbiamo cambiare il livello di log a runtime per debuggare un problema specifico.&lt;/p&gt;

&lt;p&gt;Ho volutamente scelto di utilizzare Java Mission Control perché questo apre la strada all’uso di Java Flight Recorder (JFR) che è uno strumento molto potente per il monitoraggio delle prestazioni e l’analisi dei dati. Inoltre, Mission Control è uno strumento gratuito e open source, disponibile per tutti gli sviluppatori Java.&lt;/p&gt;

&lt;p&gt;In tema di Java Flight Recorder, Red Hat sponsorizza il progetto Cryostat, che è un’alternativa open source a Mission Control, che consente di utilizzare Java Flight Recorder in ambienti containerizzati. Invito a leggere l’articolo &lt;a href="https://quarkus.io/blog/monitoring-quarkus-jvm-mode-with-cryostat/" rel="noopener noreferrer"&gt;Monitoring Quarkus JVM Mode With Cryostat&lt;/a&gt; per ulteriori dettagli.&lt;/p&gt;

&lt;p&gt;L'articolo &lt;a href="https://www.dontesta.it/2024/06/19/come-usare-java-jmx-in-ambienti-container/" rel="noopener noreferrer"&gt;Come usare Java JMX in ambienti container&lt;/a&gt; sembra essere il primo su &lt;a href="https://www.dontesta.it" rel="noopener noreferrer"&gt;Antonio Musarra's Blog&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>blog</category>
      <category>framework</category>
      <category>tools</category>
      <category>java</category>
    </item>
    <item>
      <title>Raspberry Pi e Smart Card Mifare Classic 1K: Realizzare un sistema di accesso</title>
      <dc:creator>Antonio Musarra</dc:creator>
      <pubDate>Fri, 11 Mar 2022 18:36:08 +0000</pubDate>
      <link>https://dev.to/amusarra/raspberry-pi-e-smart-card-mifare-classic-1k-realizzare-un-sistema-di-accesso-33h6</link>
      <guid>https://dev.to/amusarra/raspberry-pi-e-smart-card-mifare-classic-1k-realizzare-un-sistema-di-accesso-33h6</guid>
      <description>&lt;p&gt;Le &lt;a href="https://it.wikipedia.org/wiki/Smart_card"&gt;&lt;strong&gt;Smart Card&lt;/strong&gt;&lt;/a&gt; fanno parte ormai da tempo del nostro quotidiano: dalla &lt;a href="https://it.wikipedia.org/wiki/Carta_SIM"&gt;SIM&lt;/a&gt; (&lt;em&gt;Subscriber Identity Module&lt;/em&gt;) del cellulare, alla carta di credito, come sistema di fidelizzazione, per accedere ai locali e come mezzo per fruire dei servizi della pubblica amministrazione.&lt;/p&gt;

&lt;p&gt;Integrare sistemi di autenticazione basati su Smart Card nei propri sistemi e applicazioni, credo che possa essere un’attività molto interessante per chi programma e l’aspetto a mio avviso più coinvolgente è la vicinanza con i “pezzi di ferro”.&lt;/p&gt;

&lt;p&gt;In questo articolo vedremo come mettere insieme &lt;a href="https://www.raspberrypi.org/"&gt;Raspberry Pi&lt;/a&gt;, modulo da quattro relè, lettore di Smart Card e &lt;a href="https://en.wikipedia.org/wiki/MIFARE"&gt;MIFARE Classic 1K&lt;/a&gt; contactless Smart Card per poi armonizzare il tutto con il software necessario allo scopo di realizzare un sistema di accesso.&lt;/p&gt;

&lt;p&gt;Per lo sviluppo del progetto è necessario toccare un numero considerevole di argomenti e cercherò di trattare i principali con il giusto livello di profondità, in caso contrario l’articolo assumerebbe delle dimensioni considerevoli. Mi impegnerò a lasciare tutti i riferimenti utili per ogni vostro approfondimento.&lt;/p&gt;

&lt;p&gt;A questo punto direi d’iniziare; mettetevi comodi e munitevi della giusta concentrazione perché la lettura di questo articolo sarà abbastanza impegnativa ma spero interessante.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Descrizione dello scenario
&lt;/h2&gt;

&lt;p&gt;Credo d’intuire quale potrebbe essere il vostro pensiero in questo momento. &lt;strong&gt;Che tipo di &lt;em&gt;Sistema di Accesso&lt;/em&gt; andremo a realizzare?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Vorrei implementare qualcosa che tutti almeno una volta abbiamo usato. Un comunissimo scenario di &lt;em&gt;Sistema di Accesso&lt;/em&gt; lo abbiamo vissuto tutti accedendo alla nostra camera di albergo grazie alla Smart Card (o chiave elettronica) consegnata al momento dell’accoglienza. La figura a seguire mostra lo schema hardware della soluzione che andremo a realizzare.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fmsXKZRd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://github.com/amusarra/smartcard-contactless-raspberry-pi/raw/master/docs/images/hardware_diagram_smartcard_access_raspberry_pi_1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fmsXKZRd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://github.com/amusarra/smartcard-contactless-raspberry-pi/raw/master/docs/images/hardware_diagram_smartcard_access_raspberry_pi_1.jpg" alt="Figura 1 - Schema hardware della soluzione di accesso" title="Figura 1 - Schema hardware della soluzione di accesso (Smart Card icon da https://www.smartcardfocus.com/)" width="880" height="482"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 1 – Schema hardware della soluzione di accesso (Smart Card Reader icon da &lt;a href="https://www.smartcardfocus.com/"&gt;https://www.smartcardfocus.com/&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;La &lt;a href="https://www.nxp.com/products/rfid-nfc/mifare-hf/mifare-classic:MC_41863"&gt;MIFARE Classic® 1K contactless si basa su NXP MF1 IC S50&lt;/a&gt;. Questa tipologia di carta è una buona scelta per applicazioni classiche come la biglietteria dei trasporti pubblici, servizi di fidelizzazione e può essere utilizzata anche per molte altre applicazioni come sistemi di apertura porte e simili.&lt;/p&gt;

&lt;p&gt;Il lettore di Smart Card deve essere conforme a standard indicati nello schema di figura 1. Nel mio caso ho utilizzato il lettore &lt;a href="https://shop.bit4id.com/en/prodotto/minilector-cie/"&gt;CIE Bit4id miniLector&lt;/a&gt; collegato al Raspberry Pi tramite la porta USB. Il nome tecnico del lettore che ho utilizzato è: BIT4ID miniLector AIR NFC v3.&lt;/p&gt;

&lt;p&gt;Al Raspberry Pi è collegato un modulo di quattro relè gestito tramite le porte &lt;a href="https://it.wikipedia.org/wiki/General_Purpose_Input/Output"&gt;&lt;strong&gt;GPIO&lt;/strong&gt;&lt;/a&gt;. Nel nostro scenario, i relè rappresentano gli attuatori necessari per aprire le porte dell’hotel dove siamo ospiti.&lt;/p&gt;

&lt;p&gt;Appurato che il nostro scenario è quello di un sistema di accesso per consentire agli ospiti di un hotel di accedere alle proprie stanze attraverso una Smart Card, vediamo quali sono i due processi che portano al raggiungimento di questo obiettivo.&lt;/p&gt;

&lt;p&gt;La figura 2 illustra il processo semplificato (in notazione &lt;a href="https://www.bpmn.org/"&gt;BPMN&lt;/a&gt;) di ciò che accade quando un ospite viene ricevuto dal personale dell’hotel. Dell’intero processo, solo il &lt;em&gt;Service Task&lt;/em&gt; (indicato in rosso) sarà l’oggetto dell’implementazione del software.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1bZMZEW2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://github.com/amusarra/smartcard-contactless-raspberry-pi/raw/master/docs/images/guest_receiving_process.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1bZMZEW2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://github.com/amusarra/smartcard-contactless-raspberry-pi/raw/master/docs/images/guest_receiving_process.jpg" alt="Figura 2 - Processo semplificato di accoglienza dell'ospite in hotel." width="880" height="470"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 2 – Processo semplificato di accoglienza dell’ospite in hotel.&lt;/p&gt;

&lt;p&gt;Il processo di figura 3 mostra invece cosa succede quando l’ospite chiede di entrare nella sua camera tramite l’uso della chiave elettronica appoggiandola sul lettore. Dell’intero processo, solo i Service Task (indicati in rosso) saranno oggetto dell’implementazione del software.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EiFHq5oi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://github.com/amusarra/smartcard-contactless-raspberry-pi/raw/master/docs/images/room_access_process.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EiFHq5oi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://github.com/amusarra/smartcard-contactless-raspberry-pi/raw/master/docs/images/room_access_process.jpg" alt="Figura 3 - Processo di accesso alla stanza" width="880" height="470"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 3 – Processo di accesso alla stanza&lt;/p&gt;

&lt;p&gt;Credo che per tutti i processi illustrati (in figura 2 e figura 3) in notazione BPMN siano abbastanza esplicativi da non richiedere ulteriori approfondimenti. I Service Task sono gli elementi che saranno oggetto di nostro interesse per l’implementazione del software che fin da questo momento possiamo dividere in due macro componenti le cui responsabilità devono essere:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;il setup della Smart Card (o chiave elettronica) in fase di registrazione dell’ospite presso la struttura alberghiera. All’interno della Smart Card sarà memorizzato l’identificativo di un documento di riconoscimento dell’ospite, sul database del sistema di gestione dell’albergo saranno invece memorizzati i dati anagrafici insieme ad altri dati necessari per associare la chiave elettronica all’ospite e alla stanza a lui assegnata;&lt;/li&gt;
&lt;li&gt;la verifica che la chiave elettronica sia abilitata e associata all’ospite e alla stanza a cui consentire l’accesso.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  2. Qualche dettaglio sulla MIFARE Classic 1K
&lt;/h2&gt;

&lt;p&gt;MIFARE è un marchio registrato di &lt;a href="https://www.nxp.com/"&gt;NXP Semiconductors&lt;/a&gt;. I prodotti MIFARE sono circuiti integrati ampiamente utilizzati per l’utilizzo in Smart Card senza contatto e molte altre applicazioni in tutto il mondo. La gamma MIFARE comprende circuiti integrati per la realizzazione di tessere contactless e lettori per la comunicazione con esse.&lt;/p&gt;

&lt;p&gt;Il nome MIFARE racchiude diversi tipi di Smart Card senza contatto, quella utilizzata in questo scenario rientra nel tipo &lt;em&gt;Classic&lt;/em&gt;. Si tratta di schede di memoria a logica cablata che solo parzialmente sono conformi allo standard &lt;a href="https://it.wikipedia.org/wiki/ISO/IEC_14443"&gt;&lt;strong&gt;ISO/IEC 14443A&lt;/strong&gt;&lt;/a&gt; (caratteristiche fisiche, potenza e interfaccia del segnale radio, inizializzazione e anticollisione), poiché utilizzano un set di comandi proprietari invece del protocollo &lt;a href="https://www.iso.org/standard/73599.html"&gt;ISO/IEC 14443-4&lt;/a&gt; di alto livello e non sono conformi al formato frame &lt;a href="https://www.iso.org/standard/73598.html"&gt;ISO/IEC 14443-3&lt;/a&gt; nelle comunicazioni crittografate. Usano un protocollo di sicurezza proprietario &lt;a href="https://en.wikipedia.org/wiki/Crypto-1"&gt;&lt;strong&gt;NXP (CRYPTO1)&lt;/strong&gt;&lt;/a&gt; per l’autenticazione e la crittografia che è stato rotto nel 2008.&lt;/p&gt;

&lt;p&gt;Dopo l’ultima frase immagino che vi stiate domandando: &lt;strong&gt;perché scrivere allora un articolo su questa Smart Card?&lt;/strong&gt; La risposta è abbastanza semplice. Questa è una delle &lt;a href="https://it.wikipedia.org/wiki/Smart_card#Smart_card_a_sola_memoria"&gt;Smart Card a sola memoria&lt;/a&gt; più diffuse e semplici da usare, e per il tipo di scenario qui presentato, la possibilità di scoprire “facilmente” la chiave di autenticazione è secondario, inoltre, questo è articolo prettamente didattico.&lt;/p&gt;

&lt;p&gt;La MIFARE Classic 1K dispone di 1024 byte di memoria (&lt;a href="https://it.wikipedia.org/wiki/EEPROM"&gt;&lt;strong&gt;EEPROM&lt;/strong&gt;&lt;/a&gt;) suddivisa in 16 segmenti; ogni settore è protetto da due chiavi che vengono chiamate A e B. In tutti i tipi di carta, 16 byte a settore sono riservati alle chiavi e alle condizioni d’accesso e non possono essere utilizzati per i dati dell’utente; inoltre, i primi 16 byte contengono il numero di serie univoco e di sola lettura. In questo modo la memoria disponibile si riduce a 752 byte.&lt;/p&gt;

&lt;p&gt;Data l’altissima diffusione di questa tipologia di Smart Card e le versioni “cinesi” esistenti, dubito che non ci siano numeri di serie duplicati, visto anche che i byte dedicati alla memorizzazione del numero di serie sono quattro.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2022/03/mifare_classic_1k_memory_organization_MF1S50YYX_V1.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WBqb-NEw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2022/03/mifare_classic_1k_memory_organization_MF1S50YYX_V1-1024x1047.png" alt="Figura 4 - Struttura della memoria della Mifare Classic 1K (dal datasheet NXP MIFARE Classic EV1 1K https://www.nxp.com/docs/en/data-sheet/MF1S50YYX_V1.pdf)" title="Figura 4 - Struttura della memoria della Mifare Classic 1K (dal datasheet NXP MIFARE Classic EV1 1K https://www.nxp.com/docs/en/data-sheet/MF1S50YYX\_V1.pdf)" width="880" height="900"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 4 – Struttura della memoria della Mifare Classic 1K (dal datasheet NXP MIFARE Classic EV1 1K &lt;a href="https://www.nxp.com/docs/en/data-sheet/MF1S50YYX%5C_V1.pdf"&gt;https://www.nxp.com/docs/en/data-sheet/MF1S50YYX\_V1.pdf&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Prima di poter compiere operazioni di lettura o scrittura sui blocchi di memoria, è necessario eseguire prima un’autenticazione tramite la chiave del settore del blocco. In genere tutte le chiavi (A e B) sono impostate su valore &lt;code&gt;FFFFFFFFFFFFh&lt;/code&gt; in fase di produzione del chip (e in ogni caso la documentazione fornita al momento dell’acquisto fornisce indicazioni sulle chiavi di accesso e su come eseguire la modifica).&lt;/p&gt;

&lt;p&gt;La tabella mostrata in figura 5 rappresenta la mappa della memoria con in evidenza il range degli indirizzi per i &lt;em&gt;Data Blocks&lt;/em&gt; e i _Trailer Block _per ogni settore. Questa mappa sarà utile nel momento in cui dovremo leggere e scrivere sui data blocks.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2022/03/mifare_1K_memory_map-2.jpg"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qmwDx-WS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2022/03/mifare_1K_memory_map-2-1024x602.jpg" alt="Figura 5 - Memory Map della MIFARE Classic 1K completa di range d'indirizzi dei blocchi" title="Figura 5 - Memory Map della MIFARE Classic 1K completa di range d'indirizzi dei blocchi" width="880" height="517"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 5 – Memory Map della MIFARE Classic 1K completa di range d’indirizzi dei blocchi&lt;/p&gt;

&lt;p&gt;Dopo questa sorvolata sulle caratteristiche principali della MIFARE Classic 1K che sono di nostro interesse per il nostro obiettivo, possiamo andare avanti ed esplorare il modo su come comunicare con la carta per le operazioni di autenticazione, lettura e scrittura.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. I misteriosi pacchetti APDU
&lt;/h2&gt;

&lt;p&gt;La comunicazione delle informazioni tra la carta e il lettore è resa possibile grazie allo scambio di pacchetti detti &lt;strong&gt;APDU&lt;/strong&gt; (&lt;em&gt;Application Protocol Data Unit&lt;/em&gt;); essi rappresentano l’unità di comunicazione tra il lettore e la carta e la loro struttura è ben definita da &lt;a href="https://www.iso.org/obp/ui/#iso:std:iso-iec:7816:-4:ed-4:v1:en"&gt;&lt;strong&gt;ISO/IEC 7816-4 Organization, security and commands for interchange&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Esistono due tipi di APDU: quelli di comando e quelli di risposta. I primi richiedono un set di attributi attraverso cui il lettore è in grado di sapere quali operazioni compiere e quali dati inviare, i secondi contengono il risultato dell’operazione richiesta con in coda l’esito dell’operazione.&lt;/p&gt;

&lt;p&gt;La tabella di figura 6 mostra la struttura dei comandi APDU che attraverso il lettore di Smart Card possiamo inviare alla carta MIFARE.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2022/03/structure_of_request_command_apdu-1-scaled.jpg"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9UMpSmTE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2022/03/structure_of_request_command_apdu-1-1024x751.jpg" alt="Figura 6 - Struttura dei comandi APDU" width="880" height="645"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 6 – Struttura dei comandi APDU&lt;/p&gt;

&lt;p&gt;La tabella di figura 7 mostra un esempio di comando APDU per ottenere l’UID della MIFARE Classic 1K, la cui lunghezza è pari a 4 byte (vedi attributo Le). A fronte dei comandi inviati, riceviamo sempre una risposta che ha la struttura indicata dalla tabella di figura 8.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2022/03/apdu_command_for_request_uid.jpg"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---jgUrYqb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2022/03/apdu_command_for_request_uid-1024x464.jpg" alt="Figura 7 - Comando per ottenere l'UID della Smart Card MIFARE Classic 1K" width="880" height="399"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 7 – Comando per ottenere l’UID della Smart Card MIFARE Classic 1K&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2022/03/structure_of_response_command_apdu-1.jpg"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ONk3EgAT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2022/03/structure_of_response_command_apdu-1-1024x521.jpg" alt="Figura 8 - Struttura di risposta APDU" title="Figura 8 - Struttura di risposta APDU" width="880" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 8 – Struttura di risposta APDU&lt;/p&gt;

&lt;p&gt;La tabella di figura 9 mostra la risposta ottenuta a fronte del comando APDU per richiedere l’UID (vedi figura 7) la cui lunghezza dell’UID è pari a 4 byte più 2 byte che segnalano l’esito del comando. L’UID è restituito con il byte meno significativo (&lt;a href="https://it.wikipedia.org/wiki/Bit_meno_significativo"&gt;LSB&lt;/a&gt;) a sinistra e quello più significativo (&lt;a href="https://it.wikipedia.org/wiki/Bit_pi%C3%B9_significativo"&gt;MSB&lt;/a&gt;) a destra (quindi usa il sistema &lt;a href="https://it.wikipedia.org/wiki/Ordine_dei_byte"&gt;little-endian&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2022/03/apdu_response_of_the_command_uid-1.jpg"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wCdVTDt_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2022/03/apdu_response_of_the_command_uid-1-1024x651.jpg" alt="Figura 9 - Risposta del comando APDU per ottenere l'UID della MIFARE Classic 1K" title="Figura 9 - Risposta del comando APDU per ottenere l'UID della MIFARE Classic 1K" width="880" height="559"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 9 – Risposta del comando APDU per ottenere l’UID della MIFARE Classic 1K&lt;/p&gt;

&lt;p&gt;Confrontando i valori di &lt;strong&gt;SW1&lt;/strong&gt; e &lt;strong&gt;SW2&lt;/strong&gt; (&lt;em&gt;Status Word&lt;/em&gt;) con quelli riportati dalla tabella mostrata in figura 10 è possibile evincere se l’esecuzione del comando è andato a buon fine.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Attenzione&lt;/strong&gt;. I valori di SW1 e SW2 fanno riferimento al comando per ottenere l’UID della carta; questi valori potrebbero essere diversi per altre classi di comando, in particolare nei casi di errore.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2022/03/response_apdu_command_uid_sw1_sw2-scaled.jpg"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4H6QfllA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2022/03/response_apdu_command_uid_sw1_sw2-1024x388.jpg" alt="Figura 10 - Codici di risposta APDU comando UID" width="880" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 10 – Codici di risposta APDU comando UID&lt;/p&gt;

&lt;p&gt;Per maggiori dettagli sui comandi ed eventuali estensioni, consiglio sempre di consultare il datasheet della &lt;a href="https://www.nxp.com/docs/en/data-sheet/MF1S50YYX_V1.pdf"&gt;MIFARE Classic 1K&lt;/a&gt;. I comandi APDU di nostro interesse per implementare lo scenario descritto nella parte introduttiva dell’articolo, sono:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;comando per ottenere l’UID della carta;&lt;/li&gt;
&lt;li&gt;comando per leggere i dati da un determinato settore e blocco;&lt;/li&gt;
&lt;li&gt;comando per scrivere dati su un determinato settore e blocco della carta.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  4. Cos’è l’Answer to reset o ATR
&lt;/h2&gt;

&lt;p&gt;La prima risposta di una Smart Card inserita in un lettore si chiama &lt;a href="https://en.wikipedia.org/wiki/Answer_to_reset"&gt;&lt;strong&gt;ATR&lt;/strong&gt;&lt;/a&gt; (&lt;em&gt;Answer to reset&lt;/em&gt;). Lo scopo dell’ATR è descrivere i parametri di comunicazione supportati, la natura e lo stato della carta. L’ottenimento di un ATR viene spesso utilizzato come prima indicazione che questa sia operativa, e il suo contenuto viene esaminato come prima prova che sia del tipo appropriato per un determinato utilizzo. Il lettore di Smart Card, il driver del lettore e il sistema operativo utilizzeranno questi parametri per stabilire una comunicazione con la scheda.&lt;/p&gt;

&lt;p&gt;L’ATR è descritto dallo standard &lt;a href="https://it.wikipedia.org/wiki/ISO/IEC_7816"&gt;&lt;strong&gt;ISO/IEC 7816-3&lt;/strong&gt;&lt;/a&gt;. I primi byte dell’ATR descrivono i parametri elettrici, seguiti da byte che descrivono le interfacce di comunicazione disponibili e i rispettivi parametri. Questi byte di interfaccia sono quindi seguiti da byte storici che non sono standardizzati e sono utili per trasmettere informazioni proprietarie come il tipo di scheda, la versione del software integrato o lo stato della scheda. Infine questi byte storici sono eventualmente seguiti da un byte di checksum.&lt;/p&gt;

&lt;p&gt;Potremmo riassumere che l’ &lt;strong&gt;ATR contiene “un sacco di dati” che ci dicono vita morte e miracoli della Smart Card&lt;/strong&gt;. Per esempio, scopriamo di più sull’ATR &lt;code&gt;3B 8F 80 01 80 4F 0C A0 00 00 03 06 03 00 01 00 00 00 00 6A&lt;/code&gt;  utilizzando il tool &lt;a href="https://smartcard-atr.apdu.fr/parse?ATR=3B8F8001804F0CA000000306030001000000006A"&gt;Smart card ATR parsing&lt;/a&gt; sviluppato da &lt;a href="https://ludovicrousseau.blogspot.com/"&gt;Ludovic Rousseau&lt;/a&gt;. La figura a seguire mostra le informazioni estratte alcune delle quali:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;tipo di Smart Card e in questo caso si tratta della MIFARE Classic 1K;&lt;/li&gt;
&lt;li&gt;produttore della Smart Card e in questo caso NXP;&lt;/li&gt;
&lt;li&gt;standard tecnologici;&lt;/li&gt;
&lt;li&gt;protocolli di comunicazione e in questo caso T=0 (orientato al byte, che costituisce l’unità minima di informazione scambiata) e T=1 (orientato al blocco di byte, grazie al quale la velocità di accesso è maggiore), protocollo solitamente utilizzato di default quando disponibile e supportato anche dal lettore.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2022/03/mifare_classic_1k_atr_parsing.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xhFCJ7MC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2022/03/mifare_classic_1k_atr_parsing-1024x1487.png" alt="Figura 11 - Dettagli estratti sull'ATR della Smart Card MIFARE Classic 1K" width="880" height="1278"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 11 – Dettagli estratti sull’ATR della Smart Card MIFARE Classic 1K&lt;/p&gt;

&lt;p&gt;Ludovic Rousseau ha fatto un ottimo lavoro tracciando dal 2002 un &lt;a href="http://ludovic.rousseau.free.fr/softwares/pcsc-tools/smartcard_list.txt"&gt;gran numero di ATR&lt;/a&gt; costruendo un vero e proprio database. Così facendo è possibile identificare una Smart Card dato il suo ATR. All’interno della lista sono presenti anche le “nostrane Smart Card” come la &lt;strong&gt;TS-CNS&lt;/strong&gt; (&lt;em&gt;Tessera Sanitaria – Carta Nazionale Servizi&lt;/em&gt;) e &lt;strong&gt;CIE&lt;/strong&gt; (&lt;em&gt;Carta d’Identità Elettronica&lt;/em&gt;). È possibile utilizzare il comando &lt;code&gt;pcsc_scan&lt;/code&gt; per ottenere informazioni di dettaglio sulla Smart Card, le stesse illustrate in figura 11. La figura 12 mostra l’output del comando menzionato da cui è possibile dedurre che la Smart Card analizzata è una CIE.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2022/03/output_of_pcsc_scan_smart_card_cie.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zww8NXGM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2022/03/output_of_pcsc_scan_smart_card_cie-1024x656.png" alt="Figura 12 - Esempio di output del comando pcsc_scan che mostra le informazioni estratte dalla Smart Card, in questo caso CIE" width="880" height="564"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 12 – Esempio di output del comando pcsc_scan che mostra le informazioni estratte dalla Smart Card, in questo caso CIE&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Requisiti Hardware
&lt;/h2&gt;

&lt;p&gt;Realizzare lo scenario descritto richiede il recupero di una serie di “pezzi di ferro”.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://www.melopero.com/shop/raspberry-pi/boards/raspberry-pi-4-model-b-8gb/?src=raspberrypi"&gt;Raspberry Pi 4 Model B 8GByte RAM&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.raspberrypi.com/documentation/computers/getting-started.html#sd-card-for-raspberry-pi"&gt;MicroSD Card (min 8GByte)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amzn.to/3rkr4uw"&gt;Elegoo 4 Channel DC 5V Modulo Relay&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amzn.to/3hKuZ1k"&gt;Jumper Wire Cable Cavo F2F female to female&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://shop.bit4id.com/prodotto/minilector-cie/"&gt;Bit4id miniLector CIE&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amzn.to/3vkAifZ"&gt;Mifare Classic 1K&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://amzn.to/3BReSbF"&gt;Mifare Classic 1K RFID Tag&lt;/a&gt; (opzionale)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Per quanto riguarda il Raspberry Pi è possibile optare per la versione con 4GByte di RAM ma è importante installare come sistema operativo l’ultima versione di &lt;a href="https://www.raspberrypi.com/documentation/computers/os.html#introduction"&gt;Raspberry Pi OS&lt;/a&gt; affinché sia supportato il lettore di Smart Card Bit4id miniLector CIE e questo grazie alla versione 1.4.34-1 della libreria libccid (check via &lt;code&gt;apt info libccid&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2022/03/debian_apt_info_libccid.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2kTb6mFD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2022/03/debian_apt_info_libccid.png" alt="Figura 13 - Dettaglio del driver libccid necessario per interoperabilità tra Sistema Operativo e lettore di Smart Card" width="880" height="703"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 13 – Dettaglio del driver libccid necessario per interoperabilità tra Sistema Operativo e lettore di Smart Card&lt;/p&gt;

&lt;p&gt;Nel caso in cui abbiate già un lettore di Smart Card o vogliate acquistarne un diverso modello, consiglio di consultare la &lt;a href="https://ccid.apdu.fr/ccid/shouldwork.html"&gt;lista dei lettori di Smart Card supportati dal driver libccid&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Requisiti Software
&lt;/h2&gt;

&lt;p&gt;Così come abbiamo bisogno dell’hardware, è necessario che siano soddisfatti una serie di requisiti software, quali:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://www.raspberrypi.com/documentation/computers/os.html#introduction"&gt;Raspberry Pi OS (64bit)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.raspberrypi.com/documentation/computers/os.html#python"&gt;Python 3.9.x&lt;/a&gt; (distribuito e installato di default con Raspberry Pi OS)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.docker.com/engine/install/debian/"&gt;Docker 20.10.12&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://packages.debian.org/bullseye/build-essential"&gt;Development Tools (make, gcc)&lt;/a&gt; (install or update via &lt;code&gt;sudo apt install build-essential&lt;/code&gt;)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Per questo genere di scenari non è assolutamente necessario provvedere all’installazione del sistema operativo in versione Desktop, consiglio pertanto di preparare e usare l’immagine di &lt;a href="https://www.raspberrypi.com/software/operating-systems/"&gt;Raspberry Pi OS Lite (64bit)&lt;/a&gt;. Per coloro che avessero bisogno di una guida su come installare questo sistema operativo, consiglio di seguire la guida ufficiale &lt;a href="https://www.raspberrypi.com/documentation/computers/getting-started.html#installing-the-operating-system"&gt;Installing the Operating System&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;L’installazione di Docker potrebbe essere anche opzionale; personalmente preferisco installare il database in forma di container.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Schema elettrico della soluzione
&lt;/h2&gt;

&lt;p&gt;Una volta ottenuto l’hardware (indicato in precedenza), possiamo procedere con il collegamento del modulo dei quattro relè all’interfaccia GPIO e alimentazione del Raspberry Pi con l’ausilio dei jumper femmina-femmina.&lt;/p&gt;

&lt;p&gt;La figura 14 mostra lo schema elettrico di collegamento tra il modulo a quattro relè e il Raspberry Pi. Ricordo che il lettore di Smart Card è collegato via USB al Raspberry Pi. Utilizzando i jumper e seguendo lo schema, il risultato sarà assicurato. È preferibile eseguire l’operazione di collegamento lasciando il proprio Raspberry Pi spento e scollegato dalla fonte di alimentazione.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2022/03/schematic_smart_card_contactless_raspberry_pi.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_SCPxkUw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2022/03/schematic_smart_card_contactless_raspberry_pi-1024x724.png" alt="Figura 14 - Schema elettrico di collegamento tra il Raspberry Pi e il modulo da quattro relè" width="880" height="622"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 14 – Schema elettrico di collegamento tra il Raspberry Pi e il modulo da quattro relè&lt;/p&gt;

&lt;p&gt;Per ogni dubbio sulla disposizione dei pin del connettore J8 del Raspberry, consultare l’output del comando &lt;code&gt;pinout&lt;/code&gt; (vedi figura 15) prima di procedere con l’operazione di collegamento, oppure, puntate il vostro browser su &lt;a href="https://pinout.xyz"&gt;pinout.xyz&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2022/03/output_of_the_pinout_command_on_rpi.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Jx9eZcB7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2022/03/output_of_the_pinout_command_on_rpi-1024x663.png" alt="Figura 15 - Output del comando pinout, utile per verificare la piedinatura del GPIO e altre informazione sul layout hardware e componenti" width="880" height="570"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 15 – Output del comando pinout, utile per verificare la piedinatura del GPIO e altre informazione sul layout hardware e componenti&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Progettare il software
&lt;/h2&gt;

&lt;p&gt;È arrivato il momento di saltare dall’hardware al software cercando di delineare ciò che dovremo implementare con l’obiettivo di soddisfare i requisiti espressi in forma di diagrammi BPMN (vedi figura 2 e figura 3). Ricordo che solo quanto espresso dai Service Task deve essere releazzato in forma di software.&lt;/p&gt;

&lt;p&gt;Cerchiamo di identificare il &lt;strong&gt;cosa&lt;/strong&gt; dovrà essere soddisfatto dal punto di vista funzionale per poi passare al &lt;strong&gt;come&lt;/strong&gt; gli aspetti funzionali dovranno essere implementati. La tabella mostrata in figura 16 (trasposizione di una classica Mind Map), descrive gli aspetti funzionali che il software che andremo a realizzare deve implementare.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2022/03/mind_map_functions_software.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XaW3PXiZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2022/03/mind_map_functions_software-1024x584.png" alt="Figura 16 - Mind Map sugli aspetti funzionali che il software dovrà implementare" width="880" height="502"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 16 – Mind Map sugli aspetti funzionali che il software dovrà implementare&lt;/p&gt;

&lt;p&gt;Il software deve prevedere due entry point, ed esattamente quelli indicati all’interno della tabella di figura 16, le cui responsabilità devo essere:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Setup Smart Card&lt;/strong&gt; : entry point la cui principale responsabilità è quella di “formattare” la Smart Card (o chiave elettronica) con i dati personali dell’ospite e in questo caso il numero del documento d’identità, inoltre, creare l’associazione tra chiave elettronica, ospite e stanza a lui assegnata. Una volta eseguiti i task di questo entry point (vedi figura 16), la Smart Card potrà essere consegnata all’ospite.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gestione Accesso Porte&lt;/strong&gt; entry point la cui principale responsabilità è quella di garantire l’accesso (apertura della porta della stanza) solo a coloro che hanno in possesso una Smart Card valida, aggiornando i dati di accesso sul database. La Mind Map di figura 16 mostra i singoli task che devono essere eseguiti da questo specifico entry point.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Più volte è stato fatto riferimento all’esistenza di un database, bene, adesso cerchiamo di capire quali sono i dati da esso trattati e le responsabilità dei due entry point in merito al trattamento di questi dati. La tabella di figura 17 mostra la struttura dati del documento che descrive l’associazione ospite, Smart Card e stanza assegnata e traccia i dati degli eventi d’inizializzazione e accesso.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2022/03/mind_map_table_guest_access_document.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ieUmzs_8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2022/03/mind_map_table_guest_access_document-1024x1806.png" alt="Figura 17 - Struttura dati che descrive l'associazione ospite, smart card e stanza assegnata e traccia i dati gli eventi di inizializzazione e accesso" width="880" height="1552"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 17 – Struttura dati che descrive l’associazione ospite, smart card e stanza assegnata e traccia i dati degli eventi d’inizializzazione e accesso&lt;/p&gt;

&lt;p&gt;La tabella mostra un’informazione importante per ogni attributo del documento, ovvero, lo scope, quindi l’entry point, con evidenza del diritto di accesso: (r -read) lettura o (w – write) scrittura.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Implementare il software
&lt;/h2&gt;

&lt;p&gt;Adesso che il  &lt;strong&gt;cosa ** è chiaro, vediamo il **come&lt;/strong&gt; , rispondendo alle domande a seguire:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Quale linguaggio usare per implementare lo scenario che abbiamo descritto all’inizio dell’articolo? &lt;strong&gt;Python&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Esiste qualche libreria Python per la costruzione di applicazioni basate su Smart Card? &lt;a href="https://pyscard.sourceforge.io/index.html"&gt;&lt;strong&gt;Pyscard&lt;/strong&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Quale tipo di database usare per la memorizzazione dei dati? &lt;a href="https://www.mongodb.com/"&gt;&lt;strong&gt;MongoDB&lt;/strong&gt;&lt;/a&gt; (&lt;a href="https://it.wikipedia.org/wiki/NoSQL"&gt;NoSQL&lt;/a&gt; database)&lt;/li&gt;
&lt;li&gt;Esiste qualche libreria Python per operare con MongoDB? &lt;a href="https://pymongo.readthedocs.io/en/stable/"&gt;&lt;strong&gt;PyMongo&lt;/strong&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Esiste qualche libreria Python per interagire con l’interfaccia GPIO del Raspberry Pi? &lt;strong&gt;&lt;a href="https://pypi.org/project/RPi.GPIO/"&gt;RPi.GPIO&lt;/a&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Da questa lista le cose da fare sono parecchie e lo spazio per vederle tutte nel dettaglio in questo articolo non c’è. Direi quindi di focalizzare la nostra attenzione sui componenti da realizzare rimanendo ad alto livello, senza scendere nello specifico del codice.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Non vi allarmate!&lt;/strong&gt; Il progetto è già stato sviluppato prima di scrivere questo articolo e disponibile sul mio repository GitHub &lt;a href="https://github.com/amusarra/smartcard-contactless-raspberry-pi"&gt;Smart Card Contactless Raspberry Pi&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  9.1 Cos’è Pyscard
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Pyscard&lt;/strong&gt; , Python Smart Card library, è un modulo Python che aggiunge il supporto per le Smart Card facilitando la costruzione di applicazioni che hanno la necessità di utilizzare la tecnologia delle Smart Card.&lt;/p&gt;

&lt;p&gt;Pyscard supporta la piattaforma Microsoft Windows utilizzando i componenti &lt;a href="https://docs.microsoft.com/en-us/previous-versions/windows/desktop/secsmart/microsoft-base-smart-card-cryptographic-service-provider"&gt;Microsoft Smart Card Base&lt;/a&gt;, Linux e macOS utilizzando &lt;a href="https://pcsclite.apdu.fr/"&gt;PCSC-lite&lt;/a&gt;. Il diagramma di figura 18 mostra l’architettura Pyscard (box in verde). Il modulo &lt;a href="https://pyscard.sourceforge.io/epydoc/smartcard.scard.scard-module.html"&gt;smartcard.scard&lt;/a&gt; è il wrapper di WinSCard API (&lt;em&gt;smart card base components&lt;/em&gt;). Il modulo &lt;a href="https://pyscard.sourceforge.io/epydoc/index.html"&gt;smartcard&lt;/a&gt; è un vero e proprio framework costruito su PC/SC API.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2022/03/architecture_of_the_pyscard_library-scaled.jpg"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TXr2pBjp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2022/03/architecture_of_the_pyscard_library-1024x931.jpg" alt="Figura 18 - Architettura di Pyscard" title="Figura 18 - Architettura di Pyscard" width="880" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 18 – Architettura di Pyscard&lt;/p&gt;

&lt;p&gt;Pyscard sarà di aiuto per:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Eseguire la connessione al lettore di Smart Card e alla MIFARE Classic 1K&lt;/li&gt;
&lt;li&gt;Filtrare le connessioni alle sole MIFARE Classic 1K tramite l’ATR&lt;/li&gt;
&lt;li&gt;Inviare i comandi APDU&lt;/li&gt;
&lt;li&gt;Ricevere le risposte ai comandi APDU&lt;/li&gt;
&lt;li&gt;Intercettare gli eventi di aggiunta e rimozione Smart Card dal lettore&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  9.2 Struttura del progetto software
&lt;/h3&gt;

&lt;p&gt;Adesso che abbiamo visto dalla superficie cos’è Pyscard e per cosa sarà utile, cerchiamo di disegnare la struttura del nostro progetto che implementerà lo scenario introdotto a inizio articolo.&lt;/p&gt;

&lt;p&gt;Il diagramma (in notazione UML) di figura 19 mostra package, component e classi utilizzati per l’implementazione dello scenario che abbiamo descritto a inizio articolo. Gli elementi del diagramma del nostro progetto sono quelli evidenziati con il colore giallo ocra e in particolare:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Classi&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/amusarra/smartcard-contactless-raspberry-pi/blob/master/rpi/gpio/manage_relay.py"&gt;ManageRelay&lt;/a&gt; (manage_relay.py). Classe che gestisce attraverso l’interfaccia GPIO l’attivazione e disattivazione dei quattro relè, nonché l’inizializzazione della stessa interfaccia GPIO.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/amusarra/smartcard-contactless-raspberry-pi/blob/master/rpi/smartcard/mongodb/smart_card_access_crud.py"&gt;SmartCardAccessCrud&lt;/a&gt; (smart_card_access_crud.py). Classe che gestisce le operazioni CRUD sul database NoSQL MongoDB.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/amusarra/smartcard-contactless-raspberry-pi/blob/master/rpi/smartcard/mifare/mifare_interface.py"&gt;MifareClassicInterface&lt;/a&gt; (mifare_interface.py). Classe che gestisce la comunicazione con il lettore di Smart Card e di conseguenza d’interagire con la Smart Card connessa. Le operazioni gestite sono: autenticazione, lettura ATR, lettura UID, lettura dalla memoria della carta e scrittura sulla memoria della carta.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Component&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/amusarra/smartcard-contactless-raspberry-pi/blob/master/setup_smart_card.py"&gt;Setup Smart Card&lt;/a&gt; (setup_smart_card.py). Script Python che rapprensentata l’entry point responsabile del setup della Smart Card e memorizzazione dei dati anagrafici dell’ospite sul database MongoDB. Questo script deve ricevere in input i parametri necessari per eseguire il setup della Smart Card.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/amusarra/smartcard-contactless-raspberry-pi/blob/master/access_via_smart_card.py"&gt;Access via Smart Card&lt;/a&gt; (access_via_smart_card.py). Script Python che rappresenta l’entry point responsabile di governare l’apertura delle porte (attraverso l’attivazione dei relè) sulla base della validazione dei dati estratti dalla Smart Card. Questo script deve ricevere in input la chiave di autenticazione della Smart Card.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2022/03/smartcard-contactless-raspberry-pi-uml-diagram-scaled.jpg"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rco--Mvu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2022/03/smartcard-contactless-raspberry-pi-uml-diagram-1024x446.jpg" alt="Figura 19 - Package/Component/Class diagram del progetto Smart Card Contactless Raspberry Pi" title="Figura 19 - Package/Component/Class diagram del progetto Smart Card Contactless Raspberry Pi" width="880" height="383"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 19 – Package/Component/Class diagram del progetto Smart Card Contactless Raspberry Pi&lt;/p&gt;

&lt;p&gt;Il package &lt;em&gt;smartcard&lt;/em&gt; (in verde) fa parte di Pyscard, e i componenti all’interno sono utilizzati per sfruttare il monitoraggio delle Smart Card. Utilizzando l’interfaccia &lt;a href="https://pyscard.sourceforge.io/epydoc/smartcard.CardMonitoring.CardObserver-class.html"&gt;CardObserver&lt;/a&gt; siamo in grado di poter sapere quando la Smart Card viene aggiunta (appoggiata sul lettore) o rimossa (dal raggio di azione del segnale RF).&lt;/p&gt;

&lt;p&gt;Il sequence diagram di figura 20 descrive lo scenario del setup della Smart Card (vedi Figura 2 – Processo semplificato di accoglienza dell’ospite in hotel), mostrando le azioni principali e gli eventuali flussi alternativi. Sempre da questo diagramma possiamo vedere le relazioni che intercorrono, in termini di messaggi, tra i vari attori, quest’ultimi sono stati descritti in precedenza e mostrati nel diagramma di figura 19.&lt;/p&gt;

&lt;p&gt;Le azioni decisamente più importanti sono quelle che riguardano l’invio dei comandi APDU, che riassumendo sono:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://github.com/amusarra/smartcard-contactless-raspberry-pi/blob/f9ae78638f3eb277ebfc7951fea436da2c6bee44/rpi/smartcard/mifare/mifare_interface.py#L238"&gt;Load Authentication Key sulla memoria volatile&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/amusarra/smartcard-contactless-raspberry-pi/blob/f9ae78638f3eb277ebfc7951fea436da2c6bee44/rpi/smartcard/mifare/mifare_interface.py#L78"&gt;Autenticazione per accedere al primo blocco del settore uno della MIFARE Classic 1K&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/amusarra/smartcard-contactless-raspberry-pi/blob/f9ae78638f3eb277ebfc7951fea436da2c6bee44/rpi/smartcard/mifare/mifare_interface.py#L213"&gt;Richiesta UID&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/amusarra/smartcard-contactless-raspberry-pi/blob/f9ae78638f3eb277ebfc7951fea436da2c6bee44/rpi/smartcard/mifare/mifare_interface.py#L172"&gt;Lettura dell’eventuale precedente documentId (numero identificativo del documento di riconoscimento)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/amusarra/smartcard-contactless-raspberry-pi/blob/f9ae78638f3eb277ebfc7951fea436da2c6bee44/rpi/smartcard/mifare/mifare_interface.py#L286"&gt;Salvataggio del documentId&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I link della precedente lista riportano direttamente sul metodo specifico della classe &lt;a href="https://github.com/amusarra/smartcard-contactless-raspberry-pi/blob/master/rpi/smartcard/mifare/mifare_interface.py"&gt;Mifare Classic Interface&lt;/a&gt; all’interno del quale è specificato il contenuto dell’APDU inviata.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2022/03/setup_smart_card_sequence.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sXs0MUTF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2022/03/setup_smart_card_sequence-1024x1235.png" alt="Figura 20 - Diagramma di sequenza dell'entry point Setup Smart Card" title="Figura 20 - Diagramma di sequenza dell'entry point Setup Smart Card" width="880" height="1061"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 20 – Diagramma di sequenza dell’entry point Setup Smart Card&lt;/p&gt;

&lt;p&gt;Nella fase di setup della Smart Card, prima di inserire i dati anagrafici dell’ospite sul database, viene eseguita la query utilizzando il filtro &lt;code&gt;{"smartCardId": f"{uid}", "documentId": f"{identification_number}"}&lt;/code&gt; , in modo che sia possibile verificare che non esista già un documento con l’associazione smartCardId e documentId (fare riferimento allo step 33 del sequence diagram di figura 20).&lt;/p&gt;

&lt;p&gt;Il sequence diagram di figura 21 descrive lo scenario di Accesso alla stanza tramite Smart Card (vedi Figura 3 – Processo di accesso alla stanza), mostrando le azioni principali e gli eventuali flussi alternativi. Sempre da questo diagramma possiamo vedere le relazioni che intercorrono, in termini di messaggi, tra i vari attori, quest’ultimi sono stati descritti in precedenza e mostrati nel diagramma di figura 19.&lt;/p&gt;

&lt;p&gt;In questo diagramma, tra gli attori in gioco abbiamo anche il componente &lt;a href="https://pyscard.sourceforge.io/epydoc/smartcard.CardMonitoring.CardMonitor-class.html"&gt;Card Monitor&lt;/a&gt; di Pyscard, che abbiamo utilizzato per aggiungere la nostra interfaccia &lt;a href="https://github.com/amusarra/smartcard-contactless-raspberry-pi/blob/master/rpi/smartcard/mifare/mifare_interface.py#L51"&gt;Mifare Classic Interface&lt;/a&gt; come observable, in questo modo il Card Monitor richiamerà il metodo &lt;a href="https://github.com/amusarra/smartcard-contactless-raspberry-pi/blob/f9ae78638f3eb277ebfc7951fea436da2c6bee44/rpi/smartcard/mifare/mifare_interface.py#L312"&gt;update(self, observable, actions)&lt;/a&gt; nel momento in cui si verificheranno gli eventi di aggiunta o rimozione della Smart Card. Il metodo update implementa quando descritto in Figura 16 – Mind Map sugli aspetti funzionali che il software dovrà implementare, di cui le azioni sono evidenti sul sequence diagram a seguire.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2022/03/access_via_smart_card_sequence-1.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8q1w0PDJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2022/03/access_via_smart_card_sequence-1-1024x1047.png" alt="Figura 21 - Diagramma di sequenza per l'entry point Access via Smart Card" title="Figura 21 - Diagramma di sequenza per l'entry point Access via Smart Card" width="880" height="900"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 21 – Diagramma di sequenza per l’entry point Access via Smart Card&lt;/p&gt;

&lt;p&gt;I dati sono estratti dal database MongoDB utilizzando il filtro &lt;code&gt;{"smartCardId": f"{uid}", "documentId":f{identification_number}", "smartCardEnabled": "true"}&lt;/code&gt;, nel caso non ci siano documenti che rispettino questo filtro, il sistema negerà l’accesso, alternativamente, sarà aggiornato il documento su MongDB e attivato il relè corrispondente al numero della stanza associato all’ospite (fare riferimento allo step 1.7 del sequence diagram di figura 21).&lt;/p&gt;

&lt;p&gt;Molto bene! Una volta descritti i sequence diagram dei nostri due scenari, direi che potremmo passare all’azione, ovvero, eseguire il deploy dell’applicazione sul Raspberry Pi 4.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. Deploy e test del software sul Raspberry Pi
&lt;/h2&gt;

&lt;p&gt;Ci siamo! È arrivato il momento d’installare il progetto software sul Raspberry Pi e verificare che tutto funzioni così per com’è stato ideato. Il deployment diagram della figura a seguire mostra tutti i componenti del nostro sistema di accesso.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2022/03/system_deployment_on_raspberry.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OCX1sqEq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2022/03/system_deployment_on_raspberry-1024x891.png" alt="Figura 22 - Deployment diagram del sistema di accesso via Smart Card Contactless su Raspberry Pi" width="880" height="766"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 22 – Deployment diagram del sistema di accesso via Smart Card Contactless su Raspberry Pi&lt;/p&gt;

&lt;p&gt;Assumiamo a questo punto che tutti i requisiti software indicati in precedenza siano tutti soddisfatti (fare riferimento a 6. Requisiti Software). Per installare il progetto software sul Raspberry Pi occorre seguire i seguenti passi:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;accedere in ssh alla Raspberry Pi;&lt;/li&gt;
&lt;li&gt;decidere una locazione dove installare il progetto software. Non ci sono restrizioni; nel mio caso ho preferito usare la home del mio account;&lt;/li&gt;
&lt;li&gt;eseguire il clone del repository del progetto;&lt;/li&gt;
&lt;li&gt;eseguire l’installazione delle dipendenze Python.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
# Accesso al Raspberry Pi via SSH
$ ssh amusarra@192.168.238.169

# Clone del repository GitHub del progetto
$ git clone https://github.com/amusarra/smartcard-contactless-raspberry-pi.git

# Installazione delle dipendenze Python
$ cd smartcard-contactless-raspberry-pi
$ make

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Il comando &lt;code&gt;make&lt;/code&gt; non fa altro che procedere con l’installazione delle dipendenze Python specificate sul file &lt;a href="https://github.com/amusarra/smartcard-contactless-raspberry-pi/blob/master/requirements.txt"&gt;requirements.txt&lt;/a&gt; utilizzando &lt;a href="https://pypi.org/project/pip/"&gt;pip&lt;/a&gt;. La figura 23 mostra il processo d’installazione delle dipendenze Python sul Raspberry Pi. Ultimata l’installazione, è possibile eseguire il test vero e proprio del software. Prima di eseguire il test occorre accertarsi che dal punto di vista hardware sia tutto regolare controllando tutti i collegamenti (vedi schema elettrico), compreso il collegamento del lettore di Smart Card via USB.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2022/03/install_rpi_access_system_via_smart_card_1.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rtU118Sb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2022/03/install_rpi_access_system_via_smart_card_1-1024x626.png" alt="Figura 23 - Installazione delle dipendenze Python tramite il comando make" width="880" height="538"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 23 – Installazione delle dipendenze Python tramite il comando make&lt;/p&gt;

&lt;p&gt;Ormai dovremmo sapere quali sono gli entry point da utilizzare, sia quello per il setup della Smart Card, sia quello che avvia il controllo degli accessi. Entrambi gli entry point, quindi gli script Python, devono essere avviati specificando una serie di parametri. Le due tabelle a seguire mostrano i parametri d’input dei due script: &lt;code&gt;setup_smart_card.py&lt;/code&gt; e &lt;code&gt;access_via_smart_card.py&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2022/03/mind_map_script_setup_smart_card.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OQhcc79m--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2022/03/mind_map_script_setup_smart_card-1024x582.png" alt="Figura 24 - Tabella dei parametri d'input per lo script Python setup_smart_card.py" width="880" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 24 – Tabella dei parametri d’input per lo script Python setup_smart_card.py&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2022/03/mind_map_script_access_via_smart_card.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oX4iog8f--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2022/03/mind_map_script_access_via_smart_card-1024x265.png" alt="Figura 25 - Tabella dei parametri d'input per lo script Python access_via_smart_card.py" title="Figura 25 - Tabella dei parametri d'input per lo script Python access\_via\_smart\_card.py" width="880" height="228"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 25 – Tabella dei parametri d’input per lo script Python access_via_smart_card.py&lt;/p&gt;

&lt;p&gt;La figura 26 mostra un esempio di come si presenta l’help in linea dello script &lt;code&gt;setup_smart_card.py&lt;/code&gt; attivato utilizzando l’opzione &lt;code&gt;--help&lt;/code&gt; (o &lt;code&gt;-h&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2022/03/setup_smart_card.py_help_option.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A-D8M02A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2022/03/setup_smart_card.py_help_option-1024x618.png" alt="Figura 26 - Come si presenta l'help in line dello script setup_smart_card.py" width="880" height="531"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 26 – Come si presenta l’help in linea dello script setup_smart_card.py&lt;/p&gt;

&lt;p&gt;A questo punto siamo davvero pronti. Il primo step è la registrazione della Smart Card per il nuovo ospite Mario Rossi il cui documento d’identità ha il numero MU589876XD e al quale assegnamo la stanza numero due.&lt;/p&gt;

&lt;p&gt;Prima di avviare la registrazione, prendiamo la Smart Card poggiandola sul lettore. Il comando da avviare per la registrazione è: &lt;code&gt;./setup_smart_card.py -a FFFFFFFFFFFF -i MU589876XD -s --firstname Mario --lastname Rossi -r 2&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Se tutto va per il verso giusto, l’output ottenuto in console dovrebbe essere quello mostrato dalla figura a seguire.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2022/03/setup_smart_card_run_1.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--78ajadOd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2022/03/setup_smart_card_run_1-1024x511.png" alt="Figura 27 - Registrazione Smart Card MIFARE Classic 1K con i dati dell'ospite" width="880" height="439"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 27 – Registrazione Smart Card MIFARE Classic 1K con i dati dell’ospite&lt;/p&gt;

&lt;p&gt;Dopo la registrazione della Smart Card e la consegna all’ospite, quest’ultimo può usare la Smart Card per accedere alla propria stanza assegnata in fase di registrazione, che ricordo essere la numero due.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2022/03/smart_card_registration_data_on_mongodb_1.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--e_Kz5urp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2022/03/smart_card_registration_data_on_mongodb_1-1024x974.png" alt="Figura 28 - Documento registrato su MongoDB a fronte del processo di registrazione Smart Card" width="880" height="837"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 28 – Documento registrato su MongoDB a fronte del processo di registrazione Smart Card&lt;/p&gt;

&lt;p&gt;Avviamo adesso il programma del controllo degli accessi utilizzando il comando: &lt;code&gt;./access_via_smart_card.py -a FFFFFFFFFFFF&lt;/code&gt;. Avviato il programma, questo resta in attesa di leggere la Smart Card. Poggiando la Smart Card registrata poc’anzi, l’ospite dovrebbe riuscire ad accedere alla sua stanza, così come mostra la figura a seguire.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2022/03/smart_card_access_control_1.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dUW3Rex6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2022/03/smart_card_access_control_1-1024x570.png" alt="Figura 29 - Richiesta di accesso via Smart Card MIFARE Classic 1K" width="880" height="490"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 29 – Richiesta di accesso via Smart Card MIFARE Classic 1K&lt;/p&gt;

&lt;p&gt;L’output mostrato dalla figura 29 evidenzia anche un accesso non riuscito perché in questo caso la Smart Card presentata non è registrata sul sistema. Gli screencast a seguire mostrano i due entry point in azione: setup_smart_card.py e access_via_smart_card.py.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://asciinema.org/a/475795"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IUJ5J9Hn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://asciinema.org/a/475795.svg" alt="Screencast 1 - Processo di registrazione Smart Card in azione" title="Screencast 1 - Processo di registrazione Smart Card in azione" width="880" height="564"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Screencast 1 – Processo di registrazione Smart Card in azione&lt;/p&gt;

&lt;p&gt;&lt;a href="https://asciinema.org/a/475797"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GrnjtqKn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://asciinema.org/a/475797.svg" alt="Screencast 2 - Processo di accesso alla stanza via Smart Card in azione" title="Screencast 2 - Processo di accesso alla stanza via Smart Card in azione" width="880" height="564"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Screencast 2 – Processo di accesso alla stanza via Smart Card in azione&lt;/p&gt;

&lt;h2&gt;
  
  
  11. Conclusioni
&lt;/h2&gt;

&lt;p&gt;Ringrazio tutti voi per essere arrivati “incolumi” alla fine di questo lungo articolo sperando di non essere stato noioso e di essere riuscito nell’intento di rendere interessanti gli argomenti trattati oltre che a spingere la vostra curiosità in avanti.&lt;/p&gt;

&lt;p&gt;Potrei lasciarvi un compito per casa: &lt;strong&gt;come aprire la porta di casa utilizzando la propria CIE o TS-CNS&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Mi sarebbe piaciuto approfondire maggiormente alcuni degli argomenti trattati, come per esempio il framework Pyscard e alcune sezioni del codice Python sviluppato. Nell’attesa di pubblicare altri articoli di approfondimento, vi chiedo di scrivere le vostre impressioni, esperienze o altro di cui vorreste approfondire, utilizzando i commenti all’articolo oppure condividendo attraverso i classici canali social.&lt;/p&gt;

&lt;h2&gt;
  
  
  12. Risorse
&lt;/h2&gt;

&lt;p&gt;Come di consueto lascio una serie di risorse che ritengo utili ai fini dell’approfondimento degli argomenti trattati nel corso di questo articolo.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Attuatori per maker – &lt;a href="https://amzn.to/3slHmE9"&gt;https://amzn.to/3slHmE9&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Raspberry Pi. La guida completa – &lt;a href="https://amzn.to/2RpYZWh"&gt;https://amzn.to/2RpYZWh&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Docker: Sviluppare e rilasciare software tramite container – &lt;a href="https://amzn.to/3tiyO1W"&gt;https://amzn.to/3tiyO1W&lt;/a&gt;  di &lt;a href="https://www.linkedin.com/in/serena-sensini/"&gt;Serena Sensini&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Valutiamo se continuare a usare Docker o passare a Podman – &lt;a href="https://www.theredcode.it/podman/what-is-podman/"&gt;https://www.theredcode.it/podman/what-is-podman/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Pillole di Docker – &lt;a href="https://www.youtube.com/watch?v=wAyUdtQF05w"&gt;https://www.youtube.com/watch?v=wAyUdtQF05w&lt;/a&gt; di &lt;a href="https://www.linkedin.com/in/mauro-cicolella-0b107076/"&gt;Mauro Cicolella&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Raspberry PI GPIO – Tutti i segreti del pinout – &lt;a href="https://www.moreware.org/wp/blog/2021/04/09/raspberry-pi-gpio-tutti-i-segreti-del-pinout/"&gt;https://www.moreware.org/wp/blog/2021/04/09/raspberry-pi-gpio-tutti-i-segreti-del-pinout/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Smart cards – A short illustrated guide ( Feb. 2022) – &lt;a href="https://www.thalesgroup.com/en/markets/digital-identity-and-security/technology/smart-cards-basics"&gt;https://www.thalesgroup.com/en/markets/digital-identity-and-security/technology/smart-cards-basics&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Hacking Mifare Classic Cards – &lt;a href="https://www.blackhat.com/docs/sp-14/materials/arsenal/sp-14-Almeida-Hacking-MIFARE-Classic-Cards-Slides.pdf"&gt;https://www.blackhat.com/docs/sp-14/materials/arsenal/sp-14-Almeida-Hacking-MIFARE-Classic-Cards-Slides.pdf&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;How to Crack Mifare Classic Cards – &lt;a href="https://firefart.at/post/how-to-crack-mifare-classic-cards/"&gt;https://firefart.at/post/how-to-crack-mifare-classic-cards/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;A Practical Attack on the MIFARE Classic – &lt;a href="https://arxiv.org/pdf/0803.2285.pdf"&gt;https://arxiv.org/pdf/0803.2285.pdf&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt; ACR122U Application Programming Interface – &lt;a href="https://www.acs.com.hk/download-manual/419/API-ACR122U-2.04.pdf"&gt;https://www.acs.com.hk/download-manual/419/API-ACR122U-2.04.pdf&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;L'articolo &lt;a href="https://www.dontesta.it/2022/03/11/raspberry-pi-smart-card-mifare-classic-1k-realizzare-sistema-accesso/"&gt;Raspberry Pi e Smart Card Mifare Classic 1K: Realizzare un sistema di accesso&lt;/a&gt; sembra essere il primo su &lt;a href="https://www.dontesta.it"&gt;Antonio Musarra's Blog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://feeds.feedburner.com/~ff/dontesta/blog?a=MJDyUuyDSEM:rvXXtvHO2XI:yIl2AUoC8zA"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ly8gdBSb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Eff/dontesta/blog%3Fd%3DyIl2AUoC8zA" alt="" width="62" height="24"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/dontesta/blog?a=MJDyUuyDSEM:rvXXtvHO2XI:dnMXMwOfBR0"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PziyOv7j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Eff/dontesta/blog%3Fd%3DdnMXMwOfBR0" alt="" width="98" height="24"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/dontesta/blog?a=MJDyUuyDSEM:rvXXtvHO2XI:D7DqB2pKExk"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2VTEoEmh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Eff/dontesta/blog%3Fi%3DMJDyUuyDSEM:rvXXtvHO2XI:D7DqB2pKExk" alt="" width="92" height="24"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/dontesta/blog?a=MJDyUuyDSEM:rvXXtvHO2XI:YwkR-u9nhCs"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DCS1IRW9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Eff/dontesta/blog%3Fd%3DYwkR-u9nhCs" alt="" width="97" height="24"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/dontesta/blog?a=MJDyUuyDSEM:rvXXtvHO2XI:F7zBnMyn0Lo"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OVvQh9AR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Eff/dontesta/blog%3Fi%3DMJDyUuyDSEM:rvXXtvHO2XI:F7zBnMyn0Lo" alt="" width="105" height="24"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/dontesta/blog?a=MJDyUuyDSEM:rvXXtvHO2XI:V_sGLiPBpWU"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yGfF7-o6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Eff/dontesta/blog%3Fi%3DMJDyUuyDSEM:rvXXtvHO2XI:V_sGLiPBpWU" alt="" width="66" height="24"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/dontesta/blog?a=MJDyUuyDSEM:rvXXtvHO2XI:qj6IDK7rITs"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lg7sfzlZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Eff/dontesta/blog%3Fd%3Dqj6IDK7rITs" alt="" width="113" height="24"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/dontesta/blog?a=MJDyUuyDSEM:rvXXtvHO2XI:KwTdNBX3Jqk"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Nz104QdL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Eff/dontesta/blog%3Fi%3DMJDyUuyDSEM:rvXXtvHO2XI:KwTdNBX3Jqk" alt="" width="1" height="1"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/dontesta/blog?a=MJDyUuyDSEM:rvXXtvHO2XI:gIN9vFwOqvQ"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jb2p4TT1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Eff/dontesta/blog%3Fi%3DMJDyUuyDSEM:rvXXtvHO2XI:gIN9vFwOqvQ" alt="" width="1" height="1"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>blog</category>
    </item>
    <item>
      <title>(English) How to use Oracle Database 19c Pre-Built Developer VM</title>
      <dc:creator>Antonio Musarra</dc:creator>
      <pubDate>Sun, 09 Jan 2022 13:02:07 +0000</pubDate>
      <link>https://dev.to/amusarra/english-how-to-use-oracle-database-19c-pre-built-developer-vm-1p9b</link>
      <guid>https://dev.to/amusarra/english-how-to-use-oracle-database-19c-pre-built-developer-vm-1p9b</guid>
      <description>&lt;p&gt;Ci spiace, ma questo articolo è disponibile soltanto in &lt;a href="https://www.dontesta.it/en/feed/" rel="noopener noreferrer"&gt;Inglese Americano&lt;/a&gt;. Per ragioni di convenienza del visitatore, il contenuto è mostrato sotto nella lingua alternativa. Puoi cliccare sul link per cambiare la lingua attiva.&lt;/p&gt;

&lt;p&gt;How many times have we faced the arduous setup of an Oracle Database instance for our development environment and “spitting blood”?&lt;/p&gt;

&lt;p&gt;I guess these times have been too many, here is a good reason to start using what Oracle makes available to us developers, that is, the &lt;a href="https://www.oracle.com/downloads/developer-vm/community-downloads.html" rel="noopener noreferrer"&gt;&lt;strong&gt;Pre-Built Developer VMs&lt;/strong&gt;&lt;/a&gt; for &lt;a href="https://www.virtualbox.org/" rel="noopener noreferrer"&gt;&lt;strong&gt;Oracle VM VirtualBox&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the course of this article, we will see how to setup an &lt;strong&gt;Oracle Database 19c VM&lt;/strong&gt; from the Database Virtual Box Appliance that Oracle provides.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Requirements
&lt;/h2&gt;

&lt;p&gt;Before starting, it is necessary to verify that the following requirements are met.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Operating System that supports Virtual Box version 6.x&lt;/li&gt;
&lt;li&gt;At least 2 GB of RAM&lt;/li&gt;
&lt;li&gt;At least 15 GB of storage space&lt;/li&gt;
&lt;li&gt;At least 2 GHz process&lt;/li&gt;
&lt;li&gt;Administrator privileges&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The reference &lt;a href="https://en.wikipedia.org/wiki/Virtual_appliance" rel="noopener noreferrer"&gt;Virtual Appliance&lt;/a&gt; is dated 20/06/2019 whose content is indicated below.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Oracle Linux 7&lt;/li&gt;
&lt;li&gt;Oracle Database 19.3&lt;/li&gt;
&lt;li&gt;Oracle SQL Developer 19.1&lt;/li&gt;
&lt;li&gt;Oracle Application Express 19.1&lt;/li&gt;
&lt;li&gt;Hands-On-Labs (accessible via the Toolbar Menu in Firefox)

&lt;ul&gt;
&lt;li&gt;Oracle REST Data Services 19.1&lt;/li&gt;
&lt;li&gt;Oracle SQL Developer Data Modeler 19.1&lt;/li&gt;
&lt;li&gt;Oracle XML DB&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Attention!&lt;/strong&gt; This Virtual Appliance is for use in development/test environments only, it should not be used in a pre-production or production environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Virtual Appliance Setup
&lt;/h2&gt;

&lt;p&gt;The setup procedure consists of some steps summarized below:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Download and install &lt;a href="https://www.oracle.com/virtualization/technologies/vm/downloads/virtualbox-downloads.html" rel="noopener noreferrer"&gt;Oracle VM VirtualBox&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.oracle.com/database/technologies/databaseappdev-vm.html#license-lightbox" rel="noopener noreferrer"&gt;Oracle DB Developer VM&lt;/a&gt; Download&lt;/li&gt;
&lt;li&gt;Importing the Virtual Appliance on Oracle VM VirtualBox&lt;/li&gt;
&lt;li&gt;Starting and testing the Virtual Appliance&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  2.1 Download and install Oracle VM VirtualBox
&lt;/h3&gt;

&lt;p&gt;From the &lt;a href="https://www.oracle.com/virtualization/technologies/vm/downloads/virtualbox-downloads.html" rel="noopener noreferrer"&gt;Oracle VM VirtualBox&lt;/a&gt; home page, you can download the binaries for your operating system. In my case, I proceeded to download the version for macOS.&lt;/p&gt;

&lt;p&gt;The installation procedure is very simple and is not the subject of this article; in case of difficulty or further information, refer to the &lt;a href="https://download.virtualbox.org/virtualbox/6.1.30/UserManual.pdf" rel="noopener noreferrer"&gt;User Manual&lt;/a&gt;. The reference version for this article is 6.1.30. Figure 1 shows detailed information about the version installed on my MacBook Pro with macOS Monterey (version 12.1).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2022/01/virtual_box_about_version_en.png" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.dontesta.it%2Fwp-content%2Fuploads%2F2022%2F01%2Fvirtual_box_about_version_en-1024x844.png" title="Figure 1 - Information on VirtualBox" alt="Figure 1 - Information on VirtualBox"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figure 1 – Information on VirtualBox&lt;/p&gt;

&lt;h3&gt;
  
  
  2.2 Downloading Oracle DB Developer VM
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://download.oracle.com/otn/other/virtualbox/dd/DeveloperDaysVM2019-05-31_20.ova" rel="noopener noreferrer"&gt;From the Oracle DB Developer VM&lt;/a&gt; link you can access the &lt;em&gt;DeveloperDaysVM2019-05-31_20.ova&lt;/em&gt; file which contains the Virtual Appliance. The &lt;a href="https://en.wikipedia.org/wiki/Open_Virtualization_Format" rel="noopener noreferrer"&gt;OVA/OVF&lt;/a&gt; format is a standard for the packaging and distribution of Virtual Appliances.&lt;/p&gt;

&lt;p&gt;Downloading the file requires the availability of an Oracle account (which you can create for free if necessary). The file size is over 7 GByte, so I recommend checking the file checksum at the end of the download. In Console 1, one of the ways for hash verification using the &lt;em&gt;md5&lt;/em&gt; and &lt;em&gt;sha&lt;/em&gt; commands available on macOS, Unix / Linux and Windows 10 is identified.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MD5 (sum): 20b5a5bd91cfe9d4f5acf5128f06146e&lt;/li&gt;
&lt;li&gt;SHA1: e0b9f8af8158664139b9ca970c3500752fc15fd2&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

# Verify the checksum MD5 and SHA1 on macOS
$ md5 DeveloperDaysVM2019-05-31_20.ova
$ shasum DeveloperDaysVM2019-05-31_20.ova

# Verify the checksum MD5 and SHA1 on Unix/Linux
$ md5sum DeveloperDaysVM2019-05-31_20.ova
$ sha1sum DeveloperDaysVM2019-05-31_20.ova

# Verify the checksum MD5 and SHA1 on Windows 10
&amp;gt; certutil -hashfile DeveloperDaysVM2019-05-31_20.ova MD5
&amp;gt; certutil -hashfile DeveloperDaysVM2019-05-31_20.ova SHA1


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  2.3 Importing the Virtual Appliance on Oracle VM VirtualBox
&lt;/h3&gt;

&lt;p&gt;Once the ova file has been obtained, it is possible to proceed with importing it using the Import Appliance (or Import Virtual Application) function of Oracle VM VirtualBox which we can access from the File menu (see Figure 2).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2022/01/virtual_box_menu_file_import_virtual_appliance_en.png" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.dontesta.it%2Fwp-content%2Fuploads%2F2022%2F01%2Fvirtual_box_menu_file_import_virtual_appliance_en.png" title="Figure 2 - Access to the Import Appliance function (or Import Virtual Application)" alt="Figure 2 - Access to the Import Appliance function (or Import Virtual Application)"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figure 2 – Access to the Import Appliance function (or Import Virtual Application)&lt;/p&gt;

&lt;p&gt;After clicking on the menu item indicated above, you should see a dialog box like the one shown in Figure 3. The only information to specify is the location of the OVA file, after which it will be possible to continue by clicking on the &lt;em&gt;Continue&lt;/em&gt; button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2022/01/virtual_box_import_ova_step_1_en.png" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.dontesta.it%2Fwp-content%2Fuploads%2F2022%2F01%2Fvirtual_box_import_ova_step_1_en-1024x757.png" title="Figure 3 - First Virtual Appliance import step: specify the location of the OVA file" alt="Figure 3 - First Virtual Appliance import step: specify the location of the OVA file"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figure 3 – First Virtual Appliance import step: specify the location of the OVA file&lt;/p&gt;

&lt;p&gt;After clicking on the &lt;em&gt;Continue&lt;/em&gt; button, a subsequent dialog box will open showing the detailed information (such as CPU, RAM, age.) Of the Virtual Appliance (see Figure 4). It is possible to change some settings, but I recommend leaving those proposed; then continue by clicking on the &lt;em&gt;Import&lt;/em&gt; button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2022/01/virtual_box_import_ova_step_2_en.png" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.dontesta.it%2Fwp-content%2Fuploads%2F2022%2F01%2Fvirtual_box_import_ova_step_2_en-1024x757.png" title="Figure 4 - Second step of Virtual Appliance import: summary of detailed information of the VA and start import" alt="Figure 4 - Second step of Virtual Appliance import: summary of detailed information of the VA and start import"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figure 4 – Second step of Virtual Appliance import: summary of detailed information of the VA and start import&lt;/p&gt;

&lt;p&gt;Figure 5 shows the progress of the import process. The duration of the import depends on the strength of your own and the availability of resources at the time of import. In my case, the import process took about 2 minutes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/12/virtual_box_import_ova_step_3.png" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.dontesta.it%2Fwp-content%2Fuploads%2F2021%2F12%2Fvirtual_box_import_ova_step_3-1024x288.png" title="Figure 5 - Virtual Appliance import process" alt="Figure 5 - Virtual Appliance import process"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figure 5 – Virtual Appliance import process&lt;/p&gt;

&lt;p&gt;Once the import process is finished, you should have a situation like the one shown in Figure 6, that is, a new &lt;em&gt;Virtual Machine&lt;/em&gt; called Oracle DB Developer VM.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2022/01/virtual_box_import_ova_step_4_en.png" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.dontesta.it%2Fwp-content%2Fuploads%2F2022%2F01%2Fvirtual_box_import_ova_step_4_en-1024x750.png" title="Figure 6 - Imported Oracle DB Developer VM virtual machine" alt="Figure 6 - Imported Oracle DB Developer VM virtual machine"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figure 6 – Imported Oracle DB Developer VM virtual machine&lt;/p&gt;

&lt;p&gt;Before you can start the virtual machine, you need to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Check and/or create a new host network. This will allow access to the Oracle database services also from the host’s network, that is, from our PC&lt;/li&gt;
&lt;li&gt;Add a new network adapter to the virtual machine and configure it to use the host’s network&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For the first step, access the &lt;em&gt;Host Network Manager window from the __File -&amp;gt; Host Network Manager&lt;/em&gt; menu, and you should see what is shown in Figure 7.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2022/01/virtual_box_manage_network_host_step_1_en.png" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.dontesta.it%2Fwp-content%2Fuploads%2F2022%2F01%2Fvirtual_box_manage_network_host_step_1_en-1024x743.png" title="Figure 7 - Host network manager" alt="Figure 7 - Host network manager"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figure 7 – Host network manager&lt;/p&gt;

&lt;p&gt;In this case there is no host network interface present, we must therefore proceed with the creation, a step that can be done by clicking on the button that shows the &lt;em&gt;Create&lt;/em&gt; label.&lt;/p&gt;

&lt;p&gt;If one or more host network configurations are already present, it would be possible to use one of those available.&lt;/p&gt;

&lt;p&gt;Figure 8 shows the new host network (vboxnet0) just created and the basic characteristics. After the creation of the network, we have to activate the &lt;strong&gt;DHCP Server&lt;/strong&gt; option, leaving the default settings. This network will be the one that we will then specify on the configuration of the new network card of the virtual machine just imported.&lt;/p&gt;

&lt;p&gt;*&lt;em&gt;Important! *&lt;/em&gt; After setting the flag to enable the DHCP server, we need to close and reopen Oracle VM VirtualBox, this to make the DHCP server start correctly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2022/01/virtual_box_manage_network_host_step_2a_en.png" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.dontesta.it%2Fwp-content%2Fuploads%2F2022%2F01%2Fvirtual_box_manage_network_host_step_2a_en-1024x700.png" title="Figure 8 - New host network 192.168.56.1/24 with active DHCP" alt="Figure 8 - New host network 192.168.56.1/24 with active DHCP"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figure 8 – New host network 192.168.56.1/24 with active DHCP&lt;/p&gt;

&lt;p&gt;For the second step, a second network card must be added from the VM network settings by setting the type (“Connected to”) to host-only card, in this case specifying the name of the host network created in the previous step.&lt;/p&gt;

&lt;p&gt;Figure 9 shows the configuration of the new network card configured to be connected to the host network (vboxnet0), while Figure 10 the summary of the VM settings after configuring the new network card.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2022/01/virtual_box_add_new_network_card_1-1_en.png" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.dontesta.it%2Fwp-content%2Fuploads%2F2022%2F01%2Fvirtual_box_add_new_network_card_1-1_en-1024x611.png" title="Figure 9 - Configuration of the second network card connected to the host network" alt="Figure 9 - Configuration of the second network card connected to the host network"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figure 9 – Configuration of the second network card connected to the host network&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2022/01/virtual_box_vm_settings_en.png" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.dontesta.it%2Fwp-content%2Fuploads%2F2022%2F01%2Fvirtual_box_vm_settings_en-1024x865.png" title="Figure 10 - Additional network card also visible on the VM summary" alt="Figure 10 - Additional network card also visible on the VM summary"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figure 10 – Additional network card also visible on the VM summary&lt;/p&gt;
&lt;h3&gt;
  
  
  2.4 Starting and testing the Virtual Appliance
&lt;/h3&gt;

&lt;p&gt;Once the step of importing and modifying the network settings has been completed, it is possible to proceed with starting the virtual machine through the start “green button”. Figure 11 shows the &lt;a href="https://en.wikipedia.org/wiki/GNU_GRUB" rel="noopener noreferrer"&gt;&lt;strong&gt;Grub&lt;/strong&gt;&lt;/a&gt; boot menu highlighting the &lt;a href="https://www.oracle.com/it/linux/" rel="noopener noreferrer"&gt;&lt;strong&gt;Oracle Linux&lt;/strong&gt;&lt;/a&gt; operating system, which will be booted by default (without any action on our part).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/12/virtual_box_start_vm_oracle_1.png" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.dontesta.it%2Fwp-content%2Fuploads%2F2021%2F12%2Fvirtual_box_start_vm_oracle_1.png" title="Figure 11 - Starting the VM. Grub boot menu of the Oracle Linux operating system" alt="Figure 11 - Starting the VM. Grub boot menu of the Oracle Linux operating system"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figure 11 – Starting the VM. Grub boot menu of the Oracle Linux operating system&lt;/p&gt;

&lt;p&gt;After a few minutes, which can vary a lot depending on your hardware resources, you should find yourself in front of the &lt;a href="https://www.gnome.org/" rel="noopener noreferrer"&gt;GNOME&lt;/a&gt; desktop as shown in Figure 12 (even if the arrangement of the objects on the desktop may be different).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/12/virtual_box_start_vm_oracle_2.png" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.dontesta.it%2Fwp-content%2Fuploads%2F2021%2F12%2Fvirtual_box_start_vm_oracle_2-1024x576.png" title="Figure 12 - GNOME desktop after starting the VM" alt="Figure 12 - GNOME desktop after starting the VM"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figure 12 – GNOME desktop after starting the VM&lt;/p&gt;

&lt;p&gt;Figure 12 highlights some important data that will be needed to connect to the Oracle database and machine via SSH. Below, I report these parameters.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Username/Password: oracle/oracle (also sudo user)&lt;/li&gt;
&lt;li&gt;Oracle SID: orclcdb&lt;/li&gt;
&lt;li&gt;Pluggable DB: orcl&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At this point, we must verify that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;the Oracle database services in particular are in listen;&lt;/li&gt;
&lt;li&gt;the connection to the database via &lt;a href="https://www.gnome.org/" rel="noopener noreferrer"&gt;SQL*Plus&lt;/a&gt; works correctly;&lt;/li&gt;
&lt;li&gt;the VM is able to communicate with the public network (internet);&lt;/li&gt;
&lt;li&gt;the new network card is seen correctly by the Oracle Linux operating system, and configure it via DHCP.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Console 2 shows the commands needed to obtain the above information.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

# Verify that the SQLNet service is listening on standard TCP / IP port 1521
$ netstat -ltnp

# Verification of connection to the Oracle database via SQL*Plus with the user who has the SYSDBA role
$ sqlplus sys/oracle as sysdba

# Check connectivity to the public network (internet)
$ ping www.google.it

# Verify the configuration of the network card connected to the host network created earlier
$ ifconfig

# Configuration of the eth1 network card (see output of 
# ifconfig command) to get the IP address from the server 
# DHCP.
$ sudo dhclient eth1


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Figures 13, 14 and 15 illustrate in the order indicated in Console 2 the output of the commands given directly on the machine. From Figure 13 it is possible to notice that the SQLNet service is correctly in LISTEN on TCP/IP port 1521 (all interfaces 0.0.0.0).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/12/virtual_box_start_vm_oracle_3.png" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.dontesta.it%2Fwp-content%2Fuploads%2F2021%2F12%2Fvirtual_box_start_vm_oracle_3.png" title="Figure 13 - Verify that Oracle's SQLNet service is active on TCP/IP port 1521" alt="Figure 13 - Verify that Oracle's SQLNet service is active on TCP/IP port 1521"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figure 13 – Verify that Oracle’s SQLNet service is active on TCP/IP port 1521&lt;/p&gt;

&lt;p&gt;From Figure 14 it is possible to notice how the connection to the Oracle database through &lt;a href="https://docs.oracle.com/en/database/oracle/oracle-database/19/sqpug/index.html" rel="noopener noreferrer"&gt;SQL*Plus&lt;/a&gt; takes place in the correct way by showing the banner with the detailed information about the Oracle instance.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/12/virtual_box_start_vm_oracle_5.png" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.dontesta.it%2Fwp-content%2Fuploads%2F2021%2F12%2Fvirtual_box_start_vm_oracle_5.png" title="Figure 14 - Test connection to the SQLNet service via SQLPlus as a user with the role of SYSDBA" alt="Figure 14 - Test connection to the SQLNet service via SQLPlus as a user with the role of SYSDBA"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figure 14 – Test connection to the SQLNet service via SQLPlus as a user with the role of SYSDBA&lt;/p&gt;

&lt;p&gt;On the desktop (see Figure 12) there is a link to the &lt;a href="https://www.oracle.com/it/database/technologies/appdev/sqldeveloper-landing.html" rel="noopener noreferrer"&gt;&lt;strong&gt;SQL Developer&lt;/strong&gt;&lt;/a&gt; tool that you could use as an interface to the Oracle database. The tool is already configured with a database connection as SYSDBA user. The version of SQL Developer installed on the VM is quite old, 19.1.&lt;/p&gt;

&lt;p&gt;Figure 15 shows the correct configuration of the network card, which acquired the IP address 192.168.56.5 from the DHCP server.&lt;/p&gt;

&lt;p&gt;To make the activation of the network card permanent via DHCP, it is possible to act on the &lt;em&gt;Connect automatically&lt;/em&gt; flag and then to &lt;em&gt;Apply&lt;/em&gt; on the configuration detail of the network card accessible through the &lt;em&gt;Network Manager&lt;/em&gt; (see figures below).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/12/virtual_box_check_network_card_1.png" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.dontesta.it%2Fwp-content%2Fuploads%2F2021%2F12%2Fvirtual_box_check_network_card_1-1024x645.png" title="Figure 15 - Verifying the correct configuration of the network card configured to use the host network" alt="Figure 15 - Verifying the correct configuration of the network card configured to use the host network"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figure 15 – Verifying the correct configuration of the network card configured to use the host network&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/12/virtual_box_active_networ_card_1.png" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.dontesta.it%2Fwp-content%2Fuploads%2F2021%2F12%2Fvirtual_box_active_networ_card_1.png" title="Figure 16 - Access to the configuration of the network cards" alt="Figure 16 - Access to the configuration of the network cards"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figure 16 – Access to the configuration of the network cards&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/12/virtual_box_active_networ_card_2.png" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.dontesta.it%2Fwp-content%2Fuploads%2F2021%2F12%2Fvirtual_box_active_networ_card_2-1024x633.png" title="Figure 17 - List of network cards present on the system" alt="Figure 17 - List of network cards present on the system"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figure 17 – List of network cards present on the system&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/12/virtual_box_active_networ_card_3.png" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.dontesta.it%2Fwp-content%2Fuploads%2F2021%2F12%2Fvirtual_box_active_networ_card_3-1024x945.png" title="Figure 18 - Permanent activation of the new eth1 network card connected to the host network" alt="Figure 18 - Permanent activation of the new eth1 network card connected to the host network"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figure 18 – Permanent activation of the new eth1 network card connected to the host network&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Connect to database from host machine
&lt;/h2&gt;

&lt;p&gt;Once the setup of the Oracle Database VM is finished, we can interact with its services directly from our host machine, thanks to the fact that we are able to reach the SQLNet and SSH service.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

# Connect to VM via SSH
# The specified IP address is the one obtained from the command
# ifconfig run on the VM. Address assigned by the server
# Host network DHCP. Remember that the default password
# of the oracle user is oracle
$ ssh oracle@192.168.56.5


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;To establish the connection to the database, you are obviously free to use any SQL client that supports Oracle. I prefer to stay around Oracle and for this I recommend installing and using &lt;a href="https://www.oracle.com/tools/downloads/sqldev-downloads.html" rel="noopener noreferrer"&gt;SQL Developer&lt;/a&gt; whose latest version is 21.41.&lt;/p&gt;

&lt;p&gt;Once SQL Developer is installed and started, we can add the database connection using the following parameters.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Username: sys&lt;/li&gt;
&lt;li&gt;Password: oracle&lt;/li&gt;
&lt;li&gt;Role: SYSDBA&lt;/li&gt;
&lt;li&gt;Host Name: 192.168.56.5 (IP address of your VM which may be different from the one indicated here and in Figure 19)&lt;/li&gt;
&lt;li&gt;Service Name: orcl&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Figures 19 and 20 show the database connection setup and query execution.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2022/01/sql_developer_connection_setup_1-1_en.png" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.dontesta.it%2Fwp-content%2Fuploads%2F2022%2F01%2Fsql_developer_connection_setup_1-1_en-1024x703.png" title="Figure 19 - Setup of the connection from the Oracle database" alt="Figure 19 - Setup of the connection from the Oracle database"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figure 19 – Setup of the connection from the Oracle database&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/12/sql_developer_connection_setup_2-1.png" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.dontesta.it%2Fwp-content%2Fuploads%2F2021%2F12%2Fsql_developer_connection_setup_2-1-1024x466.png" title="Figure 20 - Example of executing a query on the Oracle database" alt="Figure 20 - Example of executing a query on the Oracle database"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figure 20 – Example of executing a query on the Oracle database&lt;/p&gt;

&lt;p&gt;At this point, we have our own Oracle development VM that we can use to host the databases of the projects we work on.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Useful resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.dontesta.it/2020/03/15/how-to-setup-docker-container-oracle-database-19c-for-liferay-development-environment/" rel="noopener noreferrer"&gt;How to setup Docker container Oracle Database 19c for Liferay Development Environment&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.dontesta.it/en/2019/08/21/how-to-build-a-docker-liferay-7-2-image-with-the-oracle-database-support/" rel="noopener noreferrer"&gt;How to build a Docker Liferay 7.2 image with the Oracle Database support&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.oracle.com/database/technologies/databaseappdev-vm.html#license-lightbox" rel="noopener noreferrer"&gt;Developer Day – Hands-on Database Application Development&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.oracle.com/tools/downloads/sqldev-downloads.html" rel="noopener noreferrer"&gt;SQL Developer 21.4.1 Downloads&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/oracle/docker-images" rel="noopener noreferrer"&gt;Docker Images from Oracle&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;L'articolo &lt;a href="https://www.dontesta.it/2022/01/09/how-to-use-oracle-database-19c-pre-built-developer-vm/" rel="noopener noreferrer"&gt;(English) How to use Oracle Database 19c Pre-Built Developer VM&lt;/a&gt; sembra essere il primo su &lt;a href="https://www.dontesta.it" rel="noopener noreferrer"&gt;Antonio Musarra's Blog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://feeds.feedburner.com/~ff/dontesta/blog?a=ns_dfw0HCHU:W60oQb9gluM:yIl2AUoC8zA" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Ffeeds.feedburner.com%2F~ff%2Fdontesta%2Fblog%3Fd%3DyIl2AUoC8zA"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/dontesta/blog?a=ns_dfw0HCHU:W60oQb9gluM:dnMXMwOfBR0" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Ffeeds.feedburner.com%2F~ff%2Fdontesta%2Fblog%3Fd%3DdnMXMwOfBR0"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/dontesta/blog?a=ns_dfw0HCHU:W60oQb9gluM:D7DqB2pKExk" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Ffeeds.feedburner.com%2F~ff%2Fdontesta%2Fblog%3Fi%3Dns_dfw0HCHU%3AW60oQb9gluM%3AD7DqB2pKExk"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/dontesta/blog?a=ns_dfw0HCHU:W60oQb9gluM:YwkR-u9nhCs" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Ffeeds.feedburner.com%2F~ff%2Fdontesta%2Fblog%3Fd%3DYwkR-u9nhCs"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/dontesta/blog?a=ns_dfw0HCHU:W60oQb9gluM:F7zBnMyn0Lo" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Ffeeds.feedburner.com%2F~ff%2Fdontesta%2Fblog%3Fi%3Dns_dfw0HCHU%3AW60oQb9gluM%3AF7zBnMyn0Lo"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/dontesta/blog?a=ns_dfw0HCHU:W60oQb9gluM:V_sGLiPBpWU" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Ffeeds.feedburner.com%2F~ff%2Fdontesta%2Fblog%3Fi%3Dns_dfw0HCHU%3AW60oQb9gluM%3AV_sGLiPBpWU"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/dontesta/blog?a=ns_dfw0HCHU:W60oQb9gluM:qj6IDK7rITs" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Ffeeds.feedburner.com%2F~ff%2Fdontesta%2Fblog%3Fd%3Dqj6IDK7rITs"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/dontesta/blog?a=ns_dfw0HCHU:W60oQb9gluM:KwTdNBX3Jqk" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Ffeeds.feedburner.com%2F~ff%2Fdontesta%2Fblog%3Fi%3Dns_dfw0HCHU%3AW60oQb9gluM%3AKwTdNBX3Jqk"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/dontesta/blog?a=ns_dfw0HCHU:W60oQb9gluM:gIN9vFwOqvQ" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Ffeeds.feedburner.com%2F~ff%2Fdontesta%2Fblog%3Fi%3Dns_dfw0HCHU%3AW60oQb9gluM%3AgIN9vFwOqvQ"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>blog</category>
      <category>database</category>
      <category>oracle</category>
      <category>rdbms</category>
    </item>
    <item>
      <title>Come usare Oracle Database 19c Pre-Built Developer VM</title>
      <dc:creator>Antonio Musarra</dc:creator>
      <pubDate>Wed, 29 Dec 2021 16:08:46 +0000</pubDate>
      <link>https://dev.to/amusarra/come-usare-oracle-database-19c-pre-built-developer-vm-1bak</link>
      <guid>https://dev.to/amusarra/come-usare-oracle-database-19c-pre-built-developer-vm-1bak</guid>
      <description>&lt;p&gt;Quante volte ci siamo trovati ad affrontare l’arduo setup di una istanza Oracle Database per il nostro ambiente di sviluppo e “sputare decisamente sangue”?&lt;/p&gt;

&lt;p&gt;Immagino che queste “volte” siano state anche troppe, ecco un buon motivo per iniziare a utilizzare quello che Oracle mette a disposizione a noi sviluppatori, ovvero, le &lt;strong&gt;&lt;a href="https://www.oracle.com/downloads/developer-vm/community-downloads.html"&gt;Pre-Built Developer VMs&lt;/a&gt;&lt;/strong&gt; per &lt;a href="https://www.virtualbox.org/"&gt;Oracle VM VirtualBox&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Nel corso di questo articolo vedremo come fare il setup di una &lt;strong&gt;VM Oracle Database 19c&lt;/strong&gt; dal Database Virtual Box Appliance che Oracle fornisce.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Requisiti
&lt;/h2&gt;

&lt;p&gt;Prima d’iniziare è necessario verificare che i seguenti requisiti siano soddisfatti.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sistema Operativo che supporti la versione di Virtual Box 6.x&lt;/li&gt;
&lt;li&gt;Almeno 2 GByte di RAM&lt;/li&gt;
&lt;li&gt;Almeno 15 GByte di spazio per lo storage&lt;/li&gt;
&lt;li&gt;Processo da almeno 2 GHz&lt;/li&gt;
&lt;li&gt;Privilegi di amministratore&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;La &lt;a href="https://en.wikipedia.org/wiki/Virtual_appliance"&gt;Virtual Appliance&lt;/a&gt; di riferimento è del 20/06/2019 il cui contenuto è indicato a seguire.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Oracle Linux 7&lt;/li&gt;
&lt;li&gt;Oracle Database 19.3&lt;/li&gt;
&lt;li&gt;Oracle SQL Developer 19.1&lt;/li&gt;
&lt;li&gt;Oracle Application Express 19.1&lt;/li&gt;
&lt;li&gt;Hands-On-Labs (accessibile via the Toolbar Menu in Firefox)

&lt;ul&gt;
&lt;li&gt;Oracle REST Data Services 19.1&lt;/li&gt;
&lt;li&gt;Oracle SQL Developer Data Modeler 19.1&lt;/li&gt;
&lt;li&gt;Oracle XML DB&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Attenzione!&lt;/strong&gt;  Questa Virtual Appliance è da utilizzare solo in ambienti di sviluppo/test, non deve essere utilizzata in un ambiente di pre-produzione o produzione.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Setup della Virtual Appliance
&lt;/h2&gt;

&lt;p&gt;La procedura di setup consta di alcuni passi riassunti a seguire:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Download e installazione di &lt;a href="https://www.oracle.com/virtualization/technologies/vm/downloads/virtualbox-downloads.html"&gt;Oracle VM VirtualBox&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Download di &lt;a href="https://www.oracle.com/database/technologies/databaseappdev-vm.html#license-lightbox"&gt;Oracle DB Developer VM&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Importazione della Virtual Appliance su Oracle VM VirtualBox&lt;/li&gt;
&lt;li&gt;Avvio e test della Virtual Appliance&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  2.1 Download e installazione di Oracle VM VirtualBox
&lt;/h3&gt;

&lt;p&gt;Dalla home page di &lt;a href="https://www.oracle.com/virtualization/technologies/vm/downloads/virtualbox-downloads.html"&gt;Oracle VM VirtualBox&lt;/a&gt; è possibile effettuare il download dei binari per il proprio sistema operativo. Nel mio caso ho provveduto a scaricare la versione per MacOS.&lt;/p&gt;

&lt;p&gt;La procedura d’installazione è molto semplice e non è oggetto di questo articolo; in caso di difficoltà o approfondimenti, fare riferimento allo &lt;a href="https://download.virtualbox.org/virtualbox/6.1.30/UserManual.pdf"&gt;User Manual&lt;/a&gt;. La versione di riferimento per questo articolo è la 6.1.30. La Figura 1 mostra le informazioni di dettaglio circa la versione installata sul mio MacBook Pro con macOS Monterey (versione 12.1).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/12/virtual_box_about_version.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Vbk8vRpJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/12/virtual_box_about_version-1024x815.png" alt="Figura 1 - Informazioni su VirtualBox" width="880" height="700"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 1 – Informazioni su VirtualBox&lt;/p&gt;

&lt;h3&gt;
  
  
  2.2 Download di Oracle DB Developer VM
&lt;/h3&gt;

&lt;p&gt;Dal link &lt;a href="https://download.oracle.com/otn/other/virtualbox/dd/DeveloperDaysVM2019-05-31_20.ova"&gt;Oracle DB Developer VM&lt;/a&gt; si accede al file &lt;em&gt;DeveloperDaysVM2019-05-31_20.ova&lt;/em&gt; che contiene la Virtual Appliance. Il formato &lt;a href="https://en.wikipedia.org/wiki/Open_Virtualization_Format"&gt;OVA/OVF&lt;/a&gt; è uno standard per il packaging e distribuzione delle Virtual Appliance.&lt;/p&gt;

&lt;p&gt;Il download del file richiede la disponibilità di un account Oracle (che alla bisogna potete creare gratuitamente). La dimensione del file è di oltre 7 GByte, consiglio pertanto di verificare al termine del download il checksum del file. In Console 1 è indacato uno dei modi per la verifica dell’hash utilizzando i comandi &lt;em&gt;md5&lt;/em&gt; e &lt;em&gt;sha&lt;/em&gt; disponibili su macOS, Unix/Linux e Windows 10.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MD5 (sum): 20b5a5bd91cfe9d4f5acf5128f06146e&lt;/li&gt;
&lt;li&gt;SHA1: e0b9f8af8158664139b9ca970c3500752fc15fd2
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Verify the checksum MD5 and SHA1 on macOS
$ md5 DeveloperDaysVM2019-05-31_20.ova
$ shasum DeveloperDaysVM2019-05-31_20.ova

# Verify the checksum MD5 and SHA1 on Unix/Linux
$ md5sum DeveloperDaysVM2019-05-31_20.ova
$ sha1sum DeveloperDaysVM2019-05-31_20.ova

# Verify the checksum MD5 and SHA1 on Windows 10
&amp;gt; certutil -hashfile DeveloperDaysVM2019-05-31_20.ova MD5
&amp;gt; certutil -hashfile DeveloperDaysVM2019-05-31_20.ova SHA1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2.3 Importazione della Virtual Appliance su Oracle VM VirtualBox
&lt;/h3&gt;

&lt;p&gt;Una volta ottenuto il file ova, è possibile procedere con l’importazione dello stesso tramite la funzionalità &lt;em&gt;Import Appliance&lt;/em&gt; (o Importa Applicazione Virtuale) di Oracle VM VirtualBox a cui possiamo accedere dal menù &lt;em&gt;File&lt;/em&gt; (vedi Figura 2).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/12/virtual_box_menu_file_import_virtual_appliance.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---bLCklQH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/12/virtual_box_menu_file_import_virtual_appliance.png" alt="Figura 2 - Accesso alla funziona di Import Appliance (o Importa Applicazione Virtuale)" width="790" height="346"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 2 – Accesso alla funziona di Import Appliance (o Importa Applicazione Virtuale)&lt;/p&gt;

&lt;p&gt;Dopo aver cliccato sulla voce di menù indicata in precedenza, dovreste vedere una finestra di dialogo come quella mostrata in Figura 3. L’unica informazione da specificare è la posizione del file OVA, dopo di ché sarà possibile proseguire cliccando sul pulsante &lt;em&gt;Continua&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/12/virtual_box_import_ova_step_1.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oAfDixAF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/12/virtual_box_import_ova_step_1-1024x700.png" alt="Figura 3 - Primo step d'importazione Virtual Appliance: specificare la locazione del file OVA" width="880" height="602"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 3 – Primo step d’importazione Virtual Appliance: specificare la locazione del file OVA&lt;/p&gt;

&lt;p&gt;Dopo il clic sul pulsante &lt;em&gt;Continua&lt;/em&gt; sarà aperta una successiva finestra di dialogo che mostra le informazioni di dettaglio (come CPU, RAM, età.) della Virtual Appliance (vedi Figura 4). È possibile cambiare alcune impostazioni ma consiglio di lasciare quelle proposte; proseguiamo quindi cliccando sul pulsante &lt;em&gt;Importa&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/12/virtual_box_import_ova_step_2.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aslxy-bU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/12/virtual_box_import_ova_step_2-1024x696.png" alt="Figura 4 - Secondo step d'importazione Virtual Appliance: riepilogo informazioni di dettalio della VA e start importazione" width="880" height="598"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 4 – Secondo step d’importazione Virtual Appliance: riepilogo informazioni di dettaglio della VA e start importazione&lt;/p&gt;

&lt;p&gt;La Figura 5 mostra l’avanzamento del processo d’importazione. La durata dell’importazione dipende dalla potenza della propria e dalla disponibilità di risorse nel momento dell’importazione. Nel mio caso il processo d’importazione ha avuto una durata di circa 2 minuti.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/12/virtual_box_import_ova_step_3.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DhMW-oU9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/12/virtual_box_import_ova_step_3-1024x288.png" alt="Figura 5 - Processo d'importazione della Virtual Appliance" width="880" height="248"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 5 – Processo d’importazione della Virtual Appliance&lt;/p&gt;

&lt;p&gt;Una volta terminato il processo d’importazione, dovreste avere una situazione come quella mostrata in Figura 6, ovvero, una nuova &lt;em&gt;Macchina Virtuale&lt;/em&gt; chiamata Oracle DB Developer VM.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/12/virtual_box_import_ova_step_4.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sQYWGZb_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/12/virtual_box_import_ova_step_4-1024x724.png" alt="Figura 6 - Macchina virtuale Oracle DB Developer VM importata" width="880" height="622"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 6 – Macchina virtuale Oracle DB Developer VM importata&lt;/p&gt;

&lt;p&gt;Prima di poter avviare la macchina virtuale è necessario:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Verificare e/o creare una nuova rete host. Questo consentirà l’accesso ai servizi del database Oracle anche dalla rete del host, ovvero, del nostro PC&lt;/li&gt;
&lt;li&gt;Aggiungere una nuova scheda di rete alla macchina virtuale e configurarla per usare la rete dell’host&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Per il primo step, accedere alla finestra del &lt;em&gt;Gestore di rete dell’host&lt;/em&gt; dal menù &lt;em&gt;File -&amp;gt; Gestore di rete dell’host&lt;/em&gt; e dovreste vedere quanto mostrato in Figura 7.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/12/virtual_box_manage_network_host_step_1.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pRxdxVC1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/12/virtual_box_manage_network_host_step_1-1024x687.png" alt="Figura 7 - Gestore di rete dell'host" width="880" height="590"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 7 – Gestore di rete dell’host&lt;/p&gt;

&lt;p&gt;In questo caso non risulta nessuna interfaccia di rete host presente, dobbiamo quindi procedere con la creazione, step ch’è possibile fare cliccando sul pulsante che riporta l’etichetta &lt;em&gt;Crea&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Nel caso in cui fossero già presenti una o più configurazioni di rete host, sarebbe possibile sfruttarne una tra quelle disponibili.&lt;/p&gt;

&lt;p&gt;La Figura 8 mostra la nuova rete host (vboxnet0) appena creata e le caratteristiche di base. Dopo la creazione della rete dobbiamo attivare l’opzione &lt;strong&gt;Server DHCP&lt;/strong&gt; lasciando le impostazioni di default. Questa rete sarà quella che andremo poi a specificare sulla configurazione della nuova scheda di rete della macchina virtuale appena importata.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Importante!&lt;/strong&gt; Dopo aver impostato il flag per attivare il server DHCP, dobbiamo chiudere e riaprire Oracle VM VirtualBox, questo per fa si che il server DHCP si avvi correttamente.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/12/virtual_box_manage_network_host_step_2a.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gwdRXjkJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/12/virtual_box_manage_network_host_step_2a-1024x704.png" alt="Figura 8 - Nuova rete host 192.168.56.1/24 con DHCP attivo" width="880" height="605"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 8 – Nuova rete host 192.168.56.1/24 con DHCP attivo&lt;/p&gt;

&lt;p&gt;Per il secondo step, occorre aggiungere dalle impostazioni di rete della VM, una seconda scheda di rete impostando la tipologia (“Connessa a”) a scheda solo host, specificando in questo caso il nome della rete host creata nel precedente step.&lt;/p&gt;

&lt;p&gt;La Figura 9 mostra la configurazione della nuova scheda di rete configurata per essere connessa alla rete dell’host (vboxnet0), mentre la Figura 10 il riepilogo delle impostazioni della VM dopo la configurazione della nuova scheda di rete.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/12/virtual_box_add_new_network_card_1-1.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0kJEJIo5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/12/virtual_box_add_new_network_card_1-1-1024x487.png" alt="Figura 9 - Configurazione delle seconda scheda di rete connessa alla rete dell'host" width="880" height="419"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 9 – Configurazione delle seconda scheda di rete connessa alla rete dell’host&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/12/virtual_box_vm_settings.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--h3IxK7eY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/12/virtual_box_vm_settings-1024x906.png" alt="Figura 10 - Scheda di rete addizionale visibile anche sul riepilogo della VM" width="880" height="779"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 10 – Scheda di rete addizionale visibile anche sul riepilogo della VM&lt;/p&gt;

&lt;h3&gt;
  
  
  2.4 Avvio e test della Virtual Appliance
&lt;/h3&gt;

&lt;p&gt;Completato lo step d’importazione e modifica delle impostazioni di rete, è possibile procedere con l’avvio della macchina virtuale attraverso il “pulsantone verde” di avvio. In Figura 11 è mostrato il boot menù di &lt;a href="https://it.wikipedia.org/wiki/GNU_GRUB"&gt;Grub&lt;/a&gt; con in evidenza il sistema operativo &lt;a href="https://www.oracle.com/it/linux/"&gt;Oracle Linux&lt;/a&gt; che sarà avviato di default (senza alcuna azione da parte nostra).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/12/virtual_box_start_vm_oracle_1.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5H6MVk1r--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/12/virtual_box_start_vm_oracle_1.png" alt="Figura 11 - Avvio della VM. Grub menù di avvio del sistema operativo Oracle Linux" width="725" height="455"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 11 – Avvio della VM. Grub menù di avvio del sistema operativo Oracle Linux&lt;/p&gt;

&lt;p&gt;Dopo qualche minuto, tempo che può variare anche di molto in base alle proprie risorse hardware, dovreste trovarvi davanti il desktop di &lt;a href="https://www.gnome.org/"&gt;GNOME&lt;/a&gt; così come mostrato in Figura 12 (anche se la disposizione degli oggetti sul desktop potrebbe essere diversa).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/12/virtual_box_start_vm_oracle_2.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iBPB-dG4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/12/virtual_box_start_vm_oracle_2-1024x576.png" alt="Figura 12 - Desktop GNOME dopo l'avvio della VM" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 12 – Desktop GNOME dopo l’avvio della VM&lt;/p&gt;

&lt;p&gt;La Figura 12 evidenzia alcuni dati importanti che serviranno per connetterci al database Oracle e alla macchina tramite SSH. A seguire riporto questi parametri.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Username/Password: oracle/oracle (è anche sudo user)&lt;/li&gt;
&lt;li&gt;Oracle SID: orclcdb&lt;/li&gt;
&lt;li&gt;Pluggable DB: orcl&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Arrivati a questo punto dobbiamo verificare che:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;i servizi Oracle del database in particolare siano in listen;&lt;/li&gt;
&lt;li&gt;la connessione al database via &lt;a href="https://docs.oracle.com/en/database/oracle/oracle-database/19/sqpug/index.html"&gt;SQL*Plus&lt;/a&gt; funzioni correttamente;&lt;/li&gt;
&lt;li&gt;la VM sia in grado di comunicare con la rete pubblica (internet);&lt;/li&gt;
&lt;li&gt;la nuova scheda di rete sia vista correttamente dal sistema operativo Oracle Linux e provvedere alla configurazione via DHCP.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In Console 2 sono indicati i comandi necessari per ottenere le informazioni indicate in precedenza.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Verifica che il servizio SQLNet sia in listen sulla porta standard TCP/IP 1521
$ netstat -ltnp

# Verifica di connessione al database Oracle via SQL*Plus con l'utente che ha il ruolo di SYSDBA
$ sqlplus sys/oracle as sysdba

# Verifica connettività verso la rete pubblica (internet)
$ ping www.google.it

# Verifica della configurazione della scheda di rete connessa alla rete host creata in precedenza
$ ifconfig

# Configurazione della scheda di rete eth1 (vedi output del 
# comando ifconfig) per acquisire l'indirizzo IP dal server 
# DHCP.
$ sudo dhclient eth1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Le Figure 13, 14 e 15 illustrano nell’ordine indicato in Console 2 l’output dei comandi impartiti direttamente sulla macchina. Dalla Figura 13 è possibile notare che il servizio SQLNet sia correttamente in LISTEN sulla porta TCP/IP 1521 (tutte le interfacce 0.0.0.0).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/12/virtual_box_start_vm_oracle_3.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Evh5TFF6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/12/virtual_box_start_vm_oracle_3.png" alt="Figura 13 - Verifica che il servizio SQLNet di Oracle sia attivo sulla porta TCP/IP 1521" width="880" height="299"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 13 – Verifica che il servizio SQLNet di Oracle sia attivo sulla porta TCP/IP 1521&lt;/p&gt;

&lt;p&gt;Dalla Figura 14 è possibile notare come la connessione al database Oracle attraverso &lt;a href="https://docs.oracle.com/en/database/oracle/oracle-database/19/sqpug/index.html"&gt;SQL*Plus&lt;/a&gt; avviene nel modo corretto mostrando il banner con le informazioni di dettaglio circa l’istanza Oracle.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/12/virtual_box_start_vm_oracle_5.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BP8PV5FN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/12/virtual_box_start_vm_oracle_5.png" alt="Figura 14 - Test di connessione al servizio SQLNet via SQLPlus come utente con il ruolo di SYSDBA" width="652" height="241"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 14 – Test di connessione al servizio SQLNet via SQLPlus come utente con il ruolo di SYSDBA&lt;/p&gt;

&lt;p&gt;Sul desktop (vedi Figura 12) è disponibile il link al tool &lt;a href="https://www.oracle.com/it/database/technologies/appdev/sqldeveloper-landing.html"&gt;&lt;strong&gt;SQL Developer&lt;/strong&gt;&lt;/a&gt; che potreste utilizzare come interfaccia verso il database Oracle. Il tool è già configurato con una connessione al database come utente SYSDBA. La versione di SQL Developer installata sulla VM è la 19.1 abbastanza vecchiotta.&lt;/p&gt;

&lt;p&gt;Dalla Figura 15 è evidente la corretta configurazione della scheda di rete che ha acquisito dal server DHCP l’indirizzo IP 192.168.56.5.&lt;/p&gt;

&lt;p&gt;Per rendere permanete l’attivazione della scheda di rete via DHCP, è possibile agire sul flag &lt;em&gt;Connect automatically&lt;/em&gt; e poi su &lt;em&gt;Apply&lt;/em&gt; sul dettaglio della configurazione della scheda di rete accessibile attraverso il &lt;em&gt;Network Manager&lt;/em&gt; (vedi Figure a seguire).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/12/virtual_box_check_network_card_1.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KsU5ghdW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/12/virtual_box_check_network_card_1-1024x645.png" alt="Figura 15 - Verifica della corretta configurazione della scheda di rete configurata per usare la rete dell'host" width="880" height="554"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 15 – Verifica della corretta configurazione della scheda di rete configurata per usare la rete dell’host&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/12/virtual_box_active_networ_card_1.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SciPPHXz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/12/virtual_box_active_networ_card_1.png" alt="Figura 16 - Accesso alla configurazione delle schede di rete" width="666" height="858"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 16 – Accesso alla configurazione delle schede di rete&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/12/virtual_box_active_networ_card_2.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AApx-uxK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/12/virtual_box_active_networ_card_2-1024x633.png" alt="Figura 17 - Lista delle schede di rete presenti sul sistema" width="880" height="544"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 17 – Lista delle schede di rete presenti sul sistema&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/12/virtual_box_active_networ_card_3.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_-QLXMz6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/12/virtual_box_active_networ_card_3-1024x945.png" alt="Figura 18 - Attivazione permanente della nuova scheda di rete eth1 connessa alla rete dell'host" width="880" height="812"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 18 – Attivazione permanente della nuova scheda di rete eth1 connessa alla rete dell’host&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Connessione al database dalla macchina host
&lt;/h2&gt;

&lt;p&gt;Terminato il setup della VM di Oracle Database, possiamo interagire con i servizi di quest’ultima direttamente dalla nostra macchina host, grazie al fatto che siamo nelle condizioni di poter raggiungere il servizio SQLNet e SSH.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Connessione alla VM via SSH
# L'indirizzo IP specificato è quello ricavato dal comando 
# ifconfig eseguito sulla VM. Indirizzo asseganto dal server
# DHCP della rete dell'host. Ricordo che la password di default
# dell'utente oracle è oracle
$ ssh oracle@192.168.56.5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Per instaurare la connessione al database siete ovviamente liberi di usare qualunque client SQL che supporti Oracle. Preferisco restare nell’intorno Oracle e per questo consiglio d’installare e usare &lt;a href="https://www.oracle.com/tools/downloads/sqldev-downloads.html"&gt;SQL Developer&lt;/a&gt; la cui ultima versione è la 21.41.&lt;/p&gt;

&lt;p&gt;Una volta installato e avviato SQL Developer, possiamo aggiungere la connessione al database utilizzando i seguenti parametri.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Nome Utente: sys&lt;/li&gt;
&lt;li&gt;Password: oracle&lt;/li&gt;
&lt;li&gt;Ruolo: SYSDBA&lt;/li&gt;
&lt;li&gt;Nome Host: 192.168.56.5 (indirizzo IP della propria VM che potrebbe essere diverso quello indicato qui e in Figura 19)&lt;/li&gt;
&lt;li&gt;Nome Servizio: orcl&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Le Figure 19 e 20 mostrano il setup della connessione al database e l’esecuzione di una query.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/12/sql_developer_connection_setup_1-1.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CxdPuZ8i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/12/sql_developer_connection_setup_1-1-1024x660.png" alt="Figura 19 - Setup della connesione dal database Oracle" width="880" height="567"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 19 – Setup della connesione dal database Oracle&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/12/sql_developer_connection_setup_2-1.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vTLrAcJx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/12/sql_developer_connection_setup_2-1-1024x466.png" alt="Figura 20 - Esempio di esecuzione di una query sul database Oracle" width="880" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 20 – Esempio di esecuzione di una query sul database Oracle&lt;/p&gt;

&lt;p&gt;A questo punto abbiamo una nostra VM di sviluppo Oracle che possiamo usare per ospitare i database dei progetti su cui lavoriamo.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Risorse utili
&lt;/h2&gt;

&lt;p&gt;A seguire una lista di risorse utili a scopo di approfondimento:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.dontesta.it/2020/03/15/how-to-setup-docker-container-oracle-database-19c-for-liferay-development-environment/"&gt;How to setup Docker container Oracle Database 19c for Liferay Development Environment&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.dontesta.it/en/2019/08/21/how-to-build-a-docker-liferay-7-2-image-with-the-oracle-database-support/"&gt;How to build a Docker Liferay 7.2 image with the Oracle Database support&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.oracle.com/database/technologies/databaseappdev-vm.html#license-lightbox"&gt;Developer Day – Hands-on Database Application Development&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.oracle.com/tools/downloads/sqldev-downloads.html"&gt;SQL Developer 21.4.1 Downloads&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/oracle/docker-images"&gt;Docker Images from Oracle&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;L'articolo &lt;a href="https://www.dontesta.it/2021/12/29/come-usare-oracle-database-19c-pre-built-developer-vm/"&gt;Come usare Oracle Database 19c Pre-Built Developer VM&lt;/a&gt; sembra essere il primo su &lt;a href="https://www.dontesta.it"&gt;Antonio Musarra's Blog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://feeds.feedburner.com/~ff/dontesta/blog?a=9wOLiMKjj3Y:8N6yVNljLzg:yIl2AUoC8zA"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ly8gdBSb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Eff/dontesta/blog%3Fd%3DyIl2AUoC8zA" alt="" width="62" height="24"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/dontesta/blog?a=9wOLiMKjj3Y:8N6yVNljLzg:dnMXMwOfBR0"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PziyOv7j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Eff/dontesta/blog%3Fd%3DdnMXMwOfBR0" alt="" width="98" height="24"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/dontesta/blog?a=9wOLiMKjj3Y:8N6yVNljLzg:D7DqB2pKExk"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--31_JSqwL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Eff/dontesta/blog%3Fi%3D9wOLiMKjj3Y:8N6yVNljLzg:D7DqB2pKExk" alt="" width="92" height="24"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/dontesta/blog?a=9wOLiMKjj3Y:8N6yVNljLzg:YwkR-u9nhCs"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DCS1IRW9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Eff/dontesta/blog%3Fd%3DYwkR-u9nhCs" alt="" width="97" height="24"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/dontesta/blog?a=9wOLiMKjj3Y:8N6yVNljLzg:F7zBnMyn0Lo"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Tx7tJjDb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Eff/dontesta/blog%3Fi%3D9wOLiMKjj3Y:8N6yVNljLzg:F7zBnMyn0Lo" alt="" width="105" height="24"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/dontesta/blog?a=9wOLiMKjj3Y:8N6yVNljLzg:V_sGLiPBpWU"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Z-yKa0Bc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Eff/dontesta/blog%3Fi%3D9wOLiMKjj3Y:8N6yVNljLzg:V_sGLiPBpWU" alt="" width="66" height="24"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/dontesta/blog?a=9wOLiMKjj3Y:8N6yVNljLzg:qj6IDK7rITs"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lg7sfzlZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Eff/dontesta/blog%3Fd%3Dqj6IDK7rITs" alt="" width="113" height="24"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/dontesta/blog?a=9wOLiMKjj3Y:8N6yVNljLzg:KwTdNBX3Jqk"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nSCW3HIw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Eff/dontesta/blog%3Fi%3D9wOLiMKjj3Y:8N6yVNljLzg:KwTdNBX3Jqk" alt="" width="1" height="1"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/dontesta/blog?a=9wOLiMKjj3Y:8N6yVNljLzg:gIN9vFwOqvQ"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XOr-MoZa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Eff/dontesta/blog%3Fi%3D9wOLiMKjj3Y:8N6yVNljLzg:gIN9vFwOqvQ" alt="" width="1" height="1"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>blog</category>
      <category>database</category>
      <category>oracle</category>
      <category>rdbms</category>
    </item>
    <item>
      <title>Apple PowerBook G4: La rinascita grazie a OpenBSD</title>
      <dc:creator>Antonio Musarra</dc:creator>
      <pubDate>Tue, 24 Aug 2021 20:11:18 +0000</pubDate>
      <link>https://dev.to/amusarra/apple-powerbook-g4-la-rinascita-grazie-a-openbsd-1ih9</link>
      <guid>https://dev.to/amusarra/apple-powerbook-g4-la-rinascita-grazie-a-openbsd-1ih9</guid>
      <description>&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/05/12243428_10205658293641273_406568089324685156_n.jpg"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--m6kf8_jd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/05/12243428_10205658293641273_406568089324685156_n-300x225.jpg" alt="Il mio primo Mac Portatile"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Il mio primo Mac Portatile&lt;/p&gt;

&lt;p&gt;Ogni volta che scendo giù a casa in Sicilia rispolvero cose del mio passato. Questa è stata la volta del mio primo portatile Apple, esattamente il &lt;a href="https://it.wikipedia.org/wiki/PowerBook_G4"&gt;PowerBook G4&lt;/a&gt; basato sul processore &lt;a href="https://it.wikipedia.org/wiki/Reduced_instruction_set_computer"&gt;RISC&lt;/a&gt; (Reduced Instruction Set Computer)  a 32bit &lt;a href="https://it.wikipedia.org/wiki/PowerPC_G4"&gt;PowerPC G4&lt;/a&gt;. Ho usato questa macchina sette giorni su sette dal 2005 fino alla metà del 2010 senza nessuna interruzione. Qui sono disponibili tutte le specifiche tecniche &lt;a href="https://everymac.com/systems/apple/powerbook_g4/specs/powerbook_g4_1.5_12.html"&gt;Apple PowerBook G4 1.5 12″ (modello A1104)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Allo stato attuale questa incredibile macchina è ancora funzionante e con il sistema operativo &lt;a href="https://it.wikipedia.org/wiki/Mac_OS_X_Leopard"&gt;Mac OS X 10.5.8 (Leopard)&lt;/a&gt;, ultima versione disponibile per questa piattaforma hardware. Purtroppo non è possibile aggiornare il resto dei software come per esempio il semplice browser per navigare su internet. Con le versioni installate dei browser (Safari, Firefox e Chrome) è negata la navigazione a causa del fatto che i nuovi protocolli &lt;a href="https://it.wikipedia.org/wiki/Transport_Layer_Security"&gt;TLS&lt;/a&gt; (1.2 e 1.3), ormai adottati dalla stragrande maggioranza dei siti web non sono ovviamente supportati; al tempo non esistevano!&lt;/p&gt;

&lt;p&gt;Le cose sono due, rimettere nuovamente il portatile in parcheggio o dargli una nuova possibilità di vita. Ho scelto la seconda opzione perchè non ho resistito alla richiesta di mio nipote di sei anni il quale mi ha domandato: zio, potrò usare questo piccolo computer?&lt;/p&gt;

&lt;p&gt;Molto bene! In questo breve articolo vi mostrerò quello che ho fatto per dare nuova vita ad una macchina che per me è stata un ottimo strumento di lavoro e su cui mio nipote potrà iniziare a mettere le mani in pasta in questo fantastico mondo e magari iniziando proprio dalla linea di comando &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pLxvm0-4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s.w.org/images/core/emoji/13.0.1/72x72/1f600.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pLxvm0-4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s.w.org/images/core/emoji/13.0.1/72x72/1f600.png" alt="😀"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1. La scelta del sistema operativo
&lt;/h2&gt;

&lt;p&gt;Non è mia intenzione scrivere un papiro su questo aspetto, per questo motivo vi svelerò immediatamente quale sistema operativo ho scelto e le motivazioni principali. &lt;a href="https://www.openbsd.org/"&gt;&lt;strong&gt;OpenBSD&lt;/strong&gt;&lt;/a&gt; è il sistema operativo che ho selezionato per dare nuova vita al mio PowerBook G4.&lt;/p&gt;

&lt;p&gt;OpenBSD è un sistema operativo libero, open-source, multipiattaforma, di tipo unix-like, derivato dalla &lt;a href="https://it.wikipedia.org/wiki/Berkeley_Software_Distribution"&gt;Berkeley Software Distribution (4.4BSD)&lt;/a&gt;. Il team di sviluppo di questo sistema operativo concentra gli sforzi per offrire: &lt;a href="https://www.openbsd.org/plat.html"&gt;massima portabilità&lt;/a&gt;, standardizzazione, sicurezza pro-attiva e la crittografia integrata. I motivi principali della mia scelta sono:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;grande esperienza di sistema operativo BSD. Sono arrivati alla 50° release, distribuita a maggio del 2021;&lt;/li&gt;
&lt;li&gt;supporto per le piattaforme hardware PowerPC ( &lt;strong&gt;anche sulle nuove release di OpenBSD&lt;/strong&gt; );&lt;/li&gt;
&lt;li&gt;supporto (OOTB) per l’hardware del PowerBook G4 (schede di rete LAN, scheda di rete WiFi, touch pad, etc.);&lt;/li&gt;
&lt;li&gt;grande disponibilità dei binari delle maggiori applicazioni anche per la piattaforma PowerPC;&lt;/li&gt;
&lt;li&gt;documentazione testuale e efficace.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;La versione specifica di OpenBSD è la &lt;a href="https://www.openbsd.org/68.html"&gt;6.8&lt;/a&gt; abbinata alla release song &lt;a href="https://www.openbsd.org/lyrics.html#68"&gt;Hacker People&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Sono sicuro che alcuni di voi si domanderanno qual è stato il motivo per non scegliere l’ultima versione 6.9, semplice, perchè non sono disponibili in formato binario alcuni pacchetti del &lt;a href="https://www.xfce.org/"&gt;Desktop Environment XFCE&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Introduzione alla procedura d’installazione
&lt;/h2&gt;

&lt;p&gt;Il programma di installazione di OpenBSD utilizza uno speciale &lt;a href="https://www.openbsd.org/faq/faq4.html#bsd.rd"&gt;kernel ramdisk (bsd.rd)&lt;/a&gt; che genera un ambiente live eseguito interamente in memoria. Contiene lo script di installazione e un piccolo numero di utilità necessarie per eseguire un’installazione completa. Queste utilità possono essere utili anche per il ripristino di emergenza.&lt;/p&gt;

&lt;p&gt;Il kernel ramdisk può essere avviato da diverse sorgenti ma non tutte le piattaforme supportano queste opzioni di avvio.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CD/DVD&lt;/li&gt;
&lt;li&gt;Chiavetta USB&lt;/li&gt;
&lt;li&gt;Una partizione esistente&lt;/li&gt;
&lt;li&gt;Tramite rete (&lt;a href="https://www.openbsd.org/faq/faq6.html#PXE"&gt;PXE&lt;/a&gt; o altre &lt;a href="https://man.openbsd.org/diskless"&gt;opzioni di avvio di rete&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Floppy disk&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nel caso del PowerBook G4 le strade da preferire sono senza dubbio le prime due, nel mio caso specifico ho scelto la seconda, tramite una chiavetta USB. Ho scartato la prima opzione perchè sprovvisto di CD o DVD vergini su cui masterizzare l’immagine di OpenBSD.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Preparazione all’installazione
&lt;/h2&gt;

&lt;p&gt;Prima di iniziare con il processo d’installazione vero e proprio, vale la pena considerare in anticipo alcuni aspetti che riporto a seguire, considerando il punto fermo dell’architettura.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Il nome da assegnare alla macchina, che nel mio caso sarà amusarra-pbook-g4.&lt;/li&gt;
&lt;li&gt;Il metodo d’installazione che in questo caso è proprio Install (tra le altre possibili scelte Upgrade, Auto Install e Shell).&lt;/li&gt;
&lt;li&gt;Il layout del disco desiderato. Nel mio caso ho scelto che &lt;strong&gt;su questa macchina sarà installato solo OpenBSD&lt;/strong&gt; e utilizzerò quindi il layout del disco di default. Per ogni approfondimento sul tema, consiglio la lettura &lt;a href="https://www.openbsd.org/faq/faq14.html"&gt;OpenBSD FAQ – Disk Setup&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Abilitare il &lt;a href="https://en.wikipedia.org/wiki/Disk_encryption"&gt;Disk Encryption&lt;/a&gt;. Nel mio caso ho scelto di non abilitare questa funzionalità; per il tipo d’uso non è necessario e risparmio anche tempo di CPU prezioso. Per ogni approfondimento sull’argomento, consiglio la lettura &lt;a href="https://www.openbsd.org/faq/faq14.html#softraidFDE"&gt;OpenBSD Full Disk Encryption&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Setup della rete. Su questa macchina abbiamo a disposizione due schede di rete, quella LAN Ethernet (via caso) e quella WiFi. In questo caso, in fase d’installazione andrò ad impostare per la scheda di rete LAN il DHCP. Il setup della scheda WiFi può essere eseguito anche in un secondo momento.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  4. Download OpenBSD e preparazione USB Disk
&lt;/h2&gt;

&lt;p&gt;Consolidato il fatto che eseguiremo l’installazione da USB Disk, le operazioni che porteremo a termine nel corso di questo capitolo sono: download e verifica dell’immagine di OpenBSD, per finire con la creazione dell’USB Disk a partire dall’immagine scaricata in precedenza.&lt;/p&gt;

&lt;p&gt;OpenBSD mette a disposizione diverse tipologie d’immagini, quella di nostro interesse si chiama &lt;strong&gt;installXX.iso&lt;/strong&gt; (nel nostro caso &lt;a href="https://cdn.openbsd.org/pub/OpenBSD/6.8/macppc/install68.iso"&gt;install68.iso&lt;/a&gt;). Si tratta di un’immagine &lt;a href="https://it.wikipedia.org/wiki/ISO_9660"&gt;ISO 9660&lt;/a&gt; che può essere utilizzata per creare un CD/DVD e USB Disk di installazione. Include i &lt;a href="https://www.openbsd.org/faq/faq4.html#FilesNeeded"&gt;set di file&lt;/a&gt;, questo si traduce nel fatto che non sia necessaria la disponibilità di una connessione alla rete internet durante il processo d’installazione.&lt;/p&gt;

&lt;p&gt;L’immagine può quindi essere scaricata dal seguente link &lt;a href="https://cdn.openbsd.org/pub/OpenBSD/6.8/macppc/install68.iso"&gt;https://cdn.openbsd.org/pub/OpenBSD/6.8/macppc/install68.iso&lt;/a&gt;. Una volta scaricata l’immagine accertiamoci che sulla stessa non ci siano alterazioni verificando il &lt;a href="https://it.wikipedia.org/wiki/Checksum"&gt;checksum&lt;/a&gt; &lt;a href="https://it.wikipedia.org/wiki/Secure_Hash_Algorithm"&gt;SHA256&lt;/a&gt;. Esistono diverse possibilità per il controllo checksum, dipendenti in genere dal proprio sistema operativo. Nel caso di MacOS è possibile utilizzare il comando &lt;code&gt;shasum -a 256 install68.iso&lt;/code&gt;  o anche il comando &lt;code&gt;openssl sha256 install68.iso&lt;/code&gt;. Il checksum atteso per il file &lt;a href="https://cdn.openbsd.org/pub/OpenBSD/6.8/macppc/SHA256"&gt;install68.iso&lt;/a&gt;  è &lt;code&gt;da45cd5149e4d28ee20c3d06db9e1f3292760a77a176ad842bfb6a4a518df351&lt;/code&gt;. La lista degli hash SHA256 è reperibile al seguente link &lt;a href="https://cdn.openbsd.org/pub/OpenBSD/6.8/macppc/SHA256"&gt;https://cdn.openbsd.org/pub/OpenBSD/6.8/macppc/SHA256&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Per il controllo del checksum su Windows è possibile utilizzare il comando &lt;code&gt;CertUtil -hashfile install68.iso SHA256&lt;/code&gt; mentre su Linux il comando &lt;code&gt;sha256 install68.iso&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A questo punto non resta altro che trasferire l’immagine ISO install68.iso su una chiavetta USB. Le dimensioni minime per la chiavetta USB sono di 512MByte. Anche per l’esecuzione di quest’operazione esistono diversi metodi sulla base del proprio sistema operativo. Nel caso di sistemi operativi Unix-like (talvolta UN*X o *nix) è possibile utilizzare il comando &lt;a href="https://it.wikipedia.org/wiki/Dd_(Unix)"&gt;dd&lt;/a&gt;. Per il comando &lt;code&gt;dd&lt;/code&gt; potrebbero esserci leggere differenze tra i vari sistemi operativi, consiglio infatti, di far sempre riferimento alla documentazione specifica accessibile tramite il comando &lt;code&gt;man dd&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Utilizzando il comando &lt;code&gt;dd if=install68.iso of=/dev/disk2 bs=1m&lt;/code&gt; quello che otterremo è una chiavetta USB da cui saremo in grado di avviare l’installazione di OpenBSD versione 6.8. Il nome del device specificato sul parametro &lt;code&gt;of&lt;/code&gt;, può essere diverso in base al proprio sistema, nel mio caso la chiavetta USB è mappata sul device &lt;code&gt;/dev/disk2&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Nel caso il proprio sistema operativo sia Windows, allora potreste utilizzare l’utility &lt;a href="https://rufus.ie/en/"&gt;Rufus&lt;/a&gt;, &lt;a href="https://www.balena.io/etcher/"&gt;balenaEtcher&lt;/a&gt; o anche il comando dd nel caso abbiate &lt;a href="https://gitforwindows.org/"&gt;GitBash&lt;/a&gt; (&lt;a href="https://dev.to/theyarin/burning-an-image-on-a-usb-flash-drive-from-a-windows-machine-using-git-bash-414i"&gt;Burning an image on a USB flash drive from a Windows machine using Git Bash&lt;/a&gt;). La figura a seguire mostra l’output dell’esecuzione del comando dd per la creazione del disco USB dall’immagine per l’installazione di OpenBSD 6.8.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/08/create_usb_disk_image_opensbd_dd.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yMX80G84--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/08/create_usb_disk_image_opensbd_dd.png" alt="Figura 1 - Creazione del disco USB dell'immagine OpenBSD 6.8 per l'installazione" title="Figura 1 - Creazione del disco USB dell'immagine OpenBSD 6.8 per l'installazione"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 1 – Creazione del disco USB dell’immagine OpenBSD 6.8 per l’installazione&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Boot in modalità Open Firmware
&lt;/h2&gt;

&lt;p&gt;Per poter installare OpenBSD sul nostro Apple PowerBook G4, dobbiamo avviare quest’ultimo in modalità &lt;a href="https://it.wikipedia.org/wiki/Open_Firmware"&gt;&lt;strong&gt;Open Firmware&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Open Firmware è una tecnologia hardware per sviluppare firmware indipendente dal sistema operativo (software caricato all’accensione del computer prima del sistema operativo) sviluppata da Sun Microsystems. È utilizzata nei computer Apple Macintosh dotati di processori PowerPC, nelle workstation SPARC e nei server della Sun Microsystems, nei computer PegasosPPCe in altri sistemi (fonte Wikipedia).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Prima di accendere la macchina ricordate d’inserire il disco USB su una delle due porte USB a disposizione e di connetterla alla vostra rete tramite cavo ethernet (non richiesto ma consigliato). Personalmente ho inserito il disco sulla prima porta, per cui il dispositivo sarà identificato con &lt;code&gt;usb0&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Per accedere a Open Firmware, occorre premere la combinazione dei tasti, &lt;strong&gt;Command(⌘) + Option(⌥) + O + F&lt;/strong&gt;, immediatamente all’avvio. Dopo qualche secondo dovreste vedere a schermo quando mostrato dalla figura a seguire.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/08/install_openbsd_68_on_powerbook_g4_openfirmware_1-scaled.jpg"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Q_xQvFrX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/08/install_openbsd_68_on_powerbook_g4_openfirmware_1-scaled.jpg" alt="Figura 2 - Avvio del PowerBook G4 in modalità Open Firmware" title="Figura 2 - Avvio del PowerBook G4 in modalità Open Firmware"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 2 – Avvio del PowerBook G4 in modalità Open Firmware&lt;/p&gt;

&lt;p&gt;Open Firmware è accessibile utilizzando un’interfaccia di tipo shell basata sul &lt;a href="https://it.wikipedia.org/wiki/Forth_(linguaggio)"&gt;Forth&lt;/a&gt;, un potente linguaggio ad alto livello, descritto nel documento &lt;a href="https://standards.ieee.org/standard/1275-1994.html"&gt;IEEE 1275-1994 – IEEE Standard for Boot (Initialization Configuration) Firmware&lt;/a&gt;. Grazie a questa shell possiamo impartire tutti i comandi necessari per avviare l’installazione di OpenBSD.&lt;/p&gt;

&lt;p&gt;Se volessimo verificare che il disco USB sia correttamente visto dal sistema, potremmo digitare il comando &lt;code&gt;devalias&lt;/code&gt;, dall’output dovremmo essere in grado d’identificare com’è stato mappato il disco USB. Le figura a seguire mostra un esempio del comando.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/08/install_openbsd_68_on_powerbook_g4_openfirmware_devalias_1-scaled.jpg"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--07GNcrmZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/08/install_openbsd_68_on_powerbook_g4_openfirmware_devalias_1-scaled.jpg" alt="Figura 3 - Uso del comando devalias per identificare la porta USB dove abbiamo collegato la chiavetta USB" title="Figura 3 - Uso del comando devalias per identificare la porta USB dove abbiamo collegato la chiavetta USB"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 3 – Uso del comando devalias per identificare la porta USB dove abbiamo collegato la chiavetta USB&lt;/p&gt;

&lt;p&gt;La figura successiva mostra invece l’uso del comando &lt;code&gt;dir usb0/disk@1:\&lt;/code&gt; e &lt;code&gt;dir usb0/disk@1: \6.8\macppc&lt;/code&gt; al fine di verificare che il contenuto sia quello desiderato.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/08/install_openbsd_68_on_powerbook_g4_openfirmware_dir_usb0_1-scaled.jpg"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Q21xZemu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/08/install_openbsd_68_on_powerbook_g4_openfirmware_dir_usb0_1-scaled.jpg" alt="Figura 4 - Utilizzo del comando dir per verificare il contenuto della chiavetta USB contenente l'immagine install68.iso" title="Figura 4 - Utilizzo del comando dir per verificare il contenuto della chiavetta USB contenente l'immagine install68.iso"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 4 – Utilizzo del comando dir per verificare il contenuto della chiavetta USB contenente l’immagine install68.iso&lt;/p&gt;

&lt;p&gt;Il programma bootstrap di OpenBSD si chiama &lt;strong&gt;ofwboot&lt;/strong&gt; , che avvierà poi il bsd.rd, il &lt;a href="https://www.openbsd.org/faq/faq4.html#bsd.rd"&gt;ramdisk Kernel&lt;/a&gt;. Dalla shell di OpenFirmware occorre eseguire il comando &lt;code&gt;boot usb0/disk@1:,ofwboot /6.8/macppc/bsd.rd&lt;/code&gt; per iniziare l’installazione di OpenBSD.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/08/install_openbsd_68_on_powerbook_g4_openfirmware_boot_opensbd_68_1-scaled.jpg"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HkjyWFgE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/08/install_openbsd_68_on_powerbook_g4_openfirmware_boot_opensbd_68_1-scaled.jpg" alt="Figura 5 - Boot OpenBSD Installer" title="Figura 5 - Boot OpenBSD Installer"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 5 – Boot OpenBSD Installer&lt;/p&gt;

&lt;p&gt;Se tutto è andato per il verso giusto, si dovrebbe avviare il boot loader che a sua volta avvierà il ramdisk Kernel dal file bsd.rd. Al termine del caricamento del Kernel, potremo procedere con la fase d’installazione di OpenBSD.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Installazione di OpenBSD
&lt;/h2&gt;

&lt;p&gt;A questo punto siamo davvero pronti per proseguire con l’installazione di OpenBSD. Gli step a seguire riguardano:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;la scelta del tipo d’installazione, in questo caso optiamo per la voce (I)stall (vedi Figura 6);&lt;/li&gt;
&lt;li&gt;la scelta dell’hostname da assegnare alla macchina, che nel mio caso imposterò a amusarra-pbook-g4 (vedi Figura 7);&lt;/li&gt;
&lt;li&gt;la scelta della scheda di rete da configurare. Questo step è opzionale (digitando done quando richiesto), le schede possono essere configurate successivamente. Personalmente ho scelto di configurare in questa fase la scheda ethernet (gem0 il su nome) via DHCP (vedi Figura 8);&lt;/li&gt;
&lt;li&gt;impostazione della password di root;&lt;/li&gt;
&lt;li&gt;scegliere se far partire il servizio SSH di default (si per default), personalmente ho scelto di si;&lt;/li&gt;
&lt;li&gt;scegliere se abilitare X Window System (si per default), personalmente ho scelto di si;&lt;/li&gt;
&lt;li&gt;scegliere se abilitare il login grafico via xenodm (no per default), personalmente ho scelto no;&lt;/li&gt;
&lt;li&gt;la creazione di un nuovo utente. Consiglio sempre di eseguire questo step, personalmente ho scelto di creare l’utente amusarra;&lt;/li&gt;
&lt;li&gt;Scegliere se consentire la login all’utente root via SSH (no per default), personalmente ho scelto no, scelta fatta anche in termini di sicurezza;&lt;/li&gt;
&lt;li&gt;scegliere il timezone. Nel mio caso Europe/Rome;&lt;/li&gt;
&lt;li&gt;scegliere il disco dove installare OpenBSD. Nel mio caso specifico il disco di destinazione sarà wd0. Nella maggior parte dei sistemi BSD, i dispositivi di storage di massa di tipo IDE-like hanno il naming &lt;a href="https://man.openbsd.org/wd"&gt;wd&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;scegliere se utilizzare tutto il disco o parte di esso. In questo caso, dove abbiamo deciso di avere il solo OpenBSD come sistema operativo, la scelta è di utilizzare tutto il disco, quindi (W)hole disk;&lt;/li&gt;
&lt;li&gt;scegliere o modificare il layout del file system. Come scritto in precedenza, a meno di particolari esigenze, consiglio di selezione il layout automatico (A)uto layout (vedi Figura 9);&lt;/li&gt;
&lt;li&gt;scegliere la locazione per &lt;a href="https://www.openbsd.org/faq/faq4.html#FilesNeeded"&gt;set di file&lt;/a&gt; che in questo caso risiedo all’interno della chiavetta USB che OpenBSD ha mappato sul dispositivo sd0. Alle domande rispondere in ordine: disk, no, sd0 (valore di default), 6.8/macppc (valore di default)&lt;/li&gt;
&lt;li&gt;scegliere il set di pacchetti da installare. Personalmente ho scelto d’installare tutti i pacchetti. Dopo la selezione dei pacchetti sarà chiesto se eseguire la verifica di questi, step che si può evitare rispondendo yes alla domanda (vedi Figura 10).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Una volta che il processo d’installazione è terminato, dobbiamo riavviare la macchina nella modalità Open Firmware (e ormai sappiamo come si fa), per impostare OpenBSD in auto-boot (vedi Figura 11). È possibile fare ciò utilizzando i seguenti due comandi: &lt;code&gt;setenv auto-boot? true&lt;/code&gt; e &lt;code&gt;setenv boot-device hd:,ofwboot&lt;/code&gt;. L’ultimo comando &lt;code&gt;reset-all&lt;/code&gt; salva le impostazioni sulla &lt;a href="https://support.apple.com/en-gb/HT204063"&gt;NVRAM (nonvolatile random-access memory)&lt;/a&gt;. Quest’ultimo comando riavvierà la macchina che dovrebbe da adesso in poi partire con OpenBSD 6.8 &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wETKQQS---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s.w.org/images/core/emoji/13.0.1/72x72/1f642.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wETKQQS---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s.w.org/images/core/emoji/13.0.1/72x72/1f642.png" alt="🙂"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;La sequenza delle figure a seguire mostra gli step d’installazione più significativi descritti in precedenza.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/08/install_openbsd_68_on_powerbook_g4_step_1-scaled.jpg"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pzqnl70f--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/08/install_openbsd_68_on_powerbook_g4_step_1-scaled.jpg" alt="Figura 6 - Step 1 =&amp;gt; Selezione del tipo d'installazione" title="Figura 6 - Step 1 =&amp;gt; Selezione del tipo d'installazione"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 6 – Step 1 =&amp;gt; Selezione del tipo d’installazione&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/08/install_openbsd_68_on_powerbook_g4_step_2-scaled.jpg"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xWGNJSH_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/08/install_openbsd_68_on_powerbook_g4_step_2-scaled.jpg" alt="Figura 7 - Step 2 =&amp;gt; Impostazione del nome host" title="Figura 7 - Step 2 =&amp;gt; Impostazione del nome host"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 7 – Step 2 =&amp;gt; Impostazione del nome host&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/08/install_openbsd_68_on_powerbook_g4_step_3-scaled.jpg"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ia6MZVvE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/08/install_openbsd_68_on_powerbook_g4_step_3-scaled.jpg" alt="Figura 8 - Step 3 =&amp;gt; Configurazione Networking"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 8 – Step 3 =&amp;gt; Configurazione Networking&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/08/install_openbsd_68_on_powerbook_g4_step_13-scaled.jpg"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pbxiVB8t--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/08/install_openbsd_68_on_powerbook_g4_step_13-scaled.jpg" alt="Figura 9 Step 13 =&amp;gt; Configurazione dei layout file system per l'installazione di OpenBSD" title="Figura 9 Step 13 =&amp;gt; Configurazione dei layout file system per l'installazione di OpenBSD"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 9 Step 13 =&amp;gt; Configurazione dei layout file system per l’installazione di OpenBSD&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/08/install_openbsd_68_on_powerbook_g4_step_14_15-scaled.jpg"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---VVoHGNm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/08/install_openbsd_68_on_powerbook_g4_step_14_15-scaled.jpg" alt="Figura 10 - Step 14-15 Installazione del set file di OpenBSD" title="Figura 10 - Step 14-15 Installazione del set file di OpenBSD"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 10 – Step 14-15 Installazione del set file di OpenBSD&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/08/install_openbsd_68_on_powerbook_g4_openfirmware_set_boot_device_1-scaled.jpg"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--c-fM6kTE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/08/install_openbsd_68_on_powerbook_g4_openfirmware_set_boot_device_1-scaled.jpg" alt="Figura 11 - Impostazione del boot device di default per far avviare OpenBSD come impostazione predefinita" title="Figura 11 - Impostazione del boot device di default per far avviare OpenBSD come impostazione predefinita"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 11 – Impostazione del boot device di default per far avviare OpenBSD come impostazione predefinita&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Il primo avvio di OpenBSD
&lt;/h2&gt;

&lt;p&gt;Il primo avvio di OpenBSD appena installato, fa un pochino di cose, alcune delle quali: generazione delle chiavi RSA per il servizio SSH ma cosa ancora più importante, l’installazione dei firmware addizionali, in questo caso installerà il bwi-firmware, necessario per far funzionare la scheda di rete WiFi.&lt;/p&gt;

&lt;p&gt;L’installazione dei firmware aggiuntivi è eseguita scaricando quest’ultimi dalla rete, è quindi necessario che la macchina sia connessa alla rete. In ogni caso è possibile installarli successivamente utilizzando il comando &lt;a href="https://man.openbsd.org/fw_update"&gt;fw_update&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/08/install_openbsd_68_on_powerbook_g4_first_start-scaled.jpg"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EUexmbyV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/08/install_openbsd_68_on_powerbook_g4_first_start-scaled.jpg" alt="Figura 12 - Primo avvio di OpenBSD" title="Figura 12 - Primo avvio di OpenBSD"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 12 – Primo avvio di OpenBSD&lt;/p&gt;

&lt;p&gt;Il nostro OpenBSD è praticamente pronto all’uso, consiglio comunque il setup della scheda WiFi per connettervi alla rete internet tramite il vostro Router WiFi. La procedura è veramente semplice e ben descritta all’interno della sezione &lt;a href="https://www.openbsd.org/faq/faq6.html#Wireless"&gt;Wireless Networking&lt;/a&gt; della documentazione di OpenBSD.&lt;/p&gt;

&lt;p&gt;Gli step di configurazione prevedono i seguenti step:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;verifica che la scheda di rete WiFi sia vista correttamente da OpenBSD. Per accertarsi di ciò, basta eseguire il comando &lt;code&gt;if config bwi0 media&lt;/code&gt;. Il nome dispositivo assegnato dovrebbe essere quello indicato dal comando; in caso di problemi eseguire il comando ifconfig senza argomenti per verificare il nome esatto del dispositivo. La Figura 13 mostra l’output del comando;&lt;/li&gt;
&lt;li&gt;creazione del file /etc/hostname.bwi0 il cui contenuto è mostrato in Figura 14;&lt;/li&gt;
&lt;li&gt;riavvio della macchina o restart del servizio di network per applicare le modifiche. Per eseguire il restart del network, lanciare il comando &lt;code&gt;sh /etc/netstart&lt;/code&gt; (vedi Figura 15). La Figura 16 mostra lo stato della scheda WiFi dopo la connessione avvenuta con successo al Router WiFi.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/08/install_openbsd_68_on_powerbook_g4_wifi_config_1-scaled.jpg"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mQ4FP28Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/08/install_openbsd_68_on_powerbook_g4_wifi_config_1-scaled.jpg" alt="Figura 13 - Output del comando ifconfig sulla scheda WiFi con lo scopo di verificare che sia correttamente vista da OpenBSD" title="Figura 13 - Output del comando ifconfig sulla scheda WiFi con lo scopo di verificare che sia correttamente vista da OpenBSD"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 13 – Output del comando ifconfig sulla scheda WiFi con lo scopo di verificare che sia correttamente vista da OpenBSD&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/08/install_openbsd_68_on_powerbook_g4_wifi_config_2.jpg"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lCpuzGyW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/08/install_openbsd_68_on_powerbook_g4_wifi_config_2.jpg" alt="Figura 14 - Creazione del file /etc/hostname.bwi0 per la configurazione di connessione della schede WiFi al Router WiFi" title="Figura 14 - Creazione del file /etc/hostname.bwi0 per la configurazione di connessione della schede WiFi al Router WiFi"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 14 – Creazione del file /etc/hostname.bwi0 per la configurazione di connessione della schede WiFi al Router WiFi&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/08/install_openbsd_68_on_powerbook_g4_wifi_config_3.jpg"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wuNh-02o--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/08/install_openbsd_68_on_powerbook_g4_wifi_config_3.jpg" alt="Figura 15 - Restart della rete per applicare le modifiche alla configurazione delle scheda WiFi" title="Figura 15 - Restart della rete per applicare le modifiche alla configurazione delle scheda WiFi"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 15 – Restart della rete per applicare le modifiche alla configurazione delle scheda WiFi&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/08/install_openbsd_68_on_powerbook_g4_wifi_config_4-scaled.jpg"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1PA6skKC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/08/install_openbsd_68_on_powerbook_g4_wifi_config_4-scaled.jpg" alt="Figura 16 - Esecuzione del comando ifconfig dopo l'applicazione della configurazione per la scheda WiFi" title="Figura 16 - Esecuzione del comando ifconfig dopo l'applicazione della configurazione per la scheda WiFi"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 16 – Esecuzione del comando ifconfig dopo l’applicazione della configurazione per la scheda WiFi&lt;/p&gt;

&lt;h2&gt;
  
  
  8. E adesso tocca a voi
&lt;/h2&gt;

&lt;p&gt;In questo articolo ho voluto mostrare la mia personale esperienza nell’attività di far risuscitare il mio Apple PowerBook G4 da anni e anni di riposo installando OpenBSD. L’operazione in fin dei conti non è stata affatto complicata, forse lo potrà essere per coloro che non sono avvezzi a questo tipo di strumenti a “basso livello”; lo scopo dell’articolo è anche quello di rendere semplice l’installazione anche per i non avvezzi.&lt;/p&gt;

&lt;p&gt;Se siete arrivati fino a questo punto della lettura, immagino che vi siate trovati nella stessa situazione o magari vorreste intraprendere quest’attività sulla vostra macchina. Vi lascio i commenti per descrivere la vostra esperienza o se avete domande in merito.&lt;/p&gt;

&lt;p&gt;Un buon inizio di avventura con OpenBSD &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UdUWSYhT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s.w.org/images/core/emoji/13.0.1/72x72/1f609.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UdUWSYhT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s.w.org/images/core/emoji/13.0.1/72x72/1f609.png" alt="😉"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/08/install_openbsd_68_on_powerbook_g4_welcome_1-scaled.jpg"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MrjKuYuc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/08/install_openbsd_68_on_powerbook_g4_welcome_1-scaled.jpg" alt="Benvenuti in OpenBSD 6.8 su Apple PowerBook G4" title="Benvenuti in OpenBSD 6.8 su Apple PowerBook G4"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Benvenuti in OpenBSD 6.8 su Apple PowerBook G4&lt;/p&gt;

&lt;p&gt;L'articolo &lt;a href="https://www.dontesta.it/2021/08/24/apple-powerbook-g4-la-rinascita-grazie-a-openbsd/"&gt;Apple PowerBook G4: La rinascita grazie a OpenBSD&lt;/a&gt; sembra essere il primo su &lt;a href="https://www.dontesta.it"&gt;Antonio Musarra's Blog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://feeds.feedburner.com/~ff/dontesta/blog?a=5wg3fTQKCMs:GuuDS3uIgDM:yIl2AUoC8zA"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ly8gdBSb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Eff/dontesta/blog%3Fd%3DyIl2AUoC8zA" alt=""&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/dontesta/blog?a=5wg3fTQKCMs:GuuDS3uIgDM:dnMXMwOfBR0"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PziyOv7j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Eff/dontesta/blog%3Fd%3DdnMXMwOfBR0" alt=""&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/dontesta/blog?a=5wg3fTQKCMs:GuuDS3uIgDM:D7DqB2pKExk"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OsePZFPd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Eff/dontesta/blog%3Fi%3D5wg3fTQKCMs:GuuDS3uIgDM:D7DqB2pKExk" alt=""&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/dontesta/blog?a=5wg3fTQKCMs:GuuDS3uIgDM:YwkR-u9nhCs"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DCS1IRW9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Eff/dontesta/blog%3Fd%3DYwkR-u9nhCs" alt=""&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/dontesta/blog?a=5wg3fTQKCMs:GuuDS3uIgDM:F7zBnMyn0Lo"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--d_zpGR-N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Eff/dontesta/blog%3Fi%3D5wg3fTQKCMs:GuuDS3uIgDM:F7zBnMyn0Lo" alt=""&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/dontesta/blog?a=5wg3fTQKCMs:GuuDS3uIgDM:V_sGLiPBpWU"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Neu3VHNH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Eff/dontesta/blog%3Fi%3D5wg3fTQKCMs:GuuDS3uIgDM:V_sGLiPBpWU" alt=""&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/dontesta/blog?a=5wg3fTQKCMs:GuuDS3uIgDM:qj6IDK7rITs"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lg7sfzlZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Eff/dontesta/blog%3Fd%3Dqj6IDK7rITs" alt=""&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/dontesta/blog?a=5wg3fTQKCMs:GuuDS3uIgDM:KwTdNBX3Jqk"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dx52vg-Y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Eff/dontesta/blog%3Fi%3D5wg3fTQKCMs:GuuDS3uIgDM:KwTdNBX3Jqk" alt=""&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/dontesta/blog?a=5wg3fTQKCMs:GuuDS3uIgDM:gIN9vFwOqvQ"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--S6Bab5K_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Eff/dontesta/blog%3Fi%3D5wg3fTQKCMs:GuuDS3uIgDM:gIN9vFwOqvQ" alt=""&gt;&lt;/a&gt;&lt;br&gt;
 &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MScw913E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Er/dontesta/blog/%257E4/5wg3fTQKCMs" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MScw913E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Er/dontesta/blog/%257E4/5wg3fTQKCMs" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>blog</category>
      <category>operatingsystems</category>
      <category>apple</category>
      <category>bsd</category>
    </item>
    <item>
      <title>Come ottenere una CIE funzionante su Fedora 34</title>
      <dc:creator>Antonio Musarra</dc:creator>
      <pubDate>Mon, 09 Aug 2021 21:37:11 +0000</pubDate>
      <link>https://dev.to/amusarra/come-ottenere-una-cie-funzionante-su-fedora-34-25kb</link>
      <guid>https://dev.to/amusarra/come-ottenere-una-cie-funzionante-su-fedora-34-25kb</guid>
      <description>&lt;p&gt;Finalmente il 26 luglio 2021 ho ottenuto la mia &lt;a href="https://developers.italia.it/it/cie/"&gt;&lt;strong&gt;CIE (Carta d’Identità Elettronica)&lt;/strong&gt;&lt;/a&gt; rilasciata dal Comune di Marino (RM). Appena arrivato a casa non ho perso un attimo e ho collegato il mio lettore &lt;a href="https://shop.bit4id.com/prodotto/minilector-cie/?utm_source=ref_blog&amp;amp;utm_medium=post&amp;amp;utm_campaign=ref_dontesta&amp;amp;utm_content=v1"&gt;&lt;strong&gt;miniLector CIE&lt;/strong&gt;&lt;/a&gt; di &lt;a href="https://www.bit4id.com/it/"&gt;Bit4id&lt;/a&gt; alla mia &lt;a href="https://www.dontesta.it/2021/05/23/la-mia-workstation-di-sviluppo-da-smart-worker/"&gt;Workstation da Smart Worker&lt;/a&gt; iniziando a fare i primi test.&lt;/p&gt;

&lt;p&gt;In questo articolo vedremo come eseguire il setup del software necessario al corretto funzionamento della CIE su sistema operativo &lt;a href="https://getfedora.org/it/workstation/download/"&gt;Fedora 34&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Affinché sia possibile utilizzare la CIE, indipendentemente dal fatto che la usiate per accedere ai servizi della Pubblica Amministrazione, è necessario disporre di un lettore di Smart Card compatibile e del software d’interfaccia tra l’hardware e il sistema operativo. Nel mio caso dispongo dei seguenti “pezzi”:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;lettore di Smart Card &lt;a href="https://shop.bit4id.com/prodotto/minilector-cie/?utm_source=ref_blog&amp;amp;utm_medium=post&amp;amp;utm_campaign=ref_dontesta&amp;amp;utm_content=v1"&gt;&lt;strong&gt;miniLector CIE&lt;/strong&gt;&lt;/a&gt; di &lt;a href="https://www.bit4id.com/it/"&gt;Bit4id&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;sistema operativo Fedora 34.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Per quel che concerne il lettore di Smart Card, non sono richieste caratteristiche specifiche, è sufficiente che sia conforme allo standard internazionale &lt;a href="https://it.wikipedia.org/wiki/PC/SC"&gt;&lt;strong&gt;PC/SC&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;(Personal Computer/Smart Card)&lt;/strong&gt; e alla norma &lt;strong&gt;&lt;a href="https://it.wikipedia.org/wiki/ISO/IEC_7816"&gt;ISO 7816-3&lt;/a&gt;&lt;/strong&gt;, e che sia compatibile con i più comuni sistemi operativi come Windows, Mac OS e Linux/Unix. La &lt;strong&gt;caratteristica&lt;/strong&gt;  &lt;strong&gt;fondamentale da prendere in considerazione&lt;/strong&gt;  è il supporto per il protocollo standard &lt;strong&gt;&lt;a href="https://en.wikipedia.org/wiki/CCID_(protocol)"&gt;CCID&lt;/a&gt; (Chip Card Interface Device)&lt;/strong&gt;. Il lettore in mio possesso è compatibile con lo standard CCID, non sarà quindi necessario installare i driver proprietari del lettore; i driver generici CCID sono in grado di far funzionare correttamente il lettore.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Verifica e installazione del software
&lt;/h2&gt;

&lt;p&gt;La prima di verifica da eseguire consiste nell’accertarsi che il lettore di Smart Card sia correttamente visto dal sistema operativo. Fare questo tipo di controllo è abbastanza semplice, basta eseguire da terminale il comando &lt;code&gt;lsusb&lt;/code&gt;. Dall’output del comando dovremmo essere in grado d’identificare il nostro lettore di Smart Card. La figura a seguire mostra l’esempio del mio lettore collegato alla mia workstation Fedora 34. Il nome “tecnico” del lettore Smart Card in uso è &lt;strong&gt;BIT4I miniLector AIR NFC v3&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/08/linux_fedora_smart_card_cie_lsusb.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9Nwxc7h4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/08/linux_fedora_smart_card_cie_lsusb.png" alt="Figura 1 - Controllo che il lettore Smart Card sia visibile a livello di Sistema Operativo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 1 – Controllo che il lettore Smart Card sia visibile a livello di Sistema Operativo&lt;/p&gt;

&lt;p&gt;Se volessimo ottenere più informazioni riguardo il nostro lettore, potremmo usare il comando lsusb in questa forma: &lt;code&gt;lsusb -v -s 3:6&lt;/code&gt;. Lo switch &lt;em&gt;-s&lt;/em&gt; del comando, consente di specificare il dispositivo identificato tramite il bus e il device id, in questo caso rispettivamente 3 e 6. La figura a seguire mostra un estratto del comando precedente.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/08/linux_fedora_smart_card_cie_lsusb_verbos.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tatM1_T5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/08/linux_fedora_smart_card_cie_lsusb_verbos.png" alt="Figura 2 - Dettagli hardware sul lettore Smart Card connesso"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 2 – Dettagli hardware sul lettore Smart Card connesso&lt;/p&gt;

&lt;p&gt;Una volta sicuri del fatto che il nostro lettore sia visto correttamente dal sistema operativo, allora, sarà possibile procedere con l’installazione del software della CIE. Questo software o middleware, consente di utilizzare la Carta d’Identità Elettronica per l’accesso sicuro in rete ai servizi web erogati dalla Pubblica Amministrazione da un PC mediante lo schema d’identificazione &lt;strong&gt;Entra con CIE&lt;/strong&gt; , i cui dettagli sono riportati sul sito del &lt;a href="https://www.cartaidentita.interno.gov.it/identificazione-digitale/entra-con-cie/"&gt;Ministero dell’Interno&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Il middleware CIE è una libreria software che implementa le interfacce crittografiche standard &lt;a href="https://en.wikipedia.org/wiki/PKCS_11"&gt;&lt;strong&gt;PKCS#11&lt;/strong&gt;&lt;/a&gt; e &lt;a href="https://docs.microsoft.com/en-us/windows/win32/seccrypto/microsoft-cryptographic-service-providers"&gt;&lt;strong&gt;CSP&lt;/strong&gt;&lt;/a&gt;. Esso consente agli applicativi integranti di utilizzare il certificato di autenticazione e la relativa chiave privata memorizzati sul chip della CIE astraendo dalle modalità di comunicazione di basso livello.&lt;/p&gt;

&lt;p&gt;L’ultima versione del middleware è la 1.4.1 di cui è possibile scaricare il file &lt;a href="https://github.com/italia/cie-middleware-linux/releases/download/1.4.1/cie-middleware-1.4.1.rpm"&gt;RPM&lt;/a&gt; pronto per poter essere installato sulla nostra Fedora 34. L’installazione è davvero semplice, basta eseguire il comando: &lt;code&gt;sudo rpm -i cie-middleware-1.4.1.rpm&lt;/code&gt;. La figura a seguire mostra i file che il comando precedente installa. Sono evidenziati in particolare il file che implementa le API dello standard PKCS#11 e il file dell’applicazione desktop. L’applicazione desktop consente di gestire la CIE in termini di PIN, PUK, associazioni CIE e funzionalità di &lt;strong&gt;Firma Elettronica Avanzata (FEA)&lt;/strong&gt;. La firma elettronica calcolata con la Carta d’Identità Elettronica è a tutti gli effetti una Firma Elettronica Avanzata, disciplinata all’interno del DPCM 22/02/2013, articolo 61.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/08/linux_fedora_smart_card_cie_install_rpm.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Op-lY6R---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/08/linux_fedora_smart_card_cie_install_rpm.png" alt="Figura 3 - Lista dei file installati via RPM del middleware CIE"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 3 – Lista dei file installati via RPM del middleware CIE&lt;/p&gt;

&lt;p&gt;Una volta installato il middleware CIE, possiamo eseguire un semplice test di lettura della propria CIE utilizzando il comando che fa parte della suite PKCS#11. Appoggiate quindi la CIE sul lettore e lanciate questo comando: &lt;code&gt;pkcs11-tool --module /usr/local/lib/libcie-pkcs11.so -I -L&lt;/code&gt;. Quello che il comando restituirà, saranno informazioni circa: il modulo PKCS#11, il lettore utilizzato e il token, che rappresenta la CIE vera e propria. La figura a seguire mostra l’output del comando che riguarda il mio lettore e CIE.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/08/linux_fedora_smart_card_cie_pkcs_11_test.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lhu49Huk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/08/linux_fedora_smart_card_cie_pkcs_11_test.png" alt="Figura 4 - Estrazione informazioni di dettaglio su lettore Smart Card e CIE via PCKS#11 tool"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 4 – Estrazione informazioni di dettaglio su lettore Smart Card e CIE via PCKS#11 tool&lt;/p&gt;

&lt;p&gt;Arrivati a questo punto, manca davvero pochissimo per utilizzare la CIE come mezzo di accesso ai servizi della Pubblica Amministrazione. Il prossimo passo da seguire è quello che viene definito &lt;strong&gt;abbinamento&lt;/strong&gt; e può essere portato a termine utilizzando l’applicazione &lt;strong&gt;CIE ID&lt;/strong&gt;. Per l’esecuzione di questo passo di configurazione vi lascio alla lettura del capitolo &lt;a href="https://github.com/italia/cie-middleware-linux/releases/download/1.4.0/CIE.3.0.-.Manuale.d.uso.del.middleware.Linux.pdf"&gt;5. Primo utilizzo della CIE&lt;/a&gt; del manuale software CIE per Linux. Portato a termine il passo di abbinamento, il passo finale è la configurazione del browser per fare in modo che sia in grado di poter accedere alla CIE attraverso il lettore. Nel mio caso ho configurato Firefox e sul sito del Ministero dell’Interno è possibile trovare la guida completa su &lt;a href="https://idserver.servizicie.interno.gov.it/idp/tutorial/computer/lettoreusb/linux/tutorial_linux_firefox.jsp"&gt;come configurare il lettore di Smart Card&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Come usare la CIE con il progetto CIE/CNS Apache Docker
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;“&lt;/strong&gt;** L’utente normale”** utilizzerebbe la sua CIE per accedere ai servizi della Pubblica Amministrazione, gente come noi, oltre a questo vorrebbe sperimentare altro.&lt;/p&gt;

&lt;p&gt;Tre anni or sono ho pubblicato come &lt;a href="https://developers.italia.it/"&gt;Developers Italia&lt;/a&gt; il progetto &lt;a href="https://github.com/italia/cie-cns-apache-docker"&gt;&lt;strong&gt;CIE/CNS Apache Docker&lt;/strong&gt;&lt;/a&gt;. L’obiettivo di questo progetto è quello di fornire un  &lt;strong&gt;template&lt;/strong&gt;  pronto all’uso che realizza un sistema di autenticazione tramite la Smart Card  &lt;strong&gt;TS-CNS&lt;/strong&gt;  (o CNS) e la  &lt;strong&gt;CIE&lt;/strong&gt;  (Carta d’Identità Elettronica) basato su &lt;a href="http://httpd.apache.org/docs/2.4/"&gt;Apache HTTP&lt;/a&gt;. Si tratta di un progetto &lt;a href="https://www.docker.com/"&gt;docker&lt;/a&gt; per la creazione di un container che implementa un sistema di  &lt;strong&gt;mutua autenticazione o autenticazione bilaterale SSL/TLS&lt;/strong&gt;. Questo meccanismo di autenticazione richiede anche il certificato digitale da parte del client, certificato che in questo caso risiede all’interno della TS-CNS o della CIE. Questo progetto è nato ancor prima di quello che viene definito &lt;a href="https://www.cartaidentita.interno.gov.it/identificazione-digitale/entra-con-cie/"&gt;&lt;strong&gt;Entra con CIE&lt;/strong&gt;&lt;/a&gt; e basato su &lt;a href="https://it.wikipedia.org/wiki/Security_Assertion_Markup_Language"&gt;SAML&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;La particolarità del sistema implementato (attraverso questo container) è quella di consentire l’autenticazione tramite:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;la &lt;strong&gt;TS-CNS (Tessera Sanitaria – Carta Nazionale Servizi)&lt;/strong&gt;, rilasciata dalla regione di appartenenza;&lt;/li&gt;
&lt;li&gt;la &lt;strong&gt;CIE (Carta d’Identità Elettronica)&lt;/strong&gt;, rilasciata dal comune di residenza.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Il progetto è stato costruito in modo che consenta l’accesso a certificati che sono riconducibili esclusivamente a TS-CNS o CIE, inoltre esegue il controllo di revoca sfruttando il protocollo &lt;a href="https://it.wikipedia.org/wiki/Online_Certificate_Status_Protocol"&gt;&lt;strong&gt;OCSP&lt;/strong&gt;&lt;/a&gt;. Uno dei possibili utilizzi è come &lt;strong&gt;Reverse Proxy di autenticazione&lt;/strong&gt; (classico scenario &lt;a href="https://it.wikipedia.org/wiki/Single_sign-on"&gt;SSO&lt;/a&gt;); una volta avvenuta con successo l’autenticazione, le richieste posso essere passate all’applicazione di backend con l’informazione di quale sia l’identificativo dell’utente appena autenticato, che nel caso di TS-CNS e CIE è il codice fiscale. La figura a seguire mostra la pagina a cui si accede solo dopo essere stati autenticati, con evidenza i dati dell’utente presenti sulla CIE o TS-CNS (in questo caso CIE). Per maggiori informazioni consiglio la lettura del &lt;a href="https://github.com/italia/cie-cns-apache-docker/blob/master/README.markdown"&gt;README&lt;/a&gt; di progetto.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--a6yTKVP5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://github.com/italia/cie-cns-apache-docker/raw/master/images/accesso_via_cie_docker_1_4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--a6yTKVP5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://github.com/italia/cie-cns-apache-docker/raw/master/images/accesso_via_cie_docker_1_4.png" alt="Figura 5 - Accesso via CIE con visualizzazione delle informazioni di dettaglio"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figura 5 – Accesso via CIE con visualizzazione delle informazioni di dettaglio&lt;/p&gt;

&lt;p&gt;Sul mio canale YouTube potreste approfondire l’argomento seguendo il tutorial &lt;a href="https://www.youtube.com/watch?v=TcAzn1POhsM"&gt;Cos’è il progetto CIE/CNS Apache Docker – Developers Italia&lt;/a&gt; dove affronto:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Introduzione al progetto&lt;/li&gt;
&lt;li&gt;Overview su TS-CNS e CIE&lt;/li&gt;
&lt;li&gt;Cos’è la Trust Service Status List&lt;/li&gt;
&lt;li&gt;Struttura del Dockerfile&lt;/li&gt;
&lt;li&gt;Struttura del progetto&lt;/li&gt;
&lt;li&gt;Esecuzione dell’immagine Docker&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  3. Conclusioni
&lt;/h2&gt;

&lt;p&gt;In questo breve articolo vi ho voluto fare partecipi della mia prima esperienza con la mia CIE su Fedora 34. Confesso che per fare i test dei vari progetti CIE dove sono stato coinvolto, ho usato la CIE di mio nipote &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wETKQQS---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s.w.org/images/core/emoji/13.0.1/72x72/1f642.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wETKQQS---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s.w.org/images/core/emoji/13.0.1/72x72/1f642.png" alt="🙂"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I campi di applicazione della CIE possono essere innumerevoli; sicuramente il primo a cui mi dedicherò appena possibile sarà quello della realizzazione di un sistema di accesso sfruttando un Raspberry Pi, analogo a quello realizzato usando la TS-CNS.&lt;/p&gt;

&lt;p&gt;A seguire vi lascio una serie di risorse a scopo di appronfondimento.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Cos’è il progetto CIE/CNS Apache Docker (&lt;a href="https://www.youtube.com/redirect?event=video_description&amp;amp;redir_token=QUFFLUhqbjhjNFJyby1XLUNHRVUtQ2MzLXRYX19EZWZvQXxBQ3Jtc0tsdW5QZE9aUjVXek0talVTaFZoYmYxYVc3bjZKbndhS3NaWmpXOE9Bb1JMTGhEdU5nRG9RRnVSbDJZelVJekJyQUoyQm9kNHNPS1pnQ3RKc0RxLTV2Tk1LUm1sLVJDdzVUaUZnUXVUSE8xQ0lYbnluQQ&amp;amp;q=http%3A%2F%2Fbit.ly%2F3aJ5Gbl"&gt;http://bit.ly/3aJ5Gbl&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;CIE Carta d’Identità Elettronica (&lt;a href="https://www.youtube.com/redirect?event=video_description&amp;amp;redir_token=QUFFLUhqa0dHcUNvU2gtX2VSMHpKMVZZRzB4Zlh3dk5NUXxBQ3Jtc0trR2xsWFpSSWs3MlRCaENQUVdSZlB6ODNOWFg4dXVDMFllZ1NLOUhqelRWXzlJMTg4MXRvbUpsdnhqYktUUXdFZXA2a2kxQnRRaXRUd1pUUl9mck53d3RiUVFlbmx3N29HLWRCeG53YnVBZHNJUDYtSQ&amp;amp;q=https%3A%2F%2Fdevelopers.italia.it%2Fit%2Fcie%2F"&gt;https://developers.italia.it/it/cie/&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Carta Nazionale dei Servizi (&lt;a href="https://www.youtube.com/redirect?event=video_description&amp;amp;redir_token=QUFFLUhqbTlCS1FiT0pGejNZZGhmSkpnWDFxcVFmNlhCQXxBQ3Jtc0tsaGxOOFBiRXI1elhyUUFxa1lNUy1qUzlRTFFXQzRHZWp0Wnh5ZElfRklxaHJfU0R3LW4yMjBiZUkwNTI2a2V3LTlBcDB0OHFSaGxubV9GZnhGaVlITFhzNjRObXNicHJVbW5mYUE4dDdNTGRNTV9jcw&amp;amp;q=https%3A%2F%2Fwww.agid.gov.it%2Fit%2Fpiattaforme%2Fcarta-nazionale-servizi"&gt;https://www.agid.gov.it/it/piattaform…&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Raspberry Pi – Un esempio di applicazione della TS-CNS (&lt;a href="https://www.youtube.com/redirect?event=video_description&amp;amp;redir_token=QUFFLUhqbUdTRlhycC14dmF6dmpTQ0pZSGxPTklEY0ZZUXxBQ3Jtc0trTEYya25KaEFXdDZQQk1jcklHUzNKSTJVUTRCMkU2TXRBTWtsMmxXSmtmRWxCWVJnRW4wVlgzMzNndGpyQWFNbXdRQjRWY0F6MG1WQWpsYjFzczlJbWZJSWs3d3loQXl6TjVmeGdOWDJhZW1wR0J0SQ&amp;amp;q=https%3A%2F%2Fbit.ly%2F3hkJ8Aj"&gt;https://bit.ly/3hkJ8Aj&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.dontesta.it/2020/11/04/raspberry-pi-come-installare-minilector-cie-ubuntu-server-20-04-lts/"&gt;Raspberry Pi: Come installare il miniLector CIE su Ubuntu Server 20.04 LTS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Pubblicare il servizio CIE/CNS Apache Docker su Azure Cloud (&lt;a href="https://www.youtube.com/redirect?event=video_description&amp;amp;redir_token=QUFFLUhqbTBPUUQxMEVLU0pmVl85UFJwdEtPNXAtVHdQQXxBQ3Jtc0tuVzl6VXNYYW1vQmRfM3NOZEF4NnVFZHdQX2JzTHZzN05YYnVaakdZdjdDdkFFcDdFZmlvMXJzVTJNZ1hsbHdMWmFwTG5KT2Z4Z2Y3c2NnWko1R2c3UjlXZzdLem1ZdTJCOGNtdmp3OG44ajhHYVF2MA&amp;amp;q=http%3A%2F%2Fbit.ly%2F3aPoq8V"&gt;http://bit.ly/3aPoq8V&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Come accedere al portale VETINFO tramite TS-CNS e Mac OS (&lt;a href="https://www.youtube.com/redirect?event=video_description&amp;amp;redir_token=QUFFLUhqa0FFOU1tRElqTHJCVUpKaFduekd1cGF3WjYxQXxBQ3Jtc0tsMTIyTllETUdEOXluemVtdWZZaHM3RE5uaEVxQWYzY1JPQmtrX2xpT3NDblBhMHhaZ1RLTXBhejdoTTE0TmotSTN1eG5abi1VYk02UmxDeWxvdURaY2lDLXRHenFSb0d3OFRLb19feElReW96c0lkTQ&amp;amp;q=http%3A%2F%2Fbit.ly%2F2VFMKq7"&gt;http://bit.ly/2VFMKq7&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.bit4id.com/carta-didentita-elettronica-come-accedere-ai-servizi-online-con-la-cie-parte-1/?utm_source=blog&amp;amp;utm_medium=post&amp;amp;utm_campaign=ref_dontesta&amp;amp;utm_content=v1"&gt;Carta d’Identità Elettronica: come accedere ai servizi online con la CIE&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://shop.bit4id.com/soluzioni-per-la-carta-didentita-elettronica/?utm_source=blog&amp;amp;utm_medium=post&amp;amp;utm_campaign=ref_dontesta&amp;amp;utm_content=v1"&gt;CIEfacile&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;L'articolo &lt;a href="https://www.dontesta.it/2021/08/09/come-ottenere-una-cie-funzionante-su-fedora-34/"&gt;Come ottenere una CIE funzionante su Fedora 34&lt;/a&gt; sembra essere il primo su &lt;a href="https://www.dontesta.it"&gt;Antonio Musarra's Blog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://feeds.feedburner.com/~ff/dontesta/blog?a=zL9cnySDlO0:KdKilj5fnvM:yIl2AUoC8zA"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ly8gdBSb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Eff/dontesta/blog%3Fd%3DyIl2AUoC8zA" alt=""&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/dontesta/blog?a=zL9cnySDlO0:KdKilj5fnvM:dnMXMwOfBR0"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PziyOv7j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Eff/dontesta/blog%3Fd%3DdnMXMwOfBR0" alt=""&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/dontesta/blog?a=zL9cnySDlO0:KdKilj5fnvM:D7DqB2pKExk"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EXWOjepT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Eff/dontesta/blog%3Fi%3DzL9cnySDlO0:KdKilj5fnvM:D7DqB2pKExk" alt=""&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/dontesta/blog?a=zL9cnySDlO0:KdKilj5fnvM:YwkR-u9nhCs"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DCS1IRW9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Eff/dontesta/blog%3Fd%3DYwkR-u9nhCs" alt=""&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/dontesta/blog?a=zL9cnySDlO0:KdKilj5fnvM:F7zBnMyn0Lo"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1Uwq-OXv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Eff/dontesta/blog%3Fi%3DzL9cnySDlO0:KdKilj5fnvM:F7zBnMyn0Lo" alt=""&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/dontesta/blog?a=zL9cnySDlO0:KdKilj5fnvM:V_sGLiPBpWU"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jVjkakOW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Eff/dontesta/blog%3Fi%3DzL9cnySDlO0:KdKilj5fnvM:V_sGLiPBpWU" alt=""&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/dontesta/blog?a=zL9cnySDlO0:KdKilj5fnvM:qj6IDK7rITs"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lg7sfzlZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Eff/dontesta/blog%3Fd%3Dqj6IDK7rITs" alt=""&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/dontesta/blog?a=zL9cnySDlO0:KdKilj5fnvM:KwTdNBX3Jqk"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--28QT5FA1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Eff/dontesta/blog%3Fi%3DzL9cnySDlO0:KdKilj5fnvM:KwTdNBX3Jqk" alt=""&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/dontesta/blog?a=zL9cnySDlO0:KdKilj5fnvM:gIN9vFwOqvQ"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aRSUgzSw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Eff/dontesta/blog%3Fi%3DzL9cnySDlO0:KdKilj5fnvM:gIN9vFwOqvQ" alt=""&gt;&lt;/a&gt;&lt;br&gt;
 &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YVzBKOYV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Er/dontesta/blog/%257E4/zL9cnySDlO0" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YVzBKOYV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Er/dontesta/blog/%257E4/zL9cnySDlO0" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>blog</category>
      <category>security</category>
    </item>
    <item>
      <title>La mia workstation di sviluppo da Smart Worker</title>
      <dc:creator>Antonio Musarra</dc:creator>
      <pubDate>Sun, 23 May 2021 21:16:12 +0000</pubDate>
      <link>https://dev.to/amusarra/la-mia-workstation-di-sviluppo-da-smart-worker-33k1</link>
      <guid>https://dev.to/amusarra/la-mia-workstation-di-sviluppo-da-smart-worker-33k1</guid>
      <description>&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/05/12243428_10205658293641273_406568089324685156_n.jpg"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HLtI3047--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/05/12243428_10205658293641273_406568089324685156_n.jpg" alt="Il mio primo portatile Macintosh (PowerBook G4)" title="Il mio primo portatile Macintosh (PowerBook G4)"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Il mio primo portatile Macintosh (PowerBook G4)&lt;/p&gt;

&lt;p&gt;Nella mia attività lavorativa sono stato affiancato e lo sono tuttora da macchine di casa &lt;a href="https://www.apple.com"&gt;Apple&lt;/a&gt; (portatili), partendo dal mio il primo &lt;a href="https://it.wikipedia.org/wiki/PowerBook_G4"&gt;PowerBook G4&lt;/a&gt; ancora operativo e attualmente affidato a mio nipote di quasi sei anni.&lt;/p&gt;

&lt;p&gt;A quasi un anno di attività lavorativa in modalità da &lt;a href="https://www.ilsole24ore.com/art/gli-smart-worker-sono-e-saranno-piu-5-milioni-si-fanno-avanti-anche-pa-e-pmi-ADPxPvz?refresh_ce=1"&gt;&lt;strong&gt;Smart Worker&lt;/strong&gt;&lt;/a&gt;, ho sentito la necessità di dotarmi di una vera e propria workstation. &lt;strong&gt;Cos’è esattamente una workstation?&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Workstation&lt;/strong&gt; (in italiano &lt;strong&gt;stazione di lavoro&lt;/strong&gt; ) è un termine della lingua inglese utilizzato in informatica per indicare un tipo di computer monoutente, che si contraddistingue dall’essere destinato principalmente a un utilizzo produttivo (da cui il prefisso work = lavoro), e dall’avere alte prestazioni per poter assolvere compiti altamente professionali di vario genere (le prestazioni dei computer sono in continuo aumento quindi “alte prestazioni” è relativo al periodo di commercializzazione della workstation).&lt;/p&gt;

&lt;p&gt;Sono utilizzate soprattutto nella forma di computer desktop, in ambiti di lavoro che necessitano di grandi potenze di calcolo come ad esempio il CAD, la ricerca scientifica, la produzione audio/video, le applicazioni di simulazione e calcolo ingegneristico. Esso è dunque sinonimo di un computer più potente rispetto ad un normale personal computer domestico o di ufficio. (Fonte Wikipedia &lt;a href="https://it.wikipedia.org/wiki/Workstation"&gt;https://it.wikipedia.org/wiki/Workstation&lt;/a&gt;)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Alla definizione standard aggiungerei che una workstation può definirsi tale se completa di uno o più monitor aventi caratteristiche che soddisfino le proprie esigenze lavorative.&lt;/p&gt;

&lt;p&gt;In questo brevissimo articolo cercherò di esporre al meglio le scelte che ho seguito per costruire una workstation che &lt;strong&gt;rispondesse alla mie esigenze&lt;/strong&gt; , senza assolutamente affermare che le scelte fatte da me siano il top. Questo articolo è in realtà la bella copia delle note che ho scritto durante la costruzione della mia workstation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quali sono le mie esigenze?
&lt;/h2&gt;

&lt;p&gt;Il mio lavoro principale è la progettazione e realizzazione di soluzioni software. L’attività secondaria da &lt;a href="https://www.mysocialweb.it/chi-e-il-blogger/"&gt;Technical Blogger&lt;/a&gt; richiede che possa creare contenuti in diversi formati, tra cui, quello che impone la disponibilità di risorse non trascurabili è il video.&lt;/p&gt;

&lt;p&gt;La selezione dell’hardware che andrà a costituire la propria workstation, deve essere eseguita sulla base delle proprie esigenze e nel mio caso queste corrispondono alle seguenti semplici domande.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Qual è il Sistema Operativo che si vuole installare?&lt;/strong&gt; Questa scelta potrebbe “tagliare” parecchio hardware, semplicemente per il fatto che siamo costretti a scegliere hardware con disponibilità di driver (possibilmente certificati) per il sistema operativo scelto.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Quali sono i programmi di produttività e i tool di sviluppo maggiormente utilizzati?&lt;/strong&gt;   I programmi che usiamo hanno un peso notevole sulla scelta dell’hardware, è infatti importante conoscere le specifiche di dettaglio di ogni singolo programma.&lt;/li&gt;
&lt;li&gt;*&lt;em&gt;Una politica di backup locale è richiesta? *&lt;/em&gt; L’applicazione di una politica di backup locale richiede senza ombra di dubbio la scelta di storage dedicato a ospitare le copie di backup dei nostri dati.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  E il budget?
&lt;/h2&gt;

&lt;p&gt;Indipendentemente dai miei desideri, la scelta del budget è il primo limite che ho imposto prima di condurre le attività di ricerca per la mia workstation. Chiaro, ognuno di noi vorrebbe tra le mani una Ferrari anche se il più delle volte risulterebbe essere troppo per le proprie esigenze. &lt;strong&gt;Per la mia workstation ho deciso di stanziare un budget di 2500€ con il 5% di tolleranza&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Brandizzata o Custom?
&lt;/h2&gt;

&lt;p&gt;Questo è il primo dilemma. Sono sicuro che anche voi abbiate dovuto affrontare questo primo quesito. Personalmente ho risolto la questione ponendo un’altra domanda, ovvero, &lt;strong&gt;quale dovrà essere la caratteristica principale della mia workstation&lt;/strong&gt;? La maggior flessibilità possibile.&lt;/p&gt;

&lt;p&gt;Ecco cosa intendo per flessibilità di una workstation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;agilità di configurazione;&lt;/li&gt;
&lt;li&gt;hardware standard;&lt;/li&gt;
&lt;li&gt;supporto ai più moderni standard hardware;&lt;/li&gt;
&lt;li&gt;CPU aggiornabile;&lt;/li&gt;
&lt;li&gt;RAM aggiornabile;&lt;/li&gt;
&lt;li&gt;hardware compatibile con sistemi operativi Unix/Linux;&lt;/li&gt;
&lt;li&gt;costo elastico.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ho impiegato diverse settimane cercando soluzioni tra i produttori più conosciuti che potessero soddisfare i miei requisiti ma senza successo. Sicuramente il costo ha avuto il suo peso nella scelta ma soprattutto la flessibilità di cui ho scritto poc anzi. Alla fine ho deciso di prendere la strada della soluzione custom o come si suol dire, dell’assemblato.&lt;/p&gt;

&lt;h2&gt;
  
  
  La scelta dell’hardware
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/05/157321717_10220036030595711_3103233920773742986_n.jpg"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0fCiW3zL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/05/157321717_10220036030595711_3103233920773742986_n.jpg" alt="I componenti hardware della mia workstation"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I componenti hardware della mia workstation&lt;/p&gt;

&lt;p&gt;La scelta dell’hardware è stata guidata dalle domande che ho illustrato in precedenza. Il fatto di aver scelto &lt;strong&gt;Linux&lt;/strong&gt; come sistema operativo, ha ristretto il range di hardware per via del supporto dei driver (anche certificati) per questo sistema operativo. Solitamente l’hardware che supporta nativamente Linux ha anche un costo maggiore. Per quanto possibile ho cercato di scegliere hardware recentissimo e con ampia possibilità di estensione. La tabella a seguire mostra i componenti hardware principali che ho scelto per la mia workstation e la motivazione che ha guidato la scelta.&lt;/p&gt;

&lt;p&gt;| &lt;strong&gt;Componente&lt;/strong&gt; | &lt;strong&gt;Modello&lt;/strong&gt; | &lt;strong&gt;Motivazione&lt;/strong&gt; |&lt;br&gt;
| CPU | &lt;a href="https://www.amd.com/en/products/cpu/amd-ryzen-9-3900x"&gt;AMD Ryzen 9 3900X&lt;/a&gt; | Per il tipo di applicazioni che uso e che sviluppo, ho necessità di avere un processore che sia in grado di offrire una potenza computazionale abbastanza generosa a un costo contenuto. Per questo motivo ho scelto questa CPU AMD che offre ben 12 Core e ben 24 Thread. Più thread significa miglior multitasking e prestazioni migliorate con i software che sfruttano pesantemente i thread come gli editor e i transcoder video.&lt;/p&gt;

&lt;p&gt;Questo processore supporta inoltre lo standard  PCIe® Gen 4.0 di cui ne trarrà grande vantaggio lo storage e lo standard DDR4 per la memoria RAM fino a 3200MHz&lt;/p&gt;

&lt;p&gt;|&lt;br&gt;
| GPU | &lt;a href="https://www.nvidia.com/content/dam/en-zz/Solutions/design-visualization/productspage/quadro/quadro-desktop/quadro-p2200-datasheet-letter-974207-r4-web.pdf"&gt;NVIDIA Quadro P2200&lt;/a&gt; | La scelta della GPU è stata abbastanza semplice, guidata dal fatto che il mio scopo è prettamente circoscritto all’uso di programmi EDA (tipo KiCAD, Eagle PCB) di progettazione elettronica, DaVinci Resolve e OBS Studio per la creazione dei miei video tutorial e alcuni software che sfruttano CUDA. Caratteristica molto importante, questa scheda video dispone dei driver certificati per Linux e anche aggiornati. |&lt;br&gt;
| Memoria RAM | DDR 4 3600MHz 64GB Intel XMP-ready e AMD Ryzen | Ho scelto questo taglio apparentemente grande perché utilizzo frequentemente applicazioni basate su container che richiedono una considerevole disponibilità di memoria RAM. La prima certificazione (Intel XMP-ready) attesta la possibilità di sfruttare appieno le potenzialità della CPU in relazione all’applicazione. La seconda, garantisce la piena funzionalità con processori AMD Ryzen. |&lt;br&gt;
| Mother Board | &lt;a href="http://it.gigabyte.com/products/page/mb/X570-AORUS-ULTRA-rev-11#kf"&gt;Gigabyte X570 AORUS ULTRA&lt;/a&gt; | Questa è stata la scelta più sofferta tra tutti i componenti hardware, le motivazioni principali sono state:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Supporto dei processori AMD Ryzen 5000 Series / 3rd Gen Ryzen &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1OPDn6Mc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s.w.org/images/core/emoji/13.0.1/72x72/2122.png" alt="™"&gt;/ 2nd Gen Ryzen &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1OPDn6Mc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s.w.org/images/core/emoji/13.0.1/72x72/2122.png" alt="™"&gt;/ 3rd Gen Ryzen &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1OPDn6Mc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s.w.org/images/core/emoji/13.0.1/72x72/2122.png" alt="™"&gt;
&lt;/li&gt;
&lt;li&gt;Triple PCIe® Gen 4.0 M.2 with Thermal Guards&lt;/li&gt;
&lt;li&gt;Intel® WiFi 6 802.11ax (con BT versione 5)&lt;/li&gt;
&lt;li&gt;Dual Channel ECC/ Non-ECC Unbuffered DDR4 (5100), 4 DIMMs fino a 128GByte&lt;/li&gt;
&lt;li&gt;Front &amp;amp; Rear USB 3.2 Gen2 Type-C &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1OPDn6Mc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s.w.org/images/core/emoji/13.0.1/72x72/2122.png" alt="™"&gt; Header &amp;amp; HDMI 2.0 support&lt;/li&gt;
&lt;li&gt;PCIe 4.0 x16/x8/x4/x1 Slot&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Queste caratteristiche consentono una grande flessibilità di estensione futura, dal processore alla memoria RAM. Inoltre i componenti hardware integrati sono compatibili con Linux e le ultime versioni del Kernel e in particolare la scheda WiFi + BT.&lt;/p&gt;

&lt;p&gt;|&lt;br&gt;
| Storage NVME | &lt;a href="https://www.samsung.com/it/memory-storage/nvme-ssd/980-pro-pcle-4-0-nvme-m-2-ssd-1tb-mz-v8p1t0bw/"&gt;Samsung SSD 980 PRO 1TB&lt;/a&gt; | Questo disco SSD NVMe 4 credo che sia una scelta obbligata per avere uno storage con impressionanti prestazioni sia in termini di scrittura sia in termini di lettura. Questo è lo storage principale per SO + Applicazioni + Dati. |&lt;br&gt;
| | &lt;a href="https://www.sabrent.com/product/SB-ROCKET-NVMe4-500/500gb-rocket-nvme-pcie-4-0-m-2-2280-internal-ssd-maximum-performance-solid-state-drive/"&gt;Sabrent Rocket 4.0 500GB&lt;/a&gt; | Questo è il disco di “seconda scelta” dedicato a un’installazione di Microsoft Windows + test delle nuove versioni della distribuzione Linux che uso. |&lt;br&gt;
| Storage HDD | &lt;a href="https://www.seagate.com/it/it/products/nas-drives/ironwolf-hard-drive/"&gt;ST4000VN008-2DR166 (SC60) 4TB x2&lt;/a&gt; | Ho scelto questo storage di casa Segate e serie IronWolf perché indicato per le operazioni di backup. |&lt;br&gt;
| | | |&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/05/158503457_10220046920027940_477791328231448925_n.jpg"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UVugjA82--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/05/158503457_10220046920027940_477791328231448925_n.jpg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Blocco Raffreddamento ad Aria, CPU, RAM e GPU&lt;/p&gt;

&lt;h2&gt;
  
  
  La scelta della distribuzione Linux
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/05/fedora_34_os_info.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--86pUrkp5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/05/fedora_34_os_info.png" alt="Fedora Workstation OS Info"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Fedora Workstation OS Info&lt;/p&gt;

&lt;p&gt;Questa è stata la scelta certa fin dall’inizio della nascita dell’idea della workstation. Per la mia workstation di lavoro ho deciso di andare su una distribuzione stabile, al passo con i tempi e orientata a chi sviluppa. La distribuzione a cui faccio riferimento è &lt;a href="https://getfedora.org/it/"&gt;Fedora&lt;/a&gt;, in particolare &lt;a href="https://fedoramagazine.org/whats-new-fedora-34-workstation/"&gt;Fedora Workstation 34&lt;/a&gt; con la nuova versione 40 di &lt;a href="https://forty.gnome.org/"&gt;GNOME&lt;/a&gt;. Secondo il mio parere sono sette i punti di forza di questa distribuzione.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Ultima versione del Desktop Environment GNOME 40&lt;/li&gt;
&lt;li&gt;Aggiornamenti veloci e affidabili&lt;/li&gt;
&lt;li&gt;Pacchetti Flatpak e Snap&lt;/li&gt;
&lt;li&gt;Una grande comunità&lt;/li&gt;
&lt;li&gt;Essenziale&lt;/li&gt;
&lt;li&gt;Già pronta per la tecnologia dei container&lt;/li&gt;
&lt;li&gt;Supportato da RedHat&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Lo schema di partizionamento
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/05/Screenshot-20210523215751-1182x527-1.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CcOISCNr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/05/Screenshot-20210523215751-1182x527-1.png" alt="Schema di partizionamento storage"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Schema di partizionamento storage&lt;/p&gt;

&lt;p&gt;L’installazione di un qualunque Sistema Operativo dovrebbe essere eseguita secondo un schema ragionato, pensando al proprio modo di lavorare e senza trascurare il modo di rendere più semplici gli aggiornamenti futuri, in particolare di major release della distribuzione. Implementare un buono schema di partizionamento dello storage a disposizione è a mio avviso essenziale.&lt;/p&gt;

&lt;p&gt;La tabella a seguire mostra lo schema di partizionamento cucito sulle mi necessità.&lt;/p&gt;

&lt;p&gt;| &lt;strong&gt;Storage&lt;/strong&gt; | &lt;strong&gt;File System (FS)&lt;/strong&gt; | &lt;strong&gt;Type&lt;/strong&gt; | &lt;strong&gt;Size&lt;/strong&gt; | &lt;strong&gt;Device&lt;/strong&gt; | &lt;strong&gt;Note&lt;/strong&gt; |&lt;br&gt;
| Samsung SSD 980 PRO 1TB (2B2QGXA7)&lt;br&gt;&lt;br&gt;
1TByte | /boot | ext4 | 500MByte | &lt;br&gt;
/dev/nvme0n1p1&lt;br&gt;
 | &lt;br&gt;
Partizione di boot (EFI System)&lt;br&gt;
 |&lt;br&gt;
| | /boot/efi | EFI (vfat) | 750MByte | &lt;br&gt;
/dev/nvme0n1p2&lt;br&gt;
 | &lt;br&gt;
EFI Boot Partition&lt;br&gt;
 |&lt;br&gt;
| | / (root) | xfs | 100GByte | &lt;br&gt;
/dev/nvme0n1p4&lt;br&gt;
 | Partizione di Root |&lt;br&gt;
| | &lt;br&gt;
/home&lt;br&gt;
 | xfs | 200GByte | &lt;br&gt;
/dev/nvme0n1p3&lt;br&gt;
 | User Home |&lt;br&gt;
| | swap | Linux Swap | 96GByte | &lt;br&gt;
/dev/nvme0n1p5&lt;br&gt;
 | Partizione di Swap del Sistema Operativo. La dimensione di questa partizione è stata calcolata sulla base della memoria RAM a disposizione sul sistema hardware. La guida all’installazione di Fedora riporta nel dettaglio la modalità di calcolo. |&lt;br&gt;
| | &lt;br&gt;
/uwfs01&lt;br&gt;
 | xfs | 80GByte | &lt;/p&gt;

&lt;p&gt;/dev/nvme0n1p6&lt;/p&gt;

&lt;p&gt;| &lt;br&gt;
Questa è la partizione dedicata a ospitare i setup/installer o archivi (zip, tar.gz, rpm, etc.) dei software installati sul sistema e fuori dai repository software standard di Fedora.&lt;br&gt;
 |&lt;br&gt;
| | &lt;/p&gt;

&lt;p&gt;/uwfs02&lt;/p&gt;

&lt;p&gt;| xfs | 180GByte | &lt;/p&gt;

&lt;p&gt;/dev/nvme0n1p7&lt;/p&gt;

&lt;p&gt;| &lt;/p&gt;

&lt;p&gt;Questa è la partizione dedicata a ospitare le macchine virtuali e container (Podman e Docker).&lt;/p&gt;

&lt;p&gt;|&lt;br&gt;
| | &lt;/p&gt;

&lt;p&gt;/uwfs03&lt;/p&gt;

&lt;p&gt;| xfs | 180GByte | &lt;/p&gt;

&lt;p&gt;/dev/nvme0n1p8&lt;/p&gt;

&lt;p&gt;| &lt;/p&gt;

&lt;p&gt;Questa è la partizione dedicata a ospitare gli ambienti di lavoro suddivisi per progetto e i tool di lavoro specifici.&lt;/p&gt;

&lt;p&gt;|&lt;br&gt;
| | &lt;/p&gt;

&lt;p&gt;/uwfs04&lt;/p&gt;

&lt;p&gt;| xfs | 95GByte | &lt;/p&gt;

&lt;p&gt;/dev/nvme0n1p9&lt;/p&gt;

&lt;p&gt;| &lt;/p&gt;

&lt;p&gt;Questa è la partizione dedicata a ospitare i sorgenti di progetti di terze parti e la cache di Gradle e Maven.&lt;/p&gt;

&lt;p&gt;|&lt;/p&gt;

&lt;p&gt;Ogni partizione indicata in tabella ha uno specifico scopo e rispecchia il mio modo personale di lavoro. Questo schema di partizionamento facilità inoltra l’aggiornamento di major release della distruzione, non intaccando in alcun modo le partizioni di lavoro. Quindi, fare una partizione unica non è mai una buona idea. Nel mio caso specifico, aggiornare da Fedora 33 a Fedora 34, con questo schema di partizionamento è stato una passeggiata di salute. Il nome del file system uwfs{n} sta per User Working File System.&lt;/p&gt;

&lt;p&gt;Qualcuno di voi ha sicuramente notato che ho adottato il file system &lt;a href="https://it.wikipedia.org/wiki/XFS_(file_system)#:~:text=XFS%20%C3%A8%20un%20file%20system,abbastanza%20stabile"&gt;XFS&lt;/a&gt;%20e%20nella%202.6.) e non &lt;a href="https://it.wikipedia.org/wiki/Btrfs"&gt;BTRFS&lt;/a&gt;, quest’ultimo di default da &lt;a href="https://fedoramagazine.org/btrfs-coming-to-fedora-33/"&gt;Fedora 33&lt;/a&gt;. La risposta è abbastanza semplice. Non ho ancora avuto modo di testare approfonditamente il BTRFS e ho quindi optato per il rodato XFS.&lt;/p&gt;

&lt;h2&gt;
  
  
  Il mio software principale di lavoro
&lt;/h2&gt;

&lt;p&gt;A seguire la lista dei software installati sulla mia workstation e che uso giornalmente.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Office Automation&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Libre Office&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;Email/Calendar&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
Mailspring&lt;/li&gt;
&lt;li&gt;GNOME Calendar (con CalDAV Remoto)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;Backup&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
Timeshift&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;Source Control&lt;/p&gt;

&lt;h2&gt;
  
  
  - Git
&lt;/h2&gt;

&lt;p&gt;Meld&lt;/p&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;Network Tools&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
Wireshark&lt;/li&gt;
&lt;li&gt;TCP Dump&lt;/li&gt;
&lt;li&gt;Nmap&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;VPN/Remote Desktop&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
FortiClient&lt;/li&gt;
&lt;li&gt;
PulseSecure&lt;/li&gt;
&lt;li&gt;
OpenConnect&lt;/li&gt;
&lt;li&gt;
Citrix Workspace&lt;/li&gt;
&lt;li&gt;Remmina&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;Shell/Terminal&lt;/p&gt;

&lt;h2&gt;
  
  
  - Tilix
&lt;/h2&gt;

&lt;h2&gt;
  
  
  ZSH 5.8
&lt;/h2&gt;

&lt;p&gt;Estensione oh-my-zsh&lt;/p&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;Editor – IDE&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
IntelliJ IDEA Enterprise&lt;/li&gt;
&lt;li&gt;
Visual Studio Code&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  - PlatformIO
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Sublime Text
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Vim + Plugins
&lt;/h2&gt;

&lt;p&gt;Typora&lt;/p&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;Linguaggi e Compilatori&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
JDK 1.7&lt;/li&gt;
&lt;li&gt;
JDK 1.8&lt;/li&gt;
&lt;li&gt;
JDK 11&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  - JDK 16
&lt;/h2&gt;

&lt;p&gt;Python 3.x&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GoLang&lt;/li&gt;
&lt;li&gt;GNU C/C++&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;Build&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
Ant&lt;/li&gt;
&lt;li&gt;
Maven&lt;/li&gt;
&lt;li&gt;
Gradle&lt;/li&gt;
&lt;li&gt;
Make&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;Tool Web Services&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
SOAP UI&lt;/li&gt;
&lt;li&gt;
Postman&lt;/li&gt;
&lt;li&gt;cURL&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;Database Client&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
SQL Developer&lt;/li&gt;
&lt;li&gt;
PostgreSQL Admin&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;Container&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
Docker&lt;/li&gt;
&lt;li&gt;
Podman&lt;/li&gt;
&lt;li&gt;
MiniOpenShift&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;VM&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
Virtual Box&lt;/li&gt;
&lt;li&gt;
VMWare Workstation&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;Mappe Mentali&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
XMind (true)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;Video&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
OBS Studio&lt;/li&gt;
&lt;li&gt;
DavinciResolve Pro&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;Design/CAD&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
Draw.io&lt;/li&gt;
&lt;li&gt;
GIMP&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  - Inkscape
&lt;/h2&gt;

&lt;h2&gt;
  
  
  EASY EDA
&lt;/h2&gt;

&lt;p&gt;KICAD&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Eagle PCB&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusioni
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.dontesta.it/wp-content/uploads/2021/05/160242341_10220093188264617_6450844205970016028_n.jpg"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dhIPbGey--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/05/160242341_10220093188264617_6450844205970016028_n.jpg" alt="Il mio desktop"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Il mio desktop&lt;/p&gt;

&lt;p&gt;Ogni mestiere necessita degli strumenti adeguati affinché possa essere compiuto nel migliore dei modi e questi devono essere scelti con cura. &lt;strong&gt;Vi ho mostrato le motiviazioni che mi hanno portato alla costruzione della mia workstation da Smart Worker, le vostre quali sono?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Credo che la scelta di andare sulla soluzione dell’assemblato è senza dubbio quella che dà la maggior libertà di configurazione e di conseguenza permette di costruire una soluzione hardware adatta alle proprie esigenze.&lt;/p&gt;

&lt;p&gt;L'articolo &lt;a href="https://www.dontesta.it/2021/05/23/la-mia-workstation-di-sviluppo-da-smart-worker/"&gt;La mia workstation di sviluppo da Smart Worker&lt;/a&gt; sembra essere il primo su &lt;a href="https://www.dontesta.it"&gt;Antonio Musarra's Blog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://feeds.feedburner.com/~ff/dontesta/blog?a=qSsRGRlu_30:pjKn1oyKwrA:yIl2AUoC8zA"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ly8gdBSb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Eff/dontesta/blog%3Fd%3DyIl2AUoC8zA" alt=""&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/dontesta/blog?a=qSsRGRlu_30:pjKn1oyKwrA:dnMXMwOfBR0"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PziyOv7j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Eff/dontesta/blog%3Fd%3DdnMXMwOfBR0" alt=""&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/dontesta/blog?a=qSsRGRlu_30:pjKn1oyKwrA:D7DqB2pKExk"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_7wNQ2EZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Eff/dontesta/blog%3Fi%3DqSsRGRlu_30:pjKn1oyKwrA:D7DqB2pKExk" alt=""&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/dontesta/blog?a=qSsRGRlu_30:pjKn1oyKwrA:YwkR-u9nhCs"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DCS1IRW9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Eff/dontesta/blog%3Fd%3DYwkR-u9nhCs" alt=""&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/dontesta/blog?a=qSsRGRlu_30:pjKn1oyKwrA:F7zBnMyn0Lo"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uc8hlacd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Eff/dontesta/blog%3Fi%3DqSsRGRlu_30:pjKn1oyKwrA:F7zBnMyn0Lo" alt=""&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/dontesta/blog?a=qSsRGRlu_30:pjKn1oyKwrA:V_sGLiPBpWU"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Vtvtz66U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Eff/dontesta/blog%3Fi%3DqSsRGRlu_30:pjKn1oyKwrA:V_sGLiPBpWU" alt=""&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/dontesta/blog?a=qSsRGRlu_30:pjKn1oyKwrA:qj6IDK7rITs"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lg7sfzlZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Eff/dontesta/blog%3Fd%3Dqj6IDK7rITs" alt=""&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/dontesta/blog?a=qSsRGRlu_30:pjKn1oyKwrA:KwTdNBX3Jqk"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bFZZe9av--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Eff/dontesta/blog%3Fi%3DqSsRGRlu_30:pjKn1oyKwrA:KwTdNBX3Jqk" alt=""&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/dontesta/blog?a=qSsRGRlu_30:pjKn1oyKwrA:gIN9vFwOqvQ"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--R3dkyyHu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Eff/dontesta/blog%3Fi%3DqSsRGRlu_30:pjKn1oyKwrA:gIN9vFwOqvQ" alt=""&gt;&lt;/a&gt;&lt;br&gt;
 &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sIp5Su8m--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Er/dontesta/blog/%257E4/qSsRGRlu_30" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sIp5Su8m--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Er/dontesta/blog/%257E4/qSsRGRlu_30" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>blog</category>
    </item>
    <item>
      <title>Raspberry Pi, ESP32, EMQ X and Node RED together</title>
      <dc:creator>Antonio Musarra</dc:creator>
      <pubDate>Mon, 10 May 2021 09:04:14 +0000</pubDate>
      <link>https://dev.to/amusarra/raspberry-pi-esp32-emq-x-and-node-red-together-1ahe</link>
      <guid>https://dev.to/amusarra/raspberry-pi-esp32-emq-x-and-node-red-together-1ahe</guid>
      <description>&lt;p&gt;This project refers to the article &lt;a href="https://bit.ly/3a3t7xq"&gt;Un trittico vincente: ESP32, Raspberry Pi e EMQ X Edge published&lt;/a&gt;&lt;br&gt;
on Antonio Musarra's Blog&lt;/p&gt;

&lt;p&gt;This project contains the source code to be installed on the ESP32 devices that &lt;br&gt;
are part of the IoT solution described by the article mentioned above.&lt;/p&gt;

&lt;p&gt;It's easy to understand how things work with a simple diagram, and the one below &lt;br&gt;
shows two devices (ESP32), a dashboard and a mobile phone. In this case and in &lt;br&gt;
the context of the Publish/Subscribe pattern, these components take on the role &lt;br&gt;
of both publisher and subscriber, and the broker is the message dispatcher.&lt;/p&gt;

&lt;p&gt;The Dashboard and the Mobile Phone indicate to the broker that they want to &lt;br&gt;
subscribe to all the messages that belong to the topic &lt;code&gt;device01/temperature&lt;/code&gt; and &lt;br&gt;
&lt;code&gt;device02/temperature&lt;/code&gt;. This means that they will receive all the messages &lt;br&gt;
published by the devices (device01 and device02) on their respective topics. &lt;br&gt;
The Dashboard and the Mobile Phone publish "command" messages on the two topics &lt;br&gt;
&lt;code&gt;device01/command&lt;/code&gt; and &lt;code&gt;device02/command&lt;/code&gt;, the respective devices are subscribed &lt;br&gt;
to these two topics and will then receive the commands to activate or deactivate, &lt;br&gt;
for example, relays or actuators.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--s5mn8n5N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/04/iot_mqtt_message_broker_sample_optimize.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--s5mn8n5N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/04/iot_mqtt_message_broker_sample_optimize.gif" alt="Animation showing the Publish/Subscribe architectural style in action"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure 1 - Animation showing the Publish/Subscribe architectural style in action&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The common dialect used for communications between Gateway, Device and Dashboard &lt;br&gt;
is the MQTT. The ESP32 communicates with the environmental sensor via the I2C bus, &lt;br&gt;
while to pursue actions towards the relay module it uses four GPIO channels.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qtRck8Br--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/03/iot-sample-solution-weather-station-scaled.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qtRck8Br--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/03/iot-sample-solution-weather-station-scaled.jpg" alt="Architecture of the IoT solution with evidence of hardware and software components"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure 2 - Architecture of the IoT solution with evidence of hardware and software components&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To implement this solution from the hardware point of view, we need to know how &lt;br&gt;
to make the connections between the pieces of "iron" so that everything can work &lt;br&gt;
correctly. The wiring diagram shows the connections concerning the device, then &lt;br&gt;
the BME 280 sensor and the relay module to the ESP32 DOIT DEV KIT development &lt;br&gt;
board (30-pin). The diagram also shows the connection of the Gateway with a &lt;br&gt;
16 × 2 LCD display, inserted with the aim of showing the environmental data and &lt;br&gt;
the status of the relays, information whose source is represented by each device.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---e1b1W2p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/03/Schematic_ESP32_MQTT_Publish_Subscribe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---e1b1W2p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/03/Schematic_ESP32_MQTT_Publish_Subscribe.png" alt="Electrical diagram of the hardware components that make up the IoT solution"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure 3 - Electrical diagram of the hardware components that make up the IoT solution&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The development board of the ESP32 is equipped with a Micro-USB port for powering &lt;br&gt;
the module itself and uploading the firmware. This development board supports &lt;br&gt;
automatic upload, so it will not be necessary to manually change the upload &lt;br&gt;
and execution mode when it is necessary to upload the new software.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. How to program the ESP32
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.espressif.com/en/products/sdks/esp-idf"&gt;ESP-IDF&lt;/a&gt; is Espressif's official IoT development framework for the ESP32 and ESP32-S series of SoCs. It provides a self-contained SDK for any generic application development on these platforms, using programming languages ​​such as C and C ++. ESP-IDF currently powers millions of devices in the field and allows you to build a variety of networked products, ranging from simple light bulbs and toys to large appliances and industrial devices.&lt;/p&gt;

&lt;p&gt;For this solution, however, I chose to adopt the &lt;a href="https://www.arduino.cc/reference/en/"&gt;Arduino&lt;/a&gt; framework based on &lt;a href="https://it.wikipedia.org/wiki/Wiring"&gt;Wiring&lt;/a&gt; , for three simple reasons: simple to use, extensive documentation and widely disseminated and known .&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Will we then use the classic Arduino IDE programming environment?&lt;/strong&gt; No, I propose something different.&lt;/p&gt;

&lt;p&gt;I have always been of the idea that from the moment a software project is created, as far as possible, it is better not to link it to a specific IDE (Integrated Development Environment). I like the fact that the projects are independent from the IDE, I have to be able to build the project from the command line: git clone, build and install .&lt;/p&gt;

&lt;p&gt;The something else is &lt;a href="https://platformio.org/"&gt;PlatformIO&lt;/a&gt; . It is a cross-platform, cross-architecture , multiple-framework : a tool for embedded systems engineers and software developers who write applications for embedded products.&lt;/p&gt;

&lt;p&gt;Without going too deeply into the implementation details of PlatformIO, the work cycle of the project developed using PlatformIO is as follows:&lt;/p&gt;

&lt;p&gt;The development boards involved are chosen by specifying them in the platformio.ini file (project configuration file).&lt;br&gt;
Based on this list of boards, PlatformIO downloads the required toolchains and installs them automatically.&lt;br&gt;
The development of the code begins and PlatformIO makes sure that it is compiled, prepared and loaded on all the cards of interest.&lt;br&gt;
To write the code you can use your favorite editor or IDE, alternatively you can use PlatformIO for VSCode . The only requirement is the installation of &lt;a href="https://docs.platformio.org/en/latest/core/index.html"&gt;PlatformIO Core (CLI)&lt;/a&gt; on your development machine. PlatformIO Core is written in Python and therefore works on Windows, macOS, Linux, FreeBSD and ARM- based credit-card sized computers ( Raspberry Pi ,  BeagleBone ,  CubieBoard ,  Samsung ARTIK , etc.).&lt;/p&gt;

&lt;p&gt;The minimum version of PlatformIO Core to install is version 5.x. If you have already installed a version of PlatformIO, you can upgrade through the command &lt;code&gt;pio upgrade&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now that we have chosen PlatformIO as a software development support tool, we can move on to analyze the developed code.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Writing the software for the ESP32
&lt;/h2&gt;

&lt;p&gt;The main responsibilities for the software to be created for the ESP32 are: the reading of environmental data and the subsequent publication on the topic esp32/telemetry_data through the Message Broker, as well as receiving the commands from the topic esp32/command and the subsequent execution of the same. The macro responsibilities are indicated below.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;I2C setup for the GY-BME280 sensor&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GPIO setup for relays&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Setup of the connection to the WiFi network&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Setup of the connection to the MQTT Message Broker&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reading of environmental data from the GY-BME280 sensor&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Preparation of the message with the environmental data in JSON format&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Preparation of the message with the relay status data in JSON format&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Publication of environmental data via MQTT&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Publication of the relay status via MQTT&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reading and execution of commands arriving on the topic esp32/command&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The basic functions of the &lt;a href="https://github.com/amusarra/esp32-mqtt-publish-subscribe/blob/master/src/esp32_mqtt_publish_subscribe.cpp"&gt;esp32_mqtt_publish_subscribe.cpp&lt;/a&gt; program are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;void setup_wifi()&lt;/strong&gt; : the responsibility of this function is to establish the connection to the WiFi network. The connection parameters (SSID and username) can be set during the build phase; later we will see how. The WiFi network to which we must connect the devices must guarantee connectivity to the Message Broker;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;void reconnect()&lt;/strong&gt; : the responsibility of this function is to establish the connection to the Message Broker and manage any reconnections, for example in cases where the connection to the WiFi network fails. Immediately after the connection to the Message Broker, the topic is subscribed to esp32/command with QoS equal to one and the initialization of the relay status to off;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;void update_relay_status(int relayId, const int status)&lt;/strong&gt; : the responsibility of this function is to update the status of the relays by publishing messages on the related topics esp32/releay _ $ {id} _status;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;int * get_relays_status()&lt;/strong&gt; : the responsibility of this function is to return an array of four elements containing the status of the relays whose values can be: 0 for off and 1 for on;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;void callback(char * topic, byte * message, unsigned int length)&lt;/strong&gt; : this is the callback function called whenever a message is received on the topic for which you have an active subscription and in this case the topic for which there is a active subscription is esp32/command. The responsibility of this function is to acquire the messages arriving on the esp32/command topic, parse the received command and perform the corresponding action which can be: activate/deactivate the relay or publish the relay status.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By adopting the Arduino framework, we also carry the mandatory &lt;a href="https://www.arduino.cc/reference/en/language/structure/sketch/setup/"&gt;&lt;strong&gt;setup()&lt;/strong&gt;&lt;/a&gt; and &lt;a href="https://www.arduino.cc/reference/en/language/structure/sketch/loop/"&gt;&lt;strong&gt;loop() functions&lt;/strong&gt;&lt;/a&gt; . The setup() function is executed only once, at start-up, and the body of this function foresees:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;initialization of the &lt;a href="https://www.arduino.cc/reference/en/language/functions/communication/serial/"&gt;serial communication interface&lt;/a&gt; ;&lt;/li&gt;
&lt;li&gt;initialization of the logging framework;&lt;/li&gt;
&lt;li&gt;initialization and check of the I2C channel for the BME280 sensor;&lt;/li&gt;
&lt;li&gt;initialization of the &lt;em&gt;clientId&lt;/em&gt; variable used to identify the device as a client in the MQTT connection to the Message Broker;&lt;/li&gt;
&lt;li&gt;initialization of the connection to the WiFi network;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.arduino.cc/reference/en/language/functions/digital-io/pinmode/"&gt;pin mode&lt;/a&gt; initialization for relays (or actuators);&lt;/li&gt;
&lt;li&gt;initialization of the state of the relays (via &lt;a href="https://www.arduino.cc/reference/en/language/functions/digital-io/digitalwrite/"&gt;digitalWrite()&lt;/a&gt; bringing them all four to the deactivated state;&lt;/li&gt;
&lt;li&gt;initialization of the NTP Client (with UTC timezone).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The loop() function is instead executed in "continuation" and the body of this function provides:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;time client update via NTP;&lt;/li&gt;
&lt;li&gt;control of the connection to the Message Broker and possible recession;&lt;/li&gt;
&lt;li&gt;calling the &lt;em&gt;loop()&lt;/em&gt; method on the MQTT client to allow processing of incoming messages and maintain connection to the server;&lt;/li&gt;
&lt;li&gt;preparation of the message in JSON format that contains the environmental data coming from the BME280 sensor;&lt;/li&gt;
&lt;li&gt;publication of environmental data on the topic esp32/telemety_data;&lt;/li&gt;
&lt;li&gt;sending of the published JSON message on the serial line (for debugging purposes)&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  3. Compilation of the project
&lt;/h2&gt;

&lt;p&gt;Building the project is quite simple and just the way I like it: &lt;strong&gt;git clone and build&lt;/strong&gt; . Remember that before proceeding further, the required requirement is the installation of PlatformIO Core on your development machine.&lt;/p&gt;

&lt;p&gt;Until now we have not made any reference to how to configure the access parameters to the WiFi network and the Message Broker. &lt;strong&gt;What must be done to configure the access parameters to the WiFi network and the Message Broker?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In these cases, I usually prefer to follow the path of &lt;a href="https://docs.platformio.org/en/latest/projectconf/section_env_build.html%23id2"&gt;build flags&lt;/a&gt; . These flags affect the pre-processor, compilation, assembly, and linking processes for C and C ++ code. All compiler and linker flags can be used. In this case we will use the build flag &lt;strong&gt;-D name = definition&lt;/strong&gt; which affects the &lt;strong&gt;CPPDEFINES&lt;/strong&gt; build &lt;strong&gt;variable&lt;/strong&gt; . The contents of the definition are tokenized and processed as if they appeared during the third translation stage in a #define directive. For more information I invite you to read &lt;a href="https://en.wikipedia.org/wiki/C_preprocessor"&gt;&lt;strong&gt;C preprocessor&lt;/strong&gt;&lt;/a&gt; .&lt;/p&gt;

&lt;p&gt;At the beginning of the &lt;a href="https://github.com/amusarra/esp32-mqtt-publish-subscribe/blob/master/src/esp32_mqtt_publish_subscribe.cpp%23L38"&gt;esp32_mqtt_publish_subscribe.cpp&lt;/a&gt; source code there are the various &lt;strong&gt;ifdef… endif sections&lt;/strong&gt; for reading all the build flags. The build flags defined on the project's &lt;a href="https://github.com/amusarra/esp32-mqtt-publish-subscribe/blob/master/platformio.ini%23L24"&gt;platformio.ini&lt;/a&gt; file are shown below . Among the build flags, in addition to those concerning the access parameters to the WiFi network and the Message Broker, we also have a build parameter that sets the name of the device. Note that the values of these parameters come from their environment variables.&lt;/p&gt;

&lt;p&gt;Before continuing with the compilation process, it is therefore necessary to set the environment variables indicated above. Since we have two devices on which to install the software, we are careful to modify the &lt;strong&gt;DEVICE_NAME&lt;/strong&gt; environment &lt;strong&gt;variable&lt;/strong&gt; . This environment variable can take the following values: esp32-zone-1 and esp32-zone-2. The device name information is reported on the JSON message that contains the environmental data.&lt;/p&gt;

&lt;p&gt;Below are the commands necessary to complete the compilation of the project and thus generate the artifact ( &lt;strong&gt;firmware.bin&lt;/strong&gt; ) which will subsequently be installed on the ESP32 device.&lt;/p&gt;

&lt;p&gt;During the build process, PlatformIO also downloads the libraries on which the project depends and which are indicated in the &lt;a href="https://github.com/amusarra/esp32-mqtt-publish-subscribe/blob/master/platformio.ini%23L33"&gt;&lt;strong&gt;lib_deps&lt;/strong&gt;&lt;/a&gt; section of the platformio.ini file (see also Table 5).&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://asciinema.org/a/406054?autoplay%3D1"&gt;Compiling the ESP32 MQTT Publish/Subscribe project with PlatformIO&lt;/a&gt; screencast is shown below so that you can see exactly the execution of the steps indicated above.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Upload of the software on the ESP32 device
&lt;/h2&gt;

&lt;p&gt;We have reached the final step for what concerns the ESP32 devices, that is, the upload of what can also be called the firmware of our devices. The upload operation is always assigned to PlatformIO using the simple command: &lt;code&gt;pio run --target upload --environment esp32dev&lt;/code&gt;. The same operation can also be performed through the IDE.&lt;/p&gt;

&lt;p&gt;In reality it is also possible to skip the project compilation process, the upload process, if necessary, will start the compilation of the code and then continue with the upload on the ESP32.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://asciinema.org/a/406685?autoplay%3D1"&gt;Upload software to ESP32 Device via PlatformIO&lt;/a&gt; screencast is shown &lt;a href="https://asciinema.org/a/406685?autoplay%3D1"&gt;below&lt;/a&gt; so that you can see exactly the execution of the .pio/build/esp32dev/firmware.bin firmware upload phase on the ESP32 device.&lt;/p&gt;

&lt;p&gt;On the image below it is possible to see the status of the LEDs after uploading the software to the devices and in particular of the blue LED. When the blue led is steady on, it means that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;the connection to the WiFi network was successful;&lt;/li&gt;
&lt;li&gt;the ping to the Message Broker was successful;&lt;/li&gt;
&lt;li&gt;the connection to the EMQ X Edge Message Broker went well;&lt;/li&gt;
&lt;li&gt;the subscription to the topic esp32/command was successful.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5_ntQWTw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/04/status_led_upload_software_esp32_device-scaled.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5_ntQWTw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/04/status_led_upload_software_esp32_device-scaled.jpg" alt="*Indication of the operation of the ESP32 device through the blue LED on the development board*"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure 4 - Indication of the operation of the ESP32 device through the blue LED on the development board&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ultimately this led ( &lt;a href="https://github.com/amusarra/esp32-mqtt-publish-subscribe/blob/master/src/esp32_mqtt_publish_subscribe.cpp%23L70"&gt;attested on GPIO 2&lt;/a&gt; ) gives us indications if everything is going the right way. In this case we are lucky, the led is on and we are therefore sure that the environmental data are published on the topic esp32/telemetry_data and that the device is ready to receive commands on the topic esp32/command. If we wanted to check the activity of the device, we could connect to the serial monitor always using PlatformIO, using the command: &lt;code&gt;pio device monitor --environment esp32dev&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The following image shows the output of the above command. As you can see, we get several information in the output. Information on the chip model, information on the WiFi network to which the device is connected, information on the Message Broker to which the device is connected and finally the JSON published on the topic esp32/telemetry_data.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nGJPtpVs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/04/platformio_attach_device_serial_monitor_to_esp32.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nGJPtpVs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/04/platformio_attach_device_serial_monitor_to_esp32.png" alt="*Attach of the serial monitor on one of the ESP32 devices in order to monitor the activities in progress*"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure 5 - Attach of the serial monitor on one of the ESP32 devices in order to monitor the activities in progress&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We have to repeat the same software compilation and upload operations also for the second device and once done we can define this phase concluded and go to carry out the first integration test.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. The final result
&lt;/h2&gt;

&lt;p&gt;The two images below show the different information that is displayed on the LCD display. The information refers in particular to environmental temperature and humidity data and the status of the relays. The LCD display also shows information on which device is the data source.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0O1rB7Fi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/04/show_telemetry_data_on_lcd_attached_to_rpi_1-scaled.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0O1rB7Fi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/04/show_telemetry_data_on_lcd_attached_to_rpi_1-scaled.jpg" alt="*LCD display showing environmental temperature and humidity data for each device*"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure 6 - LCD display showing environmental temperature and humidity data for each device&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GF_IZH5y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/04/show_telemetry_data_on_lcd_attached_to_rpi_2-scaled.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GF_IZH5y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/04/show_telemetry_data_on_lcd_attached_to_rpi_2-scaled.jpg" alt="*LCD display showing the status of the relays for each device*"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure 7 - LCD display showing the status of the relays for each device&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DYEbTnNs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/04/node_red_dashboard_2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DYEbTnNs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.dontesta.it/wp-content/uploads/2021/04/node_red_dashboard_2.png" alt="*MQTT Dashboard Node-RED for the ESP32 Device 1*"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure 8 - MQTT Dashboard Node-RED for the ESP32 Device 1&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>esp32</category>
      <category>raspberrypi</category>
      <category>nodered</category>
      <category>mqtt</category>
    </item>
  </channel>
</rss>
