65 lines
2.3 KiB
Markdown
65 lines
2.3 KiB
Markdown
# 3.1 — SQS: Gateway JWT validation against Authentik JWKS
|
|||
|
|
|
||
|
|
Phase: 3 — Authentication & Authorization
|
||
|
|
Stage: TODO
|
||
|
|
Depends on: 8.2 (X-Service dispatcher), 8.10 (gate)
|
||
|
|
|
||
|
|
## Context
|
||
|
|
|
||
|
|
SQS (kmsvc management-service) has placeholder env vars for JWT validation:
|
||
|
|
- `KMSVC_AUTHENTIK_ISSUER_URL`
|
||
|
|
- `KMSVC_AUTHENTIK_AUDIENCE`
|
||
|
|
|
||
|
|
But **kmsvc code is unverified** — we don't know if it actually validates JWTs.
|
||
|
|
**Phase 8.2 decision**: Gateway validates SQS JWTs at ingress (not pushing to kmsvc).
|
||
|
|
|
||
|
|
## Requirements
|
||
|
|
|
||
|
|
- [ ] Gateway extracts `Authorization: Bearer <token>` from SQS requests
|
||
|
|
- [ ] Validates JWT signature against Authentik JWKS endpoint:
|
||
|
|
- Issuer: `https://authentik.riotpiao.com/application/o/sqs/`
|
||
|
|
- JWKS: `https://authentik.riotpiao.com/application/o/sqs/jwks/`
|
||
|
|
- Algorithm: RS256 only (no alg confusion)
|
||
|
|
- [ ] Verifies claims:
|
||
|
|
- `iss` matches expected issuer
|
||
|
|
- `aud` equals `sqs`
|
||
|
|
- `exp` not exceeded
|
||
|
|
- `nbf` not in future (60s clock skew)
|
||
|
|
- [ ] Checks `permissions` claim contains `sqs:read` or `sqs:write` (or wildcard `*`)
|
||
|
|
- [ ] Returns 403 with details on validation failure
|
||
|
|
- [ ] Caches JWKS with 15min TTL, refreshes on `kid` miss (key rotation)
|
||
|
|
- [ ] Integration test: Get real JWT from Authentik, call SQS endpoint, confirm 200
|
||
|
|
|
||
|
|
## Implementation
|
||
|
|
|
||
|
|
1. Add JWT validator to `internal/auth/jwt.go` (was removed, restore as Phase 3 work)
|
||
|
|
2. Wire into `internal/serviceadapter/router.go` Dispatcher for SQS only
|
||
|
|
3. Update `k8s/configmap.yaml` SQS `auth.required: true` + capability check
|
||
|
|
4. Add test to `internal/serviceadapter/real_integration_test.go`
|
||
|
|
|
||
|
|
## Verification
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Get JWT from Authentik
|
||
|
|
export JWT=$(curl -s -X POST https://authentik.riotpiao.com/application/o/token/ \
|
||
|
|
-d "grant_type=client_credentials&client_id=<id>&client_secret=<secret>&scope=openid" \
|
||
|
|
| jq -r '.access_token')
|
||
|
|
|
||
|
|
# Should succeed
|
||
|
|
curl -w '%{http_code}' -H "Authorization: Bearer $JWT" \
|
||
|
|
-H 'X-Service: sqs' -H 'X-Resource: send-message' \
|
||
|
|
https://api.riotpiao.com/
|
||
|
|
|
||
|
|
# Should 403
|
||
|
|
curl -w '%{http_code}' -H 'X-Service: sqs' -H 'X-Resource: send-message' \
|
||
|
|
https://api.riotpiao.com/
|
||
|
|
# expected: 403
|
||
|
|
```
|
||
|
|
|
||
|
|
## Notes
|
||
|
|
|
||
|
|
- **Not Phase 8.2**: Phase 8 was about routing & dispatcher architecture
|
||
|
|
- **Phase 3 scope**: Full auth integration & JWT validation
|
||
|
|
- **MinIO/Temporal**: Have native JWT support, tested in Phase 3 separately
|
||
|
|
- **Memory/IAM**: Services validate own JWTs (dumb pipe)
|