1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
# MEDIA_ACCESS_API
## Objectif
Definir une couche d'autorisation entre viewer-bff et MinIO afin d'appliquer les ACL Keycloak avant chaque lecture media.
## Principes de securite
- Deny-by-default.
- Validation JWT obligatoire (issuer, audience, signature, expiration).
- Evaluation des roles cumulables pour obtenir les prefixes MinIO autorises.
- Jamais d'acces public direct au bucket prive.
- Utilisation d'URLs pre-signees courtes (TTL court) pour la lecture.
## Variables d'environnement minimales
- `OIDC_ISSUER=https://kc.arauco.online/realms/chiruca`
- `OIDC_AUDIENCE=media-access-api`
- `OIDC_JWKS_URL=https://kc.arauco.online/realms/chiruca/protocol/openid-connect/certs`
- `RBAC_ROLE_PREFIX=media_reader:folder:`
- `RBAC_ROLE_ALL=media_reader:all`
- `S3_ENDPOINT=http://minio:9000`
- `S3_BUCKET=medias-private`
- `S3_FORCE_PATH_STYLE=true`
- `PRESIGN_TTL_SECONDS=120`
## Contrat API propose
### `GET /health`
- Reponse: `200` si service operationnel.
### `GET /v1/permissions`
- Auth: `Bearer <jwt>`
- Reponse `200`:
```json
{
"subject": "user-id",
"allowAll": false,
"allowedPrefixes": [
"photos/equipeA/",
"photos/projetX/"
]
}
```
### `POST /v1/presign`
- Auth: `Bearer <jwt>`
- Payload:
```json
{
"objectKey": "photos/equipeA/2026/03/image-001.jpg"
}
```
- Reponse `200`:
```json
{
"url": "https://...signature...",
"expiresIn": 120
}
```
- Reponses d'erreur:
- `401`: token invalide/absent.
- `403`: role insuffisant ou `objectKey` hors prefixe autorise.
- `404`: objet introuvable.
## Algorithme d'autorisation (reference)
1. Extraire les roles client depuis le token (`resource_access.media-access-api.roles`).
2. Si `RBAC_ROLE_ALL` present, autoriser.
3. Sinon, filtrer les roles commencant par `RBAC_ROLE_PREFIX`.
4. Convertir chaque role en prefixe MinIO (ex: `media_reader:folder:photos/equipeA` -> `photos/equipeA/`).
5. Autoriser uniquement si `objectKey` commence par un prefixe calcule.
## Integration viewer-bff
- Le viewer-bff conserve la navigation et la recherche cote interface web.
- Les originaux proteges sont servis via `media-access-api` (URL pre-signee).
- Le bucket MinIO reste prive (pas de policy publique de lecture).
## Journalisation et audit
- Logger `subject`, `objectKey`, decision (`allow`/`deny`), raison, `requestId`.
- Ne jamais logger un token complet ni des secrets.
- Exporter des metriques de refus ACL pour detection d'erreurs de mapping.
|