Skip to main content

ADR-003: Phase 2C - Deny-by-Default per Mutacions

Data: 2024-12
Estat: Implementat
Decisors: Equip de desenvolupament LDP


Context

Abans de Phase 2C, el sistema tenia una regla excessivament permissiva:

.requestMatchers(HttpMethod.POST, "/api/**").authenticated()
.requestMatchers(HttpMethod.PUT, "/api/**").authenticated()

Això permetia a qualsevol usuari autenticat (rol USER) crear o editar recursos de catàleg (Dance, Song, Event), el que no és desitjable:

  • El catàleg hauria de ser gestionat per administradors
  • Els usuaris normals no haurien de poder crear contingut de catàleg

Decisió

Implementar deny-by-default per a totes les mutacions (POST/PUT) amb permisos explícits per recurs:

Matriu de Permisos

RecursPOSTPUTDELETEPolítica
/api/dances/**ADMINADMINADMINCatàleg gestionat per admin
/api/songs/**ADMINADMINADMINCatàleg gestionat per admin
/api/events/**ADMINADMINADMINTemporal; futur: venue owners
/api/locations/**authenticatedBOLAADMINOwner pot editar
/api/venues/**authenticatedBOLAADMINOwner pot editar
/api/choreographers/*N/ABOLAN/AOwner pot editar
Fallback /api/**ADMINADMINADMINFail-secure

Canvis Implementats

  1. SecurityConfig.java: Regles explícites per cada tipus de recurs
  2. DanceController.java: @PreAuthorize("hasRole('ADMIN')") per POST/PUT
  3. SongController.java: @PreAuthorize("hasRole('ADMIN')") per POST/PUT
  4. EventController.java: @PreAuthorize("hasRole('ADMIN')") per POST/PUT
  5. Security Playbook: Actualitzat a v1.3 amb nova secció de permisos

Conseqüències

Positives

  • Fail-secure: Qualsevol endpoint no especificat requereix ADMIN
  • Principi de mínim privilegi: USER només pot llegir
  • Claritat: La matriu de permisos és explícita i documentada

Negatives

  • Més restrictiu: Pot requerir canvis si en el futur es vol permetre que users creïn contingut
  • Gestió d'events: Temporalment ADMIN-only; cal implementar ownership per venue promoters

Implementació

SecurityConfig.java (fragment)

// Phase 2C: Catalog resources (Dance/Song) are ADMIN-only
.requestMatchers(HttpMethod.POST, "/api/dances/**").hasRole("ADMIN")
.requestMatchers(HttpMethod.PUT, "/api/dances/**").hasRole("ADMIN")
.requestMatchers(HttpMethod.POST, "/api/songs/**").hasRole("ADMIN")
.requestMatchers(HttpMethod.PUT, "/api/songs/**").hasRole("ADMIN")
.requestMatchers(HttpMethod.POST, "/api/events/**").hasRole("ADMIN")
.requestMatchers(HttpMethod.PUT, "/api/events/**").hasRole("ADMIN")

// Deny-by-default: any other POST/PUT requires ADMIN (fail secure)
.requestMatchers(HttpMethod.POST, "/api/**").hasRole("ADMIN")
.requestMatchers(HttpMethod.PUT, "/api/**").hasRole("ADMIN")

Tests de Referència

  • CatalogAccessControlTest.java: 12 tests per verificar:
    • USER rep 403 ACCESS_DENIED en POST/PUT a catàleg
    • Anonymous rep 401 Unauthorized
    • ADMIN passa la capa d'autorització

Notes

  • Els tests d'integració requereixen que l'ApplicationContext Spring Boot funcioni correctament. Si hi ha problemes de configuració (DB, beans), els tests fallaran.
  • La validació manual amb curl/Postman confirma el comportament correcte.

Historial

DataVersióCanvis
2024-121.0Document inicial