Skip to content

Commit d3e239c

Browse files
authored
Merge branch 'alpha' into feat/issue-3237-tipimail-preprod-prod
2 parents 95d055d + 6407cbc commit d3e239c

43 files changed

Lines changed: 1140 additions & 24 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.kontinuous/Chart.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
dependencies:
2+
- name: valkey
3+
repository: https://valkey.io/valkey-helm
4+
version: 0.9.4
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
kind: ConfigMap
2+
apiVersion: v1
3+
metadata:
4+
name: valkey
5+
data:
6+
VALKEY_URL: "redis://valkey:6379"
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
kind: ConfigMap
2+
apiVersion: v1
3+
metadata:
4+
name: valkey
5+
data:
6+
VALKEY_URL: "redis://valkey:6379"
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
kind: ConfigMap
2+
apiVersion: v1
3+
metadata:
4+
name: valkey
5+
data:
6+
VALKEY_URL: "redis://valkey:6379"

.kontinuous/env/prod/values.yaml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,24 @@ app:
1616
limits:
1717
cpu: 1
1818
memory: 2G
19+
20+
valkey:
21+
replica:
22+
enabled: true
23+
# One replica pod per always-on app pod (= app.autoscale.minReplicas below).
24+
# valkey-helm deploys 1 primary + N replicas, so this gives 3 total pods,
25+
# matching the app HA floor. valkey has no HPA, so we pin to minReplicas
26+
# rather than maxReplicas to avoid over-provisioning cache storage.
27+
replicas: 2
28+
persistence:
29+
size: 1Gi
30+
podDisruptionBudget:
31+
enabled: true
32+
maxUnavailable: 1
33+
resources:
34+
requests:
35+
cpu: 100m
36+
memory: 256Mi
37+
limits:
38+
cpu: 1
39+
memory: 1Gi

.kontinuous/values.yaml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ app:
55
~chart: app
66
~needs:
77
- pg
8+
- valkey
89
imagePackage: app
910
probesPath: /api/healthz
1011
containerPort: 3000
@@ -46,6 +47,9 @@ app:
4647
- secretRef:
4748
name: "audit-cleanup"
4849
optional: true
50+
- configMapRef:
51+
name: "valkey"
52+
optional: true
4953
env:
5054
- name: POSTGRES_HOST
5155
valueFrom:
@@ -125,5 +129,32 @@ app:
125129
pg:
126130
~chart: pg
127131

132+
# Valkey cache. Official valkey-io/valkey-helm chart pulled as a Helm dependency
133+
# from .kontinuous/Chart.yaml. Values below flow straight through to that chart.
134+
valkey:
135+
# Pin service name so VALKEY_URL (redis://valkey:6379) resolves in every namespace.
136+
fullnameOverride: valkey
137+
image:
138+
tag: "9.0.2"
139+
service:
140+
type: ClusterIP
141+
port: 6379
142+
# Dev and preprod run a single-pod standalone deployment — cache loss on
143+
# restart is acceptable, and it keeps infra cost minimal. Prod overrides
144+
# this to a master/replica topology sized against app.autoscale.
145+
replica:
146+
enabled: false
147+
dataStorage:
148+
enabled: false
149+
auth:
150+
enabled: false
151+
resources:
152+
requests:
153+
cpu: 50m
154+
memory: 128Mi
155+
limits:
156+
cpu: 500m
157+
memory: 512Mi
158+
128159
clamav:
129160
~chart: clamav

README.md

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -174,19 +174,31 @@ SUIT EgaPro
174174
la clé publique de SUIT
175175
176176
6. Vérifie que le timestamp
177-
date de moins de 30s
177+
est dans la fenêtre de validité
178+
(30s en preprod/prod, 30j en dev)
178179
```
179180

181+
### Fenêtre de validité du timestamp
182+
183+
La durée pendant laquelle un timestamp signé reste accepté dépend de l'environnement (`NEXT_PUBLIC_EGAPRO_ENV`) :
184+
185+
| Environnement | Fenêtre | Raison |
186+
|---|---|---|
187+
| `dev` | **30 jours** | Permet de réutiliser une signature générée localement sans re-signer à chaque appel pendant une session de debug |
188+
| `preprod` / `prod` | **30 secondes** | Fenêtre anti-rejeu stricte |
189+
190+
Implémenté dans `packages/app/src/server/services/suitApiAuth.ts`.
191+
180192
### Génération et rotation des clés
181193

182194
```bash
183195
# Première génération
184-
./scripts/generate-suit-signing-keys.sh generate dev # → ./suit-signing-keys/dev/
185-
./scripts/generate-suit-signing-keys.sh generate prod # → ./suit-signing-keys/prod/
186-
./scripts/generate-suit-signing-keys.sh generate all # → les deux
196+
./packages/app/scripts/generate-suit-signing-keys.sh generate dev # → ./suit-signing-keys/dev/
197+
./packages/app/scripts/generate-suit-signing-keys.sh generate prod # → ./suit-signing-keys/prod/
198+
./packages/app/scripts/generate-suit-signing-keys.sh generate all # → les deux
187199

188200
# Rotation (sauvegarde les anciennes clés, génère de nouvelles)
189-
./scripts/generate-suit-signing-keys.sh renew prod
201+
./packages/app/scripts/generate-suit-signing-keys.sh renew prod
190202
```
191203

192204
`generate` refuse d'écraser des clés existantes. `renew` les sauvegarde dans un dossier `backup-{date}` avant de regénérer.
@@ -202,7 +214,9 @@ SUIT EgaPro
202214

203215
1. **Côté EgaPro** : encoder `suit-signing.pub` en base64 et le placer dans le sealed-secret K8s (`EGAPRO_SUIT_PUBLIC_KEY_PEM`).
204216
2. **Côté SUIT** : conserver `suit-signing.key` de manière sécurisée et signer chaque requête.
205-
3. **Appel API** :
217+
3. **Appel API** — deux options équivalentes :
218+
219+
**Option A (openssl)** :
206220
```bash
207221
TIMESTAMP=$(date +%s)
208222
PAYLOAD="$TIMESTAMP|GET|/api/v1/export/declarations"
@@ -213,9 +227,17 @@ SUIT EgaPro
213227
https://<host>/api/v1/export/declarations?date_begin=2026-01-01
214228
```
215229

230+
**Option B (script Node fourni)** — signe **toutes les routes SUIT protégées** en une seule exécution et affiche les `curl` prêts à copier :
231+
```bash
232+
node packages/app/scripts/generate-suit-signature.js \
233+
--key-file ./suit-signing-keys/dev/suit-signing.key
234+
```
235+
236+
Le script itère automatiquement sur les routes SUIT (actuellement `GET /api/v1/export/declarations` et `GET /api/v1/files`). Pour signer `GET /api/v1/files/<id>`, passer `--file-id <uuid>`. Pour surcharger l'URL cible, passer `--url https://egapro-preprod.fabrique.social.gouv.fr`. Voir `--help` pour toutes les options. Il suffit ensuite d'exporter `EGAPRO_SUIT_API_KEY=<api-key>` et d'exécuter un des `curl` affichés.
237+
216238
### Procédure de rotation
217239

218-
1. `./scripts/generate-suit-signing-keys.sh renew <env>` — génère une nouvelle paire, sauvegarde l'ancienne
240+
1. `./packages/app/scripts/generate-suit-signing-keys.sh renew <env>` — génère une nouvelle paire, sauvegarde l'ancienne
219241
2. Mettre à jour le sealed-secret K8s avec la nouvelle clé publique
220242
3. Déployer EgaPro
221243
4. Transmettre la nouvelle clé privée à SUIT — ils doivent basculer juste après le déploiement

docker-compose.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,20 @@ services:
8181
retries: 10
8282
start_period: 300s
8383

84+
valkey:
85+
image: valkey/valkey:8-alpine
86+
ports:
87+
- 6379:6379
88+
volumes:
89+
- valkeydata:/data
90+
healthcheck:
91+
test: ["CMD", "valkey-cli", "ping"]
92+
interval: 5s
93+
timeout: 5s
94+
retries: 5
95+
8496
volumes:
8597
pgdata:
8698
miniodata:
8799
clamdata:
100+
valkeydata:

packages/app/.env.example

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,5 @@ MAIL_ENABLED="true"
2828
SMTP_HOST="localhost"
2929
SMTP_PORT="1025"
3030
MAIL_FROM="no-reply@egapro.local"
31+
# Valkey cache — optional, app works without it (in-memory fallback)
32+
VALKEY_URL="redis://localhost:6379"

0 commit comments

Comments
 (0)