unit-test-demo-app

L’obiettivo di questo progetto è di mostrare come è possibile usare dei tag degli unit test per cercare di garantire la verifica di aspetti specifici di una applicazione.

Keep a Changelog v1.1.0 badge Quality Gate Status Coverage License: MIT code of conduct CI workflow

Indice

Il progetto

Questo progetto dimostra come implementare una strategia di testing basata su tag JUnit per garantire la copertura dei requisiti di sicurezza in un’applicazione Quarkus con autenticazione JWT e RBAC (Role-Based Access Control).

Stack tecnologico

I principali componenti usati per questo progetto sono:

Mappatura ruoli e permessi

L’applicazione è configurata per gestire 3 ruoli e 4 path, che generano lo stesso documento in formati diversi. Non tutti i ruoli sono autorizzati a generare ogni path. Ecco la mappa dei permessi:

Path Output Ruoli autorizzati
/doc/example.md 📝 MarkDown admin, user, guest
/doc/example.adoc 📄 AsciiDoc admin
/doc/example.html 🌐 HTML admin, user
/doc/example.pdf 📑 PDF admin

Architettura della sicurezza

L’applicazione implementa un sistema di sicurezza a più livelli:

  1. Autenticazione JWT: Verifica dell’identità tramite token firmati
  2. RBAC: Controllo accessi basato su ruoli
  3. Test automatizzati: Garanzia della copertura dei requisiti di sicurezza tramite tag JUnit

Flusso di autenticazione

User → JWT Token → Quarkus Security → Role Check → Resource Access

Quickstart

Requisiti

Verifica dell’applicazione

Per eseguire i test standard:

mvn verify

Per attivare anche la verifica dei tag di sicurezza con il plugin junit5-tag-check-maven-plugin:

mvn verify -P security

Avvio dell’applicazione

mvn quarkus:dev

Utilizzo dell’applicazione

  1. Apri la Swagger UI
  2. Genera un JWT token (vedi sezione successiva)
  3. Autorizza le richieste con il token
  4. Testa gli endpoint disponibili

Generazione e utilizzo dei JWT token

Generazione del token

Usa l’endpoint /demo/{roles}.txt per generare un JWT con i ruoli desiderati.

I ruoli disponibili sono:

Esempio per generare un token con ruoli multipli (separati da virgola):

GET /demo/admin,user.txt

⚠️ Nota importante: L’endpoint /demo/{roles}.txt è fornito solo per scopi dimostrativi. In produzione, l’autenticazione deve avvenire tramite un Identity Provider (IDP) esterno.

generazione del jwt dimostrativo

Autorizzazione nella Swagger UI

  1. Clicca sul pulsante “Authorize” nella Swagger UI
  2. Inserisci il JWT ottenuto in precedenza nel formato: Bearer <token>
  3. Clicca su “Authorize”

autorizzazione con il jwt dimostrativo

Test: Accesso negato (403 Forbidden)

Se tenti di accedere a un endpoint senza i ruoli necessari, riceverai un errore 403.

Esempio: Tentativo di accesso a /doc/example.adoc senza ruolo admin

ruolo non autorizzato per il formato

Test: Accesso consentito (200 OK)

Con i ruoli appropriati, puoi accedere agli endpoint autorizzati.

Esempio: Accesso a /doc/example.md con ruoli guest o user

documento generato

Vedi la mappatura di ruoli e path per maggiori dettagli.

Note sugli unit test

Le classi di test principali sono:

Security JUnit con tagging

Strategia di testing

Il progetto utilizza un approccio basato su tag JUnit per garantire la copertura completa dei requisiti di sicurezza.

Definizione dei tag di sicurezza

Definiamo i gruppi di test con cui vogliamo classificare i nostri test:

Tag Descrizione Status Code atteso
authorized Test per accessi autorizzati 200, 201
unauthorized Test per utenti non autenticati (JWT mancante o non valido) 401
forbidden Test per utenti autenticati senza i permessi necessari 403
security Tag generico per qualsiasi altro controllo di sicurezza vari

Esempio di test

Ecco un esempio di test con tag forbidden:

@Test
@Tag("security")
@Tag("forbidden")
void testMarkdown403NoAdminRole() {
    String token = JwtGenerator.generateUserToken();
    given()
        .header("Authorization", "Bearer " + token)
        .when().get("/doc/example.adoc")
        .then().statusCode(Response.Status.FORBIDDEN.getStatusCode());
}

Verifica presenza test

Ci sono vari modi per verificare la presenza di test sui tag definiti.

Per questa demo usiamo il più semplice, ovvero andremo a verificare con il maven-surefire-plugin che sia presente almeno un test per ogni tag.

Questo può essere fatto con una execution del plugin per ogni tag, es:

<execution>
    <id>verify-security-tests</id>
    <phase>test</phase>
    <goals>
        <goal>test</goal>
    </goals>
    <configuration>
        <groups>security</groups>
        <failIfNoTests>true</failIfNoTests>
    </configuration>
</execution>

Nel nostro caso attiviamo questo controllo con il profilo security:

mvn verify -P security

Nota: È possibile usare questo meccanismo per verificare anche altri tag custom definiti dallo sviluppatore.

Note su test e coverage

Un effetto collaterale dell’utilizzo del profilo security è che vengono eseguiti solo i test con i tag definiti.

Nella nostra CI per ovviare a questa situazione, abbiamo separato lo step di verifica da quello per il calcolo del quality gate e coverage:

- name: Check security unit test tags
  run: mvn verify -P security
  
- name: Build and analyze
  env:
    SONAR_TOKEN: $
  run: mvn -B clean install org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.organization=fugerit79 -Dsonar.projectKey=fugerit79_unit-test-demo-app

Nota: In futuro potremmo rendere più robusto il meccanismo, ad esempio con un sistema più personalizzabile di verifica (es. custom maven plugin).

Troubleshooting

Errore 401 Unauthorized

Errore 403 Forbidden

Build fallisce con profilo security

Verifica che tutti i tag richiesti siano coperti dai test:

mvn test -P security

Se mancano test per un tag specifico, il plugin junit5-tag-check-maven-plugin segnalerà l’errore con un messaggio chiaro.

Problemi con la versione di Quarkus

Se riscontri errori di tipo IllegalAccessError o problemi con ConfigMappingContext, verifica:

  1. Di utilizzare una versione stabile di Quarkus (attualmente 3.31.1)
  2. Che il file application.yaml sia correttamente formattato
  3. Di eseguire una pulizia completa: mvn clean

Contribuire

Contributi sono benvenuti! Per favore:

  1. Fork del repository
  2. Crea un branch per la tua feature (git checkout -b feature/AmazingFeature)
  3. Commit delle modifiche (git commit -m 'Add some AmazingFeature')
  4. Push al branch (git push origin feature/AmazingFeature)
  5. Apri una Pull Request

Assicurati che:

Licenza

Questo progetto è rilasciato sotto licenza MIT - vedi il file LICENSE per i dettagli.